diff options
author | Simon Rettberg | 2021-04-06 14:23:46 +0200 |
---|---|---|
committer | Simon Rettberg | 2021-04-06 14:23:46 +0200 |
commit | 26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9 (patch) | |
tree | a51e1637554bcd84e63cccb1cb220c898a2c4ee8 /utils | |
parent | 5.44 (diff) | |
download | xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.tar.gz xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.tar.xz xscreensaver-26b6e4255d4b9ff79a6dca10de5bec7bfc8691f9.zip |
xscreensaver 6.00
Diffstat (limited to 'utils')
37 files changed, 3859 insertions, 767 deletions
diff --git a/utils/Makefile.in b/utils/Makefile.in index dbb593b..d624e2f 100644 --- a/utils/Makefile.in +++ b/utils/Makefile.in @@ -1,4 +1,4 @@ -# utils/Makefile.in --- xscreensaver, Copyright (c) 1997-2010 Jamie Zawinski. +# utils/Makefile.in --- xscreensaver, Copyright © 1997-2021 Jamie Zawinski. # the `../configure' script generates `utils/Makefile' from this file. @@ -102,35 +102,33 @@ X_CFLAGS = @X_CFLAGS@ INCLUDES_1 = -I$(srcdir) -I.. INCLUDES = $(INCLUDES_1) @INCLUDES@ -SRCS = alpha.c colors.c fade.c grabscreen.c grabclient.c hsv.c \ +SRCS = alpha.c colors.c grabscreen.c grabclient.c hsv.c \ overlay.c resources.c spline.c usleep.c visual.c \ visual-gl.c xmu.c logo.c yarandom.c erase.c \ xshm.c xdbe.c colorbars.c minixpm.c textclient.c \ textclient-mobile.c aligned_malloc.c thread_util.c \ - async_netdb.c xft.c utf8wc.c pow2.c font-retry.c -OBJS = alpha.o colors.o fade.o grabscreen.o grabclient.o hsv.o \ + async_netdb.c xft.c xftwrap.c utf8wc.c pow2.c font-retry.c +OBJS = alpha.o colors.o grabscreen.o grabclient.o hsv.o \ overlay.o resources.o spline.o usleep.o visual.o \ visual-gl.o xmu.o logo.o yarandom.o erase.o \ xshm.o xdbe.o colorbars.o minixpm.o textclient.o \ - textclient-mobile.o aligned_malloc.o thread_util.o \ - async_netdb.o xft.o utf8wc.o pow2.o \ - font-retry.o font-retry-xft.o -HDRS = alpha.h colors.h fade.h grabscreen.h hsv.h resources.h \ + aligned_malloc.o thread_util.o \ + async_netdb.o xft.o xftwrap.o utf8wc.o pow2.o \ + font-retry.o +HDRS = alpha.h colors.h grabscreen.h hsv.h resources.h \ spline.h usleep.h utils.h version.h visual.h vroot.h xmu.h \ yarandom.h erase.h xshm.h xdbe.h colorbars.h minixpm.h \ xscreensaver-intl.h textclient.h aligned_malloc.h \ - thread_util.h async_netdb.h xft.h utf8wc.h pow2.h \ - font-retry.h + thread_util.h async_netdb.h xft.h xftwrap.h utf8wc.h pow2.h \ + font-retry.h queue.h STAR = * LOGOS = images/$(STAR).xpm \ images/$(STAR).png \ images/$(STAR).gif \ - images/$(STAR).eps + images/$(STAR).pdf EXTRAS = README Makefile.in ad2c bin2c -VMSFILES = compile_axp.com compile_decc.com vms-gtod.c vms-gtod.h \ - vms-strdup.c -TARFILES = $(EXTRAS) $(VMSFILES) $(SRCS) $(HDRS) $(LOGOS) +TARFILES = $(EXTRAS) $(SRCS) $(HDRS) $(LOGOS) default: all @@ -185,49 +183,24 @@ TAGS: tags tags: find $(srcdir) -name '*.[chly]' -print | xargs etags -a -echo_tarfiles: - @echo $(TARFILES) - +list_tarfiles: + @find $(TARFILES) -type f -print | sort # How we build object files in this directory. CCUTILS = $(INCLUDES) $(DEFS) $(CPPFLAGS) $(CFLAGS) $(X_CFLAGS) .c.o: $(CC) -c $(CCUTILS) $< -# Two versions of this: driver/ does not link with Xft, but hacks/ does. -font-retry-xft.o: $(srcdir)/font-retry.c +font-retry.o: $(srcdir)/font-retry.c $(CC) -c $(CCUTILS) -DUSE_XFT $< -o $@ -# Rules for generating the VMS makefiles on Unix, so that it doesn't have to -# be done by hand... -# -VMS_AXP_COMPILE=$$ CC/DECC/PREFIX=ALL/DEFINE=(VMS,HAVE_CONFIG_H)/INCL=([],[-]) - -compile_axp.com: Makefile.in - @echo generating $@ from $<... ; \ - ( ( for c in $(SRCS) vms-*.c ; do \ - c=`echo $$c | tr a-z A-Z` ; \ - echo "$(VMS_AXP_COMPILE) $$c" ; \ - done ; \ - ) | sort -d ; \ - echo '$$ lib/cre utils.olb_axp' ; \ - echo '$$ lib utils.olb_axp *.obj' ; \ - echo '$$! delete/noconf *.obj;' ; \ - ) > $@ - -compile_decc.com: compile_axp.com - @echo generating $@ from $<... ; \ - sed 's/axp/decc/g' < $< > $@ - -distdepend:: compile_axp.com compile_decc.com - - ############################################################################## # # DO NOT DELETE: updated by make distdepend aligned_malloc.o: $(srcdir)/aligned_malloc.h +aligned_malloc.o: ../config.h alpha.o: $(srcdir)/alpha.h alpha.o: ../config.h alpha.o: $(srcdir)/hsv.h @@ -256,11 +229,6 @@ erase.o: $(srcdir)/resources.h erase.o: $(srcdir)/usleep.h erase.o: $(srcdir)/utils.h erase.o: $(srcdir)/yarandom.h -fade.o: ../config.h -fade.o: $(srcdir)/fade.h -fade.o: $(srcdir)/usleep.h -fade.o: $(srcdir)/utils.h -fade.o: $(srcdir)/visual.h font-retry.o: ../config.h font-retry.o: $(srcdir)/font-retry.h font-retry.o: $(srcdir)/utils.h @@ -286,11 +254,11 @@ hsv.o: $(srcdir)/hsv.h hsv.o: $(srcdir)/utils.h logo.o: ../config.h logo.o: $(srcdir)/images/logo-180.xpm +logo.o: $(srcdir)/images/logo-360.xpm logo.o: $(srcdir)/images/logo-50.xpm logo.o: $(srcdir)/minixpm.h logo.o: $(srcdir)/resources.h logo.o: $(srcdir)/utils.h -logo.o: $(srcdir)/visual.h minixpm.o: ../config.h minixpm.o: $(srcdir)/minixpm.h overlay.o: ../config.h @@ -328,12 +296,17 @@ xdbe.o: ../config.h xdbe.o: $(srcdir)/resources.h xdbe.o: $(srcdir)/utils.h xdbe.o: $(srcdir)/xdbe.h +xdbe.o: $(srcdir)/xmu.h xft.o: ../config.h +xftwrap.o: ../config.h +xftwrap.o: $(srcdir)/utils.h +xftwrap.o: $(srcdir)/xft.h +xftwrap.o: $(srcdir)/xftwrap.h xmu.o: ../config.h +xmu.o: $(srcdir)/xmu.h xshm.o: $(srcdir)/aligned_malloc.h xshm.o: ../config.h xshm.o: $(srcdir)/resources.h -xshm.o: $(srcdir)/thread_util.h xshm.o: $(srcdir)/utils.h xshm.o: $(srcdir)/xshm.h yarandom.o: ../config.h diff --git a/utils/aligned_malloc.c b/utils/aligned_malloc.c index b345ad1..8c45fc8 100644 --- a/utils/aligned_malloc.c +++ b/utils/aligned_malloc.c @@ -13,6 +13,10 @@ software for any purpose. It is provided "as is" without express or implied warranty. */ +#if HAVE_CONFIG_H +# include "config.h" +#endif + #include "aligned_malloc.h" #include <stddef.h> @@ -21,6 +25,254 @@ implied warranty. #include <assert.h> #include <errno.h> +/* Might be changed by thread_util.c:threads_available() + */ +unsigned int aligned_malloc_default_alignment = sizeof(void *); + + +#if HAVE_UNISTD_H +# include <unistd.h> +#endif + +#if defined __MACH__ && defined __APPLE__ /* OS X, iOS */ +# include <sys/sysctl.h> +# include <inttypes.h> +#endif + +#define IS_POWER_OF_2(x) ((x) > 0 && !((x) & ((x) - 1))) + +/* + arraysize(a). Also known as countof(x), XtNumber(x), NELEMS(x), LEN(x), + NUMOF(x), ARRAY_SIZE(x), etc., since the fine folks behind C never got + around to including this incredibly useful macro in the standard library, + which is where it belongs. + + Much of the code here assumes that multiple processors in a system all use + the same cache line size...which might be wrong on occasion. +*/ + +#define arraysize(a) (sizeof(a) / sizeof(*(a))) +#define arrayend(a) ((a) + arraysize(a)) + +/* +These numbers are from: +- Linux: arch/(arch name)/include/asm/cache.h, note + L1_CACHE_BYTES/L1_CACHE_SHIFT/SMP_CACHE_BYTES. +- FreeBSD: sys/(sys name)/include/param.h, note + CACHE_LINE_SHIFT/CACHE_LINE_SIZE. + +Preprocessor symbols come from: +- TARGET_CPU_CPP_BUILTINS() in the GNU C preprocessor + <http://code.ohloh.net/?s=%22TARGET_CPU_CPP_BUILTINS%22&fp=304413> +- http://predef.sourceforge.net/ +*/ + +/* +Several architectures need preprocessor symbols. + +Qualcomm Hexagon: 1 << 5 +Imagination Technologies META: 1 << 6 +OpenRISC: 16 (Linux has the cache line size as a todo.) +Unicore: 1 << 5 +*/ + +#if defined __MACH__ && defined __APPLE__ /* OS X, iOS */ +# include <TargetConditionals.h> /* For TARGET_OS_IPHONE. */ +# ifdef TARGET_OS_IPHONE +# define _CACHE_LINE_SIZE 64 +# endif +#endif + +#if defined __FreeBSD__ && !defined _CACHE_LINE_SIZE +# include <machine/param.h> +# ifdef CACHE_LINE_SIZE +# define _CACHE_LINE_SIZE CACHE_LINE_SIZE +# endif +#endif + +#if !defined _CACHE_LINE_SIZE +# if defined __alpha || defined __alpha__ +/* DEC Alpha */ +# define _CACHE_LINE_SIZE 64 /* EV6 and above. EV4 and EV5 use 32 bytes. */ +# elif defined __arm__ +/* ARM architecture */ +# define _CACHE_LINE_SIZE (1 << 6) +# elif defined __AVR || defined __AVR__ +/* Atmel AVR32 */ +# define _CACHE_LINE_SIZE (1 << 5) +# elif defined __bfin || defined __BFIN__ +/* Analog Devices Blackfin */ +# define _CACHE_LINE_SIZE (1 << 5) +# elif defined _TMS320C6X || defined __TMS320C6X__ +/* Texas Instruments TMS320C6x */ +# define _CACHE_LINE_SIZE (1 << 7) /* From L2. L1 data cache line is 1 << 6. */ +# elif defined __cris +/* Axis Communications ETRAX CRIS */ +# define _CACHE_LINE_SIZE 32 +# elif defined __ia64__ || defined _IA64 +/* Intel Itanium */ +# define _CACHE_LINE_SIZE (1 << 7) +# elif defined __M32R__ || defined __m32r__ +/* Mitsubishi/Renesas M32R */ +# define _CACHE_LINE_SIZE (1 << 4) +# elif defined __m68k__ || defined M68000 || defined __MC68K__ +/* Motorola 68000 */ +# define _CACHE_LINE_SIZE (1 << 4) +# elif defined __MICROBLAZE__ || defined __microblaze__ +/* Xilinx MicroBlaze */ +# define _CACHE_LINE_SIZE (1 << 5) +# elif defined __mips__ || defined __mips || defined __MIPS__ +/* MIPS */ +# define _CACHE_LINE_SIZE (1 << 6) +# elif defined __mn10300__ || defined __MN10300__ +/* Matsushita/Panasonic MN103 */ +# define _CACHE_LINE_SIZE 32 /* MN103E010 has 16 bytes. */ +# elif defined __hppa || defined __hppa__ +/* Hewlett-Packard PA-RISC */ +# define _CACHE_LINE_SIZE 64 /* PA-RISC 2.0 uses 64 bytes, PA-RISC 1.1 uses 32. */ +# elif defined __powerpc || defined _ARCH_PPC +/* Power Architecture (a.k.a. PowerPC) */ +# define _CACHE_LINE_SIZE (1 << 7) /* Linux has a list of PPC models with associated L1_CACHE_SHIFT values. */ +# elif defined __s390__ || defined __370__ || defined __zarch__ || defined __SYSC_ZARCH__ +/* IBM System/390 */ +# define _CACHE_LINE_SIZE 256 +# elif defined SUNPLUS || defined __SCORE__ || defined __score__ +/* Sunplus S+core */ +# define _CACHE_LINE_SIZE (1 << 4) +# elif defined __sh__ +/* Hitachi SuperH */ +# define _CACHE_LINE_SIZE (1 << 5) /* SH3 and earlier used 1 << 4. */ +# elif defined __sparc__ || defined __sparc +/* SPARC */ +# define _CACHE_LINE_SIZE (1 << 7) /* Linux and FreeBSD disagree as to what this should be. */ +# elif defined __tile__ +/* Tilera TILE series */ +# define _CACHE_LINE_SIZE (1 << 6) /* TILEPro uses different sizes for L1 and L2. */ +# elif defined __i386 || defined __x86_64 +/* x86(-64) */ +# define _CACHE_LINE_SIZE (1 << 7) +# elif defined __xtensa__ || defined __XTENSA__ +/* Cadence Design Systems/Tensilica Xtensa */ +# define _CACHE_LINE_SIZE (1 << 5) /* 1 << 4 on some models. */ +# endif +#endif /* !defined _CACHE_LINE_SIZE */ + +#if defined __NetBSD__ && !defined _CACHE_LINE_SIZE +/* +NetBSD defines COHERENCY_UNIT to be 32 on MIPS, and 64 for all other platforms -- which is wrong. Still, this is what the kernel +uses; if this value didn't work, the system wouldn't run. +*/ +# include <sys/param.h> +# ifdef COHERENCY_UNIT +# define _CACHE_LINE_SIZE COHERENCY_UNIT +# endif +#endif + +#ifndef _CACHE_LINE_SIZE +# define _CACHE_LINE_SIZE 256 /* Fallback cache line size. */ +#endif + +static unsigned _get_cache_line_size(void) +{ + /* + The general idea: + - Try to get the actual cache line size from the operating system. + - In the interest of keeping things simple, this only checks with + glibc and OS X. + - A few other methods that could be added: + - Query x86 CPUs directly with the CPUID instruction. + - Query various ELF systems through the auxillary vector. + (Power, Alpha, SuperH) + - Query Linux through + /sys/devices/system/cpu/cpu?/cache/index?/coherency_line_size + (x86 only, AFAIK) + - Query Linux through cache_alignment in /proc/cpuinfo + - Query Solaris through PICL. + - If that fails, return a value appropriate for the current CPU + architecture. + - Otherwise, return a sufficiently large number. + */ + + /* + sysconf(3) is not a syscall, it's a glibc call that, for cache line sizes, + uses CPUID on x86 and returns 0 on other platforms. If it were to work on + most other platforms, it would have to get cache information from the + kernel, since that information is usually made available by the processor + only in privileged mode. + https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/i386/sysconf.c;hb=HEAD + */ + + /* uClibc, newlib, dietlibc, musl, Bionic do not have this. */ + +# if HAVE_UNISTD_H && ( \ + defined _SC_LEVEL1_DCACHE_LINESIZE || \ + defined _SC_LEVEL2_CACHE_LINESIZE || \ + defined _SC_LEVEL3_CACHE_LINESIZE || \ + defined _SC_LEVEL4_CACHE_LINESIZE) + { + static const int names[] = + { +# ifdef _SC_LEVEL1_DCACHE_LINESIZE + _SC_LEVEL1_DCACHE_LINESIZE, +# endif +# ifdef _SC_LEVEL2_CACHE_LINESIZE + _SC_LEVEL2_CACHE_LINESIZE, +# endif +# ifdef _SC_LEVEL3_CACHE_LINESIZE + _SC_LEVEL3_CACHE_LINESIZE, +# endif +# ifdef _SC_LEVEL4_CACHE_LINESIZE + _SC_LEVEL4_CACHE_LINESIZE +# endif + }; + + const int *name; + long result = 0; + + for(name = names; name != arrayend(names); ++name) + { + long sysconf_result = sysconf(*name); /* Can return -1 or 0 on + failure. */ + + if(sysconf_result > result) + result = sysconf_result; + } + + if(result) + return result; + + /* Currently, this fails for every platform that isn't x86. Perhaps + future versions will support other processors? */ + } +# endif + +# if defined __MACH__ && defined __APPLE__ + { + uint32_t result; /* sysctl.h says that hw.cachelinesize is a + CTLTYPE_INT. */ + size_t size = sizeof(result); + static const int name[] = {CTL_HW, HW_CACHELINE}; + + if(!sysctl((int *)name, 2, &result, &size, NULL, 0)) /* (int *) is for OS X. */ + { + assert(size == sizeof(result)); + return result; + }; + } +# endif + + /* Guess based on the CPU type. */ + return _CACHE_LINE_SIZE; +} + +unsigned get_cache_line_size(void) +{ + unsigned result = _get_cache_line_size(); + assert(result >= sizeof(void *)); + assert(IS_POWER_OF_2(result)); + return result; +} + /* aligned_alloc() (C11) or posix_memalign() (POSIX) are other possibilities for aligned_malloc(). */ @@ -28,10 +280,15 @@ implied warranty. int aligned_malloc(void **ptr, unsigned alignment, size_t size) { void *block_start; - ptrdiff_t align1 = alignment - 1; + ptrdiff_t align1; + + if (alignment == 0) + alignment = aligned_malloc_default_alignment; assert(alignment && !(alignment & (alignment - 1))); /* alignment must be a power of two. */ + align1 = alignment - 1; + size += sizeof(void *) + align1; block_start = malloc(size); if(!block_start) diff --git a/utils/aligned_malloc.h b/utils/aligned_malloc.h index b3f43c9..0ec675f 100644 --- a/utils/aligned_malloc.h +++ b/utils/aligned_malloc.h @@ -18,9 +18,13 @@ implied warranty. #include <stdlib.h> +extern unsigned int aligned_malloc_default_alignment; + +unsigned get_cache_line_size(void); + /* This can't simply be named posix_memalign, since the real thing uses free(), but this one can't. */ - int aligned_malloc(void **ptr, unsigned alignment, size_t size); - void aligned_free(void *); +int aligned_malloc(void **ptr, unsigned alignment, size_t size); +void aligned_free(void *); #endif /* __ALIGNED_MALLOC_H__ */ diff --git a/utils/async_netdb.c b/utils/async_netdb.c index 930da40..d9e2102 100644 --- a/utils/async_netdb.c +++ b/utils/async_netdb.c @@ -48,10 +48,10 @@ int _async_netdb_is_done (struct io_thread *io) # define _get_addr_family(addr) ((addr)->x_sockaddr_in.sin_family) # define _get_addr_len(addr) ((addr)->x_sockaddr_in.sin_len) -static const int _has_threads = -1; - # if ASYNC_NETDB_FAKE_EAI +static const int _has_threads = -1; + const char *_async_netdb_strerror (int errcode) { /* (h)strerror should return messages in the user's preferred language. */ diff --git a/utils/font-retry.c b/utils/font-retry.c index f8e6507..3122969 100644 --- a/utils/font-retry.c +++ b/utils/font-retry.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2018 by Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright (c) 2018-2021 by Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -9,11 +9,56 @@ * implied warranty. */ -/* Like XLoadQueryFont, but if it fails, it tries some heuristics to - load something close. +/* The value of XScreenSaver's font resource strings is a comma-separated + list of font names that look like this: + + Helvetica Bold Italic 12 + + We parse that into an XLFD and pass that along to the underlying systems: + XftFontOpenXlfd or jwxyz. + + Xft does aggressive substitution of unknown fonts, so if we don't get an + exact match on the font name, we move on to the next element in the list. + For the last element, we take whatever substitution we got. + + XftNameParse uses this syntax: + + "Helvetica Neue-12:style=Bold" + "Helvetica Neue-12:style=Bold Italic" + "Helvetica Neue-12:slant=110:weight=200" + + Cocoa uses PostScript names, with hyphens: + + [NSFont fontWithName:@"Helvetica-BoldOblique" size:12]; + [NSFont fontWithName:@"Times-Roman" size:12]; + + Alternately, with separated styles: + + [[NSFontManager sharedFontManager] + fontWithFamily:@"Helvetica" traits:NSBoldFontMask weight:5 size:12]; + + Android separates names from styles: + + Paint.setTypeface (Typeface.create ("Helvetica", Typeface.BOLD)); + Paint.setTextSize (12); + + See android/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java + + + In XScreenSaver 6, USE_XFT is always true, as all programs now use Xft. + + In XScreenSaver 5, this file was compiled in two different ways: + - As font-retry.o for programs that did not link with libXft; + - As font-retry-xft.o for programs that did. + + #ifdef USE_XFT is whether Xft code should be called. + #ifdef HAVE_XFT is whether libXft is natively available. + + The reason there are two defines is that if HAVE_XFT is not defined, + the Xft API is still available through emulation provided by "xft.h". */ -#define _GNU_SOURCE +#define _GNU_SOURCE /* Why is this here? */ #include "utils.h" #include "visual.h" @@ -26,194 +71,471 @@ extern const char *progname; #define countof(x) (sizeof((x))/sizeof((*x))) #undef DEBUG +#undef SELFTEST + +#ifdef HAVE_JWXYZ +# define USE_XFT 1 +#endif + +#ifdef SELFTEST +static void xft_selftest (Display *dpy, int screen); +#endif + + +/* Parse font names of the form "Helvetica Neue Bold Italic 12". + */ +static char * +font_name_to_xlfd (const char *font_name) +{ + char *name = strdup (font_name); + char *xlfd = 0; + char *s, *s2, *b, *i, *o, c; + float size; + + if (name[0] == '-' || name[0] == '*') + return name; /* Already an XLFD */ + + /* Downcase ASCII; dash to space */ + for (s = name; *s; s++) + if (*s >= 'A' && *s <= 'Z') + *s += 'a'-'A'; + else if (*s == '-') + *s = ' '; + + /* "Family NN" or "Family-NN" */ + s = strrchr (name, ' '); + s2 = strrchr (name, '-'); + if (s && s2 && s2 > s) s = s2; + if (!s) goto FAIL; + if (1 != sscanf (s+1, " %f %c", &size, &c)) goto FAIL; + if (size <= 0) goto FAIL; + *s = 0; + + /* "Family Bold", etc. */ + b = strstr (name, " bold"); + i = strstr (name, " italic"); + o = strstr (name, " oblique"); + if (b) *b = 0; + if (i) *i = 0; + if (o) *o = 0; + + xlfd = (char *) malloc (strlen(name) + 80); + sprintf (xlfd, "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-*-*", + name, + (b ? "bold" : "medium"), + (i ? "i" : o ? "o" : "r"), + (int) (size * 10)); + free (name); + return xlfd; + + FAIL: + fprintf (stderr, "%s: XFT: unparsable: \"%s\"\n", progname, font_name); + if (name) free (name); + if (xlfd) free (xlfd); + return 0; +} + + +#ifdef USE_XFT + +/* Xft silently substitutes fonts if the one you requested wasn't available. + This leads to the deplorable situation where we ask for a fixed width font + and are given a variable width font instead. This doesn't happen with + Courier, since Xft special-cases that one, but it happens with any other + fixed width font that is not similarly privileged. + + Even worse: when Xft substitutes fonts, it makes no attempt to return fonts + that are capable of displaying the language of the current locale. For + example: if your locale is set to Japanese and you request "Helvetica", Xft + silently substitutes "Nimbus Sans" -- a font which is not capable of + displaying Japanese characters. If instead you requested "asdfasdfghjkl", + you get "Noto Sans CJK JP", which does work. So that's just spectacular. + + Since there does not appear to be a way to ask Xft whether a particular + font exists, we load the font and then check to see if the name we got + is the name we requested. + + In more detail: + + - XftFontOpenXlfd is defined as: + XftFontOpenPattern (XftFontMatch (XftXlfdParse (xlfd))) + - XftFontOpenName is defined as: + XftFontOpenPattern (XftFontMatch (XftNameParse (name))) + - Calling XftFontOpenPattern with a pattern that has not been filtered + through XftFontMatch does not work. + - XftFontMatch substitutes another font if the pattern doesn't match. + - If the pattern has family "Courier", it substitutes a fixed width + font, e.g. "Liberation Mono". + - Otherwise it substitutes a variable width font, e.g. "DejaVu Sans". + It does this even if the pattern contained "spacing=100" or "110", + indicating a monospace or charcell font. + - XftXlfdParse does not translate "spacing" from XLFD to XftPattern, + but that doesn't matter since XftFontMatch ignores it anyway. + + Xft source is here: + https://opensource.apple.com/source/X11ForMacOSXSource/X11ForMacOSXSource-1.0/xc/lib/Xft1/ + + Courier, Helvetica and the other historical PostScript font names seem to + be special-cased in /etc/fonts/conf.d/ in the files 30-metric-aliases.conf, + 45-latin.conf and/or 60-latin.conf, which uses an idiosyncratic scripting + language implemented as XML! Some incomplete documentation on that baroque + mess is here: + https://www.freedesktop.org/software/fontconfig/fontconfig-user.html + + The Xft configuration files seem to special-case the names "monospace", + "serif" and "sans-serif" as generic fallback fonts. + + However, "sans-serif" is problematic because it does not survive the trip + through XftXlfdParse and XftFontOpenPattern -- XLFD font families cannot + include hyphens. So we have no choice but to turn it into "sans serif", + which is *not* special-cased by the Xft config files. + + In summary, everything is terrible, and it's a wonder anything works at all. + */ +static Bool +xlfd_substituted_p (XftFont *f, const char *xlfd) +{ +# ifndef HAVE_XFT + return False; /* No substitutions in the Xft emulator. */ +# else /* HAVE_XFT */ + + Bool ret = True; + const char *oxlfd = xlfd; + char *s = 0; + char *xname = 0; + char fname[1024]; + + if (*xlfd == '-' || strchr (xlfd, '*')) /* it's an xlfd */ + { + if (*xlfd != '-') goto FAIL; + xlfd++; + s = strchr (xlfd, '-'); if (!s) goto FAIL; /* skip foundry */ + xlfd = s+1; + s = strchr (xlfd, '-'); if (!s) goto FAIL; /* skip family */ + + { + char buf[1024]; + XftPattern *pat = XftXlfdParse (oxlfd, True, True); + XftNameUnparse (pat, buf, sizeof(buf)-1); + } + } + else /* It's an Xft name */ + { + s = strchr (xlfd, '-'); if (!s) goto FAIL; /* skip family */ + } + + xname = strdup (xlfd); + xname[s - xlfd] = 0; + + *fname = 0; + XftNameUnparse (f->pattern, fname, sizeof(fname)-1); + s = strchr (fname, ':'); /* Strip to "Family-NN" */ + if (s) *s = 0; + s = strrchr (fname, '-'); /* Strip to family */ + if (s) *s = 0; + + ret = !strcasestr (fname, xname); + +# ifdef DEBUG + if (ret) + fprintf (stderr, "%s: XFT: requested \"%s\" but got \"%s\"\n", + progname, xname, fname); +# endif + + FAIL: + + if (!s) + fprintf (stderr, "%s: unparsable XLFD: %s\n", progname, oxlfd); + if (xname) free (xname); + return ret; +# endif /* HAVE_XFT */ +} +#endif /* USE_XFT */ + static void * -load_font_retry_1 (Display *dpy, int screen, const char *xlfd, Bool xft_p) +load_font_retry_1 (Display *dpy, int screen, const char *font_list, Bool xft_p) { # ifdef USE_XFT # define LOADFONT(F) (xft_p \ - ? (void *) XftFontOpenXlfd (dpy, screen, (F)) \ + ? (void *) XftFontOpenXlfd (dpy, screen, (F)) \ : (void *) XLoadQueryFont (dpy, (F))) +# define UNLOADFONT(F) (xft_p \ + ? (void) XftFontClose (dpy, (F)) \ + : (void) XFreeFont (dpy, (F))) # else # define LOADFONT(F) ((void *) XLoadQueryFont (dpy, (F))) +# define UNLOADFONT(F) XFreeFont (dpy, (F)) # endif - void *f = xlfd ? LOADFONT(xlfd) : 0; + char *font_name = 0; + void *f = 0; + void *fallback = 0; # ifndef USE_XFT if (xft_p) abort(); # endif -# ifdef HAVE_JWXYZ - return f; -# else /* !HAVE_JWXYZ */ - if (! xlfd) xlfd = "<null>"; - if (f) - { -# ifdef DEBUG - fprintf (stderr, "%s: loaded %s\n", progname, xlfd); +# ifdef SELFTEST + xft_selftest (dpy, screen); # endif - return f; - } - else + + if (! font_list) font_list = "<null>"; + + /* Treat the string as a comma-separated list of font names. + Names are XLFDs or the XScreenSaver syntax described above. + Try to load each of them in order. + If a substitution was made, keep going, unless this is the last. + */ + if (font_list) { - Bool bold_p = (!!strcasestr (xlfd, "-bold-") || - !!strcasestr (xlfd, "-ocr")); - Bool italic_p = (!!strcasestr (xlfd, "-i-") || - !!strcasestr (xlfd, "-o-")); - Bool fixed_p = (!!strcasestr (xlfd, "courier") || - !!strcasestr (xlfd, "-ocr") || - !!strcasestr (xlfd, "-m-") || - !!strcasestr (xlfd, "-c-")); - int size = 0; + char *token = strdup (font_list); + char *otoken = token; + char *name2, *lasts; + if (!token) abort(); + while ((name2 = strtok_r (token, ",", &lasts))) + { + int L; + token = 0; + + /* Strip leading and trailing whitespace */ + while (*name2 == ' ' || *name2 == '\t' || *name2 == '\n') + name2++; + L = strlen(name2); + while (L && (name2[L-1] == ' ' || name2[L-1] == '\t' || + name2[L-1] == '\n')) + name2[--L] = 0; + + if (font_name) free (font_name); + font_name = font_name_to_xlfd (name2); # ifdef DEBUG - fprintf (stderr, "%s: failed %s\n", progname, xlfd); + fprintf (stderr, "%s: trying \"%s\" as \"%s\"\n", progname, + name2, font_name); # endif - if (!strcmp (xlfd, "vga")) /* BSOD uses this: it has no XLFD name. */ - fixed_p = True, size = 120; + f = LOADFONT (font_name); - /* Look for the first number in the string like "-180-" */ - if (! size) - { - const char *s; - for (s = xlfd; *s; s++) - if (s[0] == '-' && s[1] >= '0' && s[1] <= '9') - { - int i = s[1] - '0'; - const char *s2 = s+2; - while (*s2 >= '0' && *s2 <= '9') - { - i = i * 10 + *s2 - '0'; - s2++; - } - if (*s2 != '-') continue; /* Number ends with dash */ - if (i < 60 || i >= 2000) continue; /* In range 6pt - 200pt */ - if (i % 10) continue; /* Multiple of 10 */ - - size = i; - break; - } - } +# ifdef USE_XFT + /* If we did not get an exact match for the font family we requested, + reject this font and try the next one in the list. */ + if (f && xft_p && xlfd_substituted_p (f, font_name)) + { + if (fallback) + UNLOADFONT (fallback); + fallback = f; + f = 0; + } +# ifdef DEBUG + else if (!f) + fprintf (stderr, "%s: no match for \"%s\"\n", progname, font_name); +# endif +# endif /* USE_XFT */ - if (! size) - { - fprintf (stderr, "%s: unloadable, unparsable font: \"%s\"\n", - progname, xlfd); - xlfd = "fixed"; - return LOADFONT(xlfd); + if (f) break; } - else + free (otoken); + if (!font_name) abort(); + + /* If the last font in the list was an Xft pattern that matched but + was inexact, use it. */ + if (!f) { - const char *variable[] = { - "helvetica", - "arial", - "bitstream vera sans", - "gill sans", - "times", - "times new roman", - "new century schoolbook", - "utopia", - "palatino", - "lucida", - "bitstream charter", - - /* Don't use a wildcard family. If none of the above worked, then - then almost none of the X11 fonts are installed, and it's not - unlikely that "-*-*-medium-r-*-*-*-140-*-*-*-10646-1" will - match an Arabic or or Japanese font that contains no Latin - glyphs at all, even in a Latin locale. So in that case, just - let "helvetica" fall back to "fixed". - */ - /* "*" */ - }; - const char *fixed[] = { - "courier", - "courier new", - "courier 10 pitch", - "lucidatypewriter", - "american typewriter", - "fixed", - "ocr a std", - /* As above, but "can't happen" because we already tried fixed? */ - /* "*" */ - }; - const char *charsets[] = { "iso10646-1", "iso8859-1", "*-*" }; - const char *weights[] = { "bold", "medium" }; - const char *slants[] = { "o", "i", "r" }; - const char *spacings[] = { "m", "c", "p" }; - int a, b, c, d, e, g; - char buf[1024]; - - for (a = 0; a < countof(charsets); a++) - for (b = (bold_p ? 0 : 1); b < countof(weights); b++) - for (c = (italic_p ? 0 : 2); c < countof(slants); c++) - for (d = 0; - d < (fixed_p ? countof(fixed) : countof(variable)); - d++) - for (g = size; g >= 60; g -= 10) - for (e = (fixed_p ? 0 : 2); e < countof(spacings); e++) - { - sprintf (buf, - "-%s-%s-%s-%s-%s-%s-%s-%d-%s-%s-%s-%s-%s", - "*", /* foundry */ - (fixed_p ? fixed[d] : variable[d]), - weights[b], - slants[c], - "*", /* set width */ - "*", /* add style */ - "*", /* pixel size */ - g, /* point size */ - "*", /* x resolution */ - "*", /* y resolution */ - spacings[e], - "*", /* average width */ - charsets[a]); -# ifdef DEBUG - fprintf(stderr, "%s: trying %s\n", progname, buf); -# endif - f = LOADFONT(buf); - if (f) - { -# ifdef DEBUG - fprintf (stderr, - "%s: substituted \"%s\" for \"%s\"\n", - progname, buf, xlfd); -# endif - return f; - } - } - - fprintf (stderr, "%s: unable to find any alternatives to \"%s\"\n", - progname, xlfd); - xlfd = "fixed"; - return LOADFONT(xlfd); + f = fallback; + fallback = 0; } } -# endif /* !HAVE_JWXYZ */ + + if (!font_name) abort(); + if (!f) abort(); + +# ifdef DEBUG + if (f && font_name) + fprintf (stderr, "%s:%s loaded %s\n", progname, + (xft_p ? " XFT:" : ""), font_name); +# if defined(USE_XFT) && defined(HAVE_XFT) + if (xft_p && f) + { + XftPattern *p = ((XftFont *) f)->pattern; + char name[1024]; + char *s, *s1, *s2, *s3; + XftNameUnparse (p, name, sizeof(name)-1); + s = strstr (name, ":style="); + s1 = (s ? strstr (s+1, ",") : 0); + s2 = (s ? strstr (s+1, ":") : 0); + s3 = (s1 && s1 < s2 ? s1 : s2); + if (s3) strcpy (s3+1, " [...]"); + fprintf (stderr, "%s: XFT name: %s\n", progname, name); + } +# endif /* USE_XFT && HAVE_XFT */ +# endif /* DEBUG */ + + if (fallback) UNLOADFONT (fallback); + if (font_name) free (font_name); + return f; } + +#if 1 /* No longer used in XScreenSaver 6. + (Used by retired flag, juggle, xsublim) */ XFontStruct * -load_font_retry (Display *dpy, const char *xlfd) +load_font_retry (Display *dpy, const char *font_list) { - return (XFontStruct *) load_font_retry_1 (dpy, 0, xlfd, 0); + return (XFontStruct *) load_font_retry_1 (dpy, 0, font_list, 0); } +#endif -#ifdef USE_XFT +#if defined(USE_XFT) || defined(HAVE_JWXYZ) XftFont * -load_xft_font_retry (Display *dpy, int screen, const char *xlfd) +load_xft_font_retry (Display *dpy, int screen, const char *font_list) { - return (XftFont *) load_font_retry_1 (dpy, screen, xlfd, 1); + return (XftFont *) load_font_retry_1 (dpy, screen, font_list, 1); } +#endif -#elif defined(HAVE_JWXYZ) -XftFont * -load_xft_font_retry (Display *dpy, int screen, const char *xlfd) + +#ifdef SELFTEST +static void +xft_selftest (Display *dpy, int screen) { - return XftFontOpenXlfd (dpy, screen, xlfd); -} + int i; + const char *tests[] = { + "-*-ocr a std-medium-r-*-*-*-480-*-*-m-*-*-*", + "OCR A Std-48", + "OCR A Std-48:style=Bold Italic", + "OCR A Std-48:spacing=100", + "OCR A Std-48:spacing=110", + "-*-courier-medium-r-*-*-*-480-*-*-m-*-*-*", + "-*-courier-bold-o-*-*-*-480-*-*-m-*-*-*", + "Courier-48:style=Bold Italic", + "Courier-48:style=Italic Bold", /* seems to be illegal */ + "Courier-48:spacing=100", + "Courier-48:spacing=110", + "-*-helvetica-bold-o-*-*-*-480-*-*-m-*-*-*", + "Helvetica-48:style=Bold Italic", + "Liberation Mono-48:style=Bold Italic", + "Liberation Sans-48:style=Bold Italic", + "-*-sans serif-bold-o-*-*-*-480-*-*-m-*-*-*", + "-*-sans-serif-bold-o-*-*-*-480-*-*-m-*-*-*", + "-*-sans\\-serif-bold-o-*-*-*-480-*-*-m-*-*-*", + }; + + const char *tests2[] = { "Helvetica 10", + "Helvetica Bold 10", + "Helvetica Bold Italic 10", + "Helvetica Oblique Bold-10.5", + "Times New Roman-10", + "Times New Roman Bold-10", + "Times New Roman-Bold Oblique Italic 10", + "Times New Roman-Oblique Italic Bold 10", + "Times-20:style=Bold", + "Times-Oblique-20:style=Bold", + "sans serif-20:style=Bold", + "sans-serif-20:style=Bold", + "sans\\-serif-20:style=Bold", + }; + + fprintf (stderr, "\n"); + for (i = 0; i < countof(tests2); i++) + fprintf (stderr, "%s\n%s\n\n", tests2[i], font_name_to_xlfd (tests2[i])); + + fprintf (stderr, "\n"); + for (i = 0; i < countof(tests); i++) { + const char *name1 = tests[i]; + XftResult ret; + XftPattern *pat1 = 0, *pat2 = 0, *pat3 = 0; + char name2[1024], name3[1024]; + XftFont *ff; + Bool xlfd_p = (*name1 == '-'); -#endif /* !HAVE_JWXYZ */ +# define TRUNC(V) do { \ + char *s = strstr (V, ":style="); \ + char *s1 = (s ? strstr (s+1, ",") : 0); \ + char *s2 = (s ? strstr (s+1, ":") : 0); \ + char *s3 = (s1 && s1 < s2 ? s1 : s2); \ + if (s3) strcpy (s3+1, " [...]"); \ + } while(0) + + *name2 = 0; + + /* Name to Parse */ + + if (xlfd_p) + pat1 = XftXlfdParse (name1, True, True); + else + pat1 = XftNameParse (name1); + XftNameUnparse (pat1, name2, sizeof(name2)-1); + TRUNC(name2); + fprintf (stderr, "%s (\"%s\")\n\t-> \"%s\"\n", + (xlfd_p ? "XftXlfdParse" : "XftNameParse"), + name1, name2); + + + /* Name to pattern to Open */ + + ff = XftFontOpenPattern (dpy, pat1); + if (ff) { + pat2 = ff->pattern; + XftNameUnparse (pat2, name3, sizeof(name3)-1); + } else { + pat2 = 0; + strcpy (name3, "NULL"); + } + TRUNC(name3); + fprintf (stderr, "XftFontOpenPattern (\"%s\")\n\t-> \"%s\"\n", + name2, name3); + + + /* Name to pattern to Match */ + + pat2 = XftFontMatch (dpy, screen, pat1, &ret); + XftNameUnparse (pat2, name3, sizeof(name3)-1); + TRUNC(name3); + fprintf (stderr, "XftFontMatch (\"%s\")\n\t-> \"%s\", %s\n", + name2, name3, + (ret == XftResultMatch ? "Match" : + ret == XftResultNoMatch ? "NoMatch" : + ret == XftResultTypeMismatch ? "TypeMismatch" : + ret == XftResultNoId ? "NoId" : "???")); + + + /* Name to pattern to Match to Open */ + + strcpy (name2, name3); + ff = XftFontOpenPattern (dpy, pat2); + if (ff) { + pat3 = ff->pattern; + XftNameUnparse (pat3, name3, sizeof(name3)-1); + } else { + pat3 = 0; + strcpy (name3, "NULL"); + } + TRUNC(name3); + fprintf (stderr, "XftFontOpenPattern (\"%s\")\n\t-> \"%s\"\n", + name2, name3); + + + /* Name to Open */ + + ff = (xlfd_p + ? XftFontOpenXlfd (dpy, screen, name1) + : XftFontOpenName (dpy, screen, name1)); + *name2 = 0; + if (ff) { + pat1 = ff->pattern; + XftNameUnparse (pat1, name2, sizeof(name2)-1); + } else { + strcpy (name2, "NULL"); + } + TRUNC(name2); + fprintf (stderr, "%s (\"%s\")\n\t-> \"%s\"\n", + (xlfd_p ? "XftFontOpenXlfd" : "XftFontOpenName"), + name1, name2); + fprintf (stderr, "\n"); + } + + exit (0); +} +#endif /* SELFTEST */ diff --git a/utils/font-retry.h b/utils/font-retry.h index 83ba0e0..2611a18 100644 --- a/utils/font-retry.h +++ b/utils/font-retry.h @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2018 by Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright © 2018-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -12,13 +12,17 @@ #ifndef __FONT_RETRY_H__ #define __FONT_RETRY_H__ -/* Like XLoadQueryFont, but if it fails, it tries some heuristics to - load something close. +/* Like XLoadQueryFont, XftFontOpenXlfd or XftFontOpenName, except that the + argument can be a comma-separated list of font names. Each name can be + either an XLFD or Xft pattern. Returns the first exact match it finds, or + if there is no exact match, applies heuristics to the last font in the list + until it finds a substitution. */ -extern XFontStruct *load_font_retry (Display *, const char *xlfd); +extern XFontStruct *load_font_retry (Display *, const char *font_list); # ifdef __XSCREENSAVER_XFT_H__ /* if xft.h has been included */ -extern XftFont *load_xft_font_retry (Display *, int screen, const char *xlfd); +extern XftFont *load_xft_font_retry (Display *, int screen, + const char *font_list); # endif #endif /* __FONT_RETRY_H__ */ diff --git a/utils/grabclient.c b/utils/grabclient.c index abe069b..58db732 100644 --- a/utils/grabclient.c +++ b/utils/grabclient.c @@ -127,11 +127,11 @@ typedef struct { XtInputId pipe_id; FILE *pipe; -# if !defined(USE_IPHONE) && !defined(HAVE_COCOA) /* Real X11 */ +# if !defined(HAVE_IPHONE) && !defined(HAVE_COCOA) /* Real X11 */ pid_t pid; # endif -# if !defined(USE_IPHONE) && defined(HAVE_COCOA) /* Desktop OSX */ +# if !defined(HAVE_IPHONE) && defined(HAVE_COCOA) /* Desktop OSX */ char *directory; # endif @@ -236,7 +236,6 @@ checkerboard (Screen *screen, Drawable drawable) win_width = xgwa.width; win_height = xgwa.height; cmap = xgwa.colormap; - screen = xgwa.screen; } else /* it's a pixmap */ { @@ -564,7 +563,7 @@ load_random_image_x11 (Screen *screen, Window window, Drawable drawable, #elif defined (HAVE_COCOA) /* OSX or iOS */ -# ifndef USE_IPHONE /* HAVE_COCOA && !USE_IPHONE -- desktop OSX */ +# ifndef HAVE_IPHONE /* HAVE_COCOA && !HAVE_IPHONE -- desktop OSX */ # define BACKSLASH(c) \ (! ((c >= 'a' && c <= 'z') || \ @@ -699,7 +698,7 @@ xscreensaver_getimage_file_cb (XtPointer closure, int *source, XtInputId *id) } -# else /* HAVE_COCOA && USE_IPHONE -- iOS */ +# else /* HAVE_COCOA && HAVE_IPHONE -- iOS */ /* Callback for ios_load_random_image(), called after we have loaded an image from the iOS device's Photo Library. See grabclient-ios.m. @@ -753,7 +752,7 @@ ios_load_random_image_cb (void *uiimage, const char *filename, free (clo2); } -# endif /* HAVE_COCOA && USE_IPHONE */ +# endif /* HAVE_COCOA && HAVE_IPHONE */ static void @@ -774,7 +773,7 @@ osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable, clo2->callback = callback; clo2->closure = closure; -# ifndef USE_IPHONE /* Desktop OSX */ +# ifndef HAVE_IPHONE /* Desktop OSX */ clo2->directory = strdup (dir); clo2->pipe = open_image_name_pipe (dir); clo2->pipe_id = XtAppAddInput (XtDisplayToApplicationContext ( @@ -782,14 +781,14 @@ osx_load_image_file_async (Screen *screen, Window xwindow, Drawable drawable, fileno (clo2->pipe), (XtPointer) (XtInputReadMask | XtInputExceptMask), xscreensaver_getimage_file_cb, (XtPointer) clo2); -# else /* USE_IPHONE */ +# else /* HAVE_IPHONE */ { XWindowAttributes xgwa; XGetWindowAttributes (DisplayOfScreen (screen), xwindow, &xgwa); ios_load_random_image (ios_load_random_image_cb, clo2, xgwa.width, xgwa.height); } -# endif /* USE_IPHONE */ +# endif /* HAVE_IPHONE */ } @@ -828,13 +827,13 @@ load_random_image_cocoa (Screen *screen, Window window, Drawable drawable, geom.width = xgwa.width; geom.height = xgwa.height; -# ifndef USE_IPHONE +# ifndef HAVE_IPHONE if (filep) dir = get_string_resource (dpy, "imageDirectory", "ImageDirectory"); if (!dir || !*dir) filep = False; -# endif /* ! USE_IPHONE */ +# endif /* ! HAVE_IPHONE */ if (deskp && filep) { deskp = !(random() & 5); /* if both, desktop 1/5th of the time */ diff --git a/utils/grabscreen.c b/utils/grabscreen.c index 77fe3c9..e2742bf 100644 --- a/utils/grabscreen.c +++ b/utils/grabscreen.c @@ -25,10 +25,8 @@ On MacOS systems running X11, which nobody does any more: - "driver/xscreensaver-getimage" runs the Perl script - "driver/xscreensaver-getimage-desktop", which in turn runs the MacOS - program "/usr/sbin/screencapture" to get the Mac desktop image as a - PNG file. + "driver/xscreensaver-getimage" runs "/usr/sbin/screencapture" to + get the Mac desktop image as a PNG. On MacOS systems running the native Cocoa build, or on iOS or Android systems: @@ -48,14 +46,6 @@ #include <X11/Xatom.h> #include <X11/Xutil.h> -#ifdef HAVE_XMU -# ifndef VMS -# include <X11/Xmu/WinUtil.h> -# else /* VMS */ -# include <Xmu/WinUtil.h> -# endif /* VMS */ -#endif - #include "usleep.h" #include "colors.h" #include "grabscreen.h" @@ -264,10 +254,7 @@ install_screen_colormaps (Screen *screen) { XWindowAttributes xgwa; Window client; -#ifdef HAVE_XMU - /* #### need to put XmuClientWindow() in xmu.c, sigh... */ - if (! (client = XmuClientWindow (dpy, kids[i]))) -#endif + /* if (! (client = XmuClientWindow (dpy, kids[i]))) */ client = kids[i]; xgwa.colormap = 0; XGetWindowAttributes (dpy, client, &xgwa); diff --git a/utils/grabscreen.h b/utils/grabscreen.h index 40054c8..a17e671 100644 --- a/utils/grabscreen.h +++ b/utils/grabscreen.h @@ -92,14 +92,14 @@ extern Bool osx_load_image_file (Screen *, Window, Drawable, const char *filename, XRectangle *geom_ret); #endif /* HAVE_JWXYZ */ -#ifdef USE_IPHONE +#ifdef HAVE_IPHONE extern void ios_load_random_image (void (*callback) (void *uiimage, const char *filename, int w, int h, void *closure), void *closure, int width, int height); -#endif /* USE_IPHONE */ +#endif /* HAVE_IPHONE */ #ifdef HAVE_ANDROID char *jwxyz_draw_random_image (Display *dpy, /* utils/grabclient.c */ diff --git a/utils/images/logo-180.xpm b/utils/images/logo-180.xpm index b093c8f..c61837c 100644 --- a/utils/images/logo-180.xpm +++ b/utils/images/logo-180.xpm @@ -1,13 +1,14 @@ /* XPM */ /* XScreenSaver Logo, designed by Angela Goodman <rzr_grl@yahoo.com> - Copyright (c) 2001, 2002 by Jamie Zawinski <jwz@jwz.org> + Copyright © 2001-2021 Jamie Zawinski <jwz@jwz.org> Unauthorized use or reproduction prohibited. https://www.jwz.org/xscreensaver/ */ static const char * const logo_180_xpm[] = { +/* columns rows colors chars-per-pixel */ "180 180 16 1", " c None m None", ") c #FF0000 m #FFFFFF", @@ -25,6 +26,7 @@ static const char * const logo_180_xpm[] = { "% c #37332D m #000000", "& c #2D0C05 m #000000", "* c #A46E00 m #000000", +/* pixels */ " ", " . ", " .. ", diff --git a/utils/images/logo-360.gif b/utils/images/logo-360.gif Binary files differnew file mode 100644 index 0000000..cb53a2c --- /dev/null +++ b/utils/images/logo-360.gif diff --git a/utils/images/logo-360.xpm b/utils/images/logo-360.xpm new file mode 100644 index 0000000..b80da2a --- /dev/null +++ b/utils/images/logo-360.xpm @@ -0,0 +1,390 @@ +/* XPM */ + +/* XScreenSaver Logo, designed by Angela Goodman <rzr_grl@yahoo.com> + Copyright © 2001-2021 Jamie Zawinski <jwz@jwz.org> + Unauthorized use or reproduction prohibited. + + https://www.jwz.org/xscreensaver/ + */ + +static const char * const logo_360_xpm[] = { +/* columns rows colors chars-per-pixel */ +"360 360 16 1", +" c None m None", +"# c #000000 m #000000", +". c #929291 m #000000", +"X c #A30204 m #000000", +"o c #604D28 m #000000", +"O c #600204 m #000000", +"+ c #37332D m #000000", +"@ c #2D0C05 m #000000", +"_ c #A46E04 m #000000", +"$ c #DBDBDA m #000000", +"% c #ED9E04 m #FFFFFF", +"& c #797977 m #000000", +"* c #B0B0AE m #000000", +"= c #FEFEFC m #FFFFFF", +"- c #4F3504 m #000000", +"; c #FD0204 m #FFFFFF", +/* pixels */ +" ", +" ## ", +" #### ", +" ###### ", +" ###### ", +" ###### ", +" ###### ", +" ####### ", +" ####### ", +" ## ####### ", +" ### ######## ", +" #### ####### ", +" ############ ", +" ###+######### ", +" +O++######## ", +" ++X#+######## ", +" @XX@######### ", +" @+;O@######## ", +" ##;;O@######## ", +" @X;;+@######## ", +" @+;;;+@####### ", +" #@X;;X#+#++#### ", +" @O;;;X@#o###### ", +" ++;;;;O#oo@#### ", +" @X;;;;+@_+@#### ", +" @O;;;;;#+o+##### ", +" ++;;;;;X#+o@##### ", +" @X;;;;;O#o+@#### ", +" @O;;;;;;+@o++#### ", +" ++;;;;;;;++o@##### ", +" #+X;;;;;;X@++@#### ", +" @X;;;;;;;X#++@#### ", +" @+;;;;;;;;++o#+#### ", +" ++;;;;;;;;;+++@##### ", +" @X;;;;;;;;X@++@#### ", +" @O;;;;;;;;;O@o++#### ", +" ++;;;;;;;;;;++o@##### ", +" ##X;;;;;;;;;X@++@#### ", +" @X;;;;;;;;;;O@o+@#### ", +" @O;;;;;;;;;;;++o@##### ", +" @+;;;;;;;;;;;X@oo@#### ", +" ++;;;;;;;;;;;;O@_+@#### ", +" +X;;;;;;;;;;;;++_#+#### ", +" @X;;;;;;;;;;;;X#oo@##### ### ", +" @O;;;;;;;;;;;;;+@_+@#### ##### ", +" @+;;;;;;;;;;;;;X@o%++#### ## ##### ", +" ++;;;;;;;;;;;;;;O#__@##### ### ###### ", +" +X;;;;;;;;;;;;;;++%+@#### ### ####### ", +" @X;;;;;;;;;;;;;;O#_%@+#### #### ###### ", +" @X;;;;;;;;;;;;;;;++%o@#### ### ####### ", +" @O;;;;;;;;;;;;;;;X#_%+@#### +++# ####### ", +" @+;;;;;;;;;;;;;;;;++%_@##### #+O# ####### ", +" @+;;;;;;;;;;;;;;;;O#_%o@#### @O++ ####### ", +" ++;;;;;;;;;;;;;;;;;@o%%+@#### @+X@ ######## ", +" ++;;;;;;;;;;;;;;;;;O@%%_@#### #+X+@ ####### ", +" #X;;;;;;;;;;;;;;;;X@o%%+@#### @OX@# ######## ", +" @X;;;;;;;;;;;;;;;;;++%%_@#### ++;O@ ######## ", +" @X;;;;;;;;;;;;;;;;;O#_%%+@#### #@X;++ ######## ", +" @X;;;;;;;;;;;;;;;;;X#_%%_@#### @+;X+ ######## ", +" @X;;;;;;;;;;;;;;;;;;+o%%%+@### ##X;O@ ######### ", +" @X;;;;;;;;;;;;;;;;;;++%%%o@#### @O;;+@######### ", +" @X;;;;;;;;;;;;;;;;;;O+%%%_@#### ++;;;++######### ", +" @X;;;;;;;;;;;;;;;;;;X#_%%%++### @O;;X+########## ", +" @X;;;;;;;;;;;;;;;;;;X#_%%%+@### ++;;;X@########## ", +" @X;;;;;;;;;;;;;;;;;;X#_%%_@+### #@X;;;O@######### ", +" @X;;;;;;;;;;;;;;;;;;O@%%%+@#### @+;;;;+@###+##### ", +" @X;;;;;;;;;;;;;;;;;;++%%_@#### #@X;;;;++##@+++### ", +" @X;;;;;;;;;;;;;;;;;X@o%%+@#### @+;;;;;++#++_+#### ", +" #;;;;;;;;;;;;;;;;;;+@_%_@#### #@X;;;;;###@o_@#### ", +" ++;;;;;;;;;;;;;;;;;X@o%%o@#### @+;;;;;X@#++%o@### ", +" ++;;;;;;;;;;;;;;;;;+@%%_@+### #@X;;;;;X@#@o%o@### ", +" @+;;;;;;;;;;;;;;;;X#o%%o@#### @+;;;;;;X@+#%%o@### ", +" @O;;;;;;;;;;;;;;;;++%%%#+### #@X;;;;;;X@@o%%+@### ", +" @X;;;;;;;;;;;;;;;X#o%%o@#### @+;;;;;;;X@+_%%+@### ", +" +X;;;;;;;;;;;;;;;+#%%%+@### @X;;;;;;;X#o%%%++### ", +" ++;;;;;;;;;;;;;;;X#_%%_@#### ++;;;;;;;;X@_%%%++### ", +" @+;;;;;;;;;;;;;;;++%%%+@### @X;;;;;;;;X@%%%%#+### ", +" @O;;;;;;;;;;;;;;X#_%%_@#### ++;;;;;;;;;X@%%%%++### ", +" #####################################################################################################+X;;;;;;;;;;;;;;++%%%+@#################@O;;;;;;;;;X@%%%_@+########################################################################################################################## ", +" #######################################################################################################++;;;;;;;;;;;;;;X#_%%_@#################++;;;;;;;;;;X@_%%_@############################################################################################################################## ", +" ########################################################################################################@O;;;;;;;;;;;;;;++%%%o@#################@O;;;;;;;;;;X#_%%_@############################################################################################################################### ", +" #########################################################################################################@X;;;;;;;;;;;;;X#_%%_@###################X;;;;;;;;;;X#_%%_@################################################################################################################################ ", +" #########################################################################################################@+;;;;;;;;;;;;;;++%%%o@#################@+;;;;;;;;;;;X#_%%_@+################################################################################################################################ ", +" ##########################################################################################################@X;;;;;;;;;;;;;X#_%%%+@#################@X;;;;;;;;;;;X#_%%_++################################################################################################################################# ", +" #########################################################################################################++;;;;;;;;;;;;;;++%%%_@#################++;;;;;;;;;;;;X@_%%%++################################################################################################################################## ", +" ##########+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#@X;;;;;;;;;;;;;X#o%%%+@##+@@@@@@@@@@@@@+@O;;;;;;;;;;;;;+o%%%#+##+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@########## ", +" ########+@@++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++@+;;;;;;;;;;;;;;+#%%%_@###++++++++++++++++X;;;;;;;;;;;;;+o%%%++##+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#@@######## ", +" ########@@&$=============================================================================================&#X;;;;;;;;;;;;;X#o%%%o@##@&============$++;;;;;;;;;;;;;;++%%%++#@+$===================================================================================================================$&#@######## ", +" #######+@*==============================================================================================*#O;;;;;;;;;;;;;;++%%%%#+##@*============*#X;;;;;;;;;;;;;;++%%%+@#@+======================================================================================================================*#@####### ", +" #######@+==============================================================================================$++;;;;;;;;;;;;;;X#o%%%o@##@+=============&@;;;;;;;;;;;;;;;O+%%%+@#+@$======================================================================================================================&@####### ", +" #######@o==============================================================================================o@X;;;;;;;;;;;;;;O@%%%%+@##@*============$+O;;;;;;;;;;;;;;;X#_%%o@##@*======================================================================================================================&@####### ", +" #######@o=============================================================================================&#X;;;;;;;;;;;;;;;@o%%%_@##@+=============*#X;;;;;;;;;;;;;;;X#_%%o@##@*======================================================================================================================&@####### ", +" #######@o============================================================================================&#O;;;;;;;;;;;;;;;O@_%%%+@##@&=============o+;;;;;;;;;;;;;;;;X@_%%o@##@*======================================================================================================================&@####### ", +" #######@o===========================================================================================&#O;;;;;;;;;;;;;;;;++%%%%++#+@$============$@O;;;;;;;;;;;;;;;;;@o%%_@##@&======================================================================================================================&@####### ", +" #######@o==========================================================================================*#+;;;;;;;;;;;;;;;;X#_%%%_@##@+=============*#X;;;;;;;;;;;;;;;;;++%%_@##@o======================================================================================================================&@####### ", +" #######@o=========================================================================================$@+;;;;;;;;;;;;;;;;;++%%%%+@##@*=============&@;;;;;;;;;;;;;;;;;;O+%%%#+#@+======================================================================================================================&@####### ", +" #######@o========================================================================================$+@X;;;;;;;;;;;;;;;;X#o%%%_@##@#$============$+O;;;;;;;;;;;;;;;;;;O@%%%++#@+======================================================================================================================&@####### ", +" #######@o========================================================================================o#X;;;;;;;;;;;;;;;;;O@%%%%o@##@o=============*#X;;;;;;;;;;;;;;;;;;X#_%%+@#@#$=====================================================================================================================&@####### ", +" #######@o=======================================================================================&#O;;;;;;;;;;;;;;;;;;@o%%%%+@##@*=============&@;;;;;;;;;;;;;;;;;;;;@o%%o@##@*=====================================================================================================================&@####### ", +" #######@o======================================================================================*#+;;;;;;;;;;;;;;;;;;X#_%%%_@##@+==============+O;;;;;;;;;;;;;;;;;;;;++%%o@##@&=====================================================================================================================&@####### ", +" #######@o=====================================================================================$++;;;;;;;;;;;;;;;;;;;++%%%%o@##@&=============*#X;;;;;;;;;;;;;;;;;;;;O+%%_@##@&=====================================================================================================================&@####### ", +" #######@o=====================================================================================+@X;;;;;;;;;;;;;;;;;;;@o%%%%+@#+@*=============*@X;;;;;;;;;;;;;;;;;;;;X#_%_@##@+=====================================================================================================================&@####### ", +" #######@o====================================================================================&#X;;;;;;;;;;;;;;;;;;;O#_%%%_@##@+==============++;;;;;;;;;;;;;;;;;;;;;X#o%%+@#@#$====================================================================================================================&@####### ", +" #######@o===================================================================================*#+;;;;;;;;;;;;;;;;;;;;++%%%%o@##@&=============$+O;;;;;;;;;;;;;;;;;;;;;;+o%%+@##@*====================================================================================================================&@####### ", +" #######@o==================================================================================$++;;;;;;;;;;;;;;;;;;;;X@o%%%%+@##@*=============*#X;;;;;;;;;;;;;;;;;;;;;;++%%o@##@&====================================================================================================================&@####### ", +" #######@o==================================================================================&#X;;;;;;;;;;;;;;;;;;;;X#_%%%_@##@+==============&@;;;;;;;;;;;;;;;;;;;;;;;X#_%_@##@o====================================================================================================================&@####### ", +" #######@o=================================================================================*#O;;;;;;;;;;;;;;;;;;;;;++%%%%_@##@&==============++;;;;;;;;;;;;;;;;;;;;;;;X@_%%++#@+====================================================================================================================&@####### ", +" #######@o=================================================================================+@;;;;;;;;;;;;;;;;;;;;;;+o%%%%o@##@*=============$+O;;;;;;;;;;;;;;;;;;;;;;;;++%%+@#+@*===================================================================================================================&@####### ", +" #######@o==============================================================*+&=====$=========*#X;;;;;;;;;;;;;;;;;;;;;X#_%%%%+@#@#$=============*#X;;;;;;;;;;;;;;;;;;;;;;;;O+%%o@##@*===================================================================================================================&@####### ", +" #######@o=============================================================*@@@$==$+@+*======$++;;;;;;;;;;;;;;;;;;;;;;O@%%%%_@##@+==============*@X;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@##@o===================================================================================================================&@####### ", +" #######@o============================================================$++O@$==+@+@+======&#X;;;;;;;;;;;;;;;;;;;;;;++%%%%_@##@&==============&@;;;;;;;;;;;;;;;;;;;;;;;;;;@o%%#+#@+$==================================================================================================================&@####### ", +" #######@o============================================================&#XX@$=*@##+@$====$#O;;;;;;;;;;;;;;;;;;;;;;;@o%%%%o@##@*==============++;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@##@*==================================================================================================================&@####### ", +" #######@o=======================$*&&ooooooooooooooooooooooooooooooooo@O;O@oo+@###+ooooo+@X;;;;;;;;;;;;;;;;;;;;;;X@_%%%%+@##@+oooooooooooooo@O;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%o@##@+ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo&&*$=======================&@####### ", +" #######@o=====================$&+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#;;O@@@@#####@@@@@#O;;;;;;;;;;;;;;;;;;;;;;;X#_%%%%++###@@@@@@@@@@@@@@@@X;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%_@###@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+&$=====================&@####### ", +" #######@o====================*+@@###################################@O;;++############+#;;;;;;;;;;;;;;;;;;;;;;;;O@_%%%_@###################+X;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@#############################################################################################@@+&====================&@####### ", +" #######@o===================&@@####################################++;;;##############@O;;;;;;;;;;;;;;;;;;;;;;;;O+%%%%_@####################;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%o@###############################################################################################@@&===================&@####### ", +" #######@o==================&@@#####################################@X;;X@##############;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%_@##################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%_@#################################################################################################@&==================&@####### ", +" #######@o=================*@@#####################################++;;;O@############@O;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%o@##################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@################################################################################################+@*=================&@####### ", +" #######@o=================+@######################################@O;;;+@############@X;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%o@##################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@_%o@#################################################################################################@#$================&@####### ", +" #######@o================*@######################################++;;;;++###########@+;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%o@##################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%_@##################################################################################################@&================&@####### ", +" #######@o================+@######################################@O;;;X+############@X;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@#################################################################################################@+================&@####### ", +" #######@o===============$@+######################################+X;;;X@#############;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%o@##################################################################################################@*===============&@####### ", +" #######@o===============*@######################################@+;;;;+@###########@+;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%_@##################################################################################################@&===============&@####### ", +" #######@o===============&@######################################@X;;;;++###########@X;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@#################################################################################################@o===============&@####### ", +" #######@o===============&@#####################################@+;;;;X@###########++;;;;;;;;;;;;;;;;;;;;;;;;;;;;O+%%%%o@##################+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@#################################################################################################@+===============&@####### ", +" #######@o===============&@#####################################@X;;;;O@###########@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@_%%%o@###################X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%++################################################################################################@+===============&@####### ", +" #######@o===============&@####################################++;;;;;++###########@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%o@#################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%o@################################################################################################@+===============&@####### ", +" #######@o===============&@####################################@O;;;;X#############+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%%%o@#################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%%++###############################################################################################@+===============&@####### ", +" #######@o===============&@####################################+X;;;;X@###########++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%_@#################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%+@###############################################################################################@+===============&@####### ", +" #######@o===============&@###################################@+;;;;;O@###########@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%%_@#################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%_@###############################################################################################@+===============&@####### ", +" #######@o===============&@###################################@X;;;;;+@###########@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%+@################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#%%+@##############################################################################################@+===============&@####### ", +" #######@o===============&@####################################;;;;;;+############@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%+@#################+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@##############################################################################################@+===============&@####### ", +" #######@o===============&@##################################@O;;;;;X@#############;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%_@##################X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@#############################################################################################@+===============&@####### ", +" #######@o===============&@##################################@X;;;;;O@###########++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%%%#+################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@#############################################################################################@+===============&@####### ", +" #######@o===============&@#################################++;;;;;;O@###########++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%%+@################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@############################################################################################@+===============&@####### ", +" #######@o===============&@#################################@O;;;;;;++###########@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%%_@################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@############################################################################################@+===============&@####### ", +" #######@o===============&@#################################@X;;;;;;++###########@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%++###############@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@###########################################################################################@+===============&@####### ", +" #######@o===============&@################################++;;;;;;X###+#########@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@+%%o@###############@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@###########################################################################################@+===============&@####### ", +" #######@o===============&@################################@O;;;;;;X@#+++########@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%#+##############@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@##########################################################################################@+===============&@####### ", +" #######@o===============&@#################################X;;;;;;X@##o+########@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%o@##############@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%_@+#########################################################################################@+===============&@####### ", +" #######@o===============&@###############################@+;;;;;;;X@@+_@########@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%#+#############++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#%%o@#########################################################################################@+===============&@####### ", +" #######@o===============&@###############################@X;;;;;;;O@@__@########@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%o@##############+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%++########################################################################################@+===============&@####### ", +" #######@o===============&@###############################+X;;;;;;;O@@%_@########@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@#############@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@_%_@########################################################################################@+===============&@####### ", +" #######@o===============&@##############################@+;;;;;;;;+@+%_@########@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#+%_@#############@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%%+@#######################################################################################@+===============&@####### ", +" #######@o===============&@##############################@O;;;;;;;;+#o%_@########@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%o@############++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%_@+######################################################################################@+===============&@####### ", +" #######@o===============&@##############################+X;;;;;;;;+@_%_@###+@@@@@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#_%+@#####@@@@@@@+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%o@#####+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@######################################@+===============&@####### ", +" #######@o===============&@#############################@+;;;;;;;;;++%%%++#++++++@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%_@####++++++++@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%+@###++++++++++++++++++++++++++++++++++++++++++++@@####################################@+===============&@####### ", +" #######@o===============&@#############################@O;;;;;;;;;++%%%#+#@+====++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%o@###@&=====$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%_@+##@+$========================================$*o@@##################################@+===============&@####### ", +" #######@o===============&@#############################+X;;;;;;;;;++%%%++#@+====&+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%+@##+@*=====&@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#+%%_@###@+===========================================*@@#################################@+===============&@####### ", +" #######@o===============&@############################++;;;;;;;;;;++%%%++#@+====&@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%+@##@@*====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%o@###@o===========================================*@+################################@+===============&@####### ", +" #######@o===============&@############################@O;;;;;;;;;;++%%%+@#@#$===*@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#__@+##@+$====++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%+@###@&===========================================&@################################@+===============&@####### ", +" #######@o===============&@############################@X;;;;;;;;;;++%%%o@##@*===$@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@__@###@+$===*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@_%%+@##+@&==========================================$+@###############################@+===============&@####### ", +" #######@o===============&@###########################++;;;;;;;;;;;++%%%o@##@*====+O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X++%o@###@o===$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%%_@+##+@&==========================================&@###############################@+===============&@####### ", +" #######@o===============&@###########################@+;;;;;;;;;;;++%%%o@##@*====o+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%+@###@&===&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#+%%_@+##+@&=========================================*@###############################@+===============&@####### ", +" #######@o===============&@###########################@X;;;;;;;;;;;O+%%%_@##@&====&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%+@###@*==$@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#o%%o@###+@&========================================*@###############################@+===============&@####### ", +" #######@o===============&@###########################@X;;;;;;;;;;;X@%%%_@##@+====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#o_@+##@@*==&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#o%%o@###+@*=======================================*@###############################@+===============&@####### ", +" #######@o===============&@##########################++;;;;;;;;;;;;X#_%%%++#@+=====++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#__@+##@@*=$@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#_%%o@###@+$======================================*@###############################@+===============&@####### ", +" #######@o===============&@##########################@O;;;;;;;;;;;;X#_%%%+@#@+$====&@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#_o@###@+$=&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%o@###@&======================================*@###############################@+===============&@####### ", +" #######@o===============&@##########################@X;;;;;;;;;;;;X@_%%%o@##@*====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@_o@###@+$=++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%%%o@##+@*=====================================*@###############################@+===============&@####### ", +" #######@o===============&@###########################X;;;;;;;;;;;;;@o%%%o@##@&=====++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#+_+@###@o=*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%%+@##@o=====================================*@###############################@+===============&@####### ", +" #######@o===============&@#########################++;;;;;;;;;;;;;;+o%%%_@##@&=====&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+_+@###@&=+@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@_%%_@###@*====================================*@###############################@+===============&@####### ", +" #######@o===============&@#########################@O;;;;;;;;;;;;;;++%%%%++#@+=====$#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%+@###@**#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@+%%%+@##@o====================================*@###############################@+===============&@####### ", +" #######@o===============&@#########################@X;;;;;;;;;;;;;;O@%%%%+@#+@$=====++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#o_+@##@@*&@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%_@##+@$===================================*@###############################@+===============&@####### ", +" #######@o===============&@##########################;;;;;;;;;;;;;;;X#_%%%o@##@&=====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#__@+##@+&+O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%+@##@&===================================*@###############################@+===============&@####### ", +" #######@o===============&@########################++;;;;;;;;;;;;;;;;@o%%%_@##@o======++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@%_@###@++@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%_@##@+$==================================*@###############################@+===============&@####### ", +" #######@o===============&@########################@+;;;;;;;;;;;;;;;;++%%%%#+#@+$=====&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%o@###@+@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@_%%+@##@*==================================*@###############################@+===============&@####### ", +" #######@o===============&@########################@O;;;;;;;;;;;;;;;;O@%%%%+@##@*=====*#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%+@###+#+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%%_@##@+==================================*@###############################@+===============&@####### ", +" #######@o===============&@########################@X;;;;;;;;;;;;;;;;X#_%%%o@##@&======++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%#@####@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%++##@*=================================*@###############################@+===============&@####### ", +" #######@o===============&@########################+;;;;;;;;;;;;;;;;;X@o%%%_@##@+======*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%_@+####+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@+%%o@##@&=================================*@###############################@+===============&@####### ", +" #######@o===============&@#######################++;;;;;;;;;;;;;;;;;;++%%%%+@##@*======++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%o@####@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%_@##@+$================================*@###############################@+===============&@####### ", +" #######@o===============&@#######################@O;;;;;;;;;;;;;;;;;;O@%%%%o@##@&======&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%+@####@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%%+@##@*================================*@###############################@+===============&@####### ", +" #######@o===============&@#######################@X;;;;;;;;;;;;;;;;;;X#_%%%_@##@+======$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%#+###@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%o@##@&================================*@###############################@+===============&@####### ", +" #######@o===============&@#######################@X;;;;;;;;;;;;;;;;;;;++%%%%+@##@*======&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%_@####@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%_@##@+================================*@###############################@+===============&@####### ", +" #######@o===============&@######################++;;;;;;;;;;;;;;;;;;;;O@_%%%o@##@&======$@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%+@###@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%+@##@*===============================*@###############################@+===============&@####### ", +" #######@o===============&@######################++;;;;;;;;;;;;;;;;;;;;X#o%%%_@##@+$======&@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%#+###@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%o@##@&===============================*@###############################@+===============&@####### ", +" #######@o===============&@######################@+;;;;;;;;;;;;;;;;;;;;;++%%%%+@##@&======*#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%o@###@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%_@##@+===============================*@###############################@+===============&@####### ", +" #######@o===============&@######################@O;;;;;;;;;;;;;;;;;;;;;X#_%%%_@##@+=======+@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@###@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%+@##@*==============================*@###############################@+===============&@####### ", +" #######@o===============&@######################@O;;;;;;;;;;;;;;;;;;;;;;+o%%%%++##@*======*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@###@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%o@##@&==============================*@###############################@+===============&@####### ", +" #######@o===============&@######################@X;;;;;;;;;;;;;;;;;;;;;;O@%%%%o@##@&=======++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@###@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#%_@##@o==============================*@###############################@+===============&@####### ", +" #######@o===============&@#######################X;;;;;;;;;;;;;;;;;;;;;;X@o%%%_@##+@$======*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@###@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%++#@#$=============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################++;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##@&======$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@###+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%+@##@*=============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################++;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%_@##@@$======&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%_@###@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#__@##@&=============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@+;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##@&======$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%%+@##++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o_@##@+=============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@O;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%_@##@+$======&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%_@###@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%+@#+@$============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@O;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##@&======$@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%+@##++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_o@##@*============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@O;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%_@##@+$======&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%o@###@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o_@##@&============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##@&======$@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@_%_@###@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O+_++#@+============================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%%_@##@@$======&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%%+@####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_+@#+@$===========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@%%%%+@##@&======$#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%_@###@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+oo@##@*===========================*@###############################@+===============&@####### ", +" #######@o===============&@######################X;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%%%_@##+@*======o@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%+@##++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++o@##@&===========================*@###############################@+===============&@####### ", +" #######@o===============&@######################;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%%+@##@o======*#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%o@###+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o+##@+===========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%_@###@*======o@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%_@###@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o+@#++$==========================*@###############################@+===============&@####### ", +" #######@o===============&@####################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%+@##@+======*#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@+%%+@##@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++o@##@*==========================*@###############################@+===============&@####### ", +" #######@o===============&@####################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%_@###@&======++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%_@##++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O+o@##@&==========================*@###############################@+===============&@####### ", +" #######@o===============&@####################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%%%o@##@+$=====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#_%+@##+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o+##@o==========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%%++##@&======++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#__+##@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++#@+==========================*@###############################@+===============&@####### ", +" #######@o===============&@######################;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%o@##+@*=====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#o+@#@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++++#+@$=========================*@###############################@+===============&@####### ", +" #######@o===============&@######################X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@o%%%+@##@+=====$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#+#+#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@++##@*=========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%_@###@&=====&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+#+O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X++###@&=========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%o@##@#$====$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+####@+=========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%%%#+##@o=====&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###@+$========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%o@###@*====$@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@###+@*========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@_%%+@##@+=====o@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+####@*========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%_@###@&====*#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++###@&========================*@###############################@+===============&@####### ", +" #######@o===============&@#####################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%%o@##@@$====++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@###@o========================*@###############################@+===============&@####### ", +" #######@o===============&@######################+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%%++##@o====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###@+========================*@###############################@+===============&@####### ", +" #######@o===============&@######################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@_%_@###@*====++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@###+@$=======================*@###############################@+===============&@####### ", +" #######@o===============&@######################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%%+@##@+====&@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#####@*=======================*@###############################@+===============&@####### ", +" #######@o===============&@######################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%_@+##@&===*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++###@&=======================*@###############################@+===============&@####### ", +" #######@o===============&@#######################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_%o@##@@*===++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@###@o=======================*@###############################@+===============&@####### ", +" #######@o===============&@#######################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@%%+@##@+===&@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###@+=======================*@###############################@+===============&@####### ", +" #######@o===============&@########################+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+%_@###@*==*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@###@+$======================*@###############################@+===============&@####### ", +" #######@o===============&@########################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%+@##@+===++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#####@*======================*@###############################@+===============&@####### ", +" #######@o===============&@########################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#_%@+##@*==o@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++###@*======================*@###############################@+===============&@####### ", +" #######@o===============&@#########################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%o@##@+==*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@###@&======================*@###############################@+===============&@####### ", +" #######@o===============&@#########################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%#+##@*=*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###@&======================*@###############################@+===============&@####### ", +" #######@o===============&@###########################;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O#_o@##@+==++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###@+======================*@###############################@+===============&@####### ", +" #######@o===============&@##########################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++_++##@*=o+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@###@+$=====================*@###############################@+===============&@####### ", +" #######@o===============&@##########################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#oo@##@+=*@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+###+@$=====================*@###############################@+===============&@####### ", +" #######@o===============&@###########################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++_#+#+@$*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#####@*=====================*@###############################@+===============&@####### ", +" #######@o===============&@###########################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_o@##@&$@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++###@&=====================*@###############################@+===============&@####### ", +" #######@o===============&@############################+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++_@##@+=+O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@###@&=====================*@###############################@+===============&@####### ", +" #######@o===============&@############################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o+@#+#$o+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###@+=====================*@###############################@+===============&@####### ", +" #######@o===============&@##############################;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+++@##@&o+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###@+$====================*@###############################@+===============&@####### ", +" #######@o===============&@#############################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+###+#++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@###+@$====================*@###############################@+===============&@####### ", +" #######@o===============&@#############################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@####+@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@++##@*====================*@###############################@+===============&@####### ", +" #######@o===============&@##############################@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@#######;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+++##@&====================*@###############################@+===============&@####### ", +" #######@o===============&@##############################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@+#####;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X++###@&====================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X++++##+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+++##@o====================*@###############################@+===============&@####### ", +" #######@o===============&@###############################++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@+++++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o++#@+====================*@###############################@+===============&@####### ", +" #######@o===============&@################################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@+#@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o+@#@+$===================*@###############################@+===============&@####### ", +" #######@o===============&@################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@@@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+oo@##@*===================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@+@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O+O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+oo@##@*===================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*o@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o_@##@*===================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@**#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o_@##@&===================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=o@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o%@##@+===================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=*#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o%++#@+===================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*==o@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o%+@#@+$==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*==$@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o%+@##@*==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*===&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+o%o@##@*==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*===$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%o@##@&==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*====*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%_@##@&==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=====+@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@_%_@+#@+==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=====*#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@_%%++#@+==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*======&@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%%+@#@+$=================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*======$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%o@#@+$=================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=======*#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;@o%%%o@##@*=================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*========+@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%_@##@&=================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*========$@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%%%_@##@&=================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=========&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%%%+@##@o=================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=========$+@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%%%+@###@&=================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*==========*#+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@%%%o@###@+==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*===========&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;#+%%o@###@+$==================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*============+@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#_%_@+##@+$===================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*============*@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%%+@##@@*====================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=============&#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o%+@###@*=====================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*==============+@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++%o@###@&======================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*==============$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#o_@###@+=======================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*===============*#+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+#_#+##@+$=======================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*================&#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@++@##+@*========================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=================+@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@+@###@&=========================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*=================$++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@#+###@+==========================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@*==================*#+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@####@+$==========================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@&===================&#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@####@@*===========================*@###############################@+===============&@####### ", +" #######@o===============&@###############################@o====================o#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++####@*============================&@###############################@+===============&@####### ", +" #######@o===============&@###############################@+$===================$+@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@####@&=============================+@###############################@+===============&@####### ", +" #######@o===============&@################################@&====================$+@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@####@+=============================*@################################@+===============&@####### ", +" #######@o===============&@################################+@*====================*@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++###@#$============================$#@################################@+===============&@####### ", +" #######@o===============&@#################################@+*====================*@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@###@@*============================*+@#################################@+===============&@####### ", +" #######@o===============&@##################################@@&$===================*@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@###+@*===========================$&+@##################################@+===============&@####### ", +" #######@o===============&@###################################+@@+oooooooooooooooooo&+@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#+###+#ooooooooooooooooooooooooooo++@@###################################@+===============&@####### ", +" #######@o===============&@#####################################@@@@@@@@@@@@@@@@@@@@@+#@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@######@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####################################@+===============&@####### ", +" #######@o===============&@#############################################################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@#########################################################################@+===============&@####### ", +" #######@o===============&@##############################################################@X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@##########################################################################@+===============&@####### ", +" #######@o===============&@##############################################################+#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X@###########################################################################@+===============&@####### ", +" #######@o===============&@###############################################################++X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X#+###########################################################################@+===============&@####### ", +" #######@o===============&@################################################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@############################################################################@+===============&@####### ", +" #######@o===============&@#################################################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@#############################################################################@+===============&@####### ", +" #######@o===============&@##################################################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@##############################################################################@+===============&@####### ", +" #######@o===============&@###################################################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@###############################################################################@+===============&@####### ", +" #######@o===============&@####################################################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@################################################################################@+===============&@####### ", +" #######@o===============&@#####################################################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+@#################################################################################@+===============&@####### ", +" #######@o===============&@######################################################################@+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@##################################################################################@+===============&@####### ", +" #######@o===============&@#######################################################################@+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@###################################################################################@+===============&@####### ", +" #######@o===============&@########################################################################@#X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X++####################################################################################@+===============&@####### ", +" #######@o===============&@#########################################################################++X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@+#####################################################################################@+===============&@####### ", +" #######@o===============&@##########################################################################+@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O@#######################################################################################@+===============&@####### ", +" #######@o===============&@############################################################################@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@########################################################################################@+===============&@####### ", +" #######@o===============&@#############################################################################@+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O+@#########################################################################################@+===============&@####### ", +" #######@o===============&@##############################################################################+@O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@###########################################################################################@+===============&@####### ", +" #######@o===============&@################################################################################@+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;O+@############################################################################################@+===============&@####### ", +" #######@o===============&@#################################################################################+@+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@##############################################################################################@o===============&@####### ", +" #######@o===============*@###################################################################################@#O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@+###############################################################################################@&===============&@####### ", +" #######@o===============$@+####################################################################################@+O;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@@#################################################################################################@*===============&@####### ", +" #######@o================+@#####################################################################################+@+OX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@@##################################################################################################@+================&@####### ", +" #######@o================*@#######################################################################################+@#+X;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;X+@+####################################################################################################@&================&@####### ", +" #######@o=================+@#########################################################################################@@+OX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;XO+#+++###################################################################################################@+$================&@####### ", +" #######@o=================*@@##########################################################################################+@#+OX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;XO+#@+_o++##################################################################################################+@*=================&@####### ", +" #######@o==================*@@############################################################################################@@+++OX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;XX++#@+o__+@@##################################################################################################+@&==================&@####### ", +" #######@o===================*@@##############################################################################################+@@@#+OOXXX;;;;;;;;;;;;;;;;;XXOO+@###+_%%%o@@###################################################################################################@@&===================&@####### ", +" #######@o====================*+@@#################################################################################################+@@@@#+++++++OO+++++++@@##++o__%%%%o#@+##################################################################################################@@+*====================&@####### ", +" #######@o=====================$&+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#####################+++@@@@@@@@@++oo___%%%%%%%o#@+#################+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+&$=====================&@####### ", +" #######@o========================**&ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo+@#################################+o_%%%%%%%_o#@+##################++ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo&&*$=======================&@####### ", +" #######@o=========================================================================================================$+@#################################+@@#+o_%_o@@+####################+@$=========================================================================================================&@####### ", +" #######@o=========================================================================================================*@#####################################+@@@+@@+#######################@&=========================================================================================================&@####### ", +" #######@o=========================================================================================================+@#########################################+##########################@+$========================================================================================================&@####### ", +" #######@o========================================================================================================*@######################################################################@&========================================================================================================&@####### ", +" #######@o========================================================================================================+@######################################################################@+$=======================================================================================================&@####### ", +" #######@o=======================================================================================================*@########################################################################@&=======================================================================================================&@####### ", +" #######@o=======================================================================================================+@########################################################################@#$======================================================================================================&@####### ", +" #######@o======================================================================================================&@##########################################################################@+======================================================================================================&@####### ", +" #######@o=====================================================================================================*@+###########################################################################@&=====================================================================================================&@####### ", +" #######@o====================================================================================================$+@############################################################################@@*====================================================================================================&@####### ", +" #######@o===================================================================================================$+@##############################################################################@+$===================================================================================================&@####### ", +" #######@o===================================================================================================o@################################################################################@+$==================================================================================================&@####### ", +" #######@o==================================================================================================&@##################################################################################@+$=================================================================================================&@####### ", +" #######@o=================================================================================================o@####################################################################################@+$================================================================================================&@####### ", +" #######@o===============================================================================================$o@######################################################################################@+$===============================================================================================&@####### ", +" #######@o==============================================================================================$+@########################################################################################@+*==============================================================================================&@####### ", +" #######@o=============================================================================================*+@##########################################################################################@@*=============================================================================================&@####### ", +" #######@o============================================================================================&@@############################################################################################@@&$===========================================================================================&@####### ", +" #######@o==========================================================================================*+@@###############################################################################################@+*==========================================================================================&@####### ", +" #######@o========================================================================================$&@@##################################################################################################@@o*========================================================================================&@####### ", +" #######@o======================================================================================$&+@+#####################################################################################################@@&$======================================================================================&@####### ", +" #######@o====================================================================================$&+@@########################################################################################################+@@&*====================================================================================&@####### ", +" #######@o=================================================================================$*o@@@############################################################################################################@@@+*$=================================================================================&@####### ", +" #######@o==============================================================================$*&+@@+################################################################################################################+@@+&*$==============================================================================&@####### ", +" #######@o============================================================================*++@@@######################################################################################################################@@@++*============================================================================&@####### ", +" #######@o===========================================================================$#@@+###########################################################################################################################@@@*===========================================================================&@####### ", +" #######@o===========================================================================&@################################################################################################################################@+===========================================================================&@####### ", +" #######@o===========================================================================o@################################################################################################################################@+===========================================================================&@####### ", +" #######@o===========================================================================&@################################################################################################################################@+===========================================================================&@####### ", +" #######@o===========================================================================$#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*===========================================================================&@####### ", +" #######@o============================================================================*o+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*============================================================================&@####### ", +" #######@o===============================================================================$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$==============================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@o==========================================================================================================================================================================================================================================================================================&@####### ", +" #######@+==========================================================================================================================================================================================================================================================================================o@####### ", +" ########@*========================================================================================================================================================================================================================================================================================*+@####### ", +" ########@@&$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$&#@######## ", +" ########+@@++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#@@######## ", +" ##########+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@########## ", +" ######################################################################################################################################################################################################################################################################################################### ", +" ######################################################################################################################################################################################################################################################################################################## ", +" ###################################################################################################################################################################################################################################################################################################### ", +" #################################################################################################################################################################################################################################################################################################### ", +" ################################################################################################################################################################################################################################################################################################## ", +" ############################################################################################################################################################################################################################################################################################## ", +" ########################################################################################################################################################################################################################################################################################## ", +" ", +" ", +" ", +" ", +" " +}; diff --git a/utils/images/logo-50.xpm b/utils/images/logo-50.xpm index 2661a96..b96acc7 100644 --- a/utils/images/logo-50.xpm +++ b/utils/images/logo-50.xpm @@ -1,7 +1,7 @@ /* XPM */ /* XScreenSaver Logo, designed by Angela Goodman <rzr_grl@yahoo.com> - Copyright (c) 2001, 2002 by Jamie Zawinski <jwz@jwz.org> + Copyright © 2001-2021 Jamie Zawinski <jwz@jwz.org> Unauthorized use or reproduction prohibited. https://www.jwz.org/xscreensaver/ diff --git a/utils/images/logo.pdf b/utils/images/logo.pdf new file mode 100644 index 0000000..fcb4e5d --- /dev/null +++ b/utils/images/logo.pdf @@ -0,0 +1,1156 @@ +%PDF-1.5
%
+1 0 obj
<</Metadata 2 0 R/OCProperties<</D<</ON[5 0 R 28 0 R 50 0 R 72 0 R]/Order 73 0 R/RBGroups[]>>/OCGs[5 0 R 28 0 R 50 0 R 72 0 R]>>/Pages 3 0 R/Type/Catalog>>
endobj
2 0 obj
<</Length 56941/Subtype/XML/Type/Metadata>>stream
+<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> +<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 "> + <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> + <rdf:Description rdf:about="" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <dc:format>application/pdf</dc:format> + <dc:title> + <rdf:Alt> + <rdf:li xml:lang="x-default">jwz 8.5x11 CMYK</rdf:li> + </rdf:Alt> + </dc:title> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmp="http://ns.adobe.com/xap/1.0/" + xmlns:xmpGImg="http://ns.adobe.com/xap/1.0/g/img/"> + <xmp:CreatorTool>Adobe Illustrator CS6 (Macintosh)</xmp:CreatorTool> + <xmp:CreateDate>2021-02-04T18:07:40-08:00</xmp:CreateDate> + <xmp:ModifyDate>2021-02-04T19:52:55-08:00</xmp:ModifyDate> + <xmp:MetadataDate>2021-02-04T19:52:55-08:00</xmp:MetadataDate> + <xmp:Thumbnails> + <rdf:Alt> + <rdf:li rdf:parseType="Resource"> + <xmpGImg:width>228</xmpGImg:width> + <xmpGImg:height>256</xmpGImg:height> + <xmpGImg:format>JPEG</xmpGImg:format> + <xmpGImg:image>/9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA
AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK
DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f
Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgBAADkAwER
AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA
AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB
UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE
1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ
qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy
obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp
0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo
+DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9U4q7FXYq7FXYq7FXYq7
FXYq8K/5yh1eK78tS6DaXU1tqmnG31aa23RLqzLPA3pkEeoYZCrsOw37VCrIv+cevzK/xj5NS0vp
ueu6MFt73kfilipSGf35KOLH+YE9xir1PFXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXYq7FXY
q7FXYq7FXYq7FXYq7FXYq7FXkf8Azkd5MtdY8rW+tlP9I0aQrNInwuLS6pFLv4IxRzXbiG8TkZ3W
3NtwiJmBL6T+L+D5m8n+ZNd/Lbzrb6tbAyRxfDdRDZLi0dgHU9aVpt4MBgx5BIWG3V6WeDIYT5j8
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
/wCkO3/5oxV3+BPI/wD1L2mf9Idv/wA0Yq7/AAJ5H/6l7TP+kO3/AOaMVd/gTyP/ANS9pn/SHb/8
0Yq7/Ankf/qXtM/6Q7f/AJoxVNLDTdO062Frp9rDZ2yklYLeNYkBO5IVABviqIxV2KuxV2KuxV2K
vBv+cvyP8E6KK7nUqgfKCTFIeD/+UR/8GX/sQxVkP5vfk35r8neZ7nV9GtZ59CluDdWF9aBme2Yt
zCSen8UZjb7L9DtvXYKseH53fmyo4/4mvfh23ZSdvGq1xWm/+V4fmz/1M1596f8ANOK07/leH5s/
9TNefen/ADTitO/5Xh+bP/UzXn3p/wA04rTv+V4fmz/1M1596f8ANOK07/leH5s/9TNefen/ADTi
tO/5Xh+bP/UzXn3p/wA04rTv+V4fmz/1M1596f8ANOK07/leH5s/9TNefen/ADTitO/5Xh+bP/Uz
Xn3p/wA04rTv+V4fmz/1M1596f8ANOK07/leH5s/9TNefen/ADTitO/5Xh+bP/UzXn3p/wA04rTv
+V4fmz/1M1596f8ANOK07/leH5s/9TNefen/ADTitO/5Xh+bP/UzXn3p/wA04rTv+V4fmz/1M159
6f8ANOK07/leH5s/9TNefen/ADTitO/5Xh+bP/UzXn3p/wA04rTv+V4fmz/1M1596f8ANOK07/le
H5s/9TNefen/ADTitO/5Xh+bP/UzXn3p/wA04rTv+V4fmz/1M1596f8ANOK07/leH5s/9TNefen/
ADTitO/5Xh+bP/UzXn3p/wA04rTv+V4fmz/1M1596f8ANOK0hHm/M38ydSt4na/8w3UdY4AeTxxV
oW32ijrtyY098VfRn/Qvkn/Kkf8AB/rR/wCIfX/S3r1Po/XuPD0+VK8PS/dcv9l7Yof/2Q==</xmpGImg:image> + </rdf:li> + </rdf:Alt> + </xmp:Thumbnails> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" + xmlns:stRef="http://ns.adobe.com/xap/1.0/sType/ResourceRef#" + xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"> + <xmpMM:OriginalDocumentID>uuid:9E3E5C9A8C81DB118734DB58FDDE4BA7</xmpMM:OriginalDocumentID> + <xmpMM:DocumentID>xmp.did:F77F11740720681183D1DC35A180BA8D</xmpMM:DocumentID> + <xmpMM:InstanceID>uuid:32b9882d-d735-f340-9045-3cc9a9725e9f</xmpMM:InstanceID> + <xmpMM:RenditionClass>proof:pdf</xmpMM:RenditionClass> + <xmpMM:DerivedFrom rdf:parseType="Resource"> + <stRef:instanceID>uuid:5043498c-ce3d-7641-8f33-296bf1a24f51</stRef:instanceID> + <stRef:documentID>xmp.did:0380117407206811822ACFB88DCA4B7E</stRef:documentID> + <stRef:originalDocumentID>uuid:9E3E5C9A8C81DB118734DB58FDDE4BA7</stRef:originalDocumentID> + <stRef:renditionClass>default</stRef:renditionClass> + </xmpMM:DerivedFrom> + <xmpMM:History> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:0280117407206811822ADEA6FFA93920</stEvt:instanceID> + <stEvt:when>2014-06-05T18:45:01-07:00</stEvt:when> + <stEvt:softwareAgent>Adobe Illustrator CS6 (Macintosh)</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <stEvt:action>saved</stEvt:action> + <stEvt:instanceID>xmp.iid:F77F11740720681183D1DC35A180BA8D</stEvt:instanceID> + <stEvt:when>2021-02-04T18:07:40-08:00</stEvt:when> + <stEvt:softwareAgent>Adobe Illustrator CS6 (Macintosh)</stEvt:softwareAgent> + <stEvt:changed>/</stEvt:changed> + </rdf:li> + </rdf:Seq> + </xmpMM:History> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:illustrator="http://ns.adobe.com/illustrator/1.0/"> + <illustrator:StartupProfile>Basic RGB</illustrator:StartupProfile> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:xmpTPg="http://ns.adobe.com/xap/1.0/t/pg/" + xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" + xmlns:xmpG="http://ns.adobe.com/xap/1.0/g/"> + <xmpTPg:NPages>1</xmpTPg:NPages> + <xmpTPg:HasVisibleTransparency>False</xmpTPg:HasVisibleTransparency> + <xmpTPg:HasVisibleOverprint>False</xmpTPg:HasVisibleOverprint> + <xmpTPg:MaxPageSize rdf:parseType="Resource"> + <stDim:w>8.000000</stDim:w> + <stDim:h>8.000000</stDim:h> + <stDim:unit>Inches</stDim:unit> + </xmpTPg:MaxPageSize> + <xmpTPg:PlateNames> + <rdf:Seq> + <rdf:li>Black</rdf:li> + <rdf:li>PANTONE 485 CVC</rdf:li> + <rdf:li>PANTONE 152 CVC</rdf:li> + </rdf:Seq> + </xmpTPg:PlateNames> + <xmpTPg:SwatchGroups> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:groupName>Default Swatch Group</xmpG:groupName> + <xmpG:groupType>0</xmpG:groupType> + <xmpG:Colorants> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>White</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>Black</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>75.020996</xmpG:cyan> + <xmpG:magenta>67.968300</xmpG:magenta> + <xmpG:yellow>67.022202</xmpG:yellow> + <xmpG:black>90.164001</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>RGB Red</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>99.398796</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>RGB Yellow</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>6.198197</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>96.514801</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>RGB Green</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>62.764900</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>RGB Cyan</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>51.793701</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>12.539900</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>RGB Blue</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>88.366501</xmpG:cyan> + <xmpG:magenta>76.916100</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>RGB Magenta</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>26.990200</xmpG:cyan> + <xmpG:magenta>81.640297</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=193 G=39 B=45</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>16.961897</xmpG:cyan> + <xmpG:magenta>97.897301</xmpG:magenta> + <xmpG:yellow>92.724503</xmpG:yellow> + <xmpG:black>6.744498</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=237 G=28 B=36</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.445598</xmpG:cyan> + <xmpG:magenta>99.142403</xmpG:magenta> + <xmpG:yellow>97.323601</xmpG:yellow> + <xmpG:black>0.094599</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=241 G=90 B=36</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>79.803200</xmpG:magenta> + <xmpG:yellow>96.874901</xmpG:yellow> + <xmpG:black>0.012201</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=247 G=147 B=30</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.036597</xmpG:cyan> + <xmpG:magenta>50.066399</xmpG:magenta> + <xmpG:yellow>98.565605</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=251 G=176 B=59</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.021398</xmpG:cyan> + <xmpG:magenta>34.848602</xmpG:magenta> + <xmpG:yellow>87.130501</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=252 G=238 B=33</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>4.513597</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>93.188400</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=217 G=224 B=33</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>18.896801</xmpG:cyan> + <xmpG:magenta>0.039703</xmpG:magenta> + <xmpG:yellow>98.232994</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=140 G=198 B=63</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>50.109100</xmpG:cyan> + <xmpG:magenta>0.137299</xmpG:magenta> + <xmpG:yellow>99.038704</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=57 G=181 B=74</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>74.615097</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>99.703995</xmpG:yellow> + <xmpG:black>0.009203</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=0 G=146 B=69</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>86.385902</xmpG:cyan> + <xmpG:magenta>17.578400</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>3.823900</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=0 G=104 B=55</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>90.218994</xmpG:cyan> + <xmpG:magenta>33.475197</xmpG:magenta> + <xmpG:yellow>98.764000</xmpG:yellow> + <xmpG:black>26.065498</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=34 G=181 B=115</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>76.195900</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>74.978294</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=0 G=169 B=157</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>78.441994</xmpG:cyan> + <xmpG:magenta>9.085202</xmpG:magenta> + <xmpG:yellow>45.755695</xmpG:yellow> + <xmpG:black>0.027502</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=41 G=171 B=226</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>69.720001</xmpG:cyan> + <xmpG:magenta>14.846998</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=0 G=113 B=188</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>87.536400</xmpG:cyan> + <xmpG:magenta>52.645100</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=46 G=49 B=146</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>99.130203</xmpG:cyan> + <xmpG:magenta>96.548401</xmpG:magenta> + <xmpG:yellow>3.494298</xmpG:yellow> + <xmpG:black>0.500500</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=27 G=20 B=100</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>100.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>26.251602</xmpG:yellow> + <xmpG:black>24.524302</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=102 G=45 B=145</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>74.520500</xmpG:cyan> + <xmpG:magenta>98.516800</xmpG:magenta> + <xmpG:yellow>0.940001</xmpG:yellow> + <xmpG:black>0.228900</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=147 G=39 B=143</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>49.558197</xmpG:cyan> + <xmpG:magenta>99.191299</xmpG:magenta> + <xmpG:yellow>1.370299</xmpG:yellow> + <xmpG:black>0.109899</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=158 G=0 B=93</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>34.891300</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>37.204506</xmpG:yellow> + <xmpG:black>10.815602</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=212 G=20 B=90</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>11.844099</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>49.249996</xmpG:yellow> + <xmpG:black>0.872803</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=237 G=30 B=121</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>97.000099</xmpG:magenta> + <xmpG:yellow>20.495903</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=199 G=178 B=153</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>22.854996</xmpG:cyan> + <xmpG:magenta>27.426601</xmpG:magenta> + <xmpG:yellow>39.942001</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=153 G=134 B=117</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>39.844398</xmpG:cyan> + <xmpG:magenta>42.853401</xmpG:magenta> + <xmpG:yellow>52.529198</xmpG:yellow> + <xmpG:black>6.808603</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=115 G=99 B=87</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>50.398998</xmpG:cyan> + <xmpG:magenta>53.136497</xmpG:magenta> + <xmpG:yellow>60.897202</xmpG:yellow> + <xmpG:black>23.593498</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=83 G=71 B=65</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>57.598198</xmpG:cyan> + <xmpG:magenta>60.415001</xmpG:magenta> + <xmpG:yellow>63.738503</xmpG:yellow> + <xmpG:black>41.934799</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=198 G=156 B=109</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>22.671902</xmpG:cyan> + <xmpG:magenta>38.394703</xmpG:magenta> + <xmpG:yellow>63.668297</xmpG:yellow> + <xmpG:black>1.181000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=166 G=124 B=82</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>31.595303</xmpG:cyan> + <xmpG:magenta>49.182903</xmpG:magenta> + <xmpG:yellow>73.931496</xmpG:yellow> + <xmpG:black>9.890902</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=140 G=98 B=57</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>36.234100</xmpG:cyan> + <xmpG:magenta>57.402897</xmpG:magenta> + <xmpG:yellow>84.057404</xmpG:yellow> + <xmpG:black>22.613901</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=117 G=76 B=36</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>39.169895</xmpG:cyan> + <xmpG:magenta>64.104698</xmpG:magenta> + <xmpG:yellow>93.441704</xmpG:yellow> + <xmpG:black>35.580997</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=96 G=56 B=19</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>41.538094</xmpG:cyan> + <xmpG:magenta>69.994698</xmpG:magenta> + <xmpG:yellow>97.024498</xmpG:yellow> + <xmpG:black>49.155403</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=66 G=33 B=11</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>47.794300</xmpG:cyan> + <xmpG:magenta>73.476799</xmpG:magenta> + <xmpG:yellow>83.712502</xmpG:yellow> + <xmpG:black>68.157501</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>PANTONE 485 CVC</xmpG:swatchName> + <xmpG:type>SPOT</xmpG:type> + <xmpG:tint>100.000000</xmpG:tint> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>100.000000</xmpG:magenta> + <xmpG:yellow>91.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>PANTONE 152 CVC</xmpG:swatchName> + <xmpG:type>SPOT</xmpG:type> + <xmpG:tint>100.000000</xmpG:tint> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:cyan>0.000000</xmpG:cyan> + <xmpG:magenta>51.000000</xmpG:magenta> + <xmpG:yellow>100.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + </rdf:Seq> + </xmpG:Colorants> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:groupName>Cold</xmpG:groupName> + <xmpG:groupType>1</xmpG:groupType> + <xmpG:Colorants> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=56 M=0 Y=20 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>55.742699</xmpG:cyan> + <xmpG:magenta>0.000000</xmpG:magenta> + <xmpG:yellow>19.989300</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=51 M=43 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>51.079601</xmpG:cyan> + <xmpG:magenta>43.097603</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>C=26 M=41 Y=0 K=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>26.440800</xmpG:cyan> + <xmpG:magenta>41.147499</xmpG:magenta> + <xmpG:yellow>0.000000</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + </rdf:Seq> + </xmpG:Colorants> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:groupName>Grays</xmpG:groupName> + <xmpG:groupType>1</xmpG:groupType> + <xmpG:Colorants> + <rdf:Seq> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=0 G=0 B=0</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>75.020996</xmpG:cyan> + <xmpG:magenta>67.968300</xmpG:magenta> + <xmpG:yellow>67.022202</xmpG:yellow> + <xmpG:black>90.164001</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=26 G=26 B=26</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>72.576500</xmpG:cyan> + <xmpG:magenta>66.600998</xmpG:magenta> + <xmpG:yellow>65.191101</xmpG:yellow> + <xmpG:black>78.161301</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=51 G=51 B=51</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>69.482002</xmpG:cyan> + <xmpG:magenta>63.180000</xmpG:magenta> + <xmpG:yellow>62.151497</xmpG:yellow> + <xmpG:black>58.361202</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=77 G=77 B=77</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>65.377304</xmpG:cyan> + <xmpG:magenta>57.988899</xmpG:magenta> + <xmpG:yellow>56.878002</xmpG:yellow> + <xmpG:black>36.661304</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=102 G=102 B=102</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>59.728401</xmpG:cyan> + <xmpG:magenta>51.235199</xmpG:magenta> + <xmpG:yellow>50.771301</xmpG:yellow> + <xmpG:black>20.132797</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=128 G=128 B=128</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>51.647198</xmpG:cyan> + <xmpG:magenta>43.149502</xmpG:magenta> + <xmpG:yellow>43.149502</xmpG:yellow> + <xmpG:black>7.547098</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=153 G=153 B=153</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>42.636799</xmpG:cyan> + <xmpG:magenta>34.787498</xmpG:magenta> + <xmpG:yellow>35.315502</xmpG:yellow> + <xmpG:black>0.985700</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=179 G=179 B=179</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>30.679798</xmpG:cyan> + <xmpG:magenta>24.246597</xmpG:magenta> + <xmpG:yellow>24.765402</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=204 G=204 B=204</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>19.366800</xmpG:cyan> + <xmpG:magenta>15.005702</xmpG:magenta> + <xmpG:yellow>15.533697</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=230 G=230 B=230</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>8.459598</xmpG:cyan> + <xmpG:magenta>6.131101</xmpG:magenta> + <xmpG:yellow>6.576598</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + <rdf:li rdf:parseType="Resource"> + <xmpG:swatchName>R=242 G=242 B=242</xmpG:swatchName> + <xmpG:mode>CMYK</xmpG:mode> + <xmpG:type>PROCESS</xmpG:type> + <xmpG:cyan>3.704900</xmpG:cyan> + <xmpG:magenta>2.508599</xmpG:magenta> + <xmpG:yellow>2.508599</xmpG:yellow> + <xmpG:black>0.000000</xmpG:black> + </rdf:li> + </rdf:Seq> + </xmpG:Colorants> + </rdf:li> + </rdf:Seq> + </xmpTPg:SwatchGroups> + </rdf:Description> + <rdf:Description rdf:about="" + xmlns:pdf="http://ns.adobe.com/pdf/1.3/"> + <pdf:Producer>Adobe PDF library 10.01</pdf:Producer> + </rdf:Description> + </rdf:RDF> +</x:xmpmeta> + + + + + + + + + + + + + + + + + + + + + +<?xpacket end="w"?>
endstream
endobj
3 0 obj
<</Count 1/Kids[7 0 R]/Type/Pages>>
endobj
7 0 obj
<</ArtBox[63.4517 35.4053 512.534 541.376]/BleedBox[0.0 0.0 576.0 576.0]/Contents 74 0 R/LastModified(D:20210204195255-08'00')/MediaBox[0.0 0.0 576.0 576.0]/Parent 3 0 R/PieceInfo<</Illustrator 75 0 R>>/Resources<</ColorSpace<</CS0 76 0 R/CS1 77 0 R>>/ExtGState<</GS0 78 0 R>>/Properties<</MC0 72 0 R>>>>/Thumb 79 0 R/TrimBox[0.0 0.0 576.0 576.0]/Type/Page>>
endobj
74 0 obj
<</Filter/FlateDecode/Length 1386>>stream
+HIn\7} +^)ik%"0@ +_A
RoA`Y/\KJ.`\HbMڵyf)cʎ9v 6qGvSg?4ѳe>g֡,2|܆ެAh;5G<מ,EKE/b_nl6l#5px?y#N,ǔWy>l=,<K۟/k\M?ĀCf6S^i~,ja}H,KV"wzto b3{_SR90^կ~RP:
{z<2m6%ЗS +j$cu +yu%nύ.q0
5A&0r%Va*<+eT<UWV .)\H>_5 +UtK/18q?& J5b~и( }QԺDnd$}S|QhUشR#!Sb^+E}!WAy?P.{qJ@JU#/AIuRyc#I~'[Ec +8;Z]"4-mc,$q4<X4"XRb<*9E2)J9:kBD?s-$&b0+E&]1!_9Ymn7%F.>0+7-7`dl_t +&"$(CG"m(k@EV&h\B,oL,KM!FM&G4jiCMdPrDjH+Qp"pccm$+FW-O%]e8q'DdeR"k +#pF0sghHa)eA%;n!(]HbVn[OXoNlFrfg%%lIc?X)RjufQ*,+bBO_[]&RARQJU-FSX +167F_,[FH<LuLE'bUO6YWQ4TTkjb\Z9(OOhZ1"l0g\7g1cIFoG(onRWj:nT+*n(t3 +OdYEjru?C,Zbsi,bk.DF4$5aHRHdE&p]ssXTc6-S\q2=j,fQgc.c8RT"E"4G6SE,* +UI,YY`L6M]VP81kY=s&A-T^9h<H0<=KV`&3a::f><'=l8,q,eLnes;IQ(QHhYf^^q +r(P"(G/@Xb@RX)OV`<'D_WFmJ^4r7P0BZ/\^4m`H:%(o-0b$@4Q-LOh%Oq(HI>9d] +gAu$X4[1MVSO43F[/;1&^`ob>Nt%!FLKRb1HFj'1Y,mY[0NbmcO=9dae&?*ALoWP> +./"`@:*&(]INXcsYS6j.FEqc<rtsp0719$HgS-n?r5:]XF%=DLbNblTjf]%\K0(UZ +X(6L1SMA%>n\Zk\b,8_R(S-ucj2_n3eOf\#17i]W!K-KKUM"=Z"IY\WK4%K.lZtNd +'RJ^6)42)re]"$Lo.4p?H?;U6B=W!ZaT&MWNCmGbR<@gsjRPM8Khc$4~>
endstream
endobj
80 0 obj
[/Indexed/DeviceRGB 255 81 0 R]
endobj
81 0 obj
<</Filter[/ASCII85Decode/FlateDecode]/Length 428>>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#s<Xl5FH@[<=!#6V)uDBXnIr.F>oRZ7Dl%MLY\.?d>Mn +6%Q2oYfNRF$$+ON<+]RUJmC0I<jlL.oXisZ;SYU[/7#<&37rclQKqeJe#,UF7Rgb1 +VNWFKf>nDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j<etJICj7e7nPMb=O6S7UOH< +PO7r\I.Hu&e0d&E<.')fERr/l+*W,)q^D*ai5<uuLX.7g/>$XKrcYp0n+Xl_nU*O( +l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~>
endstream
endobj
72 0 obj
<</Intent 82 0 R/Name(Layer 1)/Type/OCG/Usage 83 0 R>>
endobj
82 0 obj
[/View/Design]
endobj
83 0 obj
<</CreatorInfo<</Creator(Adobe Illustrator 16.0)/Subtype/Artwork>>>>
endobj
78 0 obj
<</AIS false/BM/Normal/CA 1.0/OP false/OPM 1/SA true/SMask/None/Type/ExtGState/ca 1.0/op false>>
endobj
76 0 obj
[/Separation/PANTONE#20152#20CVC/DeviceCMYK<</C0[0.0 0.0 0.0 0.0]/C1[0.0 0.51 1.0 0.0]/Domain[0 1]/FunctionType 2/N 1.0/Range[0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]>>]
endobj
77 0 obj
[/Separation/PANTONE#20485#20CVC/DeviceCMYK<</C0[0.0 0.0 0.0 0.0]/C1[0.0 1.0 0.91 0.0]/Domain[0 1]/FunctionType 2/N 1.0/Range[0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]>>]
endobj
75 0 obj
<</LastModified(D:20210204195255-08'00')/Private 84 0 R>>
endobj
84 0 obj
<</AIMetaData 85 0 R/AIPDFPrivateData1 86 0 R/AIPDFPrivateData2 87 0 R/AIPDFPrivateData3 88 0 R/AIPDFPrivateData4 89 0 R/AIPDFPrivateData5 90 0 R/AIPDFPrivateData6 91 0 R/AIPDFPrivateData7 92 0 R/AIPDFPrivateData8 93 0 R/ContainerVersion 11/CreatorVersion 16/NumBlock 8/RoundtripVersion 16>>
endobj
85 0 obj
<</Length 1127>>stream
+%!PS-Adobe-3.0
%%Creator: Adobe Illustrator(R) 16.0
%%AI8_CreatorVersion: 16.0.0
%%For: (Jamie Zawinski) ()
%%Title: (logo.pdf)
%%CreationDate: 2/4/21 7:52 PM
%%Canvassize: 16383
%%BoundingBox: 81 -649 531 -142
%%HiResBoundingBox: 81.4517 -648.5947 530.5342 -142.624
%%DocumentProcessColors: Black
%AI5_FileFormat 12.0
%AI12_BuildNumber: 682
%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)
%%CMYKProcessColor: 1 1 1 1 ([Registration])
%AI3_Cropmarks: 18 -684 594 -108
%AI3_TemplateBox: 306.5 -396.5 306.5 -396.5
%AI3_TileBox: 34.3765 -881.1035 613.1768 -126.3032
%AI3_DocumentPreview: None
%AI5_ArtSize: 14400 14400
%AI5_RulerUnits: 0
%AI9_ColorModel: 2
%AI5_ArtFlags: 0 0 0 1 0 0 1 0 0
%AI5_TargetResolution: 800
%AI5_NumLayers: 1
%AI9_OpenToView: 15.1631 -118.1631 1.96 1225 1158 18 1 1 310 161 1 0 0 1 1 0 1 1 0 1
%AI5_OpenViewLayers: 7
%%PageOrigin:-0.223633 -791.7031
%AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9
%AI9_Flatten: 1
%AI12_CMSettings: 00.MS
%%EndComments
endstream
endobj
86 0 obj
<</Length 19373>>stream
+%%BoundingBox: 81 -649 531 -142
%%HiResBoundingBox: 81.4517 -648.5947 530.5342 -142.624
%AI7_Thumbnail: 116 128 8
%%BeginData: 19220 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
%524C45FD27FF5252FD72FF27F87DFD6FFFA8FF7D2720FD70FF277D202752
%FD6FFFA8272720277DFD6EFFA8522727F827A8FD6EFF7D764B27F852FD6E
%FFA84B932727F87DFD6EFF7D939A272727A8FD6DFF7D759376272721A8FD
%6CFFA84BB59376272752FD6DFF526F939352F82752FD6CFF7D9A93B59352
%27277DFD6BFFA84B9393936F51F827A8FD6AFFA87693B593B551522752FD
%6BFF52FD05932751F87DFD0DFFA8FFA827A8FD58FF7D6FBB93B5939A5227
%20A8FD0BFF7D52FF27277DFD58FF7D75FD059376512727FD0AFFA8F8A852
%2752FD59FFA875B593B593B56F7C522752FD09FF277D7D2727A8FD59FFA8
%76FD06934BA0F827A8FD07FF52517D27F852FD5BFF76B593BC93B593767C
%7C207DFD06FF7D76765220277DFD5AFFA876FD06936F7C9F2727FD05FFA8
%526F52F827F8FD5BFFA951B593B593B5939951C22727A8FD04FF7D6F76F8
%272752FD5BFFA876FD06936F76752727FD04FFA84B934B27F82752FD5BFF
%A851BB93B593BC93767B5227A8FD04FF529A93522776277DFD5BFF7D75FD
%05939A51A0F852FD04FF7D519393277651277DFD5BFF7D6FB593B593B54B
%A05127A8FD04FF7D6FB593529F76F8FD36FF7EA87DA87DA87DA87DA87DA8
%7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA851FD0593
%6F76752727A87DA8A87D4B9393934BC127277DA87DA87DA87DA87DA87DA8
%7DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA8
%7DA87DA8FD05FFA87D272720272727202727272027272720272727202727
%2720272727202727272027272720272727207693B593BC93529F52272720
%272727209A93B593769F5220272727202727272027272720272727202727
%27202727272027272720272727202727272027272720272727202727527D
%FFFFA827F827F827F827F827F827F827F827F827F827F827F827F827F827
%F827F827F827F827F827F827F8276FFD049376759FF827F827F827F852FD
%04934BA04B27F827F827F827F827F827F827F827F827F827F827F827F827
%F827F827F827F827F827F827F827F827F827F827F827F82752FF7D2727F8
%FD25274BB593B593934BC252FD072775B593B593769F52FD2E27F8272727
%A8F827F852A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8
%FFA8FFA8FFA8FFA8FFFFFF5299FD04936F76992727A8A8FFFFA84BFD0593
%4BA051277DFFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FF
%A8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFFFA82727F87D272727A8FD23
%FF527693B593BC93529F7C277DFD04FF7D7693B593BC93767B7C27A8FD2D
%FF7D272752F827F8A8FD22FF7D75FD05937675C12027A8FD04FF766FFD05
%936F7C75277DFD2DFF5227F87D27F827A8FD21FF7D7693B593B593B54BC2
%762752FD05FF52B593B593B5939A76A0F87DFD2DFF7DF82753F827F8A8FD
%20FF7D51FD06936F529952F8A8FD04FF7D75FD079376752727FD2DFF5227
%F87D272027A8FD1FFFA85293BB93B593BC93767BC22752FD05FF7D6FB593
%BC93B593BC51A02727AFFD2CFF7D202753F827F8A8FD1FFF526FFD079351
%C1752752FD05FF51FD0893767552F8A8FD2CFF5227F87D2727277EFD17FF
%A8FD06FF7D4BB593B593B593B56F7C9F52F8A8FD04FFA87693B593B593B5
%93B56F7C76277DFD2CFF7D272752F827F8A8FD0CFFA8FFFFFFA8FFFFFFA8
%FFA8277DA8F87DFFA84BFD08937575C12627A8FD04FF7D6FFD09934B7CF8
%52FD04FFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FFFFFFA8FF
%FFFFA8FD0BFF5227F87D272727A8FD07FFA87D5252275252522752285227
%5227526F5227272752279A93BC93B593BC93B551C29F2727522852275227
%9A93BC93B593BC93B593767C522052525227525252275252522752525227
%522852275228522752285227522852275252527DFD08FF7D272752F827F8
%A8FD06FF7D27F827F827F827F827F827F827F8276F75F827F827F852FD09
%93529FA0F827F827F827F827FD0A936F765127F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F82752FD07FF52
%27F87D27F827A8FD05FFA8272727F8272727F8272727F8FD0427B55127F8
%2727276FB593B593B593B5939A51C175272727F82727274BB593B593B593
%B593B593B551A02727F8272727F8272727F8272727F8272727F8272727F8
%272727F8272727F8272727F827272752FD06FF7DF82753F827F8A8FD05FF
%7DF827F827F827F827F827F827F827F876934BF827F8274BFD09936F769F
%76F827F827F827F852FD0B93755152F827F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827A8FD05FF5227F8
%7D272027A8FD05FF52272727202727272027272720272727939A27272027
%277693BC93B593BC93B593BC52C2752727272027272751BB93B593BC93B5
%93BC93B59376762720272727202727272027272720272727202727272027
%272720272727202727272027272720A8FD05FF7D202753F827F8A8FD05FF
%52F827F827F827F827F827F827F8274B934B27F827F827FD0B93769F7CF8
%27F827F827F876FD0C934B7C2727F827F827F827F827F827F827F827F827
%F827F827F827F827F827F827F827F827F827F8277DFD05FF5227F87D2727
%277EFD05FF5227F8272727F8272727F8272727F89A9352F8FD0427B593B5
%93B593B593B593B56FA09F27F8272727F82751B593B593B593B593B593B5
%939A517C2727F8272727F8272727F8272727F8272727F8272727F8272727
%F8272727F8272727F82727A8FD05FF7D272752F827F8A8FD05FF52F827F8
%27F827F827F827F827F85193932727F827F852FD0C934B9F2727F827F827
%F876FD0D93767527F827F827F827F827F827F827F827F827F827F827F827
%F827F827F827F827F827F827F8277DFD05FF5227F87D272727A8FD05FF52
%2720272727202727272027272775BB99272027272775BB93B593BC93B593
%BC93B593767C7C20272727202751B593BC93B593BC93B593BC93B56F7C76
%272027272720272727202727272027272720272727202727272027272720
%272727202727A8FD05FF7D272752F827F8A8FD05FF52F827F827F827F827
%F827F82727939376F827F827F876FD0C936F527527F827F827F852FD0E93
%4B7C2727F827F827F827F827F827F827F827F827F827F827F827F827F827
%F827F827F827F8277DFD05FF5227F87D27F827A8FD05FF52272727F82727
%27F8272727F87693B54B515127F82775B593B593B593B593B593B593B56F
%7C5227F8FD04279A93B593B593B593B593B593B59399517C2727F8272727
%F8272727F8272727F8272727F8272727F8272727F8272727F8272727F8A8
%FD05FF7DF82753F827F8A8FD05FF52F827F827F827F827F827F8276F9393
%515152F827F876FD0E934B762727F827F8276FFD0E93757576F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F8277D
%FD05FF5227F87D272027A8FD05FF522727272027272720FD0427BC93B551
%A05227525275B593BC93B593BC93B593BC93B593BC51762727527D277693
%B593BC93B593BC93B593BC93B593767C5220FD04527D5252527D5252527D
%FD0452272720272727202727272027272720A8FD05FF7D202753F827F8A8
%FD05FF52F827F827F827F827F827F876939393769F76F8A8A876FD109351
%52F852FFFF51FD0F936F527527F8A8FD10FF2727F827F827F827F827F827
%F8277DFD05FF5227F87D2727277EFD05FF5227F8272727F8272727F82775
%B593B575A05127A8FF51B593B593B593B593B593B593B59393939A5152F8
%52FF7D6FB593B593B593B593B593B593B593B56F7C7627F8A8FD10FF2727
%F8272727F8272727F82727A8FD05FF7D272752F827F8A8FD05FF52F827F8
%27F827F827F82727FD0493769F76F87DFF766FFD1093994B27F852A852FD
%10934B7C7527F8A8FD0FFF27F827F827F827F827F827F8277DFD05FF5227
%F87D272727A8FD05FF52272027272720272727207693B593BB75A07B2752
%FF7D7693B593BC93B593BC93B593BC93B593BC939A5152277D7D7693B593
%BC93B593BC93B593BC93B593BB517C752727FD0FFF272720272727202727
%27202727A8FD05FF7D272752F827F8A8FD05FF52F827F827F827F827F827
%6FFD049376759FF852FFFF4BFD1293752727F85252FD11934B9F512752FD
%0EFF52F827F827F827F827F827F8277DFD05FF5227F87D27F827A8FD05FF
%52272727F8272727F827279A93B593B56F7C9F51F8FFFF7D6FB593B593B5
%93B593B593B593B593B593B593765151275275B593B593B593B593B593B5
%93B59393939A51A02027A8FD0DFFFD0427F8272727F8272727F8A8FD05FF
%7DF82753F827F8A8FD05FF52F827F827F827F827F84BFD06934BC151277D
%FF7D51FD1393764B27F8276FFD1093767576F87DFD0DFF27F827F827F827
%F827F827F8277DFD05FF5227F87D272027A8FD05FF522727272027272720
%2751B593BC93B593769FA02059FFFF529A93B593BC93B593BC93B593BC93
%B593BC93B593765227207693B593BC93B593BC93B593BC93B593BC93767B
%2727FD0DFFFD0427202727272027272720A8FD05FF7D202753F827F8A8FD
%05FF52F827F827F827F827F876FD06936F7C9F27F8FFFFA84BFD13936F76
%5127F89AFD10936F7C51277DFD0CFF27F827F827F827F827F827F8277DFD
%05FF5227F87D2727277EFD05FF5227F8272727F82727276FB593B593B593
%9351C276277DFFFF5293B593B593B593B593B593B593B593B593B593B56F
%7C51274BB593B593B593B593B593B593B593B593B5517CF87DFD0CFF2727
%F8272727F8272727F82727A8FD05FF7D272752F827F8A8FD05FF52F827F8
%27F827F82727FD08937675A0F827A8FF7D75FD14934B7CF8276FFD109376
%5127F8FD0CFF27F827F827F827F827F827F8277DFD05FF5227F87D272727
%A8FD05FF5227202727272027275293BC93B593BC93B56F769F5220A8FFFF
%529A93B593BC93B593BC93B593BC93B593BC93B5939A767C205293B593BC
%93B593BC93B593BC93B593BC9376512784FD0BFF27272027272720272727
%202727A8FD05FF7D272752F827F8A8FD05FF52F827F827F827F82727FD09
%934BA0752727FFFF7D4BFD1493767527F89AFD10937552F87DFD0BFF52F8
%27F827F827F827F827F8277DFD05FF5227F87D27F827A8FD05FF52272727
%F8272727F87693B593B593B593B5939A51C251277DFFFF5293B593B593B5
%93B593B593B593B593B593B593B56F7C52274BB593B593B593B593B593B5
%93B593B5939A512727FD0BFFFD0427F8272727F8272727F8A8FD05FF7DF8
%2753F827F8A8FD05FF52F827F827F827F8274BFD0A937675A0F827A8FF7D
%75FD14934BA0F8276FFD1093522727A8FD0AFF27F827F827F827F827F827
%F8277DFD05FF5227F87D272027A8FD05FF5227272720272727207693B593
%BC93B593BC93B593529F76207DFFFF529A93B593BC93B593BC93B593BC93
%B593BC93B593767C52207693B593BC93B593BC93B593BC93B593BB752720
%A8FD0AFFFD0427202727272027272720A8FD05FF7D202753F827F8A8FD05
%FF52F827F827F827F8274BFD0B936F769F27F8A8FF7D4BFD13936F767527
%27FD10939A272752FD0AFF27F827F827F827F827F827F8277DFD05FF5227
%F87D2727277EFD05FF5227F8272727F827277693B593B593B593B593B593
%B54BA0762752FFFF5293B593B593B593B593B593B593B593B593B593B56F
%52272793B593B593B593B593B593B593B593B593522752FD0AFF2727F827
%2727F8272727F82727A8FD05FF7D272752F827F8A8FD05FF52F827F827F8
%27F8274BFD0D934BA04B277DFF7D75FD14936F766FFD11934B27F8A8FD09
%FF27F827F827F827F827F827F8277DFD05FF5227F87D272727A8FD05FF52
%27202727272027277693BC93B593BC93B593BC93B5939A52A02027A8FF52
%9A93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93
%B593BC93B593BC93B5939A27277DFD09FF27272027272720272727202727
%A8FD05FF7D272752F827F8A8FD05FF52F827F827F827F82727FD0E937675
%76F852FF7D4BFD27936F27F87DFD09FF52F827F827F827F827F827F8277D
%FD05FF5227F87D27F827A8FD05FF52272727F8272727F82793B593B593B5
%93B593B593B593B593767652F8A8FF5293B593B593B593B593B593B593B5
%93B593B593B593B593B593B593B593B593B593B593B593B593B54B2752FD
%09FFFD0427F8272727F8272727F8A8FD05FF7DF82753F827F8A8FD05FF52
%F827F827F827F827F876FD0F93525127F8FF7D6FFD279352F852FD09FF27
%F827F827F827F827F827F8277DFD05FF5227F87D272027A8FD05FF522727
%272027272720274BB593BC93B593BC93B593BC93B593BB937651277DA84B
%BB93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93
%B593BC93B593BC93B5752727FD09FFFD0427202727272027272720A8FD05
%FF7D202753F827F8A8FD05FF52F827F827F827F827F8276FFD0F936F5227
%277D76FD279375F8277DFD08FF27F827F827F827F827F827F8277DFD05FF
%5227F87D2727277EFD05FF5227F8272727F8272727F85293B593B593B593
%B593B593B593B593B57552F87D769993B593B593B593B593B593B593B593
%B593B593B593B593B593B593B593B593B593B593B593B59327F884FD08FF
%2727F8272727F8272727F82727A8FD05FF7D272752F827F8A8FD05FF52F8
%27F827F827F827F827F899FD10934B27F87D6FFD2793272752FD08FF27F8
%27F827F827F827F827F8277DFD05FF5227F87D272727A8FD05FF52272027
%272720272727202751B593BC93B593BC93B593BC93B593BC93762727279A
%93BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC
%93B593BC93B593BC93522052FD08FF27272027272720272727202727A8FD
%05FF7D272752F827F8A8FD05FF52F827F827F827F827F827F8276FFD1093
%4BF8276FFD27934B2727FD08FF52F827F827F827F827F827F8277DFD05FF
%5227F87D27F827A8FD05FF52272727F8272727F8272727F87693B593B593
%B593B593B593B593B593B57527F89A93B593B593B593B593B593B593B593
%B593B593B593B593B593B593B593B593B593B593B593B593762727A8FD07
%FFFD0427F8272727F8272727F8A8FD05FF7DF82753F827F8A8FD05FF52F8
%27F827F827F827F827F827F899FD10936F516FFD27934B4BF8A8FD07FF27
%F827F827F827F827F827F8277DFD05FF5227F87D272027A8FD05FF522727
%272027272720272727207D52B593BC93B593BC93B593BC93B593BC93B593
%BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93
%B593BC93B593BC93B593764B277DFD07FFFD0427202727272027272720A8
%FD05FF7D202753F827F8A8FD05FF52F827F827F827F827F827F8277D7D6F
%FD39934B76F87DFD07FF27F827F827F827F827F827F8277DFD05FF5227F8
%7D2727277EFD05FF5227F8272727F8272727F827277DFF5293B593B593B5
%93B593B593B593B593B593B593B593B593B593B593B593B593B593B593B5
%93B593B593B593B593B593B593B593B593B593B59376752752FD07FF2727
%F8272727F8272727F82727A8FD05FF7D272752F827F8A8FD05FF52F827F8
%27F827F827F827F8277DFF7D52FD389351A0F852FD07FF27F827F827F827
%F827F827F8277DFD05FF5227F87D272727A8FD05FF522720272727202727
%272027277DFFFF529A93BC93B593BC93B593BC93B593BC93B593BC93B593
%BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93
%B593BC93769F5227FD07FF27272027272720272727202727A8FD05FF7D27
%2752F827F8A8FD05FF52F827F827F827F827F827F8277DFFFFFF4BFD3693
%7675C12727A8FD06FF52F827F827F827F827F827F8277DFD05FF5227F87D
%27F827A8FD05FF52272727F8272727F8272727F87DFFFFFFA84BB593B593
%B593B593B593B593B593B593B593B593B593B593B593B593B593B593B593
%B593B593B593B593B593B593B593B593B593B551A0522727FD07FFFD0427
%F8272727F8272727F8A8FD05FF7DF82753F827F8A8FD05FF52F827F827F8
%27F827F827F82753FD04FF7D4BFD33936F76512727FD08FF27F827F827F8
%27F827F827F8277DFD05FF5227F87D272027A8FD05FF5227272720272727
%20272727207DFD05FF526FBB93B593BC93B593BC93B593BC93B593BC93B5
%93BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593BC
%9376512727FD09FFFD0427202727272027272720A8FD05FF7D202753F827
%F8A8FD05FF52F827F827F827F827F827F8277DFD05FFA852FD3193992727
%F8A8FD09FF27F827F827F827F827F827F8277DFD05FF5227F87D2727277E
%FD05FF5227F8272727F8272727F827277DFD06FFA85293B593B593B593B5
%93B593B593B593B593B593B593B593B593B593B593B593B593B593B593B5
%93B593B593B593B593B54B27277DFD0AFF2727F8272727F8272727F82727
%A8FD05FF7D272752F827F8A8FD05FF52F827F827F827F827F827F82752FD
%07FF7D51FD2E936F27F853FD0AFFA827F827F827F827F827F827F8277DFD
%05FF5227F87D272727A8FD05FF52272027272720272727202727277DFD07
%FF7D7693B593BC93B593BC93B593BC93B593BC93B593BC93B593BC93B593
%BC93B593BC93B593BC93B593BC93B593BB934B207DFD0AFFAF5227272027
%272720272727202727A8FD05FF7D272752F827F8A8FD05FF52F827F827F8
%27F827F827F827F827277D527D527D527DF876FD2B9352F827527D527D52
%7D527D527D5227F827F827F827F827F827F827F8277DFD05FF5227F87D27
%F827A8FD05FF52272727F8272727F8272727F8272727F8272727F8272727
%F87693B593B593B593B593B593B593B593B593B593B593B593B593B593B5
%93B593B593B593B593B593B59376F8272727F8272727F8272727F8272727
%F8272727F8272727F8272727F8A8FD05FF7DF82753F827F8A8FD05FF52F8
%27F827F827F827F827F827F827F827F827F827F827F827F876FD279376F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F8277D
%FD05FF5227F87D272027A8FD05FF52272727202727272027272720272727
%20272727202727272027277693BC93B593BC93B593BC93B593BC93B593BC
%93B593BC93B593BC93B593BC93B593BC93B5937627272027272720272727
%202727272027272720272727202727272027272720A8FD05FF7D202753F8
%27F8A8FD05FF52F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F876FD239376F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F827F8277DFD05FF5227F87D2727277EFD05FF5227F827
%2727F8272727F8272727F8272727F8272727F8272727F827277693B593B5
%93B593B593B593B593B593B593B593B593B593B593B593B593B593B59352
%2727F8272727F8272727F8272727F8272727F8272727F8272727F8272727
%F82727A8FD05FF7D272752F827F8A8FD05FF52F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F84B6FFD1D936F27F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F8277D
%FD05FF5227F87D272727A8FD05FF52272027272720272727202727272027
%2727202727272027272720272727202775B593BC93B593BC93B593BC93B5
%93BC93B593BC93B593BC93B5939A51272027272720272727202727272027
%272720272727202727272027272720272727202727A8FD05FF7D272752F8
%27F8A8FD05FF7DF827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F8272776FD1793762727F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827A8FD05FF5227F8
%7D27F827A8FD05FFA8272727F8272727F8272727F8272727F8272727F827
%2727F8272727F8272727F827274B4B9A93B593B593B593B593B593B593B5
%93B5939A51522727F8272727F8272727F8272727F8272727F8272727F827
%2727F8272727F8272727F827272752FD06FF7DF82753F827F8A8FD06FF52
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F84B4B756F99FD0793996F754B764B27F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F82727
%A8FD06FF5227F87D272027A8FD07FF7D52FD2027202727272027274B2752
%27524B7676A0757C51272027272720FD212752FD08FF7D202753F827F8A8
%FD0AFFA8AFA8A8A8AFA8A8A8AFA8A8A8AFA8A8A8AFA8A8A8AFA8A8A8AFA8
%A8A8FF2727F827F827F827F827F827F82720527552F827F827F827F827F8
%7DA8A8A8AFA8A8A8AFA8A8A8AFA8A8A8AFA8A8A8AFA8A8A8AFA8A8A8AFA8
%A8A8FD09FF5227F87D2727277EFD27FFA8272727F8272727F8272727F827
%2727F8272727F8272727F8FD0427FD28FF7D272752F827F8A8FD27FF27F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F82752FD27
%FF5227F87D272727A8FD26FF7D2027272720272727202727272027272720
%27272720272727202727272027A8FD26FF7D272752F827F8A8FD25FF7DF8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27A8FD25FF5227F87D27F827A8FD24FF7DF8272727F8272727F8272727F8
%272727F8272727F8272727F8272727F8272727F827A8FD24FF7DF82753F8
%27F8A8FD22FF7E52F827F827F827F827F827F827F827F827F827F827F827
%F827F827F827F827F827F827F82752FD23FF5227F87D272027A8FD20FFA8
%522727272027272720272727202727272027272720272727202727272027
%27272027272720FD0427A8FD21FF7D202753F827F8A8FD1DFFA87D52F827
%F827F827F827F827F827F827F827F827F827F827F827F827F827F827F827
%F827F827F827F827F827F82752A8A8FD1DFF5227F87D2727277EFD1CFFA8
%2727F8272727F8272727F8272727F8272727F8272727F8272727F8272727
%F8272727F8272727F8272727F8272727F8272752A8FD1CFF7D272752F827
%F8A8FD1CFF5227F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F8A8FD1CFF
%5227F87D272727A8FD1DFF7DA87DA87DA87DA87DA87DA87DA87DA87DA87D
%A87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87DA87D
%A8FD1DFF7D272752F827F8A8FD6CFF5227F87D27F827A8FD6CFF7DF82753
%F827F8A8FD6CFF5227F87D52202752FD6BA87D2720277D7D27F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F8FFFF5227F8272727F8272727
%F8272727F8272727F8272727F8272727F8272727F8272727F8272727F827
%2727F8272727F8272727F8272727F8272727F8272727F8272727F8272727
%F8272727F8272727F8272727F8272727F8272727F8272727F8272727F827
%2727F8272727F8272727F82727A8FFFFFF7D52F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F827F827F827F827F827F827F827F827F827F827F827F827F8
%27F827F827F82752A8FFFF
%%EndData
endstream
endobj
87 0 obj
<</Filter[/FlateDecode]/Length 25623>>stream
+HWko +
E +4=ɥDqW,w<
<y"nlS7gur4z\^?ͺ33e&S_eȾKq<U)sLm=[->tBm0W1߽xk^TREZmT̕=r |xf#BkS7c4͚K26M}q]̍拃C(som\ӆĿEx]~qr.}=Lon>_b2ln0Ypu}yzv"kgq
$F7F]V<=7S#=}~[D f<Wˬ&N'õlDM0g=JtV/Q1)>QrBgDplA|>ݹz\ȿo*o#6<Ayw;~[͇شQU7"/~}Zf&RF*\emr1 +wnlwU]7ZfcFehg7SSl8+VwFn`hyX?ǥ{4L@*\~67wOM[\Txr[lEr{yrӛh^5Z]OOʍ*kU- +P"_8#FW$*#(:ji]k.4ˮ#փz=؊Mq=.n0>=#C{ za^D/җ2z {z{IzvB=Dj')w9זBj8,(҈4s^ +O@0R(H"sGғnL[r)J2L\SΤ*PLq%TJ*RJpHcz݇X[BGX,8柰DZFZYx%sKR['GMϟo5pO#Id%X:0!f4E X +$@BD( C0 +%a<*R +)(d"GFL$ʓ)dڪB.4Cn#r"=9R?F Q + +@a`*E )*G +(. A,59N0ګwJxlOXc.A +FP|cUO!}(`h_4e` k;E
ST3dHã>TUv715:0*@snL +SCS]Z
`=HC@ Ly7fqJp@@Ӫ#fy +4};,SƾLrӬO3pg3($q(A!ToS$<LіHٓ>iS0vxӎ}?W 3 &6@8&ӱ0w=o݃ݝ>{Hwdx@3 ë;?|lsݶ{|;ova>..#;5ƹxwv-;!3!kM?&)'E-8ִ~pbS݊oVr^uxػqAq +gI| +iQhgR@h` +a68!DY+TmHU$p,X@% +b7D1a,n6ƜGa?tY&CJӠ,*ܫ+(6DS}SќtءSB LA @1Hɍ6_f:sVHSr\ϫ]_TGkEkjk4|2sh}nPajR,Wp , +$-OوsVS\(e8p] +vTY )ʖЁck%Ԕ"$DX*J`ъ-HE21iqUv(>J.e嬯VM[+Lt1ȷ/^+,H++M+8:rQ(^R +6zt}X)UTOK?VGLRiRs|:sC|Ö1чd)y&ϽsxJUrGzXA<>9PsxD[(ǗȨM9-Ŝ'@ps۬m-2JD-Tr9K 0HqN^,v`Ҳnhf5u6yIiv/8G,),{x +8lbTcwfw!P^9Aaw ]+kpP2W+>FZA#KGJX1BD=Nmycꄫ*?߆iR9Ubr*;GQs*C*ڙP=Q*f9&LIGVR8-fb<(Z]F/ +ѱAJ"" +P/ș5ۗo/eqÒw3{XgO-nP-%,+}ȯ +@T]
==g7cmߣ;(ы\ռ~ڊY@Ρz@%77m}%~Ypw`ך~Ze:}1)ce\r, Ԙ|?`4+@w< +iǭi/f +% +䃸60^vbN@ +ĬtBumS +vK4rfIIى:q?o8]89].#0 +<"uYϑ?|'`ǗߜeFӨr[
48ҹ~G9,\CsAsfR :YAn="eGtA4Z
Ȱ+Cl1˾|*"=e5Hb v^Ġf;JPl<@l`0VY#;vnГ:i͔&ytRܡoQnct. +@BPj=tgKF9KOx<݅r\1$䐑597pmhJlT/,cU'ѝ˩Sy}@Yµ +\)$LMRha#T?H> +p >UTR[`Xz@t' w}z@//4Y56 (JdT-|\lsԇ:fQԂ<ςBtWR7ϹsO2 #աP`'*yS/VGDߺZ5/V5['ȿ:ӣ0^ׁ~%T,>. +|UIhѬjf$q)Wc3K@hˀk0?ZW_F͡B/WwZ!y>(LyJfĭ
b+[j=L`
zEsװ +V@Z,<<]n0}7 +DO `T9[g+8}ŅS8+Y-MANpS=Go?cf5-M`F +7]OԐxa}nXuS7(60nndtwWMՋLLi:0 ^ +"P₾H@ħ{2@T`_+_WK Λ]<BŴFKXM8mT$.h=-] XLn&p :UZ +9 +ϓ;Ɂyd6.ٷOS%Q:as9^=_
"z9RE!GY8TINJ-&ǮQpOW\+Vd7u{[K.,}WiQEM* $x6ŧ8^.D+g + Fs6mo7gp +D8k:%ήgS]c ++rP;mq<Dpd$Njn֭j·ND
+P{^[(h:%]f9 +9KZcvE0[4@;!!ï#1Ox+ՕywBpમ +9!e'R?8w9zAu:'ӤcP0[Urt;3VhX!ɯ"JS+Dn}@[qy-Т2+d;ү
*^T7LᔮVMq6<+.[@R0^JDV OU)bdF;7DC D.48@tpxT/3mɏ~__>~o_ v_~/˧~|7ӿp/?bp7k;ס&S%&o~̤.zN`7M*3( +eS8* +RcgmMy}Pcma
lOTLTJm5|
ij؞6MBYZhG<ūZ +P=A]ZRMĮFCj[\G=:.=촬7^@k\FMPp|X5ݪEq)qp:X&8Ĩ4$0`7#{Yϸ\b8
.1&yWfԸ6~t㚝a>d=7iƤ1 +%@&\uA`ɀcuhDϋ֯BN5[ţR_3[Tm${ +6v#NT[CI1vvw?'8` +"If4]8\%y"rQj (D"N=Z{pJ!\s/
>B @A?"}EK2N~P܇ +'|E&Q|j^I , +sqS
PvڧCyוϱR 5;E+j;"BO4ѪMHsu̿+|"Ee(A=U[R\hDV4ry!2 +FSu64x +CMjGdK6!!VKiyt +)Jq7#@7 +`eO G +~7*ѮBhN{RL9kIpْ1b'xr@"32)'tÀ-Ae,d+r،m$(NVlq DYb?f̸/(cAsIUKU-ki~Q1;5ԏJE1?W{
L: ynhUdz +)!4V
7ᑱ`'JA {W1utq4#ȅ6l#67.? ܷ+Y"iuo@UWpC1$
}/乞Tv"2JV0%MXܫ?fs:3]2sE>"۰c._zh>xѦN0a]a~<VQT|t$lƤw +vxD"JFyxGND' Dm+И>ZѺU>JR Ll4i_Ǡ +Cu +cɚSL]Gc2Ɨ2)TiDU*0e0Z+_&+t7VhKRCZhٯS)\h͚ȕ{2U=LjqhOr!i:8!jO{SרYt?Nd~a$V[nDbIrWo켟9'=FwQ֯]TLQ
deO쾸[b(#`Y1DT*L,׳"OBdQxN5Ejych[Εr%pj4ԞFsjRbb$K,;'Q[JUs' +]*`hyl7RS
ʴ +3oQCJTd;/܊UztlHo-
r~_sNE[;3E!iPۋ$ңT+`Jm\-mvw'c:ݯn%+L$|Dt&@ |ҕzVQx+$70bfǀsl3ov\ړ +v:%:8&1X0_AЏ T>)4b5ev-TDEЃNsI.||1"5؉=mR<";u\B=%Pb!n1hVT^~c'r0gQUCXK8BZ6=Qt +PtƲVpvV]0^fSz`9;zŒ\!NsXlfA=9-cQ"m8?6+0kMt`8݆g^jUc+yKC5KmxK\{($PnҲIm4Qw:K2mt%Xo!lʙeu+x'탒"nӃ~zBCZ0ۀ-Hj*zYKxC#C蠍L{F- UO +< K`ҍBv%-~VmC R,\},5B0lqZo5OC]B,K./p$6oJ~O_>ۯ|}W(-b}/?W?_~ۯ_З?ϺC*#_L[VA; +m1:F;¸`+C^F4FC/I68Zq>gޠ+>B
4j92}qH̜J⋞1x;Vj]XEOfT%f`w%qDcw?0a(,̃'fV5$+zytEӐ{2:
+TGKZ{@q6'#]H4TMyFdV(gZG_\> +Aei$SFsNĨf5 Ћέ ρyOm=b +*e-K#"Y;ZGWŤ:bZ5m1|rR`!zg>6Rx3@`j=iN
0Jٯ30MPTetXDc+M,.P(,)@bKwz*ǻ"F`\w`ZbqcQ<Gg00o(<36AS/!͢}{7"ܝ[dJ;hEADp- Ԃc! +h&Aө{L^ +4(6RO"lKy$T뫈vKu(}K3Mi:}e5fa +S橻<KefeҔh״i.{98 +>[Hh_iQָ@8ԑf0J 85ZgJkʜ
Xܰ=<6A9Z!C3`vQ*MTf@r$0b֯ȊpB6¯r)S
#B}}s$jʶ4^CS +7p{wHf*fFDoDH'hR3˿Ɯ)1Ī.I7L5 x߿T^
M2>@A}Ze:~hK^öjFݎ!/5[=Ɖq_n[ΩTc:x Jk@sn +U-*w6·A"t++Vkp)'V~U+XH,ϸUV
0֪qRws,Z>qRw3aR"HBTJJo_ MK/^}mQL"$`ƚocOyBk*Xf~<|{q3HNՈ +UۇP&6F1;875`Y1+G nX&;c[թEzX>nQQI)Phi*}o=rb\z UβB] !$DwGQ +D%Y3y
vQx^ef\!k15M[ZR}d@zf(FK+>2(`BJB.dW"F1ȴ'h8l"8KqbܟV%T+BmzzEgrXrX,VX=h[yj)^,cz{nJa'sx&e?5hYn5a@hIR,=O <ъB~MLפtB
Y[xd{2
m7Ow.!j<Ф$%ȆwB)Sp36t&A&]}-װy"w2=ar7MOs,1v)oڡ&+SjŢ0AYq#ð57F8Ӭ2-j4[twe;4%6z-kR
ZsU-Mzǫ=\l,F묵dU gS .rMW{EAsfνP:JF}Ե}a5иMc:R
J9-kP$w5{oKZȬ-$B kdrx,^9`\)s +j<`snoPAB-Z[ؐJta%IsCU +;=iF!z J9I;OZU_bV|lv
7Y*<
u;8_
+6>`I92I +|LLB +
tSZH@րѱ:Z4f,:VP%n7WDRJX b&i
Lt\$=pC2ک\LYlYz_e\1*2ḅ@ +
NVP[yo5NUT +qɝbBGm5[ +[Hvem#'weGKerՎ< +f(-ed;~
wѾ%H +$FaвnX%Ua9x+q4^$"?Y"M<@bOn#c +QMIhs#(aF({@K3wz/?T-N$rS-'^c)9':]k2T3}w~ +E((7VC +W@nC!Bf]"1|PH"@5 b+ĩ+{G> G[54؞Hh)Չ+1Ol3ZKuQTv%oW/4'YTWR72PȰ5<HM!҂D+/NPUMmrS6,wūO=H],ң~L/7 +Nɼ<(OisZpV2EqYx$pZ
.VBNA15u4^!{cBjn";*ѡx_nB~+2h+䮌+ƥB8
] u=sCϓ|tQJJ LEZVf:!0VQLH96hǶ$sr-gTߴ%On P<,\Fڙ!9Y}X#ҝf )JiʂqM: +o%˶ԈSԂPVVf* +4ޯb
;=S5J2v[
9ʂU&UAB(2_
/ku*B&?rOwM:1fОI*]UyϲSg0iRJnk 辤wf$d@iB5Sԋܝ<1TWb*ԘvVTT{~oqllYynҚks4ˊ
.U
c ào
RiYXlsA`kn1}yꓺc;HD# -Y$Z5㱒&@(<Pi9&3س#YfŖ+B$]3ķ1yaC!YBRۅ<Jϒi&9%'1V}|m֕M&\Х(\fc +g8ֲ"k=&fW6i.i9r!3ឮn
YN|Tu4(I +.sXf8ac@,9w28
erj\`)!
6":}T;Tv"c A㾺"v ~|3cD3ӱœ~X1CFIxMy7 +D{ m0^mLx~2-?EIL9?DeJeLNfkHܷM8 +Rݻ:]{YW$:z~W.?{ٶx4̋+:`j@ Qsz
.p2Y$[rSMnĭ`hDjin6pRm1y$[Fy-:hy:#ڣXrBeQxH +HdWۮ]Ga %Vfg) +Pt=QdDlriiR-(X_-P%!QMFs`dN2__I~@" +K,Ml)"VQ wjؽu.oq?57bY^lI-G\jPpBZW3LYiZ
4%=e + +xOV +&,t;GH*bĈ܍;fVȜ/;GNՙ-MAJ7Τ~ik`b"6;js +eWrtN5dHMrDX
e&(e5f(YkcfجaBJ +n/ 7-t[3Zd:NI$'$&
FuPD,X +I\=6fii[9;؈L+?Q 6e6α*1{؟vϓQfvi`X5N +()-j5JW,A< +dD?yĖW@Q6G;8Z܀mW
PO sA
^#*)pF0w(q)|,#/%/DߎO?||~πqD*|o?}߯۷_~ϟگ_ʿt[6d}!7(xTjd?ι<ca@Bv+̪DHHyPFFvRbӓۗR6$=%/U'Ɣm}1mFsa&jz :Iߝ0Q%Rr +WyqcLgRT(2YyiKHOV|5;E-Oy"y x@C/BNl"ĝPRb(ȎFE]Q.#1щze$ +z1b7x!SdeP<@쓝Q|?Q<T +NaWHm"TxZ +5j<ٕ%$Ao>Lt4)*ً8ҏiDhHĒJ\ħҔic%A0#s Ӆ3y +C8\)*:^g-DLn :ţeyإt+ܢl8WYr0Xv̮rsKZffLp!!sb{bWpϧ0Ud;39D"J+HbR &RcvʻxXiR9v,c~YV8HRCh#9Y'l+/\@Ē"dK%Ǚ|+Qx9аHy&W:uM`̼bYC+xQ):VcD7cb݉(<I'+ZO;Bu.$5ӡx7<Y \RH%-m B%>ϸJ)Rg\$IB1_hIW|Tu3h .vED"9O +QcBN=|]/)tfab02j$[9IҼ%hZ
G[MOIJVk#ްrvOq«92U[d잘)$[(JT!tK=e: -rDfd$YMwǝAI(V*IL\M)&
qY,N1|֤B: +[ƬCB,VxV5Y?gi
@|QA;$5gszz dw!wFHG& +r-څ'`bU$kmw3!-|Db<JGȽ<a;5g+2n7hٻ;*~oKGRQ{^5x+ŷO[r_`Übȭ4>d!((k!V##:L/B +8|u!!nV{ؤ͑ +IyAKRiY/^C$<PǸ6a~è/k^S"գtrf +=*DIOʸU t3d,OHT3D( 1?JvAc˃,vZޠStGWi.d-6*Tc[K4bɊ&ΦS" tdEkݧzyX[ЦԜ.-EF !*7E-8b+l#Ɖ
HOMSF]FKGLI$UrLͰT\ǩl.
i}dvL<[aUG+t>]
:=:оF N_,dETGKHܒQ<l $=X1}n<3fL;=Q@X[md2(nuhCCK>:js*>Zуy(<mq/8RpgS'6VQ"ӈuzV1ŋNATB+aB+ۆLL%3dg6Zq9z=AŬm +rv_l*_x(\sBrl/;/MyAKw!HXw̡ +Xq
1QTY)酸z1nwNĹA^찪mZ_~/_O?~}߽jB?{ۿ^珿w|o>s^YPU*VF[ҋoȅKa}U5ږ(ڪyBN !kh-[:mv!29B&MzB<WL3C>GhnS[6MdI$)C~1(o[_{de($Zv-#e˴jV5dBԠhp!DD]wB +#P1:lklt><z
}? +8 }ɝ5-ՊvUFxw=Ό}1Z=ܞHt\E +^mPsDzt.:.H~;Cfr)A^!͗ H$ `w{[m1*HdS^lD2:$[!l\Ĵ7F~KFMy2^*uGd +!V&x((3mKUw|i]%av#{o}GE-.%<9+и|u4ߌT~76Xj˰?v)5{Jjt)i=xrs/Ӻ)KESUKcT{gtYz(1Y6@#`VͲz:ci#,1w|EJέ_#Aң^>E^gHiUzK^k+l +{lɖ|&`9\h`UX2϶50-dҝJ3}CsFi\Ϙ +_|.G;. CB 8z |o
g>GAusjK1F܍J)$LpFJEV(Zm%0 -.sg3aFÎ& +pq}X=]'%cDB
N2z6N:UcC%Kj ,,rm(l9+=xXfl~:}[sIrً R_W)"UB.cƪ9f?(߁Yb`I)39WiE{Q:v]uUVCb@(]=QZ3KVoNw9
|W]gL-J[gS@ؤt( KTЫkf`=0T[л]}ECiDF#>3Q@!%%=PIiOnAPuj#ե7DU9 +(<P5r8-qj%?Rn`&w6_ǝec|SN,5LgC1AJqI̍jӚbņ"hjmPM
Q;+3qE}vZV=Ä7r~*@ JInrDWYz/+O~Wpw|_iڬ, Dܝ2"g\5}:aٸOqӁFUGk¼*mflQGN٪c=H-w-( ) +TUjn1=ҕQy+ܔs +¯rvH_-=AB SAA6yO}/cN/kժϠ=@fSD/_ +
zKAvBAʭGE㔶:ȫ,}8N.ܽ!}TWӄN(dׁ -M0;3C2{bw*?YP&»Pg0DUhqH5,Y8DcM9N1AY4ĩ};gP-ho} +Ě,d=M0>d +L5K:]+5+D/RE=\C@]}{7Bh;~H$nAA]A,"BuGaFz;Mt +At-3A"im-uphVծx*u죲ǔu:%Ri@vbl;HjK,}0㲫Ӎty+ХâzAZ$f'dFT-d;'O(郄.^h\ICo6ps3l5@KXp!x+h?h鼁J 9[hi¨ѳ +s4)۴+(hzV\N~ +<LT8_0BFwN'"|57EmFK,̱bߑ8jd\cn_aPȤ%u { eRO6.糠֟oe^'LlR)ǿj^fRQn!'?_tցU7zVq7$Ρkrtcz>^/h>LL8)Luȭ%1&8Jhه՟}rK Q?in)KQqS63
K:k&Sgguyj *FbR;PpsDDPU3+Z +H-hB@݉\r["x\#!,VyH:T/w+X=W!2vwGXv_)TR?`+ɍ7>^[KX{ܲ[%HZ>jIaP聑|{LliBLΎiyӛRD(3sF +xL-dQQ +胱OkРP| +}o~aGk*EՃpTgmcvb/HSVT֤(hatޛ1 +vZӔغw kkhQKGm}xn<Đ-Ӣi]EeDbrkJ%A鑄z^QGPBf.CL![LD;]&|yGDt'
ԉf!8x3Ph%jQױ`<
#|6vcmgk?O~Vj}_?OO?oןo쥞ݥid70k~UQ +n'YRj(I +Lƚ=x4y4NOxWb];R}vWچy>\0J\"~u2W|%}*+.y~≯53jDh)PgB)+J8V"KIk lW+?4Wsnޜ?f
+Ԛo[O%zf^K <*=N~@9m31~/-ˈaoZcCN T"(&C3?e..HEܥw<$,TD<02Jt6>JD<8U^tEU +Zzr~:0g
ȥ~jܨ#m+𪪚{4ph2b6b),
> +eNHMj2;x`~k@_~~bxm >+p<=$.71{yh:@:ʃP;҈1DpPQ0Qt92LWwf.5) ^f0a +lݣ0 +>ωI9j\ڟ ['-ENIQTE
AKY +,! %H30i0&{S^څF]'==Nr墦+Kz=lqUBEy+v!?>{6mqЮb m_<Ƌ"7nbAlyZCz+b2aѦn-Xpp=3ʥE#%[Z56Գ +@1H#f +sê<p-2q5b1h+b;f}%
IѬi;@fjbE$30yfёi'F)q[%;k
@SUqC@pp +n7a$X:Qi
Yj 0HGs9$<<,2OP|V<4Rlu2o"HPhnF^L:
O&l,V +@hDr,1,rc;ӘF<`s +oX4~Xwٞ#aPQ#b\ +;y4/4Q6GD:s xK',uwK +XZ?N'_GO_|ssھ|v~_>ܲחG,MzK1~˴6ɫݛS}nO?~arҳyyї_/v?~f=Bp?^Ym{J_n|߮?<}ϯީ =W/Qd7Ǐ'lq>_˳OG?\]ܽ[7gny^>n^/yI˷˿wriDHk1 dmncDS~{5fPc?)ZWDWO4a`rOe0[׳ d:F˝ޏEC^dKxoಙ*CnN٨kpI[Ig6Q*tPc˼Ɍ`RԠ(%d#cס{L1ox]
E-G +'epuM~qinMh^+]T; +!J<0P
GABwQkh
_5QzFueA4VRy5,ipOXB&b-P
qѳ1eY~XnvtX9+.İN0A}]fxZi_pt6zmZ9%FhlRW'KL5atqiq)\eBnu2dkYX
5^$ $ze9lg<QS| +pu^skujփ`! `j-(s5PuǮ^*>;zh%zP}B(VA<èK-Ջ)Avkreke-EYNzpn|cyusvXjgM ;5cd{o,['rұcXh`i-{.ٗvFwLg{ɾb5T-c+ ŵ@na;=9IQ)j::tߞ)kP/Nug\Z1>TW5NmIZΚwp1gkUޘ~ +S#r[Gn^wՏ"9md% +fVuCY+6&J7Rɑ|VJ$XY2g(7#5ha9{F\02a-Ka<[qmwgBJs9o'ܦxx`Ø{g!t1fo9G$yLS;5> +Z\1$Kc +:{ƞ%R]l5J֑M1
ő]9Jy("<PְN)f:Ǫzs9
7`jh2e3T
,<!WFMxo"૮y[)̶r`g
6W2]$6/>I}tńVQ[(并bJs +w>V7E3kM%c vgq=-<a/`DREn=X*IY3
NePZk>)3G1u;\4\<_Kb!P&Hp95V Qs#$ju?:$j[2N"ZW +T-J*ٍ-W3uS@st;77]h6w`jVOFK0g,YW>)F`[k JYBG̰@KiRJc;|~Œ9>ӷudͭG92G0N">ٲTU4Hm H+$bEgwG֬FfNMWǢf08u+ӡ*JLڴ `<Y`iԵB(531(u ˶<խ^ؑ8l+O>>ScE@דTE@yͶ.;MnA%: +2|_Zkf -)dK?\]
rYgu1gYO9K(z[r^GC
@v3{_cQ^!@pc,Z2<Z9{b~W-Ys-·n`eP[TyK=t/J-?f5PCF<}z4l* +ԅvʛ9|[;3`MClK` +ʧ;N`T +=?aB\3t₳>fhV +2 +C~6܊] + R(^ok9YsƝ{]k[>Y3c~+lfRTY=G2-
|Ѡ|f05׀9J;ߓF :ߠU/yڪ!&4RF]X#VܖRVRnޟyS_w_Y +I,~T2AYŔV}|0k="*Ôb + +Q{=ۺE#DZR8A3UU4cR.I\RfjQ64^hNX +0?v)l62X3$F-WO0}gG3a'9,,^%V>zB$>OV߷tA\j68
45tX^kF0)ļUvLi3`K5Ozkfh~M<V 2Y@gwi2VnyGC }$, yg}bZ +;UAFvuwQ}ypXW@01GÆ(wu Si'_;.3Q'k +f_ƃ53e)!]!_|VO +`ۘA4.eA'K{S٪ +}'8'>|~w#}NC豣$cj<yKGxВ^p| Q%mnF3+ mRD]MԸ{k`5jt5T5|\( pښMxHUp538hX8&Tp5vjΪʐu* ++YAtR5v8ZZ%;Ģ%K\"%f|Ե{LB۪$V$xEhh+(BL
P +-^OU(W.J +tEY>qh P {\
#kg' +-IG}&Vm&mk~YLpOqG0Q4zIY(ioƅ*?uט▲`
)%`s_U~ߟڝNp$[
3D)!.JZKx=Hsk' w%N{`PO,C,,]`+c%LFMvV9e +Mr%,:ثOrz^7C4@gXU=MFx~<98^$/tmoO{[=
,3d|-7`ѕyw{Z
ނ`l4_ZW6SW}}D.LQ[5"[Mqe6IpZg^럸a2N(pL>a/6-n0 +R-Fwcv6-DŽ70?3tm|?M<]cNk6KB29H]B':3 +*a7H!>f3Ta"
2[ۦO +t^021V-9k~ +.oq\,wffHrKyLǢ~o#|IY|M_<=Lr?*褋E6e\ac'9T;M}Z +HWkoI%#qOv2eEOv#VVh$_?nu7/$-d[ܺ-MeI[[X0!&Ai@KGP_
gs4Fh"0MtO8Uֺ=oA}aZ"Ly +@I + Vv)tyJ*.(d\;rB3n%-Mh1_X~uBu +]\
5p05[+V"9 SZxGX\=rm+SzI ۔ZT\pWٖ g+LʹL2.E7BؘxƄvXFP#m3rFr+!h +A()hA+QW 6.~m4I;
/Ij ̃D%d!q:Q!F}fXm@`%&X(b +EbXWmDn.x*5* +WI j\lJvh+Pd
n/Ѷl/1]G6*6]=iE
n/YY~,x`˵$<yLϥ7iWfDA
pi5Ve]_uCC +|=\72=~%k~J`Ɋ$.4xIw +5kFT^cjݵH#7ՑMW*CrUMkJ+ƽ
K68pxFؠy=`=VWlVma ǧ-K\&^N]jRzQ^MzWGwOet5UKHڞm)Bj֔URrjZtA>Nw +l>lk7ŠlZ_`5/8{56v[T
=7Z~oXN*`*]ܭ{i'{9M'AT@6~|M"6Sm8X<G|6(vȝÏdM)\zɳ5y|@O4q&#ހ7౽<WDހ
$pM
x+:
oi7zx=ڷ.WhH^
'cȾRGhi>[wxhBxgA:ުam^织(ͅ4ݻ#ϕc/jy7ˊpWfut˷I>fu']E>dz""{9txɇ0q7lP63NvIwQT
o[g/X$qm>bbZlChhi>1pyE5!r=MG7|ɮ~ڼ4j3;|fJI>ɦio5=Նc\z&lz5[sBu\?u!BWax9M'Att:(h!ux$|j[v }^oYx|M?eΓ_mH~.{XrVdYcUSV*W6%d@@C4O%Ť=@PalnDv!99=`?Qܻzw6:-E_h.HxK88ӓF[{'z au ןoÔϚ.c_dYhq3VEن_Gnj28\iuPĒ9e,ћH5fi`xZIrG)43\FmtRa
gmuuiǠNE_$>G%t-Óm%
qcv`doi@9rǧ6?,)H/P"$+B;%lrKʁXgbәyENwFY0HNIwY^;zrVéc$Ls:%Tie8F%/ҶEi$dRfI vS~{8<>ƶIߍ: +E,E8|c=;x'cmh +oXvg4E@ $G?dpFKTmC S"q>b3eį-=?ib8=O#BG)8>o8&x6|gȘ ^_8cݦ%qu~pֽY<)=5ʕ_WN8l&X./6YdJFY0HNI7_X^;zOrVétdx8i UcZ0λaKmUl)ezR>mT;|
#J\<<`^llh !<pKw2h%@DZq&8ڦcfL05PC\+PN('.u89=`?Qܻzw6:-O#!G|؞.ç,')qʖOe6LEiRf4\%$VER7Y`N:}U[Ѝo.oMN:usWnxԭSNNMf`j(mx3hD+˧X Q\D0|WD]UX,qWg=FUQ~^D+>Q/˾=L)+x!ˍ,TDȓJiǏp,{xSZdsXVvΖ߫dNj"aD];xGH3Ռ5yx"r&$zvNJ)3,5ұRy}Ww^iG7:~/ʟWz(fO2Dа~ϱnY/,SmSNr`0iXQD#Z =Tu{yҩa
ALcfL05eQv4Nr!8^Ktx
u{&KJd3a{{>]1ߛP>R\
r\e +
sEC,f'vRX~VZJ~ShN(2͞AHC֜(];~%bMdǚVW藿rF
H}#nڪ(?PQ]DsSXz] +;h{8Djġr-Fdq*XNZP; +&cJOlJq(FԥoFJf4wpyPj*晉3'P2%V8:-;{\`O+wzy9H~ԈCywr`'|z97+1%&0xL֥Ћ% +|u쌽XbDD_9c%|J+qn+w^e.u0^ #ҷ;Z?Cf4wѽw)T +HWn:_p +4K([@ņ"u(҉Cq,Ei) +vqi.B@7Gbɛ^߂aiޟOq@Yu|ԫ=~}<L +hS{3iQU\(^)DQQ,2_G,~}
2E{9gT۫cɥ{mUUpspqlp0Kʹ|b41A\LrGTH`>9P
w`EBOx;`=Ky0ZEC1-uɖU[ +*zcaxoWRTCrSU(LQ +C=tp< `؟am +#C-ݲ:X[_ +pH_;W`P2|(iF5QT37b$NؑK(H +WNB
˨/'w +YwP7X[P;oE۹{4{5sLL?:TF4)">O}NI|*g(֗bv)VGuĭJ4 +PlÖm邡B`HEq0M{
`H\:1<B8(q0Q%#YF+Lr3%^t6VapX9+4Q(O҅CttNS)\ǃ!=xxF7MŋxN^>y4af(֗bv)o5}أ +dLC.:ҵ-L) +ĥc6-f 9"YF+Lr3%^t6="{sǶV|C(w}=CEWi_'ؤSva0H[ + +m^ЪfO +x
0mc<<:xw2C? + +"}u`DBN58*_pܪ p8b&\V/i*(Xq
BfJќ"=6`[Wh`Qd#AĬ|1ûE̵^ƙȱ0dq|#Vh -yHy|/p/k۵~mu{mWzD_d\;_y+>y}!_n"x4 +e+1DD҈"9UHKn +Zބ^,]{cFGɧ0 +R`M)l>إ2QZG~+Yq`9𬋁]-]b`{d:?聩1xx@A?RBpR`)g6θqڄ&fw& +)Ç}ɡdLHE|o0ې SK'3L:v{Dn5H^XdNѫ])\Qr*X!F6K5Xr>8G2G;]r!3Ya=ӶTbVHW4f8'u +.mȜ*]kx6-QޕrY0
xh$1!8Op_IQh$C]ps6095jyxحܨam(8eCQeOjܣh"-8a;ˌNx^~ +rs +|pFݑ38$ +)ÇH1fTIE9#&: OBD.p$4rrCAb_$(ESml7TiFNiѾH[ +7`WX?)04 +P`HP(3TOcK0WU~1jf}8xw 9LNa|6VM +Gdwr%
t:cd?tH>
OO\oEƮj[Z`eA.
`c$Qgp&c` +F)Jֶ Sk6<v#AHcw1bcNb_'6HdN,MਮdXƊC,GxbľHw`F^oۻRcvFb @̓%'Fvg,-)ft1&%eY ,vWW9uӞD|?^,R༺tjhWRWzW3V[^͇gO|wd+}.n'&۟m|<_[^?blxz?_-cq&/1N=9Ϧ_ovZ-c HHfoW)>NV{7S!ތ7@XB8偸ʀS4kdڿ8^K1x9zȒdv1*VRIL[aҧϳ4{ֻ[LGgv=wx1xCg.E&E>SgsP +!l^HƋӬج(B!~FUCR1Ɯx?KB[EZԳ~.9͚7Ȥ=\:δ=BlPx:Mo9rZNOVn;+%NY^'e*ДW]QꍡVYDo#'N5@}v1'^h3n uwn9. +(JNܰ/W7W(u<O'jy=Tik9|=R/=m^~],W[PFOyGƀp->Wj"߯VΉz2t[PJf ^"dUiI\'5[3SU|#kcUݛ>vaܥ콚۴muF@64U3HWO@8T5o`-zAZ"[lݖ_ȄV Z/?*aCGݫuKS|SJh5DO- 72L0j`iqJkN-e||~hEr]YŪ +HHA{ǭ,D7WepRW
Dy:ЌN;lpT0jhYY&6hxI7pG .6QJY)VyCq'3 *o( +&9"5'%x'!0[@
+}NjAod
v9J9l6T.X/w: ߂܄2g7܈%x#r.E Dg$ +FEuHA%8.bhL8ᇐ1` 84$A4/^!nDܠ5O>'111rX@ q"2I5ƴtȸ$߄*)mFvG4#0HXN(~c1@Y2R?S)4n4`iC^_LSoZ)%eL^R<sT+dTK,MG<=()|" @Lþ?"jg9!"Ƙ"KU]xTMshR75\Oळ&I: Qb<+)c8mԞO;\㐰 +!%f0zTPd!\@NH&]3Ѻv[ќUnȷ0i6S]|Q'HSt<gU +HWkOKJ +6$DFZ{زM=U=~lV+:u:ϫׅWE(Ɗv3҈":*6"JaV)eJ$ l2кT*hTiB2) y6eVN[HIF(lsJ(lCT<_]n5?,p#6Szet&/T54W;
^(
YJ邧2b[FelX}2et-_d`{8#$-B[> .PvQ% T+[NtLJ7&CWŔpB_Qy҂Nq{GK8|f갰eP*7 U֔))j~X.ƴLY>y +NU2JIe6j
\9Jb7Jyˁp +`C3q&aݤwDN1E 0`B3F7p\WR}Β1" HZ)abUA.'do5$ii +-[Br2G.880^
y$e1< +Ad<-F +,P`Hց̎nf&KqY +CQΑ nY=$^*ϵ~`T +۱$Kc&+TVeݸ$@!]dTdDǍNJp
=Z*#DŵmlAtp,,J:~U9E_QBJ4\cp?h +ژ-j^[9 +"Iĕ$Mm#% \<ԆdZhCS$kY@Ğ5xDw2ABL9($X":M]ɤfQ\+2"s +:~ǭ F mx@Ң·q5JˀG~EDpC˹@阣<dь>zP]4<= 4ה?fWaT:X)Pv$nD+HI=ЬQ$Hp'{>pQ)L%Սރh2:JHJN*"
a@O+7=)H3C**-У](8
gL_Zu|~o:۱e֝|#bpiuU/!-{w7k1\ +t҂ +igoa0\ԣzr>' +yo&[n +r8C]gBj8#KxKN9yHMQ@*OG=~_;mdIx_fe`2?2 +T!0`eɍng/L:bojH7Y̧e$/2)y'EyM^rR-RБߑ|f1Xyf7B]#'X3~7B$NC%ÔXJ{y:> oV4{;$l姖>ZٱѐΛlD^F
"gyXܹl9nqH)LbzLjDFln{gyfЈ7F<0H3|<ۓB['D({dh"k|[A@K'7jfbK67%o.)E?Y{V,{e)Lt`(XpW#EFbDY<a=[_Qd: IzaBx|nl_1-o]8{<>c3g<ڪ/=emzD ++Taj=Qw#pِNz +2(q`Mi6+ӊy +i +^m{vOJG|6`CRH0 +aK㬖FU\\ݰZ9rT^IR RR 5U +ZށTbO,QWyC,pU\8DkϔډPo,@!S:AŘ;ȂJ+7gHv:9( @`BWi-m`b +Ѐ +5 DOu:0Z-s5V\*9[ajOKn0IHeD:z}洚8'N(Z/ +QU.qx)ѵƆj8M8cMT1(%^K>wX pDγn _FHqV1u +S*caM!XCn2 +*LB*l +h +[u$@R"$OQ(9%9`rYl,hADc<ca ++PYQ + +eBoԩl +^%7qŵ277_wIq50cֺemݵᡢ>u)6mO¿jn䓠0i7'|МѭÅ xSL.AeL!u9,&bDO-!+,NOv9ԧGۇ'~$Gd627ɳk.7:H5+?,T(Rfߒ=pG.ˊx4цH"qm0UւHqrVDKi$~IcHdI3Z0 +Jp=bϫ,S%2䪂{a-+/ҿK].ؙ5)C$gn4@)+v$<G!![E<sjw
?0lh\FY.4 +n=[@KTe/hl24+}HV)@+(ex4RC^41&B֯hyr +`*IRSU1@
.Td vx4\8,G-UEAZ:t&c9{fimK5bnݒ[k4
ůS
`gEhF}&qEѠ@ۻSȅBl
3NZ=In +nouХGXܱQ1*wP$Iv!
aS
;e0\Q^69`h\2pYպV
/HZYF~T LU +(_yP|l$B4+GQIMa"=orr
_('T'tf6(?i4pVOIM~Jj\Q}[zPZN&m'B]fxCRxytn&ţyCMuuWE*ʷpYS.@PŇdـ_jzfDqk=fEP X/g?GO|O} +h8Y]~{Zfs.EтQ,A!닫Fw#O,1RL
&2J% +@6PD~Õ^Tۙ"up{t)-P 5ReX}LX*2#}G4@^GfG}
at)"_z:N{ZVO({_I%O4ADN喫%;J+(,)\&o2
ޤ Yǁ-=G:}q7R+*e^Iz^1iXr]dBχ,lTuVFRAՆ^sP0;&}=0k_}&y#hpgқ4&V=FvֆU<]7cEat:lCʣt 6p]$h5eؤ0[U`IQ +T'G$=Q&ԎGע1=eU>;OR:.fюpy +]`X=Ӈ1'svc +{;ZMCj=8䡦rp>WYYWNW $Ōbin: ]TҒE"|r50)'w\GkuHQ)--AӼ(ȩ%A>=
C_?3^j}(D?,Ħ +ټjq1'g=yE٪ L̙p_V"CH9Y=pt~b :S!Q+o^8V?[s] q_LEsw`h{0MD|\lܬ}[Qtu
oOk9b~#M.7q{po]l7)I;aC0~xhZ-'7+6ϵ#cwG6,!12Z +s?J\ 4Wyta7jZ=5Yoj֠מda6^<*`q(*v(#Y^k
Y((MN
<[sh#͔=(LyV .Ɖ!/=|^~۳H[6]fOodJG. SaLzdz +D0kJҲ +yGT@%HHjgv*\m?FӤ QwνM"X~pQT㓭Zq/I_LbZB +Ռ`ĄA|R(ܜ,tދhWSc;JSҍGGI.5O1U}#=:P +8l+hZotS,p> ta;tZBf:ipҁ4\ai +lXss"Z}:fP|3[];c)IT
2w b{0铉{$x*9Yk`O3'3 K+Obq14N$Z]o~w
AqEy~~LVg"ZIf*LMjʀC +nl" +!`-V/ RlU{/Gű^-}&^FTW="1TK+=a77DqZ?MAV4" +2ٷF<m&s;Tlq5H@CQsA?VNxhYgΔ%UUG>|yc#4g"|Oa >>cK;ON+<?ZxVS^X:(QP%Ah>biSEgƧIѬ@wYhnkFQR]L-P9E'ϕOC^
$uFƤ¡y:Qՠ4gѷBhA pԢ2eC7 Ov:R+ +34g/\%}=$͐+i*iWf\$.LNVJ)g
\DI5L錝 9IEdf=ϔBy@&ѲE5mf-kLJҰb=ICSs@!P1.@q4KC=$ҫ%J>2|܀k{dRbJt*a0ܕ+'4N}
:a4]o#~2<xNߏ3ֶmqb*UrOM[ix}q~|BaY +[] +e@;g] +g6:_
!@=̑"hqn0G쭴N)ϧet6`4f\Zz{M@+ +WRc30hҿNnM]A͵J5^?>:ߙ<}>
Vmɓ)5YP߬W疢}~L@VɬڢmY|ճ8SkO2Gz!55Ő:UP/d"d9,l,ʏvUdTo0&8T̒$n
@PoCNt^l +;,V#6l^!9-q$01ަLdݑAVJ\ヅmn^{jZI{Amrks}~6?b#a$%tZj7gXww<|vwĕ#ԃL9d} +^L'g `&8vjJX/DٱF^Z+X~?lNj, 5OZtٿMoDcs~J&0D+WyE쫡A(GǍf^mQ*Y|چ6}z _ʚq$M9@K{љrm&̶t>SP9B.sl8-tƊғKcVG(\
3#ک8R$pGNYkiXtcP 8W`o߷}]YRCyw')&.E>6脣iB +:c/5e-L^nY*_rgzV@yX{؎*_mwgU7g!6][olIQ9tma=߫Ese|/<a/G~ +,'X;rz6/
'M_WJx.T#*6p$G=Oak.|q}J?_tq@d
L%?+",|ĠIO?[f$_qQtp
<q
#ϟJ2]PE5G8;
d.,e5تH}2N(*7tb2Ur'9N&w9(Q=}=R}@˩?]D,@6qӤ>˟PK,q!wjL))~8i)c5z7ux/Krź
+uj[z_uhC*s^ +2)ϙZƺ۾mmO x +v#i~@5եܢ@}"])mVbDS'9'8IbY)6fםQ{ɇz +;uAHݜKlf3vRT/̩;,'4P.3=ygǤofmT#@Ă)|;W=>'{:r)wqWj2HS{$., ^VdH-~I7;LŇ'RNLZy53n%d[LfS9?8-YU)4^BqV( fox
5B>,=ݨĶLҌӰW +a@k㫉.۔axkf]XQvx8/ӵu. +"r@C P)Mw[oEl`w+:prb@B>Ry"bDžJp*f`.O*N`84xJ/.$bio9|zu:?{4) 1Oxĸ\mˢİ~t>Ģ{ǾEi_5tr
L3CeeZe?K9Gޅn73?WφZS]+$ .ٳ-DR쌟zq̠ ;=FM=w0;l_|yy?G!ZC9gMeOjҎy-]!v]@пgk,u:G7
m0+mΫB5]`49$T5JBΕC,hV;wNu_ᚤw1d4]$pHGL1s̽5_)n0BZ㭄 +Rߘ#zDTH'*9HD?Ȣ@f@:nt"IjbX&P@3 Y$H16Fҗ3AvҜZ^%뼪&ꪎ\0ZL2
-6t!!6! +-E"bUD] x&n{~һ%Hkƹ G~Z+koAF ۜyZej<۹G{
'673z:ս*z3>ݟeL[\,w) +E2]m\;?y⼠)
/b +Ƴ(~?/-.R)\Nm}0$>ڷ/C#ᘎRg?cU0oe>ԉ#F* ho*\ZN]B1Pl`
DҘK,3z- #& +4|͈YC"]1PT$,lRjH +wf!uV4p@1lF%M9@7j_
rƤ)Ij2|`0A)]aʁxN)eS#Xylr8==Su~uQls/§@4s_o:,u`4t+犠\tUC:>Cr.ƺFgI;Uo_O_*1ٶV\j[. +8{ J̑}ٲq."A Zz6n60"zki-ISzcq:}L +1ڧ4ޱO6҈nt[yeHw8~<ӻЯP)QINĘB]( +Ĩdw(>*('>mo3Ā('6ܗ-5|Cȯ85㚯 +Mjɸ}ZuV̵oFm[3Ǝ@V +HWz8}?bVC;Hٳd#02$$HBe?8w?]\%L)njn^υ?uMoUf>G2C-_z)gړ^~3}s +,'_izm<je$9-jjCe/::U+i:VӋy]ѵ=,Z*a@@,יx"NBT2gJV6.(0Eg2K29e/.]b +a$CtrMsmN!OB1 KTՐ.$W#d|G#m ++N$:Fd.Xp ̆*c'kLIDD&g&|P_POIvCy?h㿦
҃$Vx*P*c1$cD30R3F 1ַ
9/hihT_hj,F< +Z)v;H)(j`G_q@zG,+ɱP;Z[㏡sT.m>MXN=5)dˣYPݷ'}څe
kzbj^lA?Cv[0=ź^98y"yކ.o]OnC#b4ÚhcWj 4M%Sv2?>Cvm +$[ODW]*wY[U( Z}_lŷX(?;K|P+`,;?#tinO +zbllw/$/QDӥ"NFfBkT6YL
yb~)<3h&z)JξiV-LQ .ooV؈kc-d~s~{o32*D<h+2̣,FO 6/#\[_pN +҄x;'#zj2zcVDL +J8|"q.gC.\L)L[3dNl==J gitEYO\k7{[,ܣRQY-Td`QupWy.\kNcK21{bBpX˹gX6y6 &shIځx}A:4`]݈H-̠ bNF8ԡ5|Pa#P5z\JG
pbȴ|B"1<IfgL/-'z"HZo@St-Vrx +g"P'\0ZtZPN0`>6Xll +x+pȥw7{3wKNs1>q>r\:26-6o"mQrA(9oi%ΔڧG@i)Df@ .n*s*]D@Pí+y-ѷX7}$ޏˢ(=Ӯz-?`ϋKr~e@
tϸ$ N8I?I}ITi+)PKf3r5jخNڞ}1+N!̥b5?ch6hL? +!_JRV5ޓi]/Q `Z]<&?5tTP]:x{WA0:Gb7?ic;=//[in8;
jiZUn)F]y)|s:qqaNgօb7$
s۩;FqrN$6]Ӽ$}#!.2״N#rjNo|΅7=SU@X+kYAP_F-!XZ<C^WRI۾u)C +;IE*KR5OE-yc;YG}')wP
'lWڅZo}(_VHmI)$*}VPNJ`¼bxL`[`rC +jN_aph5@H2ƷEEZS_/zݩT-9ƹ`Sn341.96bf; +5S;1Uf<S;NK'A*(#fVjN +ZZ*Zwћ+ݽ@j)bqdRS ]2AYiӫ6|c0˟AٕlPבefMm2jw#+|
EQ"D%j)`j.Ŋ\z=]Ruc#ah]4D
C`4h
gL'9 ^>~=ݲč5-E
V>9,U\(_) H{~Լ')DLXtO%Ȯ3- +q-Ͱ^`u<1σE<.߅0D̔yve*lk*u0ŝŬQɬ`<0+` +: +ɜcAQ!K5"N)DE^[{D^Ӷ52#/XSQ6t$ɒsWv+_:o&7phJ2$oews 4S+n߂$1H %)JoFa5|Cᒜ;cʈ9-ye90$g9q;(l,
Cs'%rCp{ +KڛƪG1)n_<=8s.N8ĮW~B~{8D2wBM + +9 i-}8Knt8:ekZ\4TÝ^ĐShp89E"rO"+ipz<Eˏo,0 ϕtԞ\iy8Kumb8 ũi lRo
pn;=nj_3
O8/Wb>l5{rX!`1^XlT&A-:_
jw ً{>'# +I"Fɒ:^{rQ xEMKC3KӬLӮ_V*f +?{Scv6UNػREh'F~tmLՈ%Kaª^JqEpK5"˫k[WņK`/_5>o48 j +Iuw]5fq*=*c)ؼ +9rH}{wj3p/NI"d}4.-Fg{E[B_S]M1\frp6 +Ppui<M:TcpWc0FMhaPc8BQ9 + +A5BnUe=*5)P4q=.Bv*(=^A$o<+ !Jֺ(`Q|vxe`=ݳ+Zy9ZI }7HWXT<gA*Tˠc(_) + +cpxkll q_E
V/ c=d +H-J锤K~q|g&lmOMqO0OX3dmYf9ce2 +OYj oD,0+ˣ:A+[- +\UI><A_2Um\Bwʬ4h),Yce>bY,x/켒-;e }OWl` +p
DjF`gWW_+XW1#U85ƲԈ/2ڜxnGvS˰KA_iop{ +]Մ8ߖPhܳ+& +Q+ ZCLd +J&Xm2s9[Wg3_JeYO;A$@0d$(A$D`>а7g?:MuuW_Uk2&l}͆(G!ׯha :ӌbA"2z%tf<BhنOTrxhy^IgmᲪ){ul4c(6}v|N,9@oKig/URb5cXMaz=f֥?#Am̑1~s̩6lkp捥9h=zs6ؽ&?HT z&8A1ơ'6܃~Sֹg;m2?bD8+@wvpI W{EI;p͇'i!N=4 +U +Y$HQ#r)J[ӜQmը]L{X'$ɭ** +OD̲{M4*t/fG_T**3x0EԼX.npAO̘W!+57 +%r]_yϫHJqn1'+AzҎ*<C +nI4sSeʮij.dP<uFQ˶&Ak۫Í%`Ğ +8L[ȁԑVi$+dcj6~;)b:- ɟ ++ܽM". 4IWVz> + +ÉP)!d']
ALP&`2AP6kK[c͛]6£StCfsl1;48U;2Btg] -'FH坉~F(${8@E1A- p/vPi#<ns6;җ&/XDqA8$I<RB>;*y9AA%ǔzTtD;a`SFsb讏Or"-v|wpY\ARA0Kі8c%AG + +N.5$Bs6EԳ:"ao^h
+)vX 5ƹ%_$]~&[z$͞UveAR3T%ZK~pSnC/'8bډh6Fp#ʬ^kz Ѹkr"Ј*ڮCH+XkHX"u#0~'#(&?|S`~mptdB?§-!Q\=AvGFcw6ajk66֊^~$j狰6ߐqOt\ݩp.tRc}<,c CqHG d{,dD齟;檷*.vJS`Q.qTBBpG#yc=8*1-3w$%9wfH ]e!:Jqeb0
C|T '0ɕ 4)ZĔo '$OY=r%l౾!OG
U"p4;]oVz* D&F +KAűԗu^Ko9bB%i/`FC!u7(Wa7BJ +Qū#uqH$+6[/brtZa5[EəfTf:գ
cI&;{7btҍ¢xH--#!B.eq83o2NDSxwzG唅tҘ}ꇜpS}0*%iIޅףV!qY#-qU^ʆ@84@L,,De}%#${.~d\Kj\}h#3)#t8o#&˟ /͏s +PqxJ*>n +J(-ƒ<<k}@xz.ڠy1зZJM0ABӹG_W8!S/
Z|AHRJ8Le=t#B%-NJ}ȳjz.t8"TqU:q8OT:c*\"B>okH Mg-9v%`~,bj$sPyےЕ<솛j͛^M̚<e_@2KF3]<y=v8]J
lU6ݜ:/xAFE8A8%Qͮl&9EI +TQ<VΕpىkҋFXK#8!jr;*/ӕ`YZ/\`O:=}S[35VGeT!g0[jIPVmc#o>):ȧgnJwLblk&s|;-9p(؇q_07C<tfM34GF"T%DIU@q.ps L&M3B*#5"3ae)$!IGtUR:)nho( "i1|@RqX1w}crۈa(za.PBHJZtMEѤ2,IvKD}~~UŞ
jj*5kv#.ўNt6|]U~˵#}0lw~ގڊ_$]*oAڧ?X G:5(Q5ST[)Y1WidgOF&x$6ìR+Q +JQ`6yuȹ5</ H*i+u +b_[H1}r(w.ႈ\HWjȷLJwry܍zqicc ""Y6Ĉ2˜bTJMRu[pC@K 9!K=l^WԬT{͕8)!9<
ZJ[}}z3^WĨh
5:!ֈn0[Q烺,(|6ו#?9
{<\lv#}ߗsaK,@y_jž9u8!㝽 0 +HUnG~YɖK_ +c$$ oY9Fk9=@,!%H{Ƽg3ɽKM[K {\jեbΗߗŏ'gח7Czһ߾x_.qzN^Ha<9N?S]ZJ:J$tW/ϒTMx8QjOu<5\F&8)[˥&[j7lc-Wk.ɢa4֑?*_u<k8 +֒b]г"pU!Eޓ:~Tb=yj2/w)lc[{ +yCJ&xTX(Ae\Y;vBI+-
f1|A|/1
(`e}%cZUg>;Rlp%Q)$렆;:k &X YF92l7t' +@X[u<rIT ahq,0=jRQޘB/Տ
>24 +7]o^^.JVސ$8 CYA=3hӊ` +j
R9)3!\$-wC%h0ͳĞR +0000000016 00000 n
+0000000187 00000 n
+0000057205 00000 n
+0000000006 00000 f
+0000175537 00000 n
+0000000008 00000 f
+0000057256 00000 n
+0000000009 00000 f
+0000000010 00000 f
+0000000011 00000 f
+0000000012 00000 f
+0000000013 00000 f
+0000000014 00000 f
+0000000015 00000 f
+0000000018 00000 f
+0000175981 00000 n
+0000176012 00000 n
+0000000019 00000 f
+0000000020 00000 f
+0000000021 00000 f
+0000000022 00000 f
+0000000023 00000 f
+0000000024 00000 f
+0000000025 00000 f
+0000000026 00000 f
+0000000027 00000 f
+0000000029 00000 f
+0000175607 00000 n
+0000000030 00000 f
+0000000031 00000 f
+0000000032 00000 f
+0000000033 00000 f
+0000000034 00000 f
+0000000035 00000 f
+0000000036 00000 f
+0000000037 00000 f
+0000000040 00000 f
+0000175865 00000 n
+0000175896 00000 n
+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
+0000000000 00000 f
+0000175678 00000 n
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000175749 00000 n
+0000175780 00000 n
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000000000 00000 f
+0000060505 00000 n
+0000176097 00000 n
+0000057630 00000 n
+0000061161 00000 n
+0000060805 00000 n
+0000060983 00000 n
+0000060692 00000 n
+0000059086 00000 n
+0000059944 00000 n
+0000059992 00000 n
+0000060576 00000 n
+0000060607 00000 n
+0000061235 00000 n
+0000061543 00000 n
+0000062721 00000 n
+0000082146 00000 n
+0000107842 00000 n
+0000132259 00000 n
+0000137352 00000 n
+0000142455 00000 n
+0000159547 00000 n
+0000174275 00000 n
+0000176122 00000 n
+trailer
<</Size 95/Root 1 0 R/Info 94 0 R/ID[<A62AE6DC91EF49CD9CCFC2B959900A7D><33F4B4E6B4824F3C934AA9C126304E54>]>>
startxref
176316
%%EOF
\ No newline at end of file diff --git a/utils/logo.c b/utils/logo.c index 9e3078f..ef6ba95 100644 --- a/utils/logo.c +++ b/utils/logo.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2001-2006 Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright © 2001-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -21,13 +21,13 @@ #include "utils.h" #include "resources.h" -#include "visual.h" #include "minixpm.h" #include <stdio.h> #include "images/logo-50.xpm" #include "images/logo-180.xpm" +#include "images/logo-360.xpm" /* Returns a pixmap of the xscreensaver logo. */ @@ -37,39 +37,41 @@ xscreensaver_logo (Screen *screen, Visual *visual, unsigned long background_color, unsigned long **pixels_ret, int *npixels_ret, Pixmap *mask_ret, - Bool big_p) + int size) { Display *dpy = DisplayOfScreen (screen); - int depth = visual_depth (screen, visual); - int iw, ih; + int x, y; + unsigned int w, h, bw; + Window root; XImage *image; Pixmap p = 0; unsigned char *mask = 0; + unsigned int depth; + XGCValues gcv; + GC gc; + + XGetGeometry (dpy, drawable, &root, &x, &y, &w, &h, &bw, &depth); image = minixpm_to_ximage (dpy, visual, cmap, depth, background_color, - (big_p ? logo_180_xpm : logo_50_xpm), - &iw, &ih, pixels_ret, npixels_ret, + (size == 0 ? logo_50_xpm : + size == 1 ? logo_180_xpm : logo_360_xpm), + &w, &h, pixels_ret, npixels_ret, (mask_ret ? &mask : 0)); + if (! image) return 0; - if (image) - { - XGCValues gcv; - GC gc; - p = XCreatePixmap (dpy, drawable, iw, ih, depth); - gc = XCreateGC (dpy, p, 0, &gcv); - XPutImage (dpy, p, gc, image, 0, 0, 0, 0, iw, ih); - free (image->data); - image->data = 0; - XDestroyImage (image); - XFreeGC (dpy, gc); + p = XCreatePixmap (dpy, drawable, w, h, depth); + gc = XCreateGC (dpy, p, 0, &gcv); + XPutImage (dpy, p, gc, image, 0, 0, 0, 0, w, h); + XDestroyImage (image); + XFreeGC (dpy, gc); - if (mask_ret && mask) - { - *mask_ret = (Pixmap) - XCreatePixmapFromBitmapData (dpy, drawable, (char *) mask, - iw, ih, 1L, 0L, 1); - free (mask); - } + if (mask_ret && mask) + { + *mask_ret = (Pixmap) + XCreatePixmapFromBitmapData (dpy, drawable, (char *) mask, + w, h, 1, 0, 1); + free (mask); } + return p; } diff --git a/utils/minixpm.c b/utils/minixpm.c index 997e628..55f25be 100644 --- a/utils/minixpm.c +++ b/utils/minixpm.c @@ -60,7 +60,7 @@ XImage * minixpm_to_ximage (Display *dpy, Visual *visual, Colormap colormap, int depth, unsigned long transparent_color, const char * const * data, - int *width_ret, int *height_ret, + unsigned int *width_ret, unsigned int *height_ret, unsigned long **pixels_ret, int *npixels_ret, unsigned char **mask_ret) { diff --git a/utils/minixpm.h b/utils/minixpm.h index f027894..8777f36 100644 --- a/utils/minixpm.h +++ b/utils/minixpm.h @@ -20,7 +20,8 @@ extern XImage * minixpm_to_ximage (Display *, Visual *, Colormap, int depth, unsigned long transparent_color, const char * const * data, - int *width_ret, int *height_ret, + unsigned int *width_ret, + unsigned int *height_ret, unsigned long **pixels_ret, int *npixels_ret, unsigned char **mask_ret); diff --git a/utils/queue.h b/utils/queue.h new file mode 100644 index 0000000..94bbf23 --- /dev/null +++ b/utils/queue.h @@ -0,0 +1,638 @@ +/* $NetBSD: queue.h,v 1.68 2014/11/19 08:10:01 uebayasi Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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. Neither the name of the University 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 REGENTS 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 REGENTS 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. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _QUEUE_H_ +#define _QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * A singly-linked list is headed by a single forward pointer. The + * elements are singly linked for minimum space and pointer manipulation + * overhead at the expense of O(n) removal for arbitrary elements. New + * elements can be added to the list after an existing element or at the + * head of the list. Elements being removed from the head of the list + * should use the explicit macro for this purpose for optimum + * efficiency. A singly-linked list may only be traversed in the forward + * direction. Singly-linked lists are ideal for applications with large + * datasets and few or no removals or for implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List access methods. + */ +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_END(head) NULL +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = (head)->slh_first; \ + (var) != SLIST_END(head); \ + (var) = (var)->field.sle_next) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) != SLIST_END(head) && \ + ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) do { \ + (head)->slh_first = SLIST_END(head); \ +} while (/*CONSTCOND*/0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define SLIST_REMOVE_AFTER(slistelm, field) do { \ + (slistelm)->field.sle_next = \ + SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \ +} while (/*CONSTCOND*/0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (/*CONSTCOND*/0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while(curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (/*CONSTCOND*/0) + + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List access methods. + */ +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_END(head) NULL +#define LIST_EMPTY(head) ((head)->lh_first == LIST_END(head)) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = ((head)->lh_first); \ + (var) != LIST_END(head); \ + (var) = ((var)->field.le_next)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) != LIST_END(head) && \ + ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_MOVE(head1, head2) do { \ + LIST_INIT((head2)); \ + if (!LIST_EMPTY((head1))) { \ + (head2)->lh_first = (head1)->lh_first; \ + LIST_INIT((head1)); \ + } \ +} while (/*CONSTCOND*/0) + +/* + * List functions. + */ +#if defined(QUEUEDEBUG) +#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ + if ((head)->lh_first && \ + (head)->lh_first->field.le_prev != &(head)->lh_first) \ + QUEUEDEBUG_ABORT("LIST_INSERT_HEAD %p %s:%d", (head), \ + __FILE__, __LINE__); +#define QUEUEDEBUG_LIST_OP(elm, field) \ + if ((elm)->field.le_next && \ + (elm)->field.le_next->field.le_prev != \ + &(elm)->field.le_next) \ + QUEUEDEBUG_ABORT("LIST_* forw %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + if (*(elm)->field.le_prev != (elm)) \ + QUEUEDEBUG_ABORT("LIST_* back %p %s:%d", (elm), \ + __FILE__, __LINE__); +#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ + (elm)->field.le_next = (void *)1L; \ + (elm)->field.le_prev = (void *)1L; +#else +#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) +#define QUEUEDEBUG_LIST_OP(elm, field) +#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) +#endif + +#define LIST_INIT(head) do { \ + (head)->lh_first = LIST_END(head); \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + if (((elm)->field.le_next = (listelm)->field.le_next) != \ + LIST_END(head)) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.le_next = (head)->lh_first) != LIST_END(head))\ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (/*CONSTCOND*/0) + +#define LIST_REMOVE(elm, field) do { \ + QUEUEDEBUG_LIST_OP((elm), field) \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ +} while (/*CONSTCOND*/0) + +#define LIST_REPLACE(elm, elm2, field) do { \ + if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \ + (elm2)->field.le_next->field.le_prev = \ + &(elm2)->field.le_next; \ + (elm2)->field.le_prev = (elm)->field.le_prev; \ + *(elm2)->field.le_prev = (elm2); \ + QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ +} while (/*CONSTCOND*/0) + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_END(head) NULL +#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head)) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->sqh_first); \ + (var) != SIMPLEQ_END(head); \ + (var) = ((var)->field.sqe_next)) + +#define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \ + for ((var) = ((head)->sqh_first); \ + (var) != SIMPLEQ_END(head) && \ + ((next = ((var)->field.sqe_next)), 1); \ + (var) = (next)) + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \ + if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \ + == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_REMOVE(head, elm, type, field) do { \ + if ((head)->sqh_first == (elm)) { \ + SIMPLEQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->sqh_first; \ + while (curelm->field.sqe_next != (elm)) \ + curelm = curelm->field.sqe_next; \ + if ((curelm->field.sqe_next = \ + curelm->field.sqe_next->field.sqe_next) == NULL) \ + (head)->sqh_last = &(curelm)->field.sqe_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_CONCAT(head1, head2) do { \ + if (!SIMPLEQ_EMPTY((head2))) { \ + *(head1)->sqh_last = (head2)->sqh_first; \ + (head1)->sqh_last = (head2)->sqh_last; \ + SIMPLEQ_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_LAST(head, type, field) \ + (SIMPLEQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->sqh_last) - offsetof(struct type, field)))) + +/* + * Tail queue definitions. + */ +#define _TAILQ_HEAD(name, type, qual) \ +struct name { \ + qual type *tqh_first; /* first element */ \ + qual type *qual *tqh_last; /* addr of last next element */ \ +} +#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) + +#define TAILQ_HEAD_INITIALIZER(head) \ + { TAILQ_END(head), &(head).tqh_first } + +#define _TAILQ_ENTRY(type, qual) \ +struct { \ + qual type *tqe_next; /* next element */ \ + qual type *qual *tqe_prev; /* address of previous next element */\ +} +#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) + +/* + * Tail queue access methods. + */ +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_END(head) (NULL) +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) +#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head)) + + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var) != TAILQ_END(head); \ + (var) = ((var)->field.tqe_next)) + +#define TAILQ_FOREACH_SAFE(var, head, field, next) \ + for ((var) = ((head)->tqh_first); \ + (var) != TAILQ_END(head) && \ + ((next) = TAILQ_NEXT(var, field), 1); (var) = (next)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\ + (var) != TAILQ_END(head); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) != TAILQ_END(head) && \ + ((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev)) + +/* + * Tail queue functions. + */ +#if defined(QUEUEDEBUG) +#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ + if ((head)->tqh_first && \ + (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ + QUEUEDEBUG_ABORT("TAILQ_INSERT_HEAD %p %s:%d", (head), \ + __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ + if (*(head)->tqh_last != NULL) \ + QUEUEDEBUG_ABORT("TAILQ_INSERT_TAIL %p %s:%d", (head), \ + __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_OP(elm, field) \ + if ((elm)->field.tqe_next && \ + (elm)->field.tqe_next->field.tqe_prev != \ + &(elm)->field.tqe_next) \ + QUEUEDEBUG_ABORT("TAILQ_* forw %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + if (*(elm)->field.tqe_prev != (elm)) \ + QUEUEDEBUG_ABORT("TAILQ_* back %p %s:%d", (elm), \ + __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \ + if ((elm)->field.tqe_next == NULL && \ + (head)->tqh_last != &(elm)->field.tqe_next) \ + QUEUEDEBUG_ABORT("TAILQ_PREREMOVE head %p elm %p %s:%d",\ + (head), (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ + (elm)->field.tqe_next = (void *)1L; \ + (elm)->field.tqe_prev = (void *)1L; +#else +#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) +#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) +#define QUEUEDEBUG_TAILQ_OP(elm, field) +#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) +#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) +#endif + +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = TAILQ_END(head); \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ + (elm)->field.tqe_next = TAILQ_END(head); \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QUEUEDEBUG_TAILQ_OP((listelm), field) \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \ + TAILQ_END(head)) \ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QUEUEDEBUG_TAILQ_OP((listelm), field) \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \ + QUEUEDEBUG_TAILQ_OP((elm), field) \ + if (((elm)->field.tqe_next) != TAILQ_END(head)) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ +} while (/*CONSTCOND*/0) + +#define TAILQ_REPLACE(head, elm, elm2, field) do { \ + if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \ + TAILQ_END(head)) \ + (elm2)->field.tqe_next->field.tqe_prev = \ + &(elm2)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm2)->field.tqe_next; \ + (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \ + *(elm2)->field.tqe_prev = (elm2); \ + QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ +} while (/*CONSTCOND*/0) + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue access methods. + */ +#define STAILQ_FIRST(head) ((head)->stqh_first) +#define STAILQ_END(head) NULL +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) +#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head)) + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_INIT(head) do { \ + (head)->stqh_first = NULL; \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/*CONSTCOND*/0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (head)->stqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &(elm)->field.stqe_next; \ +} while (/*CONSTCOND*/0) + +#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (listelm)->field.stqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/*CONSTCOND*/0) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if ((head)->stqh_first == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->stqh_first; \ + while (curelm->field.stqe_next != (elm)) \ + curelm = curelm->field.stqe_next; \ + if ((curelm->field.stqe_next = \ + curelm->field.stqe_next->field.stqe_next) == NULL) \ + (head)->stqh_last = &(curelm)->field.stqe_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->stqh_first); \ + (var); \ + (var) = ((var)->field.stqe_next)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (/*CONSTCOND*/0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - offsetof(struct type, field)))) + +#endif /* !_QUEUE_H_ */ diff --git a/utils/textclient-mobile.c b/utils/textclient-mobile.c index 4d0d891..8745cb0 100644 --- a/utils/textclient-mobile.c +++ b/utils/textclient-mobile.c @@ -16,7 +16,7 @@ #include "utils.h" -#if defined(USE_IPHONE) || defined(HAVE_ANDROID) /* whole file */ +#if defined(HAVE_IPHONE) || defined(HAVE_ANDROID) /* whole file */ #include "textclient.h" #include "resources.h" diff --git a/utils/textclient.c b/utils/textclient.c index fe40928..4a4c895 100644 --- a/utils/textclient.c +++ b/utils/textclient.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2012-2016 Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright © 2012-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -22,7 +22,7 @@ #include "utils.h" -#if !defined(USE_IPHONE) && !defined(HAVE_ANDROID) /* whole file */ +#if !defined(HAVE_IPHONE) && !defined(HAVE_ANDROID) /* whole file */ #include "textclient.h" #include "resources.h" @@ -117,6 +117,72 @@ escape_str (char *s, const char *src) } #endif + +/* Let's see if we're able to fork and exec at all. Thanks, macOS. + */ +static Bool +selftest (void) +{ + static Bool done = False; + pid_t pid; + char buf [255]; + if (done) return True; + + pid = fork (); + switch ((int) pid) + { + case -1: + sprintf (buf, "%s: textclient: selftest: couldn't fork", progname); + perror (buf); + return False; + + case 0: /* child */ + { + char * const av[] = { "/bin/sh", "-c", "true", 0 }; + execvp (av[0], av); + exit (1); /* exits child fork */ + break; + } + + default: /* parent */ + { + int status = -1; + int i; + /* Busy-loops are bad mmmmkayyyy */ + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100000L; /* 0.1 sec */ + for (i = 0; i < 50; i++) { /* 5 sec max */ + pid_t pid2 = waitpid (pid, &status, 0); + if (pid == pid2) break; + (void) select (0, 0, 0, 0, &tv); + } + + if (status != 0) + { +# ifdef DEBUG + fprintf (stderr, "%s: selftest: textclient: status %d\n", + progname, status); +# endif + return False; + } + else + { +# ifdef DEBUG + fprintf (stderr, "%s: textclient: selftest ok\n", progname); +# endif + done = True; + } + break; + } + } + + return True; +} + + +static void start_timer (text_data *d); + static void launch_text_generator (text_data *d) { @@ -142,6 +208,15 @@ launch_text_generator (text_data *d) char *cmd = s = malloc ((strlen(oprogram)) * 2 + 100); # endif + if (!selftest()) + { + if (!d->out_buffer || !*d->out_buffer) + d->out_buffer = "Can't exec; Gatekeeper problem?\r\n\r\n"; + start_timer (d); + free (cmd); + return; + } + strcpy (s, "( "); strcat (s, oprogram); s += strlen (s); @@ -204,26 +279,39 @@ launch_text_generator (text_data *d) free (text_mode); } - strcpy (s, text_mode_flag); - s += strlen (s); - - if (value_res) + /* If the 'program' resource already has a text-mode option in it, + don't override that! 'gltext' does this. */ + if (! (strstr (cmd, " --date") || + strstr (cmd, " --text") || + strstr (cmd, " --file") || + strstr (cmd, " --url") || + strstr (cmd, " --program"))) { - size_t old_s = s - cmd; - char *value = get_string_resource (d->dpy, value_res, ""); - if (!value) - value = strdup(""); - cmd = realloc(cmd, cmd_capacity + strlen(value) * 2); - s = cmd + old_s; - *s = ' '; - ++s; - s = escape_str(s, value); - free(value); + strcpy (s, text_mode_flag); + s += strlen (s); + + if (value_res) + { + size_t old_s = s - cmd; + char *value = get_string_resource (d->dpy, value_res, ""); + if (!value) + value = strdup(""); + cmd = realloc(cmd, cmd_capacity + strlen(value) * 2); + s = cmd + old_s; + *s = ' '; + ++s; + s = escape_str(s, value); + free(value); + } } # endif /* HAVE_COCOA */ } +# if 1 strcpy (s, " ) 2>&1"); +# else + strcpy (s, " )"); +# endif # ifdef DEBUG fprintf (stderr, "%s: textclient: launch %s: %s\n", progname, @@ -477,6 +565,13 @@ textclient_open (Display *dpy) d->program = get_string_resource (dpy, "program", "Program"); + /* Just in case the resource is blank, e.g. gltext. */ + if (!d->program || !*d->program || !strcmp(d->program, "(default)")) + { + if (d->program) free (d->program); + d->program = strdup ("xscreensaver-text"); + } + # ifdef HAVE_FORKPTY /* Kludge for MacOS standalone mode: see OSX/SaverRunner.m. */ @@ -670,4 +765,4 @@ textclient_putc (text_data *d, XKeyEvent *k) return False; } -#endif /* !USE_IPHONE -- whole file */ +#endif /* !HAVE_IPHONE -- whole file */ diff --git a/utils/textclient.h b/utils/textclient.h index 0fe582d..5be8079 100644 --- a/utils/textclient.h +++ b/utils/textclient.h @@ -14,7 +14,7 @@ #ifndef __TEXTCLIENT_H__ #define __TEXTCLIENT_H__ -# ifdef USE_IPHONE +# ifdef HAVE_IPHONE # undef HAVE_FORKPTY # endif @@ -29,7 +29,7 @@ extern void textclient_reshape (text_data *, extern int textclient_getc (text_data *); extern Bool textclient_putc (text_data *, XKeyEvent *); -# if defined(USE_IPHONE) || defined(HAVE_ANDROID) +# if defined(HAVE_IPHONE) || defined(HAVE_ANDROID) extern char *textclient_mobile_date_string (void); extern char *textclient_mobile_url_string (Display *, const char *url); # endif diff --git a/utils/thread_util.c b/utils/thread_util.c index 71c8633..7d7fd10 100644 --- a/utils/thread_util.c +++ b/utils/thread_util.c @@ -28,13 +28,8 @@ implied warranty. # include <alloca.h> #endif -#if HAVE_UNISTD_H -# include <unistd.h> -#endif - #if defined __MACH__ && defined __APPLE__ /* OS X, iOS */ # include <sys/sysctl.h> -# include <inttypes.h> #endif #include "thread_util.h" @@ -42,238 +37,12 @@ implied warranty. #include "aligned_malloc.h" #include "resources.h" -#define IS_POWER_OF_2(x) ((x) > 0 && !((x) & ((x) - 1))) - -/* - arraysize(a). Also known as countof(x), XtNumber(x), NELEMS(x), LEN(x), - NUMOF(x), ARRAY_SIZE(x), etc., since the fine folks behind C never got - around to including this incredibly useful macro in the standard library, - which is where it belongs. - - Much of the code here assumes that multiple processors in a system all use - the same cache line size...which might be wrong on occasion. -*/ - -#define arraysize(a) (sizeof(a) / sizeof(*(a))) -#define arrayend(a) ((a) + arraysize(a)) - -/* -These numbers are from: -- Linux: arch/(arch name)/include/asm/cache.h, note - L1_CACHE_BYTES/L1_CACHE_SHIFT/SMP_CACHE_BYTES. -- FreeBSD: sys/(sys name)/include/param.h, note - CACHE_LINE_SHIFT/CACHE_LINE_SIZE. - -Preprocessor symbols come from: -- TARGET_CPU_CPP_BUILTINS() in the GNU C preprocessor - <http://code.ohloh.net/?s=%22TARGET_CPU_CPP_BUILTINS%22&fp=304413> -- http://predef.sourceforge.net/ -*/ - -/* -Several architectures need preprocessor symbols. - -Qualcomm Hexagon: 1 << 5 -Imagination Technologies META: 1 << 6 -OpenRISC: 16 (Linux has the cache line size as a todo.) -Unicore: 1 << 5 -*/ - #if HAVE_PTHREAD # if !HAVE_UNISTD_H # error unistd.h must be present whenever pthread.h is. # endif -# if defined __MACH__ && defined __APPLE__ /* OS X, iOS */ -# include <TargetConditionals.h> /* For TARGET_OS_IPHONE. */ -# ifdef TARGET_OS_IPHONE -# define _CACHE_LINE_SIZE 64 -# endif -# endif - -# if defined __FreeBSD__ && !defined _CACHE_LINE_SIZE -# include <machine/param.h> -# ifdef CACHE_LINE_SIZE -# define _CACHE_LINE_SIZE CACHE_LINE_SIZE -# endif -# endif - -# if !defined _CACHE_LINE_SIZE -# if defined __alpha || defined __alpha__ -/* DEC Alpha */ -# define _CACHE_LINE_SIZE 64 /* EV6 and above. EV4 and EV5 use 32 bytes. */ -# elif defined __arm__ -/* ARM architecture */ -# define _CACHE_LINE_SIZE (1 << 6) -# elif defined __AVR || defined __AVR__ -/* Atmel AVR32 */ -# define _CACHE_LINE_SIZE (1 << 5) -# elif defined __bfin || defined __BFIN__ -/* Analog Devices Blackfin */ -# define _CACHE_LINE_SIZE (1 << 5) -# elif defined _TMS320C6X || defined __TMS320C6X__ -/* Texas Instruments TMS320C6x */ -# define _CACHE_LINE_SIZE (1 << 7) /* From L2. L1 data cache line is 1 << 6. */ -# elif defined __cris -/* Axis Communications ETRAX CRIS */ -# define _CACHE_LINE_SIZE 32 -# elif defined __ia64__ || defined _IA64 -/* Intel Itanium */ -# define _CACHE_LINE_SIZE (1 << 7) -# elif defined __M32R__ || defined __m32r__ -/* Mitsubishi/Renesas M32R */ -# define _CACHE_LINE_SIZE (1 << 4) -# elif defined __m68k__ || defined M68000 || defined __MC68K__ -/* Motorola 68000 */ -# define _CACHE_LINE_SIZE (1 << 4) -# elif defined __MICROBLAZE__ || defined __microblaze__ -/* Xilinx MicroBlaze */ -# define _CACHE_LINE_SIZE (1 << 5) -# elif defined __mips__ || defined __mips || defined __MIPS__ -/* MIPS */ -# define _CACHE_LINE_SIZE (1 << 6) -# elif defined __mn10300__ || defined __MN10300__ -/* Matsushita/Panasonic MN103 */ -# define _CACHE_LINE_SIZE 32 /* MN103E010 has 16 bytes. */ -# elif defined __hppa || defined __hppa__ -/* Hewlett-Packard PA-RISC */ -# define _CACHE_LINE_SIZE 64 /* PA-RISC 2.0 uses 64 bytes, PA-RISC 1.1 uses 32. */ -# elif defined __powerpc || defined _ARCH_PPC -/* Power Architecture (a.k.a. PowerPC) */ -# define _CACHE_LINE_SIZE (1 << 7) /* Linux has a list of PPC models with associated L1_CACHE_SHIFT values. */ -# elif defined __s390__ || defined __370__ || defined __zarch__ || defined __SYSC_ZARCH__ -/* IBM System/390 */ -# define _CACHE_LINE_SIZE 256 -# elif defined SUNPLUS || defined __SCORE__ || defined __score__ -/* Sunplus S+core */ -# define _CACHE_LINE_SIZE (1 << 4) -# elif defined __sh__ -/* Hitachi SuperH */ -# define _CACHE_LINE_SIZE (1 << 5) /* SH3 and earlier used 1 << 4. */ -# elif defined __sparc__ || defined __sparc -/* SPARC */ -# define _CACHE_LINE_SIZE (1 << 7) /* Linux and FreeBSD disagree as to what this should be. */ -# elif defined __tile__ -/* Tilera TILE series */ -# define _CACHE_LINE_SIZE (1 << 6) /* TILEPro uses different sizes for L1 and L2. */ -# elif defined __i386 || defined __x86_64 -/* x86(-64) */ -# define _CACHE_LINE_SIZE (1 << 7) -# elif defined __xtensa__ || defined __XTENSA__ -/* Cadence Design Systems/Tensilica Xtensa */ -# define _CACHE_LINE_SIZE (1 << 5) /* 1 << 4 on some models. */ -# endif -# endif /* !defined _CACHE_LINE_SIZE */ - -# if defined __NetBSD__ && !defined _CACHE_LINE_SIZE -/* -NetBSD defines COHERENCY_UNIT to be 32 on MIPS, and 64 for all other platforms -- which is wrong. Still, this is what the kernel -uses; if this value didn't work, the system wouldn't run. -*/ -# include <sys/param.h> -# ifdef COHERENCY_UNIT -# define _CACHE_LINE_SIZE COHERENCY_UNIT -# endif -# endif - -# ifndef _CACHE_LINE_SIZE -# define _CACHE_LINE_SIZE 256 /* Fallback cache line size. */ -# endif - -static unsigned _get_cache_line_size(void) -{ - /* - The general idea: - - Try to get the actual cache line size from the operating system. - - In the interest of keeping things simple, this only checks with - glibc and OS X. - - A few other methods that could be added: - - Query x86 CPUs directly with the CPUID instruction. - - Query various ELF systems through the auxillary vector. - (Power, Alpha, SuperH) - - Query Linux through - /sys/devices/system/cpu/cpu?/cache/index?/coherency_line_size - (x86 only, AFAIK) - - Query Linux through cache_alignment in /proc/cpuinfo - - Query Solaris through PICL. - - If that fails, return a value appropriate for the current CPU - architecture. - - Otherwise, return a sufficiently large number. - */ - - /* - sysconf(3) is not a syscall, it's a glibc call that, for cache line sizes, - uses CPUID on x86 and returns 0 on other platforms. If it were to work on - most other platforms, it would have to get cache information from the - kernel, since that information is usually made available by the processor - only in privileged mode. - https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/i386/sysconf.c;hb=HEAD - */ - - /* uClibc, newlib, dietlibc, musl, Bionic do not have this. */ - -# if HAVE_UNISTD_H && ( \ - defined _SC_LEVEL1_DCACHE_LINESIZE || \ - defined _SC_LEVEL2_CACHE_LINESIZE || \ - defined _SC_LEVEL3_CACHE_LINESIZE || \ - defined _SC_LEVEL4_CACHE_LINESIZE) - { - static const int names[] = - { -# ifdef _SC_LEVEL1_DCACHE_LINESIZE - _SC_LEVEL1_DCACHE_LINESIZE, -# endif -# ifdef _SC_LEVEL2_CACHE_LINESIZE - _SC_LEVEL2_CACHE_LINESIZE, -# endif -# ifdef _SC_LEVEL3_CACHE_LINESIZE - _SC_LEVEL3_CACHE_LINESIZE, -# endif -# ifdef _SC_LEVEL4_CACHE_LINESIZE - _SC_LEVEL4_CACHE_LINESIZE -# endif - }; - - const int *name; - long result = 0; - - for(name = names; name != arrayend(names); ++name) - { - long sysconf_result = sysconf(*name); /* Can return -1 or 0 on - failure. */ - - if(sysconf_result > result) - result = sysconf_result; - } - - if(result) - return result; - - /* Currently, this fails for every platform that isn't x86. Perhaps - future versions will support other processors? */ - } -# endif - -# if defined __MACH__ && defined __APPLE__ - { - uint32_t result; /* sysctl.h says that hw.cachelinesize is a - CTLTYPE_INT. */ - size_t size = sizeof(result); - static const int name[] = {CTL_HW, HW_CACHELINE}; - - if(!sysctl((int *)name, 2, &result, &size, NULL, 0)) /* (int *) is for OS X. */ - { - assert(size == sizeof(result)); - return result; - }; - } -# endif - - /* Guess based on the CPU type. */ - return _CACHE_LINE_SIZE; -} - const pthread_mutex_t mutex_initializer = # if defined _GNU_SOURCE && !defined NDEBUG PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP @@ -304,15 +73,9 @@ int threads_available(Display *dpy) if(_has_pthread >= 0) { if(get_boolean_resource(dpy, "useThreads", "Boolean")) - { - _cache_line_size = _get_cache_line_size(); - assert(_cache_line_size >= sizeof(void *)); - assert(IS_POWER_OF_2(_cache_line_size)); - } + _cache_line_size = get_cache_line_size(); else - { _has_pthread = -1; - } } } diff --git a/utils/thread_util.h b/utils/thread_util.h index 6dff8de..a8faf2d 100644 --- a/utils/thread_util.h +++ b/utils/thread_util.h @@ -161,7 +161,7 @@ unsigned thread_memory_alignment(Display *dpy); /* int thread_malloc(void **ptr, Display *dpy, unsigned size); */ #define thread_malloc(ptr, dpy, size) \ - (aligned_malloc((ptr), thread_memory_alignment(dpy), (size))) + (aligned_malloc((ptr), 0, (size))) /* This simply does a malloc aligned to thread_memory_alignment(). See diff --git a/utils/usleep.h b/utils/usleep.h index 3225d66..f32a9c9 100644 --- a/utils/usleep.h +++ b/utils/usleep.h @@ -12,10 +12,6 @@ #ifndef __SCREENHACK_USLEEP_H__ #define __SCREENHACK_USLEEP_H__ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #ifdef HAVE_UNISTD_H # include <unistd.h> #endif diff --git a/utils/utf8wc.c b/utils/utf8wc.c index c948f22..b445f30 100644 --- a/utils/utf8wc.c +++ b/utils/utf8wc.c @@ -266,7 +266,7 @@ utf8_split (const char *string, int *length_ret) unsigned long uc; long len2 = utf8_decode (in, len, &uc); char tmp[10]; - strncpy (tmp, (char *) in, len2); + memcpy (tmp, (char *) in, len2); tmp[len2] = 0; ret[i++] = strdup (tmp); in += len2; @@ -299,8 +299,8 @@ utf8_split (const char *string, int *length_ret) long L1 = strlen(ret[i-2]); long L2 = strlen(ret[i-1]); char *s2 = (char *) malloc (L1 + L2 + 1); - strncpy (s2, ret[i-2], L1); - strncpy (s2 + L1, ret[i-1], L2); + memcpy (s2, ret[i-2], L1); + memcpy (s2 + L1, ret[i-1], L2); s2[L1 + L2] = 0; free (ret[i-2]); ret[i-2] = s2; diff --git a/utils/version.h b/utils/version.h index 7a20c66..8e38585 100644 --- a/utils/version.h +++ b/utils/version.h @@ -1,2 +1,4 @@ static const char screensaver_id[] = - "@(#)xscreensaver 5.44 (20-Mar-2020), by Jamie Zawinski (jwz@jwz.org)"; + "@(#)xscreensaver 6.00 (01-Apr-2021), by Jamie Zawinski (jwz@jwz.org)"; +#define XSCREENSAVER_VERSION "6.00" +#define XSCREENSAVER_RELEASED 1617303600 diff --git a/utils/visual-gl.c b/utils/visual-gl.c index c4b940b..cca4ecf 100644 --- a/utils/visual-gl.c +++ b/utils/visual-gl.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1999-2018 by Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright © 1999-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -21,21 +21,78 @@ */ #include "utils.h" -#include "visual.h" #include "resources.h" #ifdef HAVE_GL # include <GL/gl.h> -# include <GL/glx.h> +# ifdef HAVE_EGL +# include <EGL/egl.h> +# include <EGL/eglext.h> +# else +# include <GL/glx.h> +# endif #endif /* HAVE_GL */ +#include "visual.h" /* after EGL/egl.h */ + +#undef countof +#define countof(x) (sizeof(x)/sizeof(*(x))) + + extern char *progname; + Visual * get_gl_visual (Screen *screen) { #ifdef HAVE_GL + Display *dpy = DisplayOfScreen (screen); + +# ifdef HAVE_EGL + + Visual *v; + EGLint vid; + EGLDisplay *egl_display; + EGLConfig egl_config = 0; + int egl_major = -1, egl_minor = -1; + + /* This is re-used, no need to close it. */ + egl_display = eglGetDisplay ((EGLNativeDisplayType) dpy); + if (!egl_display) + { + fprintf (stderr, "%s: eglGetDisplay failed\n", progname); + return 0; + } + + if (! eglInitialize (egl_display, &egl_major, &egl_minor)) + { + fprintf (stderr, "%s: eglInitialize failed\n", progname); + abort(); + } + + /* Get the best EGL config on any visual, then see what visual it used. */ + get_egl_config (dpy, egl_display, -1, &egl_config); + if (!egl_config) abort(); + + if (!eglGetConfigAttrib (egl_display, egl_config, + EGL_NATIVE_VISUAL_ID, &vid)) + { + fprintf (stderr, "%s: EGL: no native visual ID\n", progname); + abort(); + } + + v = id_to_visual (screen, vid); + if (!v) + { + fprintf (stderr, "%s: EGL: no X11 visual 0x%x\n", progname, vid); + abort(); + } + + return v; + +# else /* !HAVE_EGL -- GLX */ + int screen_num = screen_number (screen); # define R GLX_RED_SIZE @@ -61,7 +118,6 @@ get_gl_visual (Screen *screen) # define SM GL_SAMPLES # endif - int attrs[][40] = { # ifdef SB /* rgba double stencil multisample */ { GLX_RGBA, R,8, G,8, B,8, A,8, D,8, DB, ST,1, SB,1, SM,8, 0 }, @@ -107,12 +163,134 @@ get_gl_visual (Screen *screen) return v; } } + +# endif /* !HAVE_EGL -- GLX */ #endif /* !HAVE_GL */ return 0; } +#ifdef HAVE_EGL +/* An X11 "visual" is an object that encapsulates the available display + formats: color mapping, depth and so on. So is a GLE "config". + So why isn't there a one-to-one mapping between visuals and configs? + Once again, I can only assume the answer is that the people responsible + for every post-2002 version of the OpenGL specification are incompetent. + + Under GLX, there will be multiple X11 visuals that appear (and behave) + identically to X11 programs, code but that have different GL parameters. + Two RGB visuals might have different alpha, depth, or stencil sizes, + for example, that would matter to a GL program but not to an X11 program. + + But EGL has dozens of 'configs' for each visual, so we can't just pass + around a Window and a Visual to describe the display parameters: we need + to pass around the 'config' as well. Or, do what we do here, have both + sides use the same code to convert a visual to the best 'config'. + (It goes down a list of parameter settings, from higher quality to lower, + and takes the first config that matches.) + + SGI solved this problem in like 1988, and like so many things, GLES went + and fucked it all up again. + */ +void +get_egl_config (Display *dpy, EGLDisplay *egl_display, + EGLint x11_visual_id, EGLConfig *egl_config) +{ +# define COMMON \ + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, \ + EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER +# define R EGL_RED_SIZE +# define G EGL_GREEN_SIZE +# define B EGL_BLUE_SIZE +# define A EGL_ALPHA_SIZE +# define D EGL_DEPTH_SIZE +# define I EGL_BUFFER_SIZE +# define ST EGL_STENCIL_SIZE +# define SB EGL_SAMPLE_BUFFERS +# define SM EGL_SAMPLES + + const EGLint templates[][40] = { +# ifdef SB + { COMMON, R,8, G,8, B,8, A,8, D,8, ST,1, SB,1, SM,8, EGL_NONE }, + { COMMON, R,8, G,8, B,8, A,8, D,8, ST,1, SB,1, SM,6, EGL_NONE }, + { COMMON, R,8, G,8, B,8, A,8, D,8, ST,1, SB,1, SM,4, EGL_NONE }, + { COMMON, R,8, G,8, B,8, A,8, D,8, ST,1, SB,1, SM,2, EGL_NONE }, +# define SB_COUNT 4 /* #### Kludgey count of preceeding lines! */ +# endif + { COMMON, R,8, G,8, B,8, A,8, D,8, ST,1, EGL_NONE }, /* rgba stencil */ + { COMMON, R,8, G,8, B,8, D,8, ST,1, EGL_NONE }, /* rgb stencil */ + { COMMON, R,4, G,4, B,4, D,4, ST,1, EGL_NONE }, + { COMMON, R,2, G,2, B,2, D,2, ST,1, EGL_NONE }, + { COMMON, R,8, G,8, B,8, A,8, D,8, EGL_NONE }, /* rgba */ + { COMMON, R,8, G,8, B,8, D,8, EGL_NONE }, /* rgb */ + { COMMON, R,4, G,4, B,4, D,4, EGL_NONE }, + { COMMON, R,2, G,2, B,2, D,2, EGL_NONE }, + { COMMON, R,1, G,1, B,1, D,1, EGL_NONE } /* monochrome */ + }; + EGLint attrs[40]; + EGLint nconfig; + int i, j, k, iter, pass; + Bool glslp; + + i = 0; +# ifdef SB + if (! get_boolean_resource (dpy, "multiSample", "MultiSample")) + i = SB_COUNT; /* skip over the multibuffer entries in 'attrs' */ +# endif /* SB */ + + glslp = get_boolean_resource (dpy, "prefersGLSL", "PrefersGLSL"); + iter = (glslp ? 2 : 1); + + *egl_config = 0; + for (pass = 0; pass < iter; pass++) + { + for (; i < countof(templates); i++) + { + for (j = 0, k = 0; templates[i][j] != EGL_NONE; j += 2) + { + attrs[k++] = templates[i][j]; + attrs[k++] = templates[i][j+1]; + } + + attrs[k++] = EGL_RENDERABLE_TYPE; +# ifdef HAVE_GLES3 + if (glslp && pass == 0) + attrs[k++] = EGL_OPENGL_ES3_BIT; + else + attrs[k++] = EGL_OPENGL_ES_BIT; +# elif defined(HAVE_JWZGLES) + attrs[k++] = EGL_OPENGL_ES_BIT; +# else + attrs[k++] = EGL_OPENGL_BIT; +# endif + + if (x11_visual_id != -1) + { + attrs[k++] = EGL_NATIVE_VISUAL_ID; + attrs[k++] = x11_visual_id; + } + + attrs[k++] = EGL_NONE; + + nconfig = -1; + if (eglChooseConfig (egl_display, attrs, egl_config, 1, &nconfig) + && nconfig == 1) + break; + } + if (i < countof(templates)) + break; + } + + if (! *egl_config) + { + fprintf (stderr, "%s: eglChooseConfig: no configs found\n", progname); + abort(); + } +} +#endif /* HAVE_EGL */ + + void describe_gl_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p) @@ -121,8 +299,13 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, #ifdef HAVE_GL { +# ifdef HAVE_EGL + EGLDisplay *egl_display; + EGLConfig config = 0; +# else /* !HAVE_EGL -- GLX */ int status; int value = False; +# endif /* !HAVE_EGL -- GLX */ Display *dpy = DisplayOfScreen (screen); XVisualInfo vi_in, *vi_out; @@ -134,6 +317,108 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, &vi_in, &out_count); if (! vi_out) abort (); +# ifdef HAVE_EGL + + /* This is re-used, no need to close it. */ + egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR, + (EGLNativeDisplayType) dpy, NULL); + if (!egl_display) + { + fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname); + return; + } + + get_egl_config (dpy, egl_display, vi_out->visualid, &config); + if (!config) + { + fprintf (stderr, "%s: no matching EGL config for X11 visual 0x%lx\n", + progname, vi_out->visualid); + abort(); + } + + { + int i; + const struct { int hexp; EGLint i; const char *s; } fields[] = { + { 1, EGL_CONFIG_ID, "config ID:" }, + { 1, EGL_CONFIG_CAVEAT, "caveat:" }, + { 1, EGL_CONFORMANT, "conformant:" }, + { 0, EGL_COLOR_BUFFER_TYPE, "buffer type:" }, + { 0, EGL_RED_SIZE, "color size:" }, + { 0, EGL_TRANSPARENT_RED_VALUE, "transparency:" }, + { 0, EGL_BUFFER_SIZE, "buffer size:" }, + { 0, EGL_DEPTH_SIZE, "depth size:" }, + { 0, EGL_LUMINANCE_SIZE, "lum size:" }, + { 0, EGL_STENCIL_SIZE, "stencil size:" }, + { 0, EGL_ALPHA_MASK_SIZE, "alpha mask:" }, + { 0, EGL_LEVEL, "level:" }, + { 0, EGL_SAMPLES, "samples:" }, + { 0, EGL_SAMPLE_BUFFERS, "sample bufs:" }, + { 0, EGL_NATIVE_RENDERABLE, "native render:" }, + { 1, EGL_NATIVE_VISUAL_TYPE, "native type:" }, + { 1, EGL_RENDERABLE_TYPE, "render type:" }, + { 0, EGL_SURFACE_TYPE, "surface type:" }, + { 0, EGL_BIND_TO_TEXTURE_RGB, "bind RGB:" }, + { 0, EGL_BIND_TO_TEXTURE_RGBA, "bind RGBA:" }, + { 0, EGL_MAX_PBUFFER_WIDTH, "buffer width:" }, + { 0, EGL_MAX_PBUFFER_HEIGHT, "buffer height:" }, + { 0, EGL_MAX_PBUFFER_PIXELS, "buffer pixels:" }, + { 0, EGL_MAX_SWAP_INTERVAL, "max swap:" }, + { 0, EGL_MIN_SWAP_INTERVAL, "min swap:" }, + }; + EGLint r=0, g=0, b=0, a=0, tt=0, tr=0, tg=0, tb=0; + eglGetConfigAttrib (egl_display, config, EGL_RED_SIZE, &r); + eglGetConfigAttrib (egl_display, config, EGL_GREEN_SIZE, &g); + eglGetConfigAttrib (egl_display, config, EGL_BLUE_SIZE, &b); + eglGetConfigAttrib (egl_display, config, EGL_ALPHA_SIZE, &a); + eglGetConfigAttrib (egl_display, config, EGL_TRANSPARENT_TYPE, &tt); + eglGetConfigAttrib (egl_display, config, EGL_TRANSPARENT_RED_VALUE, &tr); + eglGetConfigAttrib (egl_display, config, EGL_TRANSPARENT_GREEN_VALUE,&tg); + eglGetConfigAttrib (egl_display, config, EGL_TRANSPARENT_BLUE_VALUE, &tb); + for (i = 0; i < countof(fields); i++) + { + EGLint v = 0; + char s[100]; + eglGetConfigAttrib (egl_display, config, fields[i].i, &v); + if (fields[i].i == EGL_RED_SIZE) + sprintf (s, "%d, %d, %d, %d", r, g, b, a); + else if (fields[i].i == EGL_TRANSPARENT_RED_VALUE && tt != EGL_NONE) + sprintf (s, "%d, %d, %d", tr, tg, tb); + else if (fields[i].i == EGL_CONFIG_CAVEAT) + strcpy (s, (v == EGL_NONE ? "none" : + v == EGL_SLOW_CONFIG ? "slow" : +# ifdef EGL_NON_CONFORMANT + v == EGL_NON_CONFORMANT ? "non-conformant" : +# endif + "???")); + else if (fields[i].i == EGL_COLOR_BUFFER_TYPE) + strcpy (s, (v == EGL_RGB_BUFFER ? "RGB" : + v == EGL_LUMINANCE_BUFFER ? "luminance" : + "???")); + else if (fields[i].i == EGL_CONFORMANT || + fields[i].i == EGL_RENDERABLE_TYPE) + { + sprintf (s, "0x%02x", v); + if (v & EGL_OPENGL_BIT) strcat (s, " OpenGL"); + if (v & EGL_OPENGL_ES_BIT) strcat (s, " GLES-1.x"); + if (v & EGL_OPENGL_ES2_BIT) strcat (s, " GLES-2.0"); +# ifdef EGL_OPENGL_ES3_BIT + if (v & EGL_OPENGL_ES3_BIT) strcat (s, " GLES-3.0"); +# endif + if (v & EGL_OPENVG_BIT) strcat (s, " OpenVG"); + } + else if (fields[i].hexp) + sprintf (s, "0x%02x", v); + else if (v) + sprintf (s, "%d", v); + else + *s = 0; + + if (*s) fprintf (f, " EGL %-14s %s\n", fields[i].s, s); + } + } + +# else /* !HAVE_EGL -- GLX */ + status = glXGetConfig (dpy, vi_out, GLX_USE_GL, &value); if (status == GLX_NO_EXTENSION) @@ -146,7 +431,7 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, if (!glXGetConfig (dpy, vi_out, GLX_LEVEL, &value) && value != 0) - printf (" GLX level: %d\n", value); + fprintf (f, " GLX level: %d\n", value); if (!glXGetConfig (dpy, vi_out, GLX_RGBA, &value) && value) { @@ -155,22 +440,22 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, glXGetConfig (dpy, vi_out, GLX_GREEN_SIZE, &g); glXGetConfig (dpy, vi_out, GLX_BLUE_SIZE, &b); glXGetConfig (dpy, vi_out, GLX_ALPHA_SIZE, &a); - printf (" GLX type: RGBA (%2d, %2d, %2d, %2d)\n", - r, g, b, a); + fprintf (f, " GLX type: RGBA (%2d, %2d, %2d, %2d)\n", + r, g, b, a); r=0, g=0, b=0, a=0; glXGetConfig (dpy, vi_out, GLX_ACCUM_RED_SIZE, &r); glXGetConfig (dpy, vi_out, GLX_ACCUM_GREEN_SIZE, &g); glXGetConfig (dpy, vi_out, GLX_ACCUM_BLUE_SIZE, &b); glXGetConfig (dpy, vi_out, GLX_ACCUM_ALPHA_SIZE, &a); - printf (" GLX accum: RGBA (%2d, %2d, %2d, %2d)\n", - r, g, b, a); + fprintf (f, " GLX accum: RGBA (%2d, %2d, %2d, %2d)\n", + r, g, b, a); } else { value = 0; glXGetConfig (dpy, vi_out, GLX_BUFFER_SIZE, &value); - printf (" GLX type: indexed (%d)\n", value); + fprintf (f, " GLX type: indexed (%d)\n", value); } # ifndef GLX_NONE_EXT /* Hooray for gratuitious name changes. */ @@ -189,36 +474,36 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, if (!glXGetConfig (dpy, vi_out, GLX_VISUAL_CAVEAT_EXT, &value) && value != GLX_NONE_EXT) # ifdef GLX_NON_CONFORMANT_EXT - printf (" GLX rating: %s\n", - (value == GLX_NONE_EXT ? "none" : - value == GLX_SLOW_VISUAL_EXT ? "slow" : - value == GLX_NON_CONFORMANT_EXT ? "non-conformant" : - "???")); + fprintf (f, " GLX rating: %s\n", + (value == GLX_NONE_EXT ? "none" : + value == GLX_SLOW_VISUAL_EXT ? "slow" : + value == GLX_NON_CONFORMANT_EXT ? "non-conformant" : + "???"); # else - printf (" GLX rating: %s\n", - (value == GLX_NONE_EXT ? "none" : - value == GLX_SLOW_VISUAL_EXT ? "slow" : - "???")); + fprintf (f, " GLX rating: %s\n", + (value == GLX_NONE_EXT ? "none" : + value == GLX_SLOW_VISUAL_EXT ? "slow" : + "???")); # endif /* GLX_NON_CONFORMANT_EXT */ # endif /* GLX_VISUAL_CAVEAT_EXT */ if (!glXGetConfig (dpy, vi_out, GLX_DOUBLEBUFFER, &value)) - printf (" GLX double-buffer: %s\n", (value ? "yes" : "no")); + fprintf (f, " GLX double-buffer: %s\n", (value ? "yes" : "no")); if (!glXGetConfig (dpy, vi_out, GLX_STEREO, &value) && value) - printf (" GLX stereo: %s\n", (value ? "yes" : "no")); + fprintf (f, " GLX stereo: %s\n", (value ? "yes" : "no")); if (!glXGetConfig (dpy, vi_out, GLX_AUX_BUFFERS, &value) && value != 0) - printf (" GLX aux buffers: %d\n", value); + fprintf (f, " GLX aux buffers: %d\n", value); if (!glXGetConfig (dpy, vi_out, GLX_DEPTH_SIZE, &value)) - printf (" GLX depth size: %d\n", value); + fprintf (f, " GLX depth size: %d\n", value); if (!glXGetConfig (dpy, vi_out, GLX_STENCIL_SIZE, &value) && value != 0) - printf (" GLX stencil size: %d\n", value); + fprintf (f, " GLX stencil size: %d\n", value); # ifdef SB /* GL_SAMPLE_BUFFERS || GLX_SAMPLE_BUFFERS_* */ if (!glXGetConfig (dpy, vi_out, SB, &value) && @@ -226,7 +511,7 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, { int bufs = value; if (!glXGetConfig (dpy, vi_out, SM, &value)) - printf (" GLX multisample: %d, %d\n", bufs, value); + fprintf (f, " GLX multisample: %d, %d\n", bufs, value); } # endif /* GL_SAMPLE_BUFFERS || GLX_SAMPLE_BUFFERS_* */ @@ -234,12 +519,12 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, value != GLX_NONE_EXT) { if (value == GLX_NONE_EXT) - printf (" GLX transparency: none\n"); + fprintf (f, " GLX transparency: none\n"); else if (value == GLX_TRANSPARENT_INDEX_EXT) { if (!glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_INDEX_VALUE_EXT, &value)) - printf (" GLX transparency: indexed (%d)\n", value); + fprintf (f, " GLX transparency: indexed (%d)\n", value); } else if (value == GLX_TRANSPARENT_RGB_EXT) { @@ -248,10 +533,11 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual, glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g); glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_BLUE_VALUE_EXT, &b); glXGetConfig (dpy, vi_out, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a); - printf (" GLX transparency: RGBA (%2d, %2d, %2d, %2d)\n", - r, g, b, a); + fprintf (f, " GLX transparency: RGBA (%2d, %2d, %2d, %2d)\n", + r, g, b, a); } } +# endif /* !HAVE_EGL */ } #endif /* HAVE_GL */ } @@ -262,13 +548,15 @@ validate_gl_visual (FILE *out, Screen *screen, const char *window_desc, Visual *visual) { #ifdef HAVE_GL +# ifndef HAVE_EGL int status; int value = False; + unsigned int id; +# endif Display *dpy = DisplayOfScreen (screen); XVisualInfo vi_in, *vi_out; int out_count; - unsigned int id; vi_in.screen = screen_number (screen); vi_in.visualid = XVisualIDFromVisual (visual); @@ -276,6 +564,7 @@ validate_gl_visual (FILE *out, Screen *screen, const char *window_desc, &vi_in, &out_count); if (! vi_out) abort (); +# ifndef HAVE_EGL status = glXGetConfig (dpy, vi_out, GLX_USE_GL, &value); id = (unsigned int) vi_out->visualid; @@ -295,6 +584,7 @@ validate_gl_visual (FILE *out, Screen *screen, const char *window_desc, return False; } else +# endif /* !HAVE_EGL */ { return True; } diff --git a/utils/visual.h b/utils/visual.h index 18ff7a6..4fd1b95 100644 --- a/utils/visual.h +++ b/utils/visual.h @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 1993-2014 by Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright © 1993-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -33,4 +33,8 @@ extern Visual *get_gl_visual (Screen *); extern void describe_gl_visual (FILE *, Screen *, Visual *, Bool priv_cmap_p); extern Bool validate_gl_visual (FILE *, Screen *, const char *, Visual *); +#ifdef __egl_h_ /* EGL/egl.h included */ +extern void get_egl_config (Display *, EGLDisplay *, EGLint vid, EGLConfig *); +#endif + #endif /* __VISUAL_H__ */ diff --git a/utils/xdbe.c b/utils/xdbe.c index d62183e..347e625 100644 --- a/utils/xdbe.c +++ b/utils/xdbe.c @@ -18,13 +18,10 @@ #include "utils.h" #include "xdbe.h" #include "resources.h" /* for get_string_resource() */ +#include "xmu.h" /* #define DEBUG */ -#ifdef DEBUG -# include <X11/Xmu/Error.h> -#endif - extern char *progname; #ifdef HAVE_DOUBLE_BUFFER_EXTENSION /* whole file */ diff --git a/utils/xft.c b/utils/xft.c index 9245752..6decd22 100644 --- a/utils/xft.c +++ b/utils/xft.c @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2014-2018 Jamie Zawinski <jwz@jwz.org> +/* xscreensaver, Copyright © 2014-2021 Jamie Zawinski <jwz@jwz.org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -37,6 +37,50 @@ struct _XftDraw { }; +Display * +XftDrawDisplay (XftDraw *draw) +{ + return draw->dpy; +} + + +Bool +XftDrawSetClipRectangles (XftDraw *draw, int x, int y, + _Xconst XRectangle *rects, int n) +{ + if (!n) + return XSetClipMask (draw->dpy, draw->gc, 0); +# if 0 + else + /* #### unimplemented in jwxyz, so clipping is a no-op */ + return XSetClipRectangles (draw->dpy, draw->gc, x, y, + (XRectangle *) rects, /* discard const */ + n, Unsorted); +# else + return False; +# endif +} + + +Bool +XftDrawSetClip (XftDraw *draw, Region region) +{ + if (!region) + return XSetClipMask (draw->dpy, draw->gc, 0); +# if 0 + else + /* #### unimplemented in jwxyz, so clipping is a no-op */ + { + XRectangle rect; /* #### untested */ + XClipBox (region, &rect); /* #### unimplemented in jwxyz */ + return XftDrawSetClipRectangles (draw, 0, 0, &rect, 1); + } +# else + return False; +# endif +} + + XftFont * XftFontOpenXlfd (Display *dpy, int screen, _Xconst char *xlfd) { @@ -60,8 +104,9 @@ XftFontOpenXlfd (Display *dpy, int screen, _Xconst char *xlfd) { unsigned i; - // In the event of -*-random-* (under JWXYZ), get the actual XLFD, - // otherwise we'll get another random font that doesn't match ff->xfont. + /* In the event of -*-random-* (under JWXYZ), get the actual XLFD, + otherwise we'll get another random font that doesn't match ff->xfont. + */ char *xlfd_resolved = NULL; char **missing_charset_list_return; @@ -111,6 +156,62 @@ XftFontOpenXlfd (Display *dpy, int screen, _Xconst char *xlfd) } +/* Very approximately convert an XFT-style name to an XLFD style name + and then call XftFontOpenXlfd on that. + */ +XftFont * +XftFontOpenName (Display *dpy, int screen, _Xconst char *xft_name) +{ + XftFont *font; + char *name = strdup (xft_name); + char *xlfd = 0; + char *s, *b, *i, *o, *c; + int size; + char dummy; + + /* Ignore any ":keywords=" */ + c = strchr (name, ':'); + if (c) *c = 0; + + /* Downcase ASCII */ + for (s = name; *s; s++) + if (*s >= 'A' && *s <= 'Z') + *s += 'a'-'A'; + + /* "Family-NN" */ + s = strrchr (name, '-'); + if (!s) goto FAIL; + if (1 != sscanf (s+1, " %d %c", &size, &dummy)) goto FAIL; + if (size <= 0) goto FAIL; + *s = 0; + + /* "Family Bold", etc. */ + b = strstr (name, " bold"); + i = strstr (name, " italic"); + o = strstr (name, " oblique"); + if (b) *b = 0; + if (i) *i = 0; + if (o) *o = 0; + + xlfd = (char *) malloc (strlen(name) + 80); + sprintf (xlfd, "-*-%s-%s-%s-*-*-*-%d-*-*-*-*-*-*", + name, + (b ? "bold" : "medium"), + (i ? "i" : o ? "o" : "r"), + size * 10); + font = XftFontOpenXlfd (dpy, screen, xlfd); + free (name); + free (xlfd); + return font; + + FAIL: + fprintf (stderr, "%s: XFT: unparsable: \"%s\"\n", progname, xft_name); + if (name) free (name); + if (xlfd) free (xlfd); + return 0; +} + + void XftFontClose (Display *dpy, XftFont *font) { @@ -132,7 +233,8 @@ XftColorAllocName (Display *dpy, XftColor *result) { XColor color; - if (!dpy || !visual || !name || !result) abort(); + if (!dpy || !visual || !result) abort(); + if (!name || !*name) name = "#FFFFFF"; if (! XParseColor (dpy, cmap, name, &color)) { diff --git a/utils/xft.h b/utils/xft.h index 385e28b..0da0188 100644 --- a/utils/xft.h +++ b/utils/xft.h @@ -118,7 +118,7 @@ typedef unsigned char FcChar8; XftFont *XftFontOpenXlfd (Display *dpy, int screen, _Xconst char *xlfd); -#define XftFontOpenName XftFontOpenXlfd +XftFont *XftFontOpenName (Display *dpy, int screen, _Xconst char *name); void XftFontClose (Display *dpy, XftFont *font); @@ -143,7 +143,10 @@ XftDraw *XftDrawCreate (Display *dpy, Drawable drawable, Visual *visual, Colormap colormap); - +Display *XftDrawDisplay (XftDraw *); +Bool XftDrawSetClipRectangles (XftDraw *, int x, int y, + _Xconst XRectangle *rects, int n); +Bool XftDrawSetClip (XftDraw *draw, Region region); void XftDrawDestroy (XftDraw *draw); void diff --git a/utils/xftwrap.c b/utils/xftwrap.c new file mode 100644 index 0000000..e880407 --- /dev/null +++ b/utils/xftwrap.c @@ -0,0 +1,206 @@ +/* xftwrap.c --- XftDrawStringUtf8 with multi-line strings. + * xscreensaver, Copyright © 2021 Jamie Zawinski <jwz@jwz.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "utils.h" +#include "xft.h" +#include "xftwrap.h" + +#undef MAX +#undef MIN +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + + +#ifdef DEBUG +static void +LOG(const char *ss, const char *s, int n) +{ + int i; + fprintf(stderr,"####%s [", ss); + for (i = 0; i < n; i++) fprintf(stderr, "%c", s[i]); + fprintf(stderr,"]\n"); +} +#else +# define LOG(ss,s,n) /**/ +#endif + + +/* Returns a new string word-wrapped to fit in the width in pixels. + */ +char * +xft_word_wrap (Display *dpy, XftFont *font, const char *str, int pixels) +{ + const char *in = str; + char *ret = (char *) malloc (strlen(in) + 2); + char *out = ret; + const char *line_out = out; + char *word_out = 0; + while (1) + { + if (*in == ' ' || *in == '\t' || + *in == '\r' || *in == '\n' || + *in == 0) + { + Bool done = (*in == 0); /* To wrap the *last* word. */ + XGlyphInfo overall; + Bool nl = (*in == '\r' || *in == '\n'); + + if (nl) in++; + while (*in == ' ' || *in == '\t') in++; + in--; + + XftTextExtentsUtf8 (dpy, font, + (FcChar8 *) line_out, + out - line_out, + &overall); + if (overall.width - overall.x >= pixels && + word_out) + { + word_out[0] = '\n'; + line_out = word_out + 1; + word_out = 0; + if (done) break; + *out++ = *in; + } + else + { + if (done) break; + word_out = out; + *out++ = *in; + if (nl) + { + line_out = out + 1; + word_out = 0; + } + } + + if (done) break; + } + else + { + *out++ = *in; + } + in++; + } + + *out = 0; + + return ret; +} + + +/* Like XftTextExtentsUtf8, but handles multi-line strings. + XGlyphInfo will contain the bounding box that encloses all of the text. + Return value is the number of lines in the text, >= 1. + */ +int +XftTextExtentsUtf8_multi (Display *dpy, XftFont *font, + const FcChar8 *str, int len, XGlyphInfo *overall) +{ + int i, start = 0; + int lines = 0; + int line_y = 0; + for (i = 0; i <= len; i++) + { + if (i == len || str[i] == '\r' || str[i] == '\n') + { + XGlyphInfo gi; + XftTextExtentsUtf8 (dpy, font, + str + start, + i - start, + &gi); + if (lines == 0) + *overall = gi; + else + { + /* Find the union of the two bounding boxes, placed at their + respective origins. */ + int ox1, oy1, ox2, oy2; /* bbox of 'overall' */ + int nx1, ny1, nx2, ny2; /* bbox of 'gi' */ + int ux1, uy1, ux2, uy2; /* union */ + + ox1 = overall->x; + oy1 = overall->y; + ox2 = ox1 + overall->width; + oy2 = oy1 + overall->height; + + line_y += font->ascent + font->descent; /* advance origin */ + + nx1 = gi.x; + ny1 = gi.y + line_y; + nx2 = nx1 + gi.width; + ny2 = ny1 + gi.height + line_y; + + ux1 = MIN (ox1, nx1); /* upper left */ + uy1 = MIN (oy1, ny1); + ux2 = MAX (ox2, nx2); /* bottom right */ + uy2 = MAX (oy2, ny2); + + overall->x = ux1; + overall->y = uy1; + overall->width = ux2 - ux1; + overall->height = uy2 - uy1; + } + lines++; + start = i+1; + } + } + + return lines; +} + + +/* Like XftDrawStringUtf8, but handles multi-line strings. + Alignment is 1, 0 or -1 for left, center, right. + */ +void +XftDrawStringUtf8_multi (XftDraw *xftdraw, const XftColor *color, + XftFont *font, int x, int y, const FcChar8 *str, + int len, + int alignment) +{ + Display *dpy = XftDrawDisplay (xftdraw); + int i, start = 0; + int lines = 0; + XGlyphInfo overall; + if (len == 0) return; + + XftTextExtentsUtf8_multi (dpy, font, str, len, &overall); + + for (i = 0; i <= len; i++) + { + if (i == len || str[i] == '\r' || str[i] == '\n') + { + XGlyphInfo gi; + int x2 = x; + XftTextExtentsUtf8 (dpy, font, str + start, i - start, &gi); + switch (alignment) { + case 1: break; + case 0: x2 += (overall.width - gi.width) / 2; break; + case -1: x2 += (overall.width - gi.width); break; + default: abort(); break; + } + + XftDrawStringUtf8 (xftdraw, color, font, x2, y, + str + start, + i - start); + y += font->ascent + font->descent; + lines++; + start = i+1; + } + } +} + diff --git a/utils/xftwrap.h b/utils/xftwrap.h new file mode 100644 index 0000000..25a55bb --- /dev/null +++ b/utils/xftwrap.h @@ -0,0 +1,35 @@ +/* xftwrap.h --- XftDrawStringUtf8 with multi-line strings. + * xscreensaver, Copyright © 2021 Jamie Zawinski <jwz@jwz.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +#ifndef __XFTWRAP_H__ +#define __XFTWRAP_H__ + +/* Returns a new string word-wrapped to fit in the width in pixels. + */ +extern char *xft_word_wrap (Display *, XftFont *, const char *, int pixels); + +/* Like XftTextExtentsUtf8, but handles multi-line strings. + XGlyphInfo will contain the bounding box that encloses all of the text. + Return value is the number of lines in the text, >= 1. + */ +extern int XftTextExtentsUtf8_multi (Display *, XftFont *, + const FcChar8 *, int L, XGlyphInfo *); + +/* Like XftDrawStringUtf8, but handles multi-line strings. + Alignment is 1, 0 or -1 for left, center, right. + */ +extern void XftDrawStringUtf8_multi (XftDraw *, const XftColor *, + XftFont *, int x, int y, + const FcChar8 *, int L, + int alignment); + +#endif /* __XFTWRAP_H__ */ diff --git a/utils/xmu.c b/utils/xmu.c index 2f273d4..051ac95 100644 --- a/utils/xmu.c +++ b/utils/xmu.c @@ -1,173 +1,46 @@ -/* This file contains compatibility routines for systems without Xmu. - * You would be better served by installing Xmu on your machine or - * yelling at your vendor to ship it. +/* xscreensaver, Copyright © 1991-2021 Jamie Zawinski <jwz@jwz.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif -#ifndef HAVE_XMU -/* - * Copyright 1989 Massachusetts Institute of Technology - * - * 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 name of M.I.T. not be used in advertising - * or publicity pertaining to distribution of the software without specific, - * written prior permission. M.I.T. makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. - * 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 <stdio.h> +#include <X11/Xlib.h> #include "xmu.h" -#ifndef NEED_EVENTS -# define NEED_EVENTS /* to make Xproto.h define xEvent */ -#endif -#ifndef VMS -# include <X11/Xproto.h> /* for xEvent (used by Xlibint.h) */ -# include <X11/Xlibint.h> /* for _XExtension */ -#else /* VMS */ -# include <X11/Xlib.h> -#endif /* VMS */ -#include <X11/Intrinsic.h> /* for XtSpecificationRelease */ +extern const char *progname; -/* - * XmuPrintDefaultErrorMessage - print a nice error that looks like the usual - * message. Returns 1 if the caller should consider exitting else 0. - */ -int XmuPrintDefaultErrorMessage (Display *dpy, XErrorEvent *event, FILE *fp) +int +XmuPrintDefaultErrorMessage (Display *dpy, XErrorEvent *event, FILE *fp) { - char buffer[BUFSIZ]; - char mesg[BUFSIZ]; - char number[32]; - char *mtype = "XlibMessage"; - _XExtension *ext = (_XExtension *)NULL; - XGetErrorText(dpy, event->error_code, buffer, BUFSIZ); - XGetErrorDatabaseText(dpy, mtype, "XError", "X Error", mesg, BUFSIZ); - (void) fprintf(fp, "%s: %s\n ", mesg, buffer); - XGetErrorDatabaseText(dpy, mtype, "MajorCode", "Request Major code %d", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, event->request_code); - if (event->request_code < 128) { - sprintf(number, "%d", event->request_code); - XGetErrorDatabaseText(dpy, "XRequest", number, "", buffer, BUFSIZ); - } else { - /* XXX this is non-portable */ - for (ext = dpy->ext_procs; - ext && (ext->codes.major_opcode != event->request_code); - ext = ext->next) - ; - if (ext) - strcpy(buffer, ext->name); - else - buffer[0] = '\0'; - } - (void) fprintf(fp, " (%s)", buffer); - fputs("\n ", fp); -#if (XtSpecificationRelease >= 5) - if (event->request_code >= 128) { - XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, event->minor_code); - if (ext) { - sprintf(mesg, "%s.%d", ext->name, event->minor_code); - XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); - (void) fprintf(fp, " (%s)", buffer); - } - fputs("\n ", fp); - } - if (event->error_code >= 128) { - /* let extensions try to print the values */ - /* XXX this is non-portable code */ - for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->error_values) - (*ext->error_values)(dpy, event, fp); - } - /* the rest is a fallback, providing a simple default */ - /* kludge, try to find the extension that caused it */ - buffer[0] = '\0'; - for (ext = dpy->ext_procs; ext; ext = ext->next) { - if (ext->error_string) - (*ext->error_string)(dpy, event->error_code, &ext->codes, - buffer, BUFSIZ); - if (buffer[0]) - break; - } - if (buffer[0]) - sprintf(buffer, "%s.%d", ext->name, - event->error_code - ext->codes.first_error); - else - strcpy(buffer, "Value"); - XGetErrorDatabaseText(dpy, mtype, buffer, "", mesg, BUFSIZ); - if (*mesg) { - (void) fprintf(fp, mesg, event->resourceid); - fputs("\n ", fp); - } - } else if ((event->error_code == BadWindow) || - (event->error_code == BadPixmap) || - (event->error_code == BadCursor) || - (event->error_code == BadFont) || - (event->error_code == BadDrawable) || - (event->error_code == BadColor) || - (event->error_code == BadGC) || - (event->error_code == BadIDChoice) || - (event->error_code == BadValue) || - (event->error_code == BadAtom)) { - if (event->error_code == BadValue) - XGetErrorDatabaseText(dpy, mtype, "Value", "Value 0x%x", - mesg, BUFSIZ); - else if (event->error_code == BadAtom) - XGetErrorDatabaseText(dpy, mtype, "AtomID", "AtomID 0x%x", - mesg, BUFSIZ); - else - XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, event->resourceid); - fputs("\n ", fp); - } -#elif (XtSpecificationRelease == 4) - XGetErrorDatabaseText(dpy, mtype, "MinorCode", "Request Minor code %d", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, event->minor_code); - fputs("\n ", fp); - if (ext) { - sprintf(mesg, "%s.%d", ext->name, event->minor_code); - XGetErrorDatabaseText(dpy, "XRequest", mesg, "", buffer, BUFSIZ); - (void) fprintf(fp, " (%s)", buffer); - } - XGetErrorDatabaseText(dpy, mtype, "ResourceID", "ResourceID 0x%x", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, event->resourceid); - fputs("\n ", fp); -#else -ERROR! Unsupported release of X11 -#endif - XGetErrorDatabaseText(dpy, mtype, "ErrorSerial", "Error Serial #%d", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, event->serial); - fputs("\n ", fp); - XGetErrorDatabaseText(dpy, mtype, "CurrentSerial", "Current Serial #%d", - mesg, BUFSIZ); - (void) fprintf(fp, mesg, NextRequest(dpy)-1); - fputs("\n", fp); - if (event->error_code == BadImplementation) return 0; - return 1; + /* The real libXmu version of this does localization and uses private, + undocumented fields inside the Display struct to print things about + errors from server-extension events. But the following is sufficient. + */ + char xerr[1024], opname[1024], num[20]; + const char *b = progname; + + /* Convert the error code to its name, e.g. "BadWindow" */ + XGetErrorText (dpy, event->error_code, xerr, sizeof(xerr)-1); + + /* Convert the request's ID number to its name, e.g., "XGetProperty" */ + sprintf (num, "%d", event->request_code); + XGetErrorDatabaseText (dpy, "XRequest", num, "", opname, sizeof(opname)-1); + + fprintf (fp, "%s: Failed request: %s\n", b, xerr); + fprintf (fp, "%s: Major opcode: %d (%s)\n", b, event->request_code, + opname); + fprintf (fp, "%s: Resource id: 0x%lx\n", b, event->resourceid); + fprintf (fp, "%s: Serial number: %ld / %ld\n\n", b, + event->serial, NextRequest(dpy)-1); + return 1; } - -#else /* HAVE_XMU */ - -/* Shut up the stupid "gcc -pedantic" warning */ -int _I_dont_care_that_ISO_C_forbids_an_empty_source_file_ = 1; - -#endif /* HAVE_XMU */ diff --git a/utils/xmu.h b/utils/xmu.h index 48084f7..e4cf7e6 100644 --- a/utils/xmu.h +++ b/utils/xmu.h @@ -1,14 +1,8 @@ -/* This file contains compatibility routines for systems without Xmu. - * You would be better served by installing Xmu on your machine or - * yelling at your vendor to ship it. - */ +/* A relic of the past. */ #ifndef __XMU_H__ #define __XMU_H__ -#include <X11/Xlib.h> -#include <stdio.h> - int XmuPrintDefaultErrorMessage (Display *dpy, XErrorEvent *event, FILE *fp); #endif /* __XMU_H__ */ diff --git a/utils/xshm.c b/utils/xshm.c index 8992140..14e5e43 100644 --- a/utils/xshm.c +++ b/utils/xshm.c @@ -33,6 +33,7 @@ /* #define DEBUG */ +#include <assert.h> #include <errno.h> /* for perror() */ #ifdef HAVE_JWXYZ @@ -42,12 +43,8 @@ #endif #include "xshm.h" +#include "aligned_malloc.h" #include "resources.h" /* for get_string_resource() */ -#include "thread_util.h" /* for thread_malloc() */ - -#ifdef DEBUG -# include <X11/Xmu/Error.h> -#endif extern char *progname; @@ -68,7 +65,7 @@ shm_ehandler (Display *dpy, XErrorEvent *error) { shm_got_x_error = True; -#ifdef DEBUG +#if 0 fprintf (stderr, "\n%s: ignoring X error from XSHM:\n", progname); XmuPrintDefaultErrorMessage (dpy, error, stderr); fprintf (stderr, "\n"); @@ -89,7 +86,7 @@ shm_ehandler (Display *dpy, XErrorEvent *error) XSync((DPY), False); \ if (old_handler) \ XSetErrorHandler (old_handler); \ - old_handler = 0; \ + old_handler = 0; \ } while(0) #endif /* HAVE_XSHM_EXTENSION */ @@ -117,8 +114,8 @@ create_fallback (Display *dpy, Visual *visual, /* Sometimes the XImage data needs to be aligned, such as for SIMD (SSE2 in Fireworkx), or multithreading (AnalogTV). */ - int error = thread_malloc ((void **)&image->data, dpy, - image->height * image->bytes_per_line); + int error = aligned_malloc ((void **)&image->data, get_cache_line_size(), + image->height * image->bytes_per_line); if (error) { print_error (error); XDestroyImage (image); @@ -291,11 +288,13 @@ void destroy_xshm_image (Display *dpy, XImage *image, XShmSegmentInfo *shm_info) { #ifdef HAVE_XSHM_EXTENSION + Status status; + if (shm_info->shmid == -1) { #endif /* HAVE_XSHM_EXTENSION */ /* Don't let XDestroyImage free image->data. */ - thread_free (image->data); + aligned_free (image->data); image->data = NULL; XDestroyImage (image); return; @@ -303,8 +302,6 @@ destroy_xshm_image (Display *dpy, XImage *image, XShmSegmentInfo *shm_info) #ifdef HAVE_XSHM_EXTENSION } - Status status; - CATCH_X_ERROR(dpy); status = XShmDetach (dpy, shm_info); UNCATCH_X_ERROR(dpy); @@ -312,10 +309,10 @@ destroy_xshm_image (Display *dpy, XImage *image, XShmSegmentInfo *shm_info) status = False; if (!status) fprintf (stderr, "%s: XShmDetach failed!\n", progname); -#ifdef DEBUG +# ifdef DEBUG else fprintf (stderr, "%s: XShmDetach(dpy, shm_info) ==> True\n", progname); -#endif +# endif XDestroyImage (image); XSync(dpy, False); @@ -329,10 +326,10 @@ destroy_xshm_image (Display *dpy, XImage *image, XShmSegmentInfo *shm_info) (unsigned long) shm_info->shmaddr); perror(buf); } -#ifdef DEBUG +# ifdef DEBUG else fprintf (stderr, "%s: shmdt(shm_info->shmaddr) ==> 0\n", progname); -#endif +# endif XSync(dpy, False); diff --git a/utils/yarandom.c b/utils/yarandom.c index f450735..0f51cb6 100644 --- a/utils/yarandom.c +++ b/utils/yarandom.c @@ -118,9 +118,9 @@ ya_rand_init(unsigned int seed) #define ROT(X,N) (((X)<<(N)) | ((X)>>((sizeof(unsigned int)*8)-(N)))) seed = (999U * (unsigned int) tp.tv_sec); seed = ROT (seed, 11); - seed += (1001 * tp.tv_usec); + seed += (1001 * (unsigned int) tp.tv_usec); seed = ROT (seed, 7); - seed += (1003 * getpid()); + seed += (1003 * (unsigned int) getpid()); seed = ROT (seed, 13); } |