info-beamer-1.0~pre4/0000755000175000017500000000000012456167031012336 5ustar nknkinfo-beamer-1.0~pre4/.git/0000755000175000017500000000000012456161610013174 5ustar nknkinfo-beamer-1.0~pre4/.git/branches/0000755000175000017500000000000012452774236014773 5ustar nknkinfo-beamer-1.0~pre4/.git/hooks/0000755000175000017500000000000012452774236014331 5ustar nknkinfo-beamer-1.0~pre4/.git/hooks/applypatch-msg.sample0000755000175000017500000000070412452774236020471 0ustar nknk#!/bin/sh # # An example hook script to check the commit log message taken by # applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. The hook is # allowed to edit the commit message file. # # To enable this hook, rename this file to "applypatch-msg". . git-sh-setup test -x "$GIT_DIR/hooks/commit-msg" && exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} : info-beamer-1.0~pre4/.git/hooks/commit-msg.sample0000755000175000017500000000160012452774236017610 0ustar nknk#!/bin/sh # # An example hook script to check the commit log message. # Called by "git commit" with one argument, the name of the file # that has the commit message. The hook should exit with non-zero # status after issuing an appropriate message if it wants to stop the # commit. The hook is allowed to edit the commit message file. # # To enable this hook, rename this file to "commit-msg". # Uncomment the below to add a Signed-off-by line to the message. # Doing this in a hook is a bad idea in general, but the prepare-commit-msg # hook is more suited to it. # # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" # This example catches duplicate Signed-off-by lines. test "" = "$(grep '^Signed-off-by: ' "$1" | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { echo >&2 Duplicate Signed-off-by lines. exit 1 } info-beamer-1.0~pre4/.git/hooks/post-update.sample0000755000175000017500000000027512452774236020010 0ustar nknk#!/bin/sh # # An example hook script to prepare a packed repository for use over # dumb transports. # # To enable this hook, rename this file to "post-update". exec git update-server-info info-beamer-1.0~pre4/.git/hooks/pre-applypatch.sample0000755000175000017500000000061612452774236020473 0ustar nknk#!/bin/sh # # An example hook script to verify what is about to be committed # by applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. # # To enable this hook, rename this file to "pre-applypatch". . git-sh-setup test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} : info-beamer-1.0~pre4/.git/hooks/pre-commit.sample0000755000175000017500000000315212452774236017614 0ustar nknk#!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, rename this file to "pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- info-beamer-1.0~pre4/.git/hooks/pre-push.sample0000755000175000017500000000251012452774236017300 0ustar nknk#!/bin/sh # An example hook script to verify what is about to be pushed. Called by "git # push" after it has checked the remote status, but before anything has been # pushed. If this script exits with a non-zero status nothing will be pushed. # # This hook is called with the following parameters: # # $1 -- Name of the remote to which the push is being done # $2 -- URL to which the push is being done # # If pushing without using a named remote those arguments will be equal. # # Information about the commits which are being pushed is supplied as lines to # the standard input in the form: # # # # This sample shows how to prevent push of commits where the log message starts # with "WIP" (work in progress). remote="$1" url="$2" z40=0000000000000000000000000000000000000000 IFS=' ' while read local_ref local_sha remote_ref remote_sha do if [ "$local_sha" = $z40 ] then # Handle delete : else if [ "$remote_sha" = $z40 ] then # New branch, examine all commits range="$local_sha" else # Update to existing branch, examine new commits range="$remote_sha..$local_sha" fi # Check for WIP commit commit=`git rev-list -n 1 --grep '^WIP' "$range"` if [ -n "$commit" ] then echo "Found WIP commit in $local_ref, not pushing" exit 1 fi fi done exit 0 info-beamer-1.0~pre4/.git/hooks/pre-rebase.sample0000755000175000017500000001144212452774236017566 0ustar nknk#!/bin/sh # # Copyright (c) 2006, 2008 Junio C Hamano # # The "pre-rebase" hook is run just before "git rebase" starts doing # its job, and can prevent the command from running by exiting with # non-zero status. # # The hook is called with the following parameters: # # $1 -- the upstream the series was forked from. # $2 -- the branch being rebased (or empty when rebasing the current branch). # # This sample shows how to prevent topic branches that are already # merged to 'next' branch from getting rebased, because allowing it # would result in rebasing already published history. publish=next basebranch="$1" if test "$#" = 2 then topic="refs/heads/$2" else topic=`git symbolic-ref HEAD` || exit 0 ;# we do not interrupt rebasing detached HEAD fi case "$topic" in refs/heads/??/*) ;; *) exit 0 ;# we do not interrupt others. ;; esac # Now we are dealing with a topic branch being rebased # on top of master. Is it OK to rebase it? # Does the topic really exist? git show-ref -q "$topic" || { echo >&2 "No such branch $topic" exit 1 } # Is topic fully merged to master? not_in_master=`git rev-list --pretty=oneline ^master "$topic"` if test -z "$not_in_master" then echo >&2 "$topic is fully merged to master; better remove it." exit 1 ;# we could allow it, but there is no point. fi # Is topic ever merged to next? If so you should not be rebasing it. only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` only_next_2=`git rev-list ^master ${publish} | sort` if test "$only_next_1" = "$only_next_2" then not_in_topic=`git rev-list "^$topic" master` if test -z "$not_in_topic" then echo >&2 "$topic is already up-to-date with master" exit 1 ;# we could allow it, but there is no point. else exit 0 fi else not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` /usr/bin/perl -e ' my $topic = $ARGV[0]; my $msg = "* $topic has commits already merged to public branch:\n"; my (%not_in_next) = map { /^([0-9a-f]+) /; ($1 => 1); } split(/\n/, $ARGV[1]); for my $elem (map { /^([0-9a-f]+) (.*)$/; [$1 => $2]; } split(/\n/, $ARGV[2])) { if (!exists $not_in_next{$elem->[0]}) { if ($msg) { print STDERR $msg; undef $msg; } print STDERR " $elem->[1]\n"; } } ' "$topic" "$not_in_next" "$not_in_master" exit 1 fi <<\DOC_END This sample hook safeguards topic branches that have been published from being rewound. The workflow assumed here is: * Once a topic branch forks from "master", "master" is never merged into it again (either directly or indirectly). * Once a topic branch is fully cooked and merged into "master", it is deleted. If you need to build on top of it to correct earlier mistakes, a new topic branch is created by forking at the tip of the "master". This is not strictly necessary, but it makes it easier to keep your history simple. * Whenever you need to test or publish your changes to topic branches, merge them into "next" branch. The script, being an example, hardcodes the publish branch name to be "next", but it is trivial to make it configurable via $GIT_DIR/config mechanism. With this workflow, you would want to know: (1) ... if a topic branch has ever been merged to "next". Young topic branches can have stupid mistakes you would rather clean up before publishing, and things that have not been merged into other branches can be easily rebased without affecting other people. But once it is published, you would not want to rewind it. (2) ... if a topic branch has been fully merged to "master". Then you can delete it. More importantly, you should not build on top of it -- other people may already want to change things related to the topic as patches against your "master", so if you need further changes, it is better to fork the topic (perhaps with the same name) afresh from the tip of "master". Let's look at this example: o---o---o---o---o---o---o---o---o---o "next" / / / / / a---a---b A / / / / / / / / c---c---c---c B / / / / \ / / / / b---b C \ / / / / / \ / ---o---o---o---o---o---o---o---o---o---o---o "master" A, B and C are topic branches. * A has one fix since it was merged up to "next". * B has finished. It has been fully merged up to "master" and "next", and is ready to be deleted. * C has not merged to "next" at all. We would want to allow C to be rebased, refuse A, and encourage B to be deleted. To compute (1): git rev-list ^master ^topic next git rev-list ^master next if these match, topic has not merged in next at all. To compute (2): git rev-list master..topic if this is empty, it is fully merged to "master". DOC_END info-beamer-1.0~pre4/.git/hooks/prepare-commit-msg.sample0000755000175000017500000000232712452774236021253 0ustar nknk#!/bin/sh # # An example hook script to prepare the commit log message. # Called by "git commit" with the name of the file that has the # commit message, followed by the description of the commit # message's source. The hook's purpose is to edit the commit # message file. If the hook fails with a non-zero status, # the commit is aborted. # # To enable this hook, rename this file to "prepare-commit-msg". # This hook includes three examples. The first comments out the # "Conflicts:" part of a merge commit. # # The second includes the output of "git diff --name-status -r" # into the message, just before the "git status" output. It is # commented because it doesn't cope with --amend or with squashed # commits. # # The third example adds a Signed-off-by line to the message, that can # still be edited. This is rarely a good idea. case "$2,$3" in merge,) /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; # ,|template,) # /usr/bin/perl -i.bak -pe ' # print "\n" . `git diff --cached --name-status -r` # if /^#/ && $first++ == 0' "$1" ;; *) ;; esac # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" info-beamer-1.0~pre4/.git/hooks/update.sample0000755000175000017500000000703312452774236017024 0ustar nknk#!/bin/sh # # An example hook script to blocks unannotated tags from entering. # Called by "git receive-pack" with arguments: refname sha1-old sha1-new # # To enable this hook, rename this file to "update". # # Config # ------ # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # hooks.allowdeletetag # This boolean sets whether deleting tags will be allowed in the # repository. By default they won't be. # hooks.allowmodifytag # This boolean sets whether a tag may be modified after creation. By default # it won't be. # hooks.allowdeletebranch # This boolean sets whether deleting branches will be allowed in the # repository. By default they won't be. # hooks.denycreatebranch # This boolean sets whether remotely creating branches will be denied # in the repository. By default this is allowed. # # --- Command line refname="$1" oldrev="$2" newrev="$3" # --- Safety check if [ -z "$GIT_DIR" ]; then echo "Don't run this script from the command line." >&2 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 )" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "usage: $0 " >&2 exit 1 fi # --- Config allowunannotated=$(git config --bool hooks.allowunannotated) allowdeletebranch=$(git config --bool hooks.allowdeletebranch) denycreatebranch=$(git config --bool hooks.denycreatebranch) allowdeletetag=$(git config --bool hooks.allowdeletetag) allowmodifytag=$(git config --bool hooks.allowmodifytag) # check for no description projectdesc=$(sed -e '1q' "$GIT_DIR/description") case "$projectdesc" in "Unnamed repository"* | "") echo "*** Project description file hasn't been set" >&2 exit 1 ;; esac # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero="0000000000000000000000000000000000000000" if [ "$newrev" = "$zero" ]; then newrev_type=delete else newrev_type=$(git cat-file -t $newrev) fi case "$refname","$newrev_type" in refs/tags/*,commit) # un-annotated tag short_refname=${refname##refs/tags/} if [ "$allowunannotated" != "true" ]; then echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,delete) # delete tag if [ "$allowdeletetag" != "true" ]; then echo "*** Deleting a tag is not allowed in this repository" >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 then echo "*** Tag '$refname' already exists." >&2 echo "*** Modifying a tag is not allowed in this repository." >&2 exit 1 fi ;; refs/heads/*,commit) # branch if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then echo "*** Creating a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/heads/*,delete) # delete branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/remotes/*,commit) # tracking branch ;; refs/remotes/*,delete) # delete tracking branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a tracking branch is not allowed in this repository" >&2 exit 1 fi ;; *) # Anything else (is there anything else?) echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac # --- Finished exit 0 info-beamer-1.0~pre4/.git/info/0000755000175000017500000000000012452774236014141 5ustar nknkinfo-beamer-1.0~pre4/.git/info/exclude0000644000175000017500000000036012452774236015514 0ustar nknk# git ls-files --others --exclude-from=.git/info/exclude # Lines that start with '#' are comments. # For a project mostly in C, the following would be a good set of # exclude patterns (uncomment them if you want to use them): # *.[oa] # *~ info-beamer-1.0~pre4/.git/logs/0000755000175000017500000000000012452774240014145 5ustar nknkinfo-beamer-1.0~pre4/.git/logs/refs/0000755000175000017500000000000012452774240015104 5ustar nknkinfo-beamer-1.0~pre4/.git/logs/refs/heads/0000755000175000017500000000000012452774240016170 5ustar nknkinfo-beamer-1.0~pre4/.git/logs/refs/heads/master0000644000175000017500000000027212452774240017407 0ustar nknk0000000000000000000000000000000000000000 7bff9611592f0eb9aefbb263104abf63ec33564c Noël Köthe 1420556448 +0100 clone: from https://github.com/dividuum/info-beamer.git info-beamer-1.0~pre4/.git/logs/refs/remotes/0000755000175000017500000000000012452774240016562 5ustar nknkinfo-beamer-1.0~pre4/.git/logs/refs/remotes/origin/0000755000175000017500000000000012452774240020051 5ustar nknkinfo-beamer-1.0~pre4/.git/logs/refs/remotes/origin/HEAD0000644000175000017500000000027212452774240020476 0ustar nknk0000000000000000000000000000000000000000 7bff9611592f0eb9aefbb263104abf63ec33564c Noël Köthe 1420556448 +0100 clone: from https://github.com/dividuum/info-beamer.git info-beamer-1.0~pre4/.git/logs/HEAD0000644000175000017500000000027212452774240014572 0ustar nknk0000000000000000000000000000000000000000 7bff9611592f0eb9aefbb263104abf63ec33564c Noël Köthe 1420556448 +0100 clone: from https://github.com/dividuum/info-beamer.git info-beamer-1.0~pre4/.git/objects/0000755000175000017500000000000012452774236014637 5ustar nknkinfo-beamer-1.0~pre4/.git/objects/info/0000755000175000017500000000000012452774236015572 5ustar nknkinfo-beamer-1.0~pre4/.git/objects/pack/0000755000175000017500000000000012452774240015550 5ustar nknkinfo-beamer-1.0~pre4/.git/objects/pack/pack-83620dd98d777142110016f667948c2384edfa3e.idx0000444000175000017500000007663012452774240024302 0ustar nknktOc',/39>@DGGJKPRW]`hjpsxy|   #(+47<>BDJSX^cdfgimqww|  "$-147=AEHKQRVX\_adehpuyz{|   '228?AELNRX]bhkmsu{} #*036:AEGOQV!Ѓ䄚#T!ox({P0ݹM6s,_Ƚ_<#/R=Jʁ y} gug46`6 ׭C &4W04YFWUm\mݺ%!N =2?>5D#Ð?G;ܚ+Ti1L \#V:}MYÍots I-Vk`)w, cy{l=\͖@KY%oLo:!c[VTGLUhC&B7eHk[frH%U`D?6h_>2ݙq0;s|+le܍D܍ig"2?gԘ~c@X^U^-@(k p;1pr_ReP~H.yr1Z/CbJZAFZ3ۗG=43ꊖ]DE 1 +b$Fw`Q"[C1LQdN^ev5`Ad-Ar:sG/[*!,ahqC I] \`mi-fc<)HwXJư?^Q:‘Je\~Τ>Æ17uf6BӴH l_׋N"A^Bip@qQtJ *[bY TGw r%1{V,DDs|#ygB^ a O$V2JS}ZŒM 5wΛ qFv)H,ejIfͫȋ'x1Rt~VDImҭ 1<_Ek Dh@'MW0 g|{Sou701=0Ss2!X}9QPqrL]0F" !8X`T  x*%6N # E `A$ 1;AFT3{& A 0f\ߔ`C :z=E8(l 4qg_k"AM {/`N YJ R(5 xx"^| t_?[];Z |?)T %D>j{p6]\ ITh%tw6.:VäV*l,G]/v,gmbuUY?L|Ct2?i5{a}Z3$NoCF!X|َK-hP}cW(/` %g"RVxW~Ћq口xO}썗Ȓ RU7(ׯe_0B C@=sWzf3;W |<,SݖLv$Ojp4QJm0\-䯦JgG8ǯ6/7~kEK]{KLR)uXeOgS x.:U(CV%Oy 2q |G2kGk7#-39tco%AGa+: &{&tlKp ,0_Le ǴI/xDZQ1$RNG/y F['F2kjt/6BHcˈxU%.|MqS6Nc>{R1_qրIܻB]2.%[֪ud$MQԟlk,O1#ίnq?} =iŗ}6L[z&U]:Zt8+gq@D9NohA`' Z@d,smH!fkc#bI'&L*ذ'E^*T4[:&Nד=zנPp -r\'T"xf6QOIN.# U/Cv4=.1rgdžHۦZb*#Kr@ȓI;1 FϷؒ (Lc75Fy\Uk³^%I^f}Ԑ pFOWl lFU\՜'uVT$|ACV2Bq eٱX^H?WVAo^'VUlsvqNay.5ջ3 z:-F:[H֌(?0|D(h'h6<怏.Y*K(K[ yb3Vϖ`\s %2 x@GqB(!4X#\@6BC _~qCb[Q@ /L/c@Dzrw SA[7 \KaJ [kžLjݏ %eᯭ2sݙpK:t!I@A bmG(x!T$>h&egap"vDi50ρ"O0q*:m89|"IBd!"Ym\\z " .ΎQw_΁"`&Ϛ>Rf" ŔKEj# +{!C|(* #PCTȟS?5#QJ?9H6c#O%]V6VO .#Bߦ(ʋRB#=yPPq #^`#Zw45ÚT\$&|T-dm$UY7Wۤ+$]s Ms ~'Rm$mйFN9s0B$}(3xP썸&0!ٹ/m'C} }%o}S~'{Mc*0Jy ڌ'pjV>g؍ ]'L̟oJi·m(CÁ<((~{=WkjY)$$3nxxtR)*"z5L{/c)2 /~f} uz)qRmJ*]c}yU;.+*i* cJoS*4xTf8*"@[f㌦C*)Ԩzۀ-9c!M*4VJM"eot)*OQ3sB\U/E+L';ف"W qɼ+Vbͮ=֫Ė+3~RB}w:@l>,*|d"q3\ 6{;,v ",SC~-oDĐ`-B2$ֈEp<Ƒ9tQ-|sp11`kS\=3-S>aQ> %Vc.8$#0@_.ly.1[W*9EnTd-.{UYP+S-$&l.ۖELiHY/h3ʖ *ޢxૈo/ >07F 0(Ro@mUD0C4.^%.qno+0CN@!-Β17f>a,z@1XE/ED`NW u1QӛX(NSts1i $;ʺ):8 29q)TS2>fP 5Hn2(5QFʛI͇MM2 +fxO 434"6Z>ƵU#LDY35}HDXq*W?-L3O1T/ޣV*|#3QY(\s3;ZQ`3Ww|v $JD4&! S!1k>4w\e&ړ4פ 8IQ]ʽĎfw4Ԑ0#CE}Z[5CA5q1m_*i7A5aWrк5IqzpnJㄔX5Z@45}iuTHpC5p"vN:q^5b[cש5꺻hz9 g$מ6uS^[e6a%ge[g-j<_6[naOZ6ڣbZ6h!~S6PgGv7=6O҄@@ĥa!6ppH]^ni7{P6>Q""m}7c3 O19 #A7o=v!uW7_ɚ"!˝rp#7Ԭc?oϕ7ܩe O=N+dÖ.8DX0 !ZrTuLX9 .kQ$EC39YcZT䀖G`99]Gwu(Me?9Ylj) 3l+)G9gwj8g)4>Bȡ9ܱOYt:bu:=٦"-Lv2G\:m XaR;7fe= a\pɄ@;y+ŅD;v0Fhr]s; ,'w24iC(.\=/X iU[:=\sv;z=7 Lt|L10ח=B_fҡ Lױ\>9CpS^>V!@ʸLr׋fm>\$7>5??(#(zoȧf?7 4 nJڍ?4%n2@? f݈KLsA_2)y y1B/ U)pewW@B ?.\OQ̬BQXʺ\, `7 B1"6c[86nB *#FI|xtBv)W\/EpSGB,Tu{vNKBXloD7kTCZzB(+GSOGAujvi9sNbGVBqޥHmGs?Zk!gG{xWKgYxۼ錵r(Zw*L&f9^݋=e)Lz9T?641M-oW2<3тM1k}"[cF_zV֍<@FMKe@÷)=V^jwSAM`ΒhoWj+jN2Fɩ (NJ# P1YmbNhG#7} eʝN-v HUdNiiW<`F}t :)d$OB["+)WY@O ueBcO*UOaf&OcεOXʞq&O䜐CЄE(T 8Ox,~`@IPy'K u֧.hP8z2#c88 PszJX {8mmPzUΉI`[Q؈P/:oH;3u M9]PNK:ǢO;߳  Qti(\*+%NQ? "D$%,QџRrJ/}m.e3]QH֜'WrnQBq+kp\SRѬj7KWjsģ=a4WSk~+0xW$9 %7qfW̍Pl63mXAsƖQ*}UI(_#%X!)#*=ӏvXVF\q繉Gl;AX3\9&Q9ukXr!_+NՊ`?=XԜlgY ­.QZ

׹qw5uzdZq)2|$|ZsU,0JpIZ}gx/dݢ2=h+Zȗ?Vy+[n-e0b__WNքMlq[s Vs[DfEU &~A\'GN/~-~D6(˽]9ij7YyE'_]9-S_"+3]At+ ,&vhR.6~]]n8 #]`Jm Fv ]mԫV mX 33^A۾ƸIN*\^B-e}R 8.x^^݀3Zε/X"^!. .[V%m^or.$htvr^òR%? ju^kb!]@F 3f?^LL&\^Z[w`3*eW_:( dmKn_=M:.ZF_ڹѡOPEąh_ (@?"`1%%<w XDY`C_| hQ`P;M˂^`Z5a>׮x``,D &6 c5`gư*Qnfx%(ax 1t:!Q:osa'G2[\bzpad:f@ޛ$?p[93al2 k9TB~-㲉awcUXK WnrbYZqU@n+&bM&45p3xbT YtwbmSe@ l N4bp[vEL,Bb~k#v]ZbK\Ac{R&zjYDc75d x3V»ݤf88~d&m8S2;bpRwbdFZ LZdR_B;YI>db'd\ ]E :O{Vdf o$/AR@!g-dt\rveEiiz el,P'ԗrJahS7f{#muB@fPxYZrfh{ͫ&$(%;f 0F7H2owg:rwMkX^D2g縡mHI%ltԞ3l/e `]Dql36KBjDylt)BNޗцS IlI%vO8+!m--B t'sm0ZitdC m2A_dQTկ՗nk|6$JopMXo aLMd|ToG612JsKr48p\xw]pD.hA `"prV52yLDփHro7q g`Ċݨ/g\ qg%Wj6M qGs=z/q B=#rQmq*?3uPqfq\]VXq|3q*25xWO_S~qH-i(W#aJrRbWh[BE0)CrHnu` iQsz{ր{ Qtamugeh :uu>$M3BWlu0(՞J(6Wu+yqkXٗu^/!j_LWv›J ;g^oCvǵ5]bMt'TfOvʼOt9f$wG6"ywZkw`igfxQ\>}PwQ eIumx4ghox:FaYߖ$Fx_PjEz,xbbc^U>Rzc1zxr3蹨Kx%kZ3xrI#AJ$?CDLxZHJaƸUȨ5xȊAc -ibS` @yMKE8$tЌpy,(N'}H,!oye&M%tgZ'y߄͚M2_r_&y繤*m[bs]!yVBmJz%zR @JJ 'jNt=z=)o3@,bN"zPt^QHh1ɽEz^a%}R5ˬ#d1psz=UZ9Q1zz"M0V$zܻ܋jFQV;4vznoᗚ{/=0oqvR+T{x^O$QRyB{Y/cJc3VL|)E+ Hk%a|܈ui}Ӻk?}5Upͯzy;}[/hCs{T\}SXU5Q"y/0~¸1bWСӈ'~8/LlLJ& H~);81+ag~>rxshlzS~(a<؍G;Ǩ9 =Kw6mm,HDc Bd~kǀe%a{i:iÀ^_}JQ [UpӃN@CECIWW% ׈hVyfSMK PCh(i)K`^EgGxvQQqp;y xTV dW(b$4DINģ$ip"DmEe&*_ 简W& (}n`1"]ՍgK1:b!_jgWudz}w1pÃIAkWQݠcgۙ6hԊRɂX NC7<5tw=$X0>wV8- [Γ3kwP[|f dވ{se_Z.ZlE8 C1~*lybOƃ ͘cAj'%)Z46ûƺ^*Aل&eq$T^d+nm.,:Ja5$ޅ͑JSy0sAN) VTo'@v[GiՑ|/5)0VVL; ܰ)O5>!mo`(/^2R=d/X$܆ ;y&+JIѦTULxjѡ@؆ɶJ(ѩIUfހcSGh LƓ 7ȁ6+;eEf鄳\·N ĚZqXbnԗOR=I&Au~ ;ELP?Zs' ǣsj"%"O+۾,J'NpzYOO\窈щAD>I(0 +3N9)!?ei]$ ݧT0 Kۊ4MjdS@$Tm NC+QړߊcL"ɬ E{-L 2t1Ƒ󭯝˯BͱCFFrnVIWE@)gv1,%҈B)7n{H ˆ 7mq#r bE"UU2HL^/ 3f7gN*vtbije=h; HH.8uӌP*Xݞ[K Bh^,F$=v^@ 1?t41 z&>J2J] RTiD}&=ab5l.֐e%tHʎq!qjlӇwM/@GMl[.#~E?ue{GH+h$d:[hfxrE/k+} ZRFʓ.~= rLaV.szLvnߏ;V]!0*pN6莩 fo@>DRzcqj46΋Ң . 3sF_ ÉbA􎑽`>2kzk@őӁ{_!)3:SZ VcJ<nBg{l[-;B;"zǕW>?fbMmTHpR*cT_ɼw@ۦ99macM2)cRQݓsvr$sO;-A֥r`GcĢ\ eȵgjQP[3\?O@Z BJ*~1& O Y~f︦H5ZG'+jn7Im/Y.*6S1Z?5Ih?lN HZ39+˴,NCj5ʢ~en{7L&#'7oR͘]g]tz= oDP կfuYL;)xwҺy5 j\4( >)SMrÙ)9$Je>l6<&w<}d٨V*(7b_vwI?:}H)Ug祷eM/^nst(W7JiNKfn>Y)uN2Y`}cKI]Mb V%GD EDyg֛%(Dd3-QћH};#=4r)ٕ;UNTHla*}q7ܴ?ph.唂y-HvRޡץ:u,x#a悖m ;&B+JP:x,BFg8)eP=GMj=#Vx.Vmgq>mUr:38¸m бsfWYaJ_ŪLݥ(nH/;L͂dWpbhЄ&?ǗXo_sGv }kvF(9OS0IqM bTNĞt"R՘17_Ϳ\ OjvڳyJ+䔞 Fj:YhO8ST>Ǥ6Z'YoXT>Hp#KI޷\.ūH/5J;AXm.uG6ʉ("`BU J~,W8x.Z| 鼲pMrQ!ϡrU?IYM3fMVK;7 Ckzwl%Q*X(VS"OP3t#RCer\i0)5˵Ԑiw5ȧ6c;^ YWYc8[Uf6&HnF1M 9> vPGe! ʃ9רzB69'A*jhȨ8:߲xmҦz_$ qW'':HB4M͙Te&Sl z~V_oR.zܪ<4PrQ{{Vm8zڬN"i(_c#X"H֫CU8tK}V}G[+Bdj1ۇ!H_urZk/ϩ%n|xy6Rϴeus[Ӏ&X`߽*{J5uP2CݮOE=uq7j34\؋;2Eǻksjv)ڼfͬu7KB:p<ri!;|dI}yZDwHg_ʎ;‘YKP$6&ĥP<9h ;ɛx;]+-&(G@pїx0yM( F~ZXE{Rk p)47~ w'үEM/K'0ڪz'OׯcLw=$@N5xg~]{gZh篟]K?11%me .8f$udkGo]dedChDR@,#X5D#U[E'4L gKM- ŰJX,faT9Dgkhwn)Os Hkih^m{c.bd'͚C""̝ϰzs$z6Qyh8&3>ӓڢ dÕb=9 ޲?=†\b5,ȗRyG{Gj>cPicIwywZ?t[R jniH6j[l`oxv8hdzڟ { դ*&B9)mf6Q?[6)2ײ" NIPf9dqtlOvJXp9!V:F#^#HBb5آFB>\CAL 5kYliz4@ V*KNd À2ol+.5oFHyԫ rj {?f >:_KJ֍]SbJ׶I 3Զ^Vk衏mC(ԟSxC' :+f Sw$D`: 9k~%S;&Mzn%-=3*2uF'EjmHMIZUj1LTOxaB7FHKMkq9GnϗwGu cൟl܃WйiO@uyJ\DWf̑AudDt7H%6UPk$ք3#Pl2#̸PLy!?5jpWop˄\g br3aA,)) w9Q 65`MDik:;2xx N*#Vo $*8t*(Xr͵ZU5>w9޹R7a]i;1`COXuJcp~"4*D%Fb|{<HiAfa҃AJ$tH 0B#BPH][xs(k^}o|sIx IQ?ʜ? '`0Wߨ9[,T޻Jc4౼W%k$"ֽzZ7Лz'-9;Lͮ-]xV3mm'㣭[FlE#<-So ԑ-|JQGP5D[(@焒r'{*0cd{m AC()+"ApdU!. n7Rveo>DtIY6đWm=֫9=yy>8&IF&Vb+%r,퉸5z ?6sw?s,w8A^=l%b{AꑲE‚f-;TI8tQʇVBs{3aTFr2~{S8 M+N U *[oTx xo໥[Z`hLVZLIMvj^R"4{x@sfʭ̈z{h>k?>;5 ^X])W zwͮ JV9Y^틃W$򗑨X(-!,YR%6W7xZKբF·*'6Њ+?-dTZ}6}B̋X?CT#đtMzq uG;} &A[8/ae8:iz?Fik\Cպ0qXڭ_Lҧޗkd1}(`Ě .TK`䧦0{Cxمɼx1 DjZP &MUhaǗ8VW7"ś؁;?WǓڦFWc9%\#fPB:|ZglL:g/9ԙJ.>?ٛ+|Ɩ]R9^@1+ME [hwá"egJov x* e(U7q&IgY\$"fO]ɵN0jXǂfkEB uXǨ}9Ab OF#zEC dIIH`s<1E̻>=~j9͜^-‡9x ۅt^ U > z1_$ޅVs_|q+;'վրwZ{ ࢈~Vٽ G)GEHWN,`CX|5hPKʀ?YZy vʄfLQoF0#ʳ'@TRV|5Đ^֣k&fSk*\ q@QW".p!D6x-yT:Gg1ˋ9>BN X3/u|_co$gG)2xg MId#!&Yt>Aw~ c=gMߒdVV̺ 픪TrS9~9A ;Ǐ'KZ9|09#k1gE/HV1#XOz}RS :ͩDqЙx)OZⵓTkR}6._b1jh<"TƓ< l22'! e&$ar<)?Cb}BU{{7Z^=+k0>>TрP^u ,.,ƀnkY܂#?B>T(KC/1^PGjLژ9^Hj,m|74tM9ݻ9i;SuUn[߂! |\, .0jVgz ,5E(𕋏8|Pteq4C> t,0yw!!"nx|13p y %҈bI܂ :9؜Қd^뜷r ¡ӃT -[Vw PӪ s y{ަ+ʵZ ucvIH)u5F ׫f`,:z $8Xx X3 Cg~ D-2/&Dj?"L=R%Ɵ _mփkYXK {y՗6oihD=̡}~P1&X5ߢS{z# K0W_kW1*#p3EYA]9@< |y6֜tݘam;iֳ;܃s VooyN3X #Ȭ^|,@y`S#(^""SA.{>xUyEMURufE6Kaak5" -נ4h;qlf|7ayњeIab~*Цmua(r_%OO?!'S+|؄OBM/xG'%Y>ؐ$>q+)6o!qUi=4N]An0 #N屜C?0D4.]tARA}HbDEz|w Z\ TeA`0ZT3O}r_PWYм9?é~w( EA# mXP'IShI &Z "$7\\|I',Ʌvq6(x!MdpkXpHܯqi>JNs8dlz-w+Am,q9cC6I݂5)4Epg{.LŒݘXd&qݱ @dT1C_ݼYާ*J*(.vCʛ+/ hltT¬JR.^t;{QeЎޯͼMgVp~۸#F&jwϕhيc<ʼn퍤L$5cI@O]ǢG`U\FJ( df I*yFfdS9o?ou,bpm<c/Kz%&ހnz6ݗK19#]A817X$M?4㲰KW&r|ѵK% / u錑n|\ḢPLn-1𞤱uJUud0VbQ8$ I }*V/+2^i._XZUHaj"̜I3KhxrƐ l(ṑsC󹮸|VruW)1zdY|a'[[;¡xVkz(abEx%B/m(H(<Gh~q04Vn扬T2SVAsc湴iRa^+yU\sXV A-zh %reZޞq+S'&w UIKtgE_sz/qB{ }~#ݩ\c#Ҭ07F62?0X:j( /޷8Q/xarkoG~.Iabo]77 md vU eUa(ަ4ng@)~fFiZi ]LD 8zoRg" J[fhwV$_B+mV` AkFE7t <)6XQX{C"eG'ցҠA}d=TڳZaW鼆9"b!2#d֮DAZE*sCs@"F򕄸(G* \g$y~dn_|ueb?Bu쇜i_飕6N5mѭ:CMQKx\#췈 @?Cd m+밬A4Щ@@K Re3#sY=xDKV]NU!Uն2zm.9bBcuX[|T'HL-JR$93,#o#FUSޙfԞVKg>j1dBjy`象*҄^(a0R~OK~.>د2M#L-0>t=V!c#lvo:rNGD恥F(| mZƵr$ RGu!mk꾩#INRWY'WiWw偑 . k (k#}/p #6xi$I{HC,C쨗 8n@KcZT|GW$֛'MB1<jc5.X#z[Gv4G-5_>C6SQ 皾~`|=F !rdnWlZooϋ 6s׈9.yO6zba7&Xϴ..Q\W ds̵%ӸjCrEJAqG2adTaӆL"!X1l)(XA/uUZk_M'R"I6$h*UbO5pxJF-yJp(:>*}!S2Nazn} M٥ +u(@4c'ǻӺ |h&?nfK\B#Rd"اbU nl)Nc93%ύ~mUOzt$v>LaGfdL3wݢ3he{L em.HXO!v)0G&PS.+<#fgθ3$lPT,J} (X%}E3 .hT㼒|%\7/;cL]SSĭP_?WSgDyJLh!Ja?l;8'Y87,=2 7Z9  3khsDʰ0mⲌAHK THʾ^ʹ^j2r8>ڋaXY$IQmER3(CC?QL\ |0pdȖ7"l<ƣXbGDƾT./y Lq^q]nExA /5+ ͋ޗ\UNc(9$@ HP? ݌񫪣l+<)ΆRI9k(ݻS+O"JivƆ$kCtv}#a\8ۥ1Et\L6lM]:5x%0^Y$0kϲYW\n5ʭ|Ơ}YK̻ZWm }^%%x}%I8L":seN)BnR]13#7l\_lwo-N`P>좋/Y4US7ZeizmI+g#h''NsF˾5g&T>BQSMy+F|33;y}URJ{_AT‚Gް1. ߲:{diQ!Â~hg^B]Xa__v&O(p0I(^3g}C n niZv9]y fR2@z#Cލ)&[%N|#Tƣ ]+e̜ſxB$;.i)Q/.dj@4*x0K CN!͏i:e԰ʻJ3̥Ҝݚ`Q{h?fP\"uS#f8 uMQB| yB( Lʄ%\O^@/Ngʒz1c2#SB4c$ Nv%؞(~,ݥXق?@`I:M>|Z"ULښqdzbaD%Kj<1!s󳑍L&b<*+(`M}!?9VgIsw ߅{. 6E _%Q0IcxВ}ڪ,x6)?< ̛#Xn :Yڒ(dTI0 'tѐ"Gnu-DeF6+Pi!JT&@K'm}%F 9Z۫"ȟA $ ,Y&xլH\/ o["bۜ lZ̽f΍)E~l&TMf\bnsQ D`C;Ұ=r !δ:@)27݀^߁%Wi?U*Jd{_^n7}ٴ4|ܱG :Z isa5w%>,Ҽ }AOх#CHdbaYc``[v_2O22Kqw*⟓_T@[zBbNEP0ҕGJ$נWLr|)=j0RsVHV^Z4 @{&ٍAO }KO-NsdOywom Ԃ?X*<֞O7ǒZNoSYgӆJ1_9'f>3+t[ؽekR㦸2]+ se]`ZՑw#yhP+Yېؼn P _'BeY&,%f1|5B8S/Q1D'L#j ~NTEcOgE|s1*!m8>du -R}?mI.جΚb5yODK2ZӐfM7.Ȅ^З(Hli 7)1uX]YŪ1 ILBq0^QG t7kKN?C;Юnik#KM5 K` ģ*ӓX[!M0FX 2 RPu&e0J1%'NǜB:%ΖH5V :dX@s,lhK&˝gR>^%Yn6xC7܎R;46f͖8ن<.|p.m5(ESQuRo"r $5>|{ȏ0vb`0>44[ lvS,\PJe-\ש +|}J*V3Z؃)h˱& eP4uAB>4fD+(1nI+LϚBO {7>J;~MmF VRv#t;u{߭w .+ G`锷xQ>LCpPs'jv>MK9A 8q.~= DoobSqk4?˵z0֓8֓& ykA1f Cv8FL&biPD 0{[RDR@{@k*~  3A .f)|5h+ԩ 8#ULˆ&iٞA| )Qh(EQ TэN vhM :Wj}  ?O2+8ɗ8J?0Lv gCs:K *9#OqqC A)6 "XF9Oza/VO $WKG!r 9gw -p(s(,xR^^S8,:T(-kB^/oV%2$YGP(]+ U 6.{t1_pr5 ,=rbL?PL\o"rzYU 8j; "%_ h "zulQl ; dz+nN9xup|  OyW~f #t %'րfBސ?#K*s) xl 5&gp!AyTL`ALu6c/%(w(l߃8BM\EqIzn _&hK_[I )6BeJXz]Dm$-$fHlp@'Y*%2 ~PkG 53Araxj,u>(bs8u y,@qE1+,ݢ # !%()I.elٴ`' G/  N "W'* !]{̖'},j8z @^I'TPkr6X{N.9ؐoB,.0eD2t ESwjP ‚T 9PQ)wWT  kHӣʶ_B-bQg hp`~hgl } IVO4`^?E8c&6vJ|p.*oD V|Q?` ._DS$ʌx  g q0|p6& &$3+j >E' J^;VA2U]Drj 3=[L^C@?qDBR%uQ xl)V=)ua=W <7AN 6\hI.GhtF/f<(Uj}ecg,hH6~fJc2G ( OyS*Mek3{ F !p)Q b+FHi7 FRe8ZDL :9O 8s3J]i 8y4* CW4* iFv'Z# 4w4<o( D9xNjki FE%W ڧ;E?SQc&+ O  ׀o J5F+ ;9I$1gF_=h/7CsC ``C}bl1&9&DJ?+^7M'9N$ "4I1nk%zRh[u{! +*R%5 EH ; _d`# L#)JiVO\J{=| ToIL/5 7= c~CnLOmdN D~ #H  ?(wI X{}> 2 s@V* +5vSZ'8  #bcXT  | ,j~H^iX(F L G MbZp sPchP2s[  EA &KbP 61:Y:`wk0G lB? 3Y?L@)8KvftYOmm1HBHHCJ|kv ̔ ?[ .*L_B C &LM\ٵ.sP8 0`k( c@͍ &kTqb˰ C,F-`Ae[Dw GLvKbDxPceEIt9b ٍwqBg#>7SwsA-u"0info-beamer-1.0~pre4/.git/objects/pack/pack-83620dd98d777142110016f667948c2384edfa3e.pack0000444000175000017500000224730712452774240024437 0ustar nknkPACKVxK 0}N1R(3W^$j~LS^kU0P$B)s?H@Y;Q8V+WDCN'cYgXK!:T>Zxls]O]3%o QeJkT* U^{;~Ƀ&FbxKj0нN1BGPJWBkmIN+7;3D$RRBZA[1O⌝ MYkyoѦ92H3"^sm[5W\^ߥ>kV Z**D۾9RĿ@Lu 896a\ :v %JxAN0 E9H%m*!ĊBn2iR%enOf8lDLn0^p6hQ4ُ(vI& 턽"Nk2Y*EX2<=FxbO{W9z44¦mx#/rg.) {I>d1M@既m[b:1_,7l R?Ȟᵕx5SpWN sӝavwxMj!@ὧ} a*WȺ2-Į } Y?>xs0C d')lS%T smvGyёsML٦]Iњ Oo^O+k70^/jKU$|v)t5Vp%VZ!*@mǶ6LF \ @ak%ʁ$*ńť 1z9pʾ^U-jLY-Fu>lû<nygp-l7xZSGm-ǿi1\ڮB]h/MMÝ x;!ОSЛ~CbW`Ȓ캆ek,_Fg DC &dM1RֈAs+] T,N R-d}Lky퍞[䥾or.|*o|IR"fozpcުNA0xj0 лBX#[PFO"kit>`F7j^ rIFDJYKLSb6oP#fC 2*V3[)Ei~.uy-8S)Rn뺌a9tn [ڭ˰cm7d AGǘx;n0{b# z}D@S+b%OqȊ9VbrW٥c1:Qo}tkNX;9ƣu^e/ }䋏[>|Kc&K @붕)k><ƾBjx=!@SЛ+`= C$q ^߽,2q,b.};uކ4 #@1'(.}!;l]_W)/{S9UjQ^˓JֵK[HM=`aF x̽n @ᝧR*?1)%oPuͅ{0n۷3?zm(e$eFcla tgl\:(覈D1L&hֱD`68kKX׸iyh@8w«RXsNKA<9 /jv%!c6 W.ܰ3ZrxM 0@}N1;Afv+:?34`ToY멣'%^ళy6pI`=L\v˧\sJ&m='G8Z꧖uE.@ca`&T[mV'io~;CxM0@}OѽMq\)%Xrwo]D{>zә` Zhܓ J$vYf3}☽Bfә,Aƺ\Vw|<}&>ruҹD} r]5_<:\}lLMXTRCx;n ОSLik)RL!F1f5?BWD`z)M83HM@IfEM0d%阰YLS>&cM.1kMP)&xέ3|k]$P`! eExAN = c\y03Ķ<GpGW eOT% FiDB^E7ږhzsO]BHABkIszMX~V>vp;:4]g t*r ֻc|蟛PwxAn ;X)H0U9 =RĦ8}F )Y1QZCڻv9+Y}.%dPtKXHs 4'γ,9j>n]< mVԶ!_aFHKjp1FnIxA ;n,`M<6PZofz. '}.X#՚,][Hb)1, BwmEdM]D,:ϥw_CVk~VBxPj0+^0# P =Je%l[2zWIeaId jefн$!D+v5[1KPkeu챗CVR#ثAԒ8Ü&eOj{=j{:uÞzw),6%}8k 4!to0#mx1]v\ 3- H%Pv1@pbbw{/\R]l+ .|xLKx+v8\dc_[F|C{xN0|JKQQS;]bq{T*3L(xM6$DQy)8%"vS1$%|UI'rr?kT&mI{qNʸZ,aRoVՒVx#$ B/ϠE8"y[޸~0v_wn >.鸎,+m' i%| 3;/exA 0E94iӂgpdf4H [ 7x˓3u >Ѐz-"V=¹bd(L̠ǭ1P/DVeKpM\ Z{#Qk;Ԉ*yNߡfu)kTV4s~_ `Hx=n!@SLɚY(J+AFbD}#_,nDm7JI֬Fk27#\=~yKXVxQ^kS^AC -|@Rx/?HWh=eQ x=!ОSLob`BbW,zWv4%e_9?xIyꁭ88u`D).dC#G03b*l6ݗlHFxAn @=}`0nW9DDZ$ӠE,!Bcj!}YW$B(dӢsdorg!\6*w#U^߹|:N*m9R 0[g:~ 'U PM%xn!{bH(U~e"#sa)fbzbH#&$&(briaL`6IFc4)ui[Vx'mNIa*.TzK wiT 'Zw.C(k9vx8^t#U@x1!WЛ8`I D XM5hž\L8d` Bԓ]CHHcv1pȐv~'v)[*&|קp}Wc95X'V ,wwNjloa=)UyEؚxPj0~ @i֑K>~RO̶ܢ4d`\?W#ڈh#^V(0M^[XItkf# _ӯ;N* d:v[ f^x.'Y P( ץ2T?5I}x1n Wl)K)Upe.2-|ߏnMlh&11'?ei(&`MJ>&b 9YAcHLGh+v+5;h38MG-GD"g qip{.yۦc tpFk4S ھd]C9YDx;0 =Ȏ6?K113'Fx]D-QHs ̐(c~'D 'ReI"5H4 1dPqKlM}* O}_,gu@ۺ18->ԧDex;j1D9EK`G㖺Y$ |CEWE.T`IXu*"1D~Sm1>ϑKAq mƄ˹Pb?_{L*Ip*ÆaKE..1{u6QV޹=8BRۭ)o.Ǡ/˜1u ym;suq;^lUa xNC&md`aS㘴gL.یefgZkYT] $/Y>E|pc:!SN?[FxMJ19E-Q* x $Iq, fXbDkYk2F; &ZgEIw(GSXKs6H.'kU8xm}^VJF@/GQn+"jOVnJQΜ9`vep i0Y~h} N9LoLdxMj0@O1B@ hFj]d%>C*4T(KMNHs,9#ޭk>\m;q79;XC c/cY.ڜxyɻPx8^mw6 LTxMn1 @}N}r~ z#&jˆT1I8/| 0h9-X);ǛNz /%k}.'6.RD  *rz( `z@hΩB]qyC7;ƹ)m Px; 1>^?+`L؀!*^`730FKDγSfm)I:NA:@O%FB"/N)hFؒHǘjZf-WDZ3_AjkBD 'ecS78] B"A)GU{'b1,B$ L%)!1Y8"&$>z+T>\5vz'&OdLjV-R5?xK 0}NPtD\yL0`z,YBc˄ Eom*6g[j"H1L%ҏ!E4͑E8ƫux^*=׳X7-KɋJԖOqrk[و/C@xAN =NW^,-OJ/ {+X79DEP#;w= 't^f#J~lk^7=nEWEarD\rpB4K:_Xg; FxK =oIq\Ðb =ozc.hYQF/q)i JE211FH(j{ )8CGf#e'+ } kmwx=OIcl7P9,RPݶ;?:U:=KeM0HP xM @ὧp_(DRj{ >xhFVL3'bڬ5-O!C $ѳq'2!%38DyЦ_N˧p- Q_5F}]Kk"ChK@x1n0 ]% /t&)["o햛CͧO sl!drJfB&w}X\%Tθ&6T zFiaEG|_>/y~zG,1` mkszfkCK>Q|^=ߚk2!p5J}۪T6/.O8FVYM}܃KQIx1n {N}/(J+# c?B4 ,ڻ%00fĊc#casYsm\<,!8'F?k6^,Y2sHXh6*$ȇS18\]y̜:|?h|UڳX.En`} sr'-,MU? ?h@O!zVvRu4>8QxOK0..tDܕ-UA=.ɋ IiS~z˞< 0LҨp-ґբ͖kWx' ,pa3QޓF=R UܖTVrJjιM#T]F8d[˝ sqt B(#+.8g6}șOH !z>ǗsVׯ)tL;)eɭ*/zI)|_eO aZ(҆%@6È ryx=O1 @ WRS%vsшRіOrdG-Q7(5H9!kYM[bc(qKG#'cpԽlUOFMà:Q|.D s8ɞ,'vӻ^R)xosbo/rxΘ8 05Bu nR&g B_j|A\>09@N&,Iekc~>o ,]@jU-+n#x=t}TMjLbGNpBWx%ύxA ;nbBYHr۶:?1 Ҿȳ-G!C>xK =I30Ob+4Xh(m1J!0ihL0hgUىuj\::DBJ1IkrY_][ Z@63Bx;n! ОS&0 EQ\akci~b7WH7,TPI= o%{Kh(qb,ŝ2ldTW&-H!9a95ǀ]vC~kz]{/ 2!#:=inعZj0ǵyBvJx91ܧ yŶDsK݂^3  H2 \BPZ梚9za-fk'[mUi J* [XbR 1<ڎW-]sc97ȅX9W:YomY4cѵL%E͜xK 0C> ebC)] ]=bI__-T 9v4:ai@lH^,1ص$9XݤV=o% 9|e>Nz=X7Uږ%*/D+ugdERm'rHxOk0CN-]ky4)K (?$9}i230{^ID鞰m5 kuӏs1/ ] BUͰohj'i%lG.v 2GA KeZU]7|܋s&sҁ]\/خޮ#Ц~k.2|A|$7v6P+\ZK!*^e p?=hb\ )ٕ!Lz x;!ОSЛf+` ̐%_,_ZѐƁ <{6;brS!@ØlM;6:";$ dYBA6w-\>{_,wmz  Xu-SEA5x;!ОSLo40|Fc5!]0,׿9tS\r}׼m!6(5=N"esShNTAV>*'u%2qvœKLؖvl&`;:'$DRr8/wxKӺM҇l[i޵9=^:5l Ix-=N0@>)?B[AECC=KJ%{`4W7fFh`3Fr#Y)  9 'Rփ6*TXOecX  ZOr$I(!:k ^Ӻ'~S:SFj-i//tVZٙ ҎwR~~HWOx1n @ўSL%0`#V[ [ #f~]~ߛDBD 1&Ѧ$6$^ցD![b7NMNF4?I{O r>`‡6ZT׵.TB0ƋrxR7\IvOxIj0 ~yI,(~gE!KqzazS$M7˒94%̜eh zukAI͊PHBȊj+9}|W|—޲~Skw-2irrG]ov?z}9=TKxA ;ػa’/x6%)ŴT}~L2}!GD:!摣hcLޓ0ZMAY2K>OA2^'-F}i[.˫,W@kᤍ*ZKT{eQS0yEVxMK0յMm+"ʂ "7 V[fƇgɗ[Mj..xu"ހ:gy"@bi#0*Xb! %[L18aB xI 0}N  + FT=g'!bʅL0 % "ʌhPak] ALL4O u~A1zM?xE_stѥ'QֵOE /FB` xK =`o 7$Ƹ R[ zҹ)TȂBdm ZDJ3*񎝷!Al)*FQFE<Һ|ZqO"s8)M*;fں1)N{mI/4A xj >Ҡ&?PDM_iO6 |0`1A{0l hV (D@Id‣ŃzbمfKQ[='^)]z̢2J 9x_.XC3fRa G˕Zϱ _A?7 8_xKn D1`m,> v^ENdMyZWg|t '6g2HON"Q(Txlp7L^ߔ3߉@M^zCj)}ϽKR'\n q SngFuloagol[>/[䰿?]x;n0 ]^c(: rz=A79T-_,2&냔RCnFpM %21V6׵z>(5J,y~}4~K{59m}r3"|C4ܷͩO3t/nht, ڄ/J x1O0wPI!D*K bDXuvZIaae|ˑdjֲZu(zIZvH>lDq!jSlDX5DƖaBგ\=[=SDUM-3Ldp&8 W< F6P\wU ):ڦm?g|*!ՁY@A$tW xOn}9@Ͽ2^Ԓ -hcΧt3D1![0̕Kn7EWcaxA 0}N 3Mۉ +3?DW^OYmD1<6cfsϴamAÌCLB`J":UL4*Roˣn%1Vz_8Dfi]ΪwLiOGYxAK0stJ'd7M$w"xax 8GaRdNQVMf]Pj48HXtz H*e2uS.s =]n]ϽERíBt6ϡ5{hc-#d†WwݫpV!pPϾ'-Ɂ.J6'ǤRr+Iyc(V8yZvc+r\xoI<_t{5!+xI 1@}"{AR* rޥA2mB,*n0i=*C]6A$g7Z3`DD炰6i#$ Hʃ[KQi+:o%ݩ;ޗc3)@tCؖ%F˝5=}W FxAN =?F>Nb~t\)36iT n_z,% ]Qbó$bFvjR: ZxNbq$; isD\} *!G%yns1XcT۶.-%;P t@D+ A_$m_β~qUVxJ0E6DGDJèƦCD MJ`>6VԢZ1Q`ktTC`[9QXiePsLcr 9l/#: 㶬Am/euSו_!G&RӴ-+O6ʜ6S`A5E)U\L8BDx]*> }SL3f kj\tWBwJt@:T?Jx;n!ОSL~ HWH E.M_+Lfhut&aiJ'GN{ShD'oE9[: łK)UuL>y~߅oNgp  :S=MntV:kC;ҢLxMn =}TU] YYF2qDpr }7@!P%hL^bt\bRpE=}hDN̚m^]]|FP1;}_i&/2yKJZգ6'?U?h KmS}pnDӟ xA ;ػYeO~3KJT}sB%8ȔsAIсTYӦ 9:+B 9Jm-#{6iӲl-=᦯2~.M}>9=MYO3B _B=xj0z,+?MrU"-M+ 7391*b(%ZjeUZו!ctbmDkÖQa,S3 N^0k73|^ݞ{ZiCU]'R8M>gS8KⲱP||8_0![I2<4 LWbx=N1@~O1] %3Xb@3SI U>Eb&&O|brDg%s[ qn?Ҝ#3hk"Qj)}sl8 `#ay Cmp:7.U,xJ1yIx<'_`fF=.PJ'@,5!.5DK\u!y2+5V]Ir(V64 )ގI㘽;IrۋJ.ғ>[ߋA\Ơ+UZSga_N xM 0}N NRq\O/`M 7@8@a̎)4& G8JaDv^\B6¤dsmzmf}*K^^Kq9@HK٪^?; xA ;1,K/xeIA&[,9ϓB)$!d2d+iꦦpJ0,y s=|R&ۣqΔ =ZiIs6eq9*8L1~@kq`sWy ?.MmSƘׅ+$ ~D/89uc3/opz??/Zjx 0 @{ 9q !N6?)ޫE%x4ZVĮ'D)tQ ΡCRiV.:W>2?,%cRsa۞|{q)g8*eߧ'C@8|CؤeruԪ`yTXgRn?uk>JxK 0}NP0M "K@& .¬CBqʕ)$7^ zR(V-0Z 1HB@3H${dN[y+V}MG֖λN_5F۲ZIny9`V?H4x˻j1@^_1}h BHf+#k| )/ۛCFNя%&9q:2#3:7;5:$"rb9jo,mtB}U&8c6A@(@!LNFTem;CCRF ]JыM[ՏyV'}?\%ei`oqx[Қ?Xki~JBxMj0EWq%E?-Cu 秧X Kf 8A`7>+hvj6] .%(S<<@No6*zRagHDc7Po[9)&7\g^zR}ϡ :1 /xQqwƶŌ *\8]VW$Y"xQ]k0|ׯ ŵq뎖^iz1U,*[F~}4/B@nFVvݶFwRuǛ(UTݱ  2;F-\rf6h\ZpNp|8EO\ja<+M@T؈m$s0ؔJvg!SHa )3Ag"KpG;T9 6 s^tnQ:aO)H%r*ƇIp|u>y޽}ۖbxt)?x2 5Rdv̌;;O@y+4J9xNH0YKo~)[I}]y xA ;ػYJ/x^v|VUN4wS!RRH)G󤪏G2'&VBыmju}*zuF;8-m]Kk4}׺|t7_EgxIN0@ѽOQ{ƕxkUE&6@_\1adw6fHf0-Q0N(%$/Vea츐w/:& l[+ΙT ߵX{:M3yވ7 ޯQky19N2Q k 7x//!}{=.4c/9*}v:[e҉nFu”ޅH>7K6L-vCM@25#^pW |<~_$ckan&m޵RË\D cx:;E)> Ojt c]LxKK@+^(7"RFإ̽cL{k7]9q2֚B4JF]UXE&RKRFGlִꜱ6żJ%J mVcw}y8l:NarI%e^`^&ʄap1KXd˼Rj lv0G2`_ssoG ϿCs޽n(N {"b0+B'!.c/1J5r>x;n0D{bR4? U w6I4(2"H97ӛPfmK'|D%`2$XbD9X?[aN ?jwAxϯO.߅&h;xCn[]T049h$F>=qg8ԿkBAD}2ITJF`g&?F@0&845@`MB`3M Q)[>w?>iua4fGv*S 6%JDϔlW  ~i↞pQcP'M<&Je^#޲Ge["yVUSI hNG<ʷ*.< ξFsfxKJ1s^*$|ހ+:$!sWU3UP3ڋٍwB Ѡdjrb2!uuĐK5j|)hJ~ uͶ9S]xM!@ὧ@OmBV,jL;O_!E w-z\uް"Z6k̐<1m2_Jx;!ОSLecb$Xyٕ ^_ U((QLlA tMtX92bNţQ;Kb2$MF h{p]ZNs]!RDG(R[:?[o`^sZ -G)xIN0E9E-$2J , Xrl㡹>Isz5+iqũuEq* bь ~qOϋ]eL[cv&:nmbyQA R}w<@%xwAbJpHk C2u+g|۲oZM`\yS] '%/8ʡnMS=ܞ y1tx;n ОSLi #EQ3H޽~ )_"Er&m&a4!d8)!9KQ]tU5>脇 >۳u7/0v!‡6Zҏ)jџ}g`׺sY|1Go x;!ОSЛc$ z}_?E4`f&Kt`-U_Au!xԨtֵC@أ.$Kwg&4gK~ɻVncWF"$Q_T׵.OUI8?xAj0zKîVP^RcYKŖ_m.3L]TтeHlKd}L}ˢ 9TT{Nj!v^PEx!VyۼrO]O{,XZvE@Ą< !vVvfAVV3uup}M:xK 0}N1{A2 "t2Cm#1+otf ;%uJ ='\4%1x#0K;o\w"e͒.B.e:3 ux,׼4UR?z.|-j,4jkjk1 hcFrDt x;0 =ȎJ1qfqH)MpVE=E#80'uPi\%^5Zƀ1/u-S#Sr/WBxIj1zE߃=$0!'!g-LG4M~VP`3 aJWL9<|K1J)8b& I8zڢ44'EGh*|˙VxϯO.chk5mL7Ԉ*^z7 ^lJ,휠ve'qT0z@~^ԯbVV— x 1{]L2'[<Jjڂυۻ#Ys&cTzosR !'? x 0 {wA5]/xΒ/x~̼`HJє fơ̳{rG%i9̊H9"6$D%tekzZ凿K*w}_jgb"m]ktXWs_R@y xA ;nb’/xMIl1Hj3lF/`aJSjT0GFBc3䲓Ĩt̵}Ү]V}ۧqlgWm!`'0mks^i?& x;!ОSЛlf>KbW`Ȓ .D1sMh9Ov!dVwنD٢q6E003s%P|e{M?}{iVs4A 1`BZ>xAn! ;R TE= =m DM߷_fT%1dܶ̉S)sGJꋹ穷lz%6zg'=|Ƭ+RUγ^| /5̘ vuB4TD:]UL>E3.d91mA%16f;|\}ZT Q'J#i*&¯OMSdړ \-mcvSDLx˽ ݤJKqrrw4W$m1f]݀Vcedz+E 9V>+DW #Iiqd RPK.p[sIÃy\czE*%F{8IRmV)}iamtR\5dG xM @=`ob+gHIl1z}{{3ˠKL٪ mpD_ 6шWCIBr :] GkT2"̱.kiy*3-P@ԶK[?>( x10 =Ȏ8_`vWDTR>|ۯof5 eHdJ9X<S6[Bd11bb9OÈ'T}n=Vew{Z껖}_.Gi[ڻ?]i>xA ;R6"UUOW1 RR*Bv3*01i< M44ysتhsEVGLX;>:lW~SYV~j>ȦpZ#mie[>Жm:|YG xM B!ཧp UWh=:#Ox ?Dt!!|@ >2'xp,juM ftEaB &DzJ~+Z>wcgD\,cT׵.Oq/d@ xA ;1 l Mbr|8 @mYrc>ύ}f#iDF xA ;nbE($x awIIli(.LBA"K K9b.2DkRuhtɸd,?Y\JraRsjU?eY_]83Mk>PԖ!OōvRJ@ xK 0}N1{A&D\yדdb4UWp Ҫ&LѲ\>E(O\xRe+l0q3{tl h1cZ;\ko7)"/'ѫEc`.KiM־T/Z*SFQ xK! =`ob:&Ƹ -A|כ%T*+)J! 4;C)t6rA %sQ8$A.89 bxyof_γCYn䐼=0y_ڻ?M^q&@HxA0@}O1{3uW^83&P \u1RXԐ%5V0H#j}xRAMk;%A/b7: Q;n?QN/o4j&gFwi 7ىs 28QV)U* ,M8IL ّŎ&/q8*TIhiQxAjC!н}!JUί| ~M o{۾E o YRLѢ?Rbԥ8YO#sZQy1d3jEsrkP1<(i 7Û6Zض!!%%ZvR_l, md HǼϘxRb xA! ;nb HO~s%]~78CD/]2:.HA$+KHPXuN H3c6,͈(EhmkV}7?|~jvr90TF~]BkxM 0@}N mq\O&Sĉz|{woN$QJ+'K3%Ddl>z$SPH<21!9CL:;tr '4@ .+lF/\i\J}2z,tZeS!u;ݙ$ӗǞR7`vH xK! =`obRda+ດ6C2x}x]V&( a(9֋ f^ADcV2/ #f ^5Hǘ9s>ǼF}ʛ'{Ͻ}_Unrw,m _ces-PNCKx;j0{bC! MHZ*+fjc:VW-y:hBb~tX;C j2q$,h/aq00O86Sy4qK1Jk5+5Q=;ߜp/xBRCbk:s||~CWCȲlyaUpxAN0 E=3 i;+%CId.[ 3Vn#N4Q1tQP׬pPhţP[ʫ~0ZЌH82o1`3¡N#asvUxMj1 @O}GcPJVBֲ%3xp= }sPBZ\vNF#ܰ'x$)HXq6΍X뱕 s?}l|"c?E`w ZSosgsp]#gFxK 1Ds L@ĕWpI:p&;zEIcyQ.R^Y4u 4`6uӓQՠ zO!!!)$?Q{mp}VhNsI]R1J+mjuۊo5 F+713O?TKfxKn! }ĘaKQ4\!k63~B*T-$)=z2opM2;ME+ED 3D 0\F]{i맴[{G,vUE]h`p!9}!=A7H0AA QЎ-wM8 Zmm4*GjdB*=ԑE [ S<v=N?_\ 6{m3-<"cjv'Wή1C~zZ{3qyHn%0iXZ^keZ+6GAy*'rn/s vFP ƃI뜝XXjt aY<:KG$Z&ǟ8+ȟo/j)QxA ;nbXH`ftf q8#ڠ*gR֑3F!!X3!CjQ)d<[AXZwV=.?TΒ^%(PJVkboG9Y֖X|DxK 09ۊ /IW^kB*\0ô J(E5hz"-Xge6GO4ȒqdRabcecP+ip}7~ NsI]Ҷ͇gZo{"\ZMQR, R\q'~FxQj0 B!նbX 1m8+f0M()QȑP9<Ť3.Y=[0%goE$0bH̗X9ֽ}U\(+|-UsT"rʾmu {_f0c~rۨ{H xA ;nbؕ/x^%%A>78]2"\#<%tUs0fPyruX%DĘ$dBp Jt!dj1yzUf{w}_ '1؃LٖOS+@xM @=`ob~W^5Pח+덈}NVhAaH&3:X*GAIhA+^Q$ Qf+$l( /秶6#.G*ߒX|=jE,u-KHckIe:GF)x1N0@ާpy xA ;nb`Yْ/x޲KJbm/xLo`Lt2F?fqRD@sgxBE 9!@BIlxekZ姽+/\>W*cGыQDs&oZ{pW1_Vm@ xA ;nb[Hj[{Uy,ɰ7D 5J:TÔ Ϛd;CZ]0CH/䟀WL؀+1 !WРP] `=IFR/M*$[|o咁}Ej$Dp6D G\}tCuїqt>rْq)UusS!6G'~7Bx;0 =Ȏuj !&ڮ?)\_ͼ̘ei86 BG!"K t[m4DN" kD-b3@峎Ӻ2yhy=v&6E uKtǘz+Vlr_BxK 0}N1{AɯW^dfB+*xz{^[UJsdujQ%ffE {&U\1^QX1II)0Jbhkò#ppQm:sclgei^ھ ޴塳HwxA0{_ѻ٥PO~vR>ب(<ӄI$'@5;@CUf A.F"ai#4fN\bFYަ{'{#}Y]w0^繴&OMw[-.Dʗ xM 0@}N $ +N`^^{Z0%,L(0d~4'T榯nkf<)a'WHG6{m}&[?s\j]3Ⱥ,si6?˜xM @=)Nb+zbOjܿ*d2؊%͙ؠ?Aw(Z@`s.bJ63jBHw6.ϥ&8).Kڶ CrFpFki*R=7PT;<}fXhGzx;0 =Ȏmb !&خA)JR>\Dw%#Aa"9YP`&ϡcD4O11 6w5|JZݸ[PH~R{eNFbt/¶dE:xn0D{bHw1H(U~!+`/O9̼єzXCz5D;4uZ ĮT@Z(nԖ $謱Ze;"%gx[j]o_j4hP-buM }vT%Ք &pI);'.g tba@'ʼn!W5ix!'w}K3q85?o x;!ОSЛYc$b{_& . Y\C&٧NDd1a1H&\gww^~o}Z9\k" ,*mksS g?Ԙ x;0 =ȎXB+0DZVO%sj%DiUbZEfjT}kCĉ^]T ' Q={(h)g>j_C$\E2 8SezA xA ;ػYX(/x^`QmM}EtMK`b(q.[dKC$]pԓ:JR=D>VСȆJK18PoǼ4"|CJ{4m H;Ԉ*zzC`S2>m*zIIxA ;ػa61Ɠ_LaIR KeQEƄM Rβ!gx[䦨PkJd$J 3n iI- .{ MtlNG$E) F/Hc{\]DxK =RHL+2CJb?Togot28bbT-E0樚Te ,&I]aĔpJPh ,#V}[./Y?ޭrrΟJ(!8۲1i}?fx;n!ОU>RgATقk> D 8۷7;dBmWuxe% I|G m" 6haYJZ߽+]pƍO*<>I( YlQ}/3zUTjM x;!ОSЛca &)2M6QXmZsQGju] "Z烋dm)g~|J1J{ޖ釼x֗彔1sFCF @KTC}[r@ x;!ОSЛe%Xykv$ ^3כ@21g9ƺP2bЬdbdL sH8Y$IPih]͋#Ocl,wf/mS*i4>@UxA!@ѽpJm 0\!k*`맯 ."-1{@( Z-JCƐQNC!4>F[(TcFM]>r򣍳  ZT{S?&k?*9Kj2Eo xK 0}N1{A2NAĕWpd4m+~vE'$Ic0>\yH eiP{:dmGTr-HK^&l@Jm:`p?fU<^ 9rmd.%8k=-25͚0RLVa@u&g\Rimy0/5Mp]aW^:nY`hykkT6p P?PL TFxIj0@ѽNQ4k(!Be lIr:O_!axbRy5ڡy FrbN:AOsnu&mVDiD!K핍Q56ྷQqL姤:^2-H%8ʜS|:UЯs{4GTϝ&`hOtx!{\I^%p vdzcAaLJǬ0y3uxє/]z 8N\s`8"U {/kim⍊=OM>oR#<s7œKƒzng*,< EGQxMj0 @O}XI,(^kٖR{+t޸Dk"*rTbD͝/^Y}e‚5[TCbZ8;V%s߷jG~{O@(Xm7֚rGC/(w(;.7:TsZGxIj1@ѽNQ{y.JnfU *!(g|򤋍9'#v|>`l}.QNi|yNh-6n~,p+GgoPF'bNRI){?"_\`0Rm+C$K xA ;nbE($x KJچR~LoVHT|b ˈ. lm9$0< QQP& Okym^;OZ>w*DZEoy>wޞ^O3jݷέn|jCx;nC!{Ne"K,&(J+^EFz$׷s4S"aӤيM`1#(^j圀HVsƣP3Eg'\~BQv:[FGSxͺY6ZT)/U j RF+Ksgz^wx{- S xK 1 }Oѽ iD\yױICmX^ @Vu_#1G'PXrBojuK+10jxbQ"pdhyoB}Ȼ/X,W<oOLu]q2? xK! =`obPHq\wh!_z*bIB{dЈ1G!G!„9,')$:x%= !DzB}+;w3:?$.8u-Ehe@x;j0ާ>HRlRfFY$%^!Uh"ctS!Mk@oV!4-UZie8K8/cGHV7~B]i] hTRh;v~pB`wsi KBl(n je/YH5 x;!ОSЛX>3$Xyk`f/z}_oZP<`M JL!DR`뼇ԙ]d#b~G[_Ag1+][7hXcT=mq#T@o x !;Up713Id a`$'ھ`^D&NglV8\vHnCB42D X;g)XAq@l4&X.ϽG}"/ne\UVX! }])Y6@- x;0 =ȎcK1qf7NJ LozjU2.*F 规B&gcXV8* %`"jJT+}[y[}ٞ{}_ZO1!dpl뺌Q0/Ɍ= x;!ОSЛᛘW`Ȓ^_`cd+1zCCL&d2@Zy2U'*bH@`WT@A瘷.7Z哏<[K{r˵$5B0A^VJmYu?>( xI 1@}N 2+:IU耱%Wpy9hє( 悡#wb5`b]ho#lLvDy|VyO}gTF '89)ȫo<@М xK 0}N |& .eҙ@?z}z)dP ֳ5Y~$RrΜ}p/&2 QѧJ~>L2~n\ߕc9\583 >0F ۲0ՙw@xKj0EѹVQ@-Ce JX`KZv 7Yaؐys x1ɊQ;GIhX1{Z•ן\xd|q6jJq1do[tV˫NMxAj0E: FJ)$zǚQEMZU0bɡWB0膤&UKℽ{>8&eOB6>nk\K8kKͲK'd1P:kM\%7y7UG\snpգ_.|\ܕ=&Z!xAn ;{ 0fYzz^C@_fơ yq!%D i2!QY$CW%# dRhC eŘro}+|O?UE/ެu }]SvG 伞d".KKxK 0}N1KE?W^uЂmJ=ozcB2ҨU:$xfELo`qyhTGXk"Jg[q6xk[/> }YhJ|U@ipA(r]ץwA;ckp OD xA !нpWѪ+qp_W299%k^{m"9Dbې)E >\ 9 Ep&84Һ|Z'iy&v(ں1)J+CXxA @=`ob)$Ƹ a$mi(+/7mQtHls!Kj&KÙF퐑0yE{kϩB~ƣ#OI>܏h>P\.KE*u^ޘ'FxAn ;{_y. I r ,8{v/0bp%9i%5͊H#/y\VBG?28oge$n( YBZinF8%L{%k QJG x;!ОSLob +`,YgoZuq(bCXR jdщWuc6VBd >R3YV"s}Jr\>pJJۜ)ZO k#A xAn @ѽO1JxKUMRx o{?VE`^hXhÉ(L×l="@nވIQ`e']-Y^ۭTRp5o>>}@㴬UËJ \=&/k9F8? |o(^˖dER\U>z/]<Wљ x;!ОSЛa@I |u z}":Cɤ`=&*.BplHc+HөTW)aef|FXoϭw{-ʜEĖȑ>Py[6?U}E? x; !SkBH+Ǒ+7fpGXbbJXq``3j$HTN=hsVs[MM#Ocw FOQ;A^(%h_; ZqݙAu x;0 =Ȏ@$T1qf7H6sά+!t69)eA@h)޴ڵMf=\D<IlL^*:{vѪ_|}i<[Q!0 eiSױQA} xA {uRzzݕMi|\ft ^zgbCI0n:@Y5)!y$ "ĔE>s-C4K޸}rfjlLvS'0eicں,]AH xK 0}N 3w@ĕWpL4Џix7b)8oc S) ylENM֮ YD΋0p\)lE\Fb>mM?մ_yz7xB(zD'm鶖C xK н}3RHj{{䂘]Ȗa%K.EkͱwBL;#yz|؈auEUjTrP?g1Ox340031QK,L/Je"%u6K?߸ks 9#1/='?4ckw:qIPE>ή~z%% 7=.[7|S2sR^3iq9͗}4҄7@:0P5k/c_h@M/Zg**)NJIp6)MTN%Ҥ|ɩgؼnӇ*MLOU{2x_׹CMٕ6UK(``]Q`KSLI;J&WgWR%r2>< UZSqҵ-Y[o<<*713ռԔ_V_{a*2Aq7!9RCf/lo*€"!yKL3AQʊ\ln܂bb38&ЊwKfg$FsǓ˛#mcUMRN)J1;dbԔ&RGnN &ulD-T5 /kp9oeP5teŝ̽ߥ+2O|e {>晊E+CT$ee04W1t vDM-?UUZZ(5jVLm"aNO7Y SVX4YJ}ʦh0z7=&'%?ۂY&?!TMYfJj>0| VnSqB'O|"EIs8ݞo%љw”҄/K_ygXB'RMPAЏKX'{"!xfh``fbY_0펩g={Κ2f{z@XƇRۧ-6^ 훘r˾R|U몗pƙ׏"8 9pdbɌE/\ԿZϢںwWN9ٓqyINu`p[z[8jjfnbz^õGW]6gZWdU&3Jg{^_ ἞qƵa&Tonbf^2CIۆW?"(kɳ ω)䷤ D2|iO)I*)Md丨ϓf~uZUs rR.\zv-H?yBiqjQNfؘ%H){ yK̿,~.BƀJB,iRYM&ؾxMA {Bb~Bv|8++4MĹy(0DG>Axn0 S`ز-RK&A, 7$i~vCSLi@w# Fȴn|X<> `}8fhB)d ĐJj8G:ͤƹ9O>ͷ+0\wV[eT P*hJ22m8˕E|b32Q8ʗQj\LnPl-)=YTK@ˆRif 䄎{ej+3/0bZ6Z<OMӦ4o%oeHs'7"/M~g^F3F=iC}ܐu_JԚQ ^ QW:aʍr {?Cɟ(,T|MI$]\7"$Fow뇧5ҥ~$`h5FuC],'Ǔ>W dJz*C|Td㙅+:_^,پB") *jN aŗ25Jl&CŶe؛MU]xUn6+{(6"[Z%fH(ś#%6I4(*!%g4-zhsis{Lqk.[Y~ }#4&j8H+H_ |n=XJKV ~ڝ~ilƱ3m h 1h5Z_*s;4P}8N5r'knAaQm#ϛ0Y~P y0h%eLӕiV@BiaE;- \"X0M4*0wP2dS%!',2a5L/R p"*iNJIx6$pH3AaaYJ p:? 2'?+hQVY;hD؏d̹W2a"_:#iZ  p]UcX/La `F-|õ:-D]𢓌aj;:#J} Nd<ۢop_#YbO-붯>!A_cnFOL̦6}W`˯Spm^ [9̈́|Z\E+|"d)#6DlCD Am=A;SBpJ:Q;xȚ}_<=Kxْj6p}c@5Qhsͼ+YYq.wpIi mrn=s/{ g~?0xQj@%!h!PʴA"T7 V\L(s6ki/^iJvS=5zaW;Wwd_삎9H?8*:׃t;>A#n}#JaJH2v,A&ŘcDN c+}1Ǣ` ST29NG4-фЅKdOH؄eP8\VT 6ruv}!Y{\j/clӘMȺˎ~|"d-u=qx;4aK0 }1VɘiiYMkf{R?1K'#MP <9R)1/Hpe1LkmVG[v[g XܦlR72azuXKh:Mbe<-WG887k\ A6ڿ홧}ԩzF]xgTҜɓY';OVb<:TNkr6/\xN0 w?%:ݑX6${{+C؟yJ%/0+x}n0EWܪ ;c{Qu(EX4((jlHEmc̽ƘVH5 Gž`4GPZ}M}1XV+|އEދUw;jI+9ی??K wErު||Cd; _oqMhZ%q$iG9{0V0!KaKגfsǯ uţYc}R:㍰{C6bǻ$~#~M̼h:W;d\ 86$3!uw۰NP 6ط; w-"I&̭ ^J_QШeA=y"LoXA;At|Lr A~(D ʒK$LgaQ~]R?'S(SHfV#|nU x340031QK-HM,+a7>-oF+Z!UE eo@Nwẻku4p6ޗl[°5Ec6'Nך\*>]AGY<[ _>8*B HQGYmAxdSB%C4Tu\zt.,5eb\[i\L~:kfձ um jC M{*U*hp+34Y /{DN-ط4{$ 8^:?)ٛcEطx[h_^b C =◇[~E ׏?&5;;@p; K `hzV:{8AFoa*(x}QN@Wؘ@ml0`lnH̶ 1sz;}ޛը18jTI,kh< Pjkk&h.jّB^dk%J7*iU.9_I[ʬ,"CvG2a!d@І 8F׹;F(<$(EM{6x^{ӱ `!T^>o*>;0e mQ\)+#"&,Sד(M#d$;jY{jkxu'YϟvCײcvb=0R*$1 q x340031Qrutu+(aPaR{X?Yw@֔ܽ !rKS d;䄿ߥc(7TDfޏo_rvFuM:jRsK vZͰ6{^!uWY|ɚ *z]>QmaE(xmQ;n0 u  u.:=@6K$ $K"߇op]GGgv E 2 $VG^Uй .@g 4R6GI ?i>&RfܐE =% ^_TLrJ]Y)C$a5qV6v{KkT0b š*;Q3rS9&]Lg<`T60jDGJvL]s`'|دwޠKmGǹPެXP rXI0okg>t3IANA#rhq.ku) x sb``p <@, $=WRAN ɼr8|B\dK9 `g7Ҁ{O몧 xX.wdRRrY8Uys|&%'(Y$)n,>kQEGO1_h:&N3u xj C +w^!J gѬ?݄QS(*8xxbDV4ƾ" x&ڪlj6DiTk]m6XP'Z?pWf[d稝eBׄ-Zqq)+J6;*ghU)j#dn2N*lz%͞P:#fҳYճP?h > Ub#Pl{-i4WJ7`x[HWX\uKNf%LaaQ4BL$l8 IzcdWn"vOU,VnljW4nCq-|~su5_=NV7~ۋR*?,[co#*2jv4j gf58@uEx8r4帬+(r ZDSף0nLPpC?zl G4B%<_L$n(a2Wߔ+ʇqɻ(Zr@jzTz~X*wIm qGL\S ADD$<A$|"CLF2;{w\Bz%*raY8vjhxF}/YS۪>oO3_!Rܺr6dƹحDe bY{q""ADb""?H9d^- y" Wɼ[ɼ{d|&J2O w'16 KZ{pW \kpw]p}<? O_~M>m(TنOi>mhԶۆOq+y@s +4W0h`\ 4whܦ s.m0iܦ ss.m0iܦ sEs=+{0W4`h\~ah\܃sMs>5}k04ai\܇IsMs;4`N2m(VŷzÃvyà}x'LFb2ףƫbZ66i'jc]bZ66i#jcFbZ6Zi#ih蝕ih蘵l^2hv%O3JyIE|ܕ>[eM ~CnWd9ϖOK.w>tOY/&*2{*l~>|=M; T-xCu7eIz{xmι5ֺ\N3۰=[C6t}_jyk}gOb\N_ Q-ߍ 7l=Ə ofio{? e֟~Ŀ|xTmo0_qcp4+TIԦ** X vd(~g;IPb=~#|ZJe@/u`Բ-mrNYr%9.(- .NݹTT\\Mؕ$# \hE'l*xҥm(Ldgu:FxKr3`kY;"DmiH.ІP`Զ8UyoJpf@T41k3 O̱c#:VQM𫗢3g # ,H #Økt9.z1THFs;2 1<R% \2u0JuKkE`O7zs)0Ƨ00xoΥPdXGo.ƾ߹zϰ[{Y`Sa}5#6vlFzJr M.yI30pyLգ T/m^ 47k"=rcb,m޽\vM؏Adv=p9+k&0N˒c@gеbq =d(HKˀzZq~Oh,8ֵ:ReUu?>pvlIdWΰPuu] * T0aO _!7Xl_ƂVy{ϋxx340031QK,L/Je8-}лWK zUkVkQWRQKڒsK>VxRb3;o !aA(<8Mr{AzO{Q S]u]qb)3Y/8%<ԅW+oDl(ZV [zݰj|ؐT$'T9Z&l2J߷D]\in[(흑)O-0S%ISp҄ T{e`i" 9H߼i ı4#qjܟN:5 ]%Ci!a:Cw+eVp]OBʯMVܮ=bPU@mאHyw8E; /Cx~PftSզ^O9`.\ hb㍹v1v/t>qG6yYl66f|jUw/$*חEfӈ*v} ,=0W~hGqr$v`mj.#ޑ??ߑ„m|[AB ƁI p7%(dGTtMEļq!ܧ)~CԴ!ϰ Ec̹Tz>p30.4^ȗ2>'LR2q4g3ndȄyɈiTCot}򓗎IJ[P7j[ JHg[SS߷ѲEgr|9#jUJu D)<εx1f$eiaKh$J6A#h<}^·U㭫+HXeTD۱&`1oRPbxky*A)KKRKB}bi %i%%`))MO-*/QP+KLQ)UҴ,RX#Q_C)=Y=3/]!-?$&OIs=NMF'x{*YdC([QjIiQ&76{&F( %x,2]t#̼ҔTĔԢ&K0m6g,aħ'i(($(l,ŤM 1yf>dF.&p xU 0D\4HKECnݔtE{{m͛ҡ#BO)*ڤ<X\B Wc9Hk{Ʈ~հ(B3M(eOwo6CE1DfqK?hK2r0_~:LxVmo8_c XtwמR,RRm?M-SBlط|@x<3yf] x՚Y̩2bOli;N}xCeSFEQyi 2I8U\*2[lCS_H7|a-Iy, !!Q+bLk~eCWYH8bҕ)&{۾TE,,۸%:Ӏd,In)в-ǒuӞWH.LMf[F@gnOBWUX*ihEZOmam%%SE΂Y/kxXʤyZVv.t NB=[XجG0*ckDZy&ydE>29EV.>E1/"5)) KRҐHK(~GXa$c7Ġ,b{)ajҞ$oRcMԺA,aXr? {5[SNO`ը-Ec`Ri}|n< l;5/UW _S Ih=q>œ\48`jv('3\촗[2W_o?E?)U](;ʢ'(m"8ȋSk\*Wˈ`?%,wDqӹw([;eS/B:#ZQ?&kHEE(grEAV4:u2(((xA<sQ?>pښ5~aOoK)O<^ԫh^_iϕ6G*#5uxi tp/x둘'_cr!< l]aVw P*WM̫TH+JMM*MKK-*VS(-NSҜ\=URUx'JtQFĒdG'g1NgIq*#{gcd=v_$@xc@|Ooljvexͱ0Oq%DII&q&@orkjQx{E6N?q"$>:jzjtLdVȍ<iV!wg˃>D OK ꊥvUu5)o"22/%ڮsa369*dEZLOY> xdje!S`a71L_ݧ43DA$BGșZ*Ӓ5SR2ӸJ4xXmo6_q˰\q}hN8*Njm0tȢ@QM"}G~I-РH{Gd{0C3y.L<(:3'3{VM1CCÃU a)Dg-GG:)A81%f)g!wW*f,wb_z1~Hf C*b"b^zZfYBIY*v\$!Od$KkwId~`<kX)/*0Nr:هBŘYGX$(z(z8{s4ˍ6:yr;1J8~˄1cvSGMYD$2M8{awJ)^Oob7In)k-. @n,4BJZbd瞀-G{`Ż||l^( ѡǖ}3t罹32춒wH,'J2Ҵ ŒD T"H}65Hphwp%*zo]8I4ϖIZ eJ+45 =ܽZv@#-((Ӧ1Wގ/[n.ʖ2r}F_vkjia|b_m ┿T:-&Q"q3:Ǡ䅎r1Ad"DQBLvm^nnGnal&~BQMXeGz] ǰWEv965n^WZSZJZNJc(@oŨȥHl(]Fs),Qj`#}ͨRUHSGvg6r1!j?a<ƤYFwY+ ȣmKr8v-{n^+mMuQ(MK5m+[!T#U^j[z̬9f&71\|x^F4yo0wT5c+xKantIBkX U d)+Uj씺i ]ئ S*G=^kTrn$~ʈ6ot NmٍPvS&y(( b,z:ɥ_ԏ4Pи#NN(sumiLc{~Gi6fg,HߢBiUmm+I XS*ͭ2! ua_h~QQM~_b^r#qr8L9,*~~u}9wrmw:j 'ҕnL3}Ry/wl'{S{="g yч0%4nsp?/eнq<ꌾ 0 xn"݉ca'o8)J^0 yTҍ[mکWkE81݄8rq\  9t?ku9m};SxRϋ@?nڥ6v#j[V1ni+"ZǴ4-E,xE_@<ٓ^IRoޛ7[C[a MO;#E6yȯtLYpEYޜs*OަL\M^jp3?HƳ!rt 'غa`#p]TTmax :gz[4^zBi<6Tw61+Sn$f%؎2p_˭B$ɭ=!tu)[-'vS`5slݔۋ`HELuRP[Xb(IL9]#ž6 RUqh͞MOA]f'eIt^@}spAvYbV\o+,?n9PBD;NSjWZa;{ݖ'{=Q`OV/܏{ꆥy40Z7UÕJlcp8_dJ|$xm 0D^~'biLR[Կ7Rff7ɡF}Lm'pBT8ZF\hAy }TY2E ȰFb!ۏ˘}Zp85MqڎD;6/s? A4_ `;Ð53 7T!jsuFxδyB> ̼ʉ'tN+ύO/)M.I,IUQpIO,Q(B0$3q2/!KmxUn0}W\lDd,RTiʴ'Nkɱ#YUke[ B"}iksϹg+Nn^^帡N:p&([ȧyylH>%N<i6#d0xm0r náQv+& 6*ۖW9*&l+.5@J&ӎhJ3Ɏ <i%w-7u'a֦PJAj|:*ݴhK ʼZNwLgGwGQcѝdXVdNYZ7}& ]QMt,XVT{}<#=_@rEpJ.}Ӿ ;/J8Am7Άq/:]#?..ߜIү7 ?4޽}2,󴸇I6[q$āya>bs9F^0: d0^7YNȝ\KT&ld܋t:LPe ./F1ck"?GNaKQqeAɫE gI}AEFNi|J/x]o7ݿ{8 P6޵*@q'](.%^-#p{g$+ۇ[ 3/^+JəٶRqCMi^OfW -Yoah9W'vw1P )"I+g"w};#B s.YB4rƇvC1 ;L.DCZǹK %DNxz(DGѪ pHZ%]u&/J+ӅpN*zKLX^  d26ObTsI')|(͂Dw&$y?&r!&2 QR.o}+ye 3/Dv =C> ec;b ܆Вn,!k f[WBe= :C;6@BXNNhh`'8B3ְv@hКYX"s qQ e l=`;5zYa`^`0$e#itb胫{MuȦyñe^ a~b~#)ЉMzPXUi j 25tuKʹvBH3ݍC/Ewnv-uRxR`'Ube޸*sṛsPς GOu0BjV38$6gG $;۬p< =ȫDmn6KUc)uc%鼤$nYIERZr /lGg-dhA?z [zH6@]ptv;'[eH?d.] }׀ɍUjUaySa+:;׍DzE˂MU5c NYYkۋ$ [!V(glE"Biirr\)6lP;-TwVԽ a[vu53P"< '6Ev#*%0 խl?4fhmC󃱦 +Q ΊdƐM*UhE+z5nrNzz:yWr2W1.!PFz'lxYP<VJWJ^lZ [) 22g. #LFRN39գ|<#_UbW np+ד%Eԛ ?r=Sy. eqܑujIebumĚUjiSxR2Yc1@؀<7kw,GྏAhv86h !>q5f,CG" R?j,U;]~Z * _g?F&?~v%JPR̟&yĺJv{doG/_ު$h߿U ﵺpԖSj>MgYuAJ$ro 0ԊCj_ο~ϜL ^Vu'a3b|SΥȨڣ,c8$q$Pw$,2ʴn:ȽPG<_w3痋{]NK@K . 1X Xg`I,c9gm(m w 'PjbK>'8A 8"T8goK(ȍIGca6c"l?]džiѵ r+MVB({l7J,F)R}F}4~kJYTS$}3YQvz3JH zD$AZՎ_CSaNWf0β< iZ;VS?!%H\76=b=?=I?C ,6q+6VQpS47o&mEZVe%^ihNrz̧=;=19w؞WyK'˯Cm6Zo$:֘0ok際i5M;8p҉&{ bdΥm.18xVoE4 6yMZhҴq!(D(Z&ޱxAT|!#qȅKqN \9z6X|gx1X;%nbLLIj4”;f#%Z)tcsv,I^4lb]ˇ)[r-V @ͺ.ctppD5BQBZ8Fv,E0E24(Q,"=hWH~%ۄvK@$N: 0WoE6{D6piKS;\A-HE~ 3VFy,57)ݵ5=PI*Z&w]׳fk[mG~bj.)Ceܼli^0dd'% ձ.J*8 )NV]q5MNs=MebTOׯK` hetXӭŖ$xx?/&EZvX@;ZڇI偦&0&|xD|:C b)9 jN x_{T)x7(q:`Wq9%W(~+UHص>9SA.ަ@J|H JÇ40ƇU-♠ i(+LvCث}̉H#ECX9t)=TDI;"#0&]</e2%j1"]pfcN< ӗr.Sɩ5fؒK]X& a: qЗlO92*f bqp}g8w8[eq l,+? ɯ!(G`vGS5.]B˛ ve]* `@ ArqbvR! g U閉%FJm}0mi,7kD]ےǃZ0M~ xJ41*$:C_5 C:?ȘFJ1SX\ӾuF{<>CΜ3g4vNI8{0~9I, $xVH \? Nsǩ8U nx~\>9L<6HNR{;c: ӠC4s8BSkUt1,kK]Z:͕$iUC=NxᦇG+n LC/q9X՝LRkt&yJ @4HvO&vpgN=I(N\0| ~N0ZVh$~qȃ\@l~ GAui>p*f5s=~wI-n:$_tNnBx !cj-t. `b0YYQP!ID ?g{t=vP 8wYe2 !CnJVL6I釢Ep`0_,jShEIOʲaԋT9Gȟ΂ƿC_F|!JvQN,&Pˬqİv*J݌5U:exe/'fF&#ry Cy 4T7K3N>),) $.zJj`3Al+OE3]L:uDwGjXWU׀҆dWi`gbGtbx545\9o 4)419Y\ODP7PE ܜtr2栋\TxjU$J8Eș󸷙ro-fp7`DpU^Ƌ @!4?_:'0_LXra)E3ņؤ$o:c#+rc2Z/eqbZV|Q*t`XecTlFQ>o:昽vGx6`ǒܐ >OM4(60/b1%`dɥLÌ[YJJ>_L-] T}KWjIXՏƒG4*kO1[H^ ?$rٹ%X4Ca_?qz mnTtv>{N{64 [̯|5[)x'}taET;j~u ąGA[j z̵Ha H=VW j+-ߔA><42Jbz`@:f!+zώ[ϱ4 \5?jAkRX%褄tC&"R3꒔ڎD Q|3vEh6Uҳ NS,A-`Q 9w} ~NԴf;mN\@[Gƿ\:OO4ox,$o|%Eɗ;wE WE*@_۠+iBWQUVfG˛>]0Gӡ%HT&Q^}muꓦ,ydmMf޼lg/.(6F@<Ԛ xp"=w~&?X$PJIC(,䗜+ &K tùVD-dsZ ܤ,_yEenmGQ%)9)tg T#Di&b%Lgy“ OY 4ւYi9?v~7#QeAE`H[Ë565`!CXJ`ncKKGsYƧ%o FYD⡁%! 7!c"ۿNv)ZXJ;J(p?t@TM׋)$DKD _L)hh7c↸Gd ud&LUIE>P*9ɒ0B1FV#c"3U,cu]x܄h A{Lv@9ώQ۝|kr62+30{E1FeMm <6TsGy?AVA1jxT2Nd86# +7v|ci`I̱8Z8UqNHycr!:w[n6bcwͪ"Ǐ8oT TՌ=W& " -Sïd^wok$gBCHBj(*T+E#[=Hart 1hD,E_4Uq!bioXNe=sJmjxJ4b4r=;+M2GxtQԢqߞUwQֹ bb6^ӀE}ѓxP6x5ߡt+p&vq͚ 8ڹ:Ci8c q8 Pom8̓]9M{R\h[-WYNU9ZM~ߏpB hiTSPCh0¶=v(Y g0T$n-]3.N$6M6>0 ]swHy0s H ӿq31 $7ivg~{˙\@Q[gz5ů%V?ˉ񥘿R[Ypnoqn:/;zju`NN[T@@2"gḒ\|* m!n[CYCSн7DhtыwdMTpJuLn 5 t$8)S;$~V!r`9UZ_\iճ#zE !gQeɟ۸+UQIwKV"cLu8] @Ƿ#07+T%fZּA|2Dl0h5A鵪73lm 2[Q,+EKD]d GJU*b)p06,zύai+&3cѽ-υGvn?sz[\TA-hW߿ ur.3T]i 5XS Pn[+V<ˆ bZa NcVzZrgEt`i~TAqV|#Rb.4ܙM*Cex!ѸsEZ\N`&KK雠3E..3)K&{(Qg DIVl/9vʥ L&тfOf|%kMr'H'-D/2Y= [!GI\[&JFiCL6Ƒ< Y"bԑtVHZ;+f =Wܥa4,Wn2n{CB+zi7cބCDf!%lZ#[R| df/eǜ[vU@g0%3,(E?cJXjٙ4&8*Op V &$w 8Q7L4ڽ8(`%<') 2G8u>8H=Gl=}X F!̅#LPM/ga|:#J[lcASqy6Hu僁(05zhTc.S&UdRLEܺBNT$'ՍL*-jVtq.$ztB8i$Fea7:kyFMbP$ʓa"851`:2s$[Yi +ܾ4 _VCQQ*+F/Sy"Jy H&Od;n-QVnnUǧJg)ۢPN)A%l@l-iˢzF ["MU,H^QUeWvC3,K*p8+XP?Zelj [Fڞ2J#CMxrǵۗ Hބn*` {EǛ赀5rirEb򡐸Y};?u3칵MSȧK̳x P,JZV "9kOժ^[K sZѼ홁Vڝ'0: VXɔr7r)ݩtZLw8ȷDYjm/J~jqf Ď'ѽ"a:xxfOqCRyK ݢT- t NΖ9O◼Iq颗;;uX?dݜD=b[_3vv =_W\(^xR5C % pj$b0K (h4f igc:%rB:L a pՌ"gJ4\bYψ+J /la c0ӠRezx Й_%7g rC `qŪ3~^|W`F=ѝ(n8=UA@[]~.PAn){5qb**>6TSqFnQJ.M!^F Ux{Xlč`{_7X{z^:hMً>/~%lwH=Z='orm5`9gneA(;뢭@\UP|%a(+??gH^A_2`=a}qiRr'mG[%3V II\ ;8]&8pJ,cX)AN0fŶxm2%oFN wc(#4 (Un{ɔq_,[:%yV˴RwJ Ƕ?[Uj8fwnߎO 7'eH#SlԫYӻm+Emsv/YfeoTY)PlvwlCKxhXe0-ًwb}YDhpa5Y1N^Iȍ SAھo[Aad@6-t1)K\9ttM bȗ5 ^#jPtC|Gp>PE/fo5|f;޽z쁖ڭ*[cC](bW +`:``^n*ͪڵ庡ŠR j274 h4Zc"ߠҮ[y-@6AUsR" ; Q3^Yf»Y)]scJ%Cw"t()pV.i2&wɄ:Y)?FNwkںXXVM"d!fkxW7?[ca&s-q.J1W4jksB.^]G a% ax}tq0@)o ;CSeJ=g48ΰs=Άn[t d+]Ղ/ eZ -:j卫AvBf6xH-;l@Rɲ0u}G+a:^X"$ h=+0'owg~{"q+me!| =KyN4& ttt#98vDW \& j7K(խVp\ jQS֤_[6TMo'y7TB Ay,$PK'N{4"ꡏs3Tצ |aݖbfʥ4 ?D=n`<>Nc?q-M!&?N<3L:(jWb2׶/|^}q |#]`ְuii}[SM|kpcǭq2v99:bS?NS@nO7ffYܽal0CjUQpKIs%FIj U+d!kTg̹q^3Z(J^/z߯#XLc|S@t,_ k}. `Ëb\G `qiV,u~IS5)~RGmӆ9JCd`4Zl[4qA}7d?d2go[[kkh~!?9~p]qޢUCMk}1b~u2to?c<*Oopkv)4= Љ?\n7} $4|D&4ЯK8DTGSJ!)fZ75S\ \; *k;՜d/YTfnH=+Z`zaeZdYf z D{vtFi10 47“;Ψ}yuڠ[D2ek0NZ v׳4F ~҂%nVqu j_}}$⿪;mMu]xZkVce5^UWk3y9LF%Nܫ@*ujyZ Q: A%}hSSO-oZoݠ~df(#T-d4 #Y8eqaG>~`q6XSqWXC m YӸ^&ZlFSz5+2h҆V#r>7-Mհ6nZ7w+xZ pu/pE}Y`/  ix;r0@R$%eJ#[V٩\QJ䍢lIm%㸜!R%r,ɉr;{!{I3ݿw o{@.z6()q9oNMdd?Jp6JI25S}''aKFp!'6Atd|b86j(ʺH+WRc^زl<2zzx<6:#goxt0v<7籛ybRRD~0B8],Inu=쇩jOLFFqB| <웊NpaDѡ)Fc~xr'IG0D'.%DML)!DHF.bOBGOQa"%QɌ,/unPI"D\"х,7!(9^e5wz1ffP$Y ^Ҽd\tirWr )θfOCqbi6/C^ü*%rxMSELN1V mNA=,Kbՙ)1ޓ_b[Sҷ)"ۏD -@j~sw68VT0qs!))Ts_o,mՐ*-=UK&KP" 9QlmD9{i>Ϊb YdٚR$ QHh n38RsS:#ȼs˕aPz!%H ʀ3̈tt/z*HY~/'G"d? 2{f- #$ƞM 1IC}c֖٘i}ؗf s:HλْŋApp{:ݢ=i5MNWӀȼ gI~*?Us#Dz ;:\F5Y]HbK ;pmG-,ɽPml]ht`3/MB~38J 52(jlv\^L'ؿ ԔYA#؇s%ħe^s9ީ,P9T+ElQVQJȬPN9S0%躨Z:.$Ei.4UUY?Fs/@g ؛h3TMe:8]0>ʫicQ`? p0+͡OIMCę1h`e{ju5^-y1W7]ym _= ;}{||6 94FꌪʢX!tzBռ(ptZ7m#Ý}a"[Ub8kKn"Ws֋V͙MH`dj()/< 6ꊐghF`s%8[I 4dF-A6p_<7 Du. &(W%W=༚b~:GvbU)jS!j Cxq잱\z&xF qp{mw6k{i 4B/ɋ,O}滝k̏ƙ4g4 >+ནI6AjB^j\P] h_]?ؼfQMCQHkŬkExNqEߍpkUs| ?jdLjj ԁYCRr?Ɛ !:l {8y kUFk 8?%˻ơvC>lS41͚0nm6*xmwwݡ$m mII:.a0I& >?>[!Q5GsALFNNG?8{P2\p/;y n&&k4jcT@WUsAJ@s0OX(ob"|!Vज़;nlL˛PA6gZ7\8E<rO&hl&VMv}z`g)\$x0st<-Dzꇁo}]?OMSc:[VbҸ$c~tc@ d&TrYpq3(5w =oY: CϿvDl8phz kyInNh&CDe^TFq$vHsC2UTo1dIW[nE8(\vpbYi@[ SnߊҭdxCLڒx>.(%N;ksUWn-\X1tל@OiJҞdS<^w޻郷7zƠջƹ28Od%rf3ю rf劔[ n Wg;kN<JWh5AAA& `Fps5ZOBz1(&M Q  41H&zzf7pA5Q\rQ\`Q,#3{oΊ<7!D4 5-uiTW1ww͋˪"f4 ff󚘖1$~p8.a> ۏSFcgF1U7.4gȸ6S=yDNw}! ޔp>vm [#c֓vJ . EΝzw q:[@E[ ܎ce;gJn𙸿a*f]t]f?-8fH0ur`pӅ^rMf "%`GjhJ=ݩ™ۿwJBG6`(w'-O)H2#G 10+݃57wWKFz0bΒb3˨B\x2B a`kXY7؉g&fa+]S*[q%TsN'>SX7ll+g='b=ߒF749UO(CZRPUbrJoWkī0GK1(\kĞRIQLv%zF%[eVop򚿔rKBp@9ŽGG=:_{pP)lpz|^:p`36-Qwo7*0zc/|tcz |7 [W^n7r/>miYAMSy93!D'UY.7'$c* =xQ /}SfIIgژE>>58Ho!cQ<:2롷93ׂps.?DZxV\u76xj|pK;-dߪ[pV3|g v,wO;=be% u%t?o-CZIu9 ֕(K#4'g9!2a+E^;, faɴ3 *?wFӷ?z2i]A3:ݹz~xN|* ߸ͽ|(?~Q?=-A#u6?EϢZlo^fPqH ̼삯azUC,MO:]kːck0Ȯh!hhwF2e=&RH\Ů`0 ]{|*N.BF)'( PBLjE3pdAdǺXkHld \n#м@O,:֢.{FDHFZ(|qkh/ƹ'=ǭ7o~*XڧNf]FHΰ#*VG8q(Ddx|p{ZgƖs{|L>M&cRpn?sI~L "G7Pٝ=>7s 2EτMָAӇpSYq)X sAwO٢~5M3M\޺.q; +I cSW+K i !%'biQ9.ptϼpV&H:R29?{i80< ;$ylH~ j|"6gg/o͛.W>>xms8)LɉC㛦Ӈ7}u j]10 ]II IZ֎ )IKd[iY&¨-%lH@+VR.[2=Md,Q=ҒC$[`۶4φV_%'In:J ({[ffЫAI~O9M#[uo5-֋X< 'zɋuȥ! gP'1E # @|#4be7tLA(8๮{IA4q|Ua>W{5JAHkJ?@ܮHd^tA4B:u˳egh7$M3 X?jj%uEl^Q|eBRy;cAܒqy‰b>"L',)m$Ȼ,b14 JV4z_ָwL B[LHk=Numۋ#lT>l3󬟷i \ά5#[X`&`!"-7Is-`aT() WհJI5V"tib۲J0_=o[&at`ڠS %lS3;CXcIxј>_N&ӿnmiTȇdxφ5ؘK_[4>}eƯ5^w[R)}q{b0D Q'O# 5Zu޿g(73<7uch3a@Ob!2u|C)c(\}l 9ƀh@u Ƅ)󁛆8]M- F Bs޶dij.ш䫝0fر|O>WS!&qx&'-O[W􂓓[ Wbյ5q7G(p)@v ")hȮF8#&/mɥK j$o7 W4OifxO:|=Wx f@pK]|B 'Y eF؎ĉc9Yu )FRh.k|zC*`Ss-asI~Q%-AU`_AmV|z(#-_x! #'oR:z?鷏+1x(2.(XB5WTsN5`(%ۇ3pedER<@ڧLݚN|`>kWV?z=x;8AyBrf^rNiJMqIJf^Ƙ4|"!%Ey J72 קe*x5 *<}\b4K5(?%gG< XiTS4\(@ d3RKK,4AEZ ś{~Qôx[oFsWsE`JZY(R!~ HrӻI>fgg~hf4?>e%Ilϒ\l2e^z+ybcgU>RҋL+ G?*OJaXhqZIX̔ަ~LlOPۻER-%P*)&;2Tb?B& u 75SZ&iIg/:멫u^R\̫l -["+(-'0(uܝ9SV&@:<$)KȪ42t6#^af:tLj>.,|TS-J. fRKaO2j#q0zLz{o^;L櫵ԣH*q0.4qzvf qLL\T4رk]$@:,*?FU <~LѮ6$iAJ[[ PB^(QP eO ^ɢnHG(֪]d6] |2-1YH: kAXL]ڷYۀ&EBPHDk ¶`U?Ħ53C 2 v%VEf,Gp$Vr G+l:k4 N JJhH^g"o :& _54vϰ oĺexpk@j5Av!v854-)01diY5EiP &3貅FVfh'IOУdn#JV?nB_XUOC-νE92 ލYn_ c` =D"@\$gah{CZ-3 ɥ4lIQ  l1llf}”a^ta=ے;L+'401%AYP3=cE%h+rӒ; Uɶp槓9;@{pZZ2*3(mw|o3D 7B\3?LAX'_]lix4~'`m &/5|!h% N*'p e76VmFd0ɘp-!eE: lD:j3$ i1]-S(3D|kVm1IgZLWF²Xq:z0scb_&bHU6,Ch(WIFov-Ss3ٚC% Y6nZ -TV&7nڙx{LHIko(EƤ'7O`cII6vv? KF`'h o\'޼nNNgg(^K-7dмzWnL~(]__&"bUn'ѹ3~{.W܇A~ ;Փi_&e_k5Mװx'! d@x-h)(2y&(G83 P,m^ ɸNR|y4u9ypYG_;69rLxsy6JSy8t {*5l1N4/WJLc`b^+F)FNHte=z;E0^qQr&ji678Q;߀}pCߪFMMba-d {ךdj/ E`37O6 ۓp0$@6n9Y >09Y$ C^-҅3s|s5sv(̇T!Y Y' /܌3<߻4DH^j~EƸEGFx0K78̳M2XBɍ$w/8UJӅ_7OPTXݝi^`$F[aP+BLGXs^yyB$Ĕz6v&3[ 5(P|RbkqÅ*lD,1V2FXSk7"Y'ωsE" Tg#3M+n4iLl1[ʼng0@I6>M+k( onJ:Dkx6~,gi' >U ئ6 fΰh]30\lscg'U5WJh|Q:8Z-kZwL2[Z&DԜq3x#1> ^UQPTUIyWs͂/'~婩ۚST([g{bA+d֛5mrI;F\YAjix.=A$fu$\TG).چb=9P8UP?InkdxsZ{ź}{0xoZכGP횒@fũ{Mr󯧋n3I^I0ȇ:9sCgI8mȴ.mL=~wayXK^.Gt@ VqS.$S%hH\^:Piz aCڼ `NuR8*8= oSulz?6N5uA|?*u,)2W=ƶ恼[27K%0 R))ͮ]ƌ:T-?!+Xt7 ѥjUۘ4#UpIDf܊/Z-XƓ&Z < K: ,>R?*NV+tS <["~m[.<Yvi71FΕΐKTұ<_יG!f _b$55 B'ω6o|~e'՚rZDxp {x+v/X,\/Y7>e,eA-"~OFB 4*{yrWh@3cĒC:1uw{F[^ Na( Ȅgԗ-ڱxTLn|?Fod YILkڰ]^ x340031Qrutu+(a7>K[W]:a}&@^ǰjn|j{dkb g3Tr34*]ujwlw 򙹉 Uwv--07kޅ$0(n vi?+mu&OĔ"O\01Ty|%[zP!ĐTDe~zo^_c#RS7%3acs94x- FNk8A%Ԓ8x~?+@~vݺ:{Jt%R ,vEj$jMUn.]Q",x340031QOI)Mdx7.x @}H;S1<&^wa:#ԥy>]Q{0X GVl6!oY 6[xmj!Ea\HM$KR&:5336M (ǐ;Ie7pјNbfi*Ğ irXwh9v  {KaRû=~]êөMÛ*_tҾWrUBZY\GoL?k?wߵ=WY{^x340031QOI)MdXub{._>ԝg,x1 @=ACz$T_獿u~uHC$\ʼjUu.]OQ~9`JZai x340031Qrutu+.N.JM+(aX|#3w~6K? Q4T.nmW]b]2|OI)Md09Q3&Umݚ|CP5v1<;[S>G Fx}TOo0 SӆwbB 8L09u[i\]8; .m 6swAa6!ۂV#-#/<2R+/+Neaqt K-A=;jRGQ.?sT au%#}D-KcYJR"yXzASygpD mqϊhżaW #RXIǂN6x%D29(9nl8_^"d%bWPfh Y0Y |[N 'o̲zf!agbgfjC3wԓmYBi[9ΈLآϤCMX)k%M#a)ml"Y17ܽ ; MEJpev{İ[^y`Aeɓ~g%aKS 뿕tY}1kϩXlC{pC8(|Q8MO[jߦ8>۹K`mgC4w΍ᰮkv@Kr(r;Pu|dj4?7F3o_yxɱ 0 )qL|dE 3ð"xwC {vrޑ*'C7<ʖ x B!E~JAD_QZFx48Q8&_İOʥ +wI_9uOMX|k^R۸@^dcLKppH`0XtZ5l||,&x[[Yy~/3x6{<;^awòf^ "AHXJ B"6 %(Ⱦ(x*g..@tvk]D8[>~ן7pO|Dxm|y9pϽtc ^JdΜ_|mDDǶ/EOtY{~KVH6󧎽2&_|/]>O4?_\r%<{GM/߯7to_|~dӽ,oBPAZ/ǽmE-ӶIC/M1d.Yue=݃eT>#zʹmi;L1?6m6G0FZNp궆S5m '\tкxJwb W/^(^\\<{j+* t`""]'U.gq]Y؍:}^}ʩSsJX牋W/'dyt!9RyȨ>{'?u_w;|0{ Pӧ4EŊw7+R5ǦL?8pf|ٻ׷9:8wos7宝]>'Z8}{Þ>HcϳϾ{߷|ڃgEю9ӵ3P̧9_!ytXyZؾ[d[C8?6o홿5ϕ[߷;f|+jN[Xc ;Re@JYy-Ok)OjOMzġUٲn.ݾa_%) teh_4A_*˳8 R@x=U-茩N<1}q鹶ke8Wzi9ĸlVXegðٱy]'fBw59;逊;n־|u} deVܖɎ5 p//Fb.|DYWFjF͆(;B'A{ǖMQ3cZjBPP_KAfgG-]vySmJ>}8lh0q mi@ Nkb\KJ4sNwk ی9~n 3o]GVI$܆a2m aBb(_ "4κTK"i`dY~f͂ʓ8E[Ѕ)cX5|*zBk^H;˗+Koﬞ&UofIwui4,abUJpңfXFfpL;5'Y? VIAhtŊ @Ψ)K/XX]s[Ѓ2 6d{Wu,nij m&_NjL7Ehziʭ8_;R@^2MBߣ<+6UjQy!Q[R4 }LR<xD%QNycXFsJOˍϨ)@O i84^,v\0^v  <Ǝz e,#8b ͳ4OӔ)zQӄ E=EZ\82 l4Ҵa8f\RaNnǨD' xO ,uVs6k΃Ra$Ql h+svBM[hƟx44]fP<=,1]y'GN_:z>VJM؎ -#9Kam 0ruAR_o~)>ߕO9ߕO w}gSx_/^=#JMvgԴWH 5pH8B Xfn 8 ˲V:z\/g̴ 7`\{+m8XkiNq <5 ou"{C# n6[ ʔUZ E+ql'9@1Ɛ/}(E #UY 3s}$`"r7 'o$b!ўc%fV⣏!Iөbj73i` VMFOM Y1y_;Ԡ1Rk:QXK߶UǠR7-A!I7b&J|T?Ğu6W,C])M/> %*Ӈ&:V Q ؀F$qC*(2ɐ9Z|˲TѪ*cGAc8=*U&Ipby5bQ d+VX=uN Kϓ39ŖC n¸}257sk&HGߺʧ S {&Kqa 'Ak癭y +4i)[P XugS9}rZU+poqRЪ Qd].jF0j#m(9npT}bkoa|c)@k-U[*\O X[#! _ WϾ])rSfٝRM UFbDrqivD?_ʽ(YymՅ̹ 0 I+eW4OE>sԸ戏d6)Nhl9UvbD4iaclAa:<YԬvR^ 9 %'"[:C],.8_b|kI^}3uywk{cGab^p5B4qn68Upbr:!m,D{PMg4xY/FÇ-sUA +*3Lj$GO#0{ҿ.ZfJ$q.-RFS\Mq(C"J05Ye}7403sKiԉTpzw;eTUi@jlL՜ ֺۮ,so>e h^ޕi H|`d hʪHg}>Jz^i%_bPo=Y^+o \BIZFO[ឍL߻uعk=xh8=C??O<ϜsǞŗ^^_85zK>kܹϮ|¡yN]T٦^'ӡq}/*!e~#F_y\zg{g_S\2oU}2em^_cObE׬oh_WtrUK>t ɪ{M0|uowPgML^9Z t=3v\E GbaHVw׋ &PlQ)6?.\.a1`~=$0" @=FC1= $${ :C=@xJX`yWV0hd({ @@l9"ll|^Uw@ ~r XumJ$%^[)|@kz= ;Bkoo`@}#` 8.@ }脾qp B@g8>Gzaq>?>.EG+[=p釾k u8pօwFġJg߁p T]@p_\ht9prww@pQ=ew{4 Y{6,:װPyz͠R@d} xWMK w 6lDd Rvx`,LEMK$ zR{%ov!P<ZeDX-YXO/f0CaJHrX'9hnS| 6wbo9 BmlBȡi^<&=HȖ򓻋[..vRҮGbrîπ{Hf끷xdl+>/mtvJFO2 ދArw^?&.w_y32ekҖTL` = q'(5veMF^Hn67^ռYGpL:ؑ pfcd\-$F>w&- a~?K(~AՅ!=I 0Z^0 b#od9'B MQrI)Kz./̵ Z8"L/EiZ]>1푙T)>1Ή!~<fEc.Fo͜ o;N",_k0`>R@YHIDT*Ǣ7ڐK1 #|R[pNeB*i ’!')lP11VCKD#n?z>wف?SaF: Z(kd6R}C<,X\Q]'-^ڔLJg6"VW8)hKFVQMQzשʃUE/ 4jiD52{x@KAxeM" @G~֥ [kFsy9OIrJ_,"67Fln8I.x,'`xxO(^(RM 絎jM% ^NNiH=8!R=߂^ɏr~R})71J@KnGc6.{rkw 4NVᴇ[eӳqXqHHu`sY`Dv/FEXN2) F_LݠǑʐl&/B߻_\h(9=t)'`"pWM6fK0rxS>5~@l.KeyM{ #k8= >B@TC9By0΍zDz1b3b+_R36T. \xbvJ)÷15q+3:aG_0Xc30|+Nhm;Bx?(e^k.9-w@d근hn{,n'M9-G$Dydzn+20};t@մLV>L{L{gjPFYV `OM((~ i4i8"J1+{N3 A0kѻz[bQ„ ?73OQ썙GѴ xc,o'5a{4IqlPPb ݎ~rVVh,dӔQqCicÆ73_JT[ \r䙛DعD.DNOp~%ŧ߹(6\ojW>Η:#J6 J6Ě1Pd٦7<3[1-cǷV4!o6n%U8g]K<4"6>L:~39V HOH;~$ 'P蹂lTDʬyѓ!(G f&'EµlзnƦϓfrլr΋No\eA@"-= ?^e%H\_\̈ɵVY#5DǰqS7}.{~Z9ܾ"xg n O%/@䜻@~};`=ꨖ!aۦFn6 tZB|7Kp|#}}E;,6 uT֞5Lu2#kD&&Lk2~_;̐Dtb MJ˿nʼn?D+9ąGeN'LDBo#/sژ-(!X<@2r}њAOHyeYrʿs?8$],z+!2\jʟi.GSNxh!dc ɔk*% 6hef?) GDfy| {|Z 2yFOя묘cI*u FdLe!l݀P=ÓN [;) w-y- MOĊFh>cLm 6ۊ恿tv^1:S+LfZ~RӢ|!Pt"޻]"jf&"ux TM/JXor Zvsߕf?Z*TT^n]b =p&WxJf/„ۻU9`;kD^lK95a.4I_̔yR2zCˆ(nYKV\9 PʓǕwW0Nm e aEgrBAmX*g%4egC2۞Kk4r:V(Z ,oq@)S.Wߝg6C544X> (;~RF;&o;Ŭ8{k8zM+:!a[C՝_"63aFxdhReqh H+"_ﻴ: ߫;37;fPL$5je,l看pP@0f߽kpo ל7WUع6!7)hDexyUxB]aKޥKbX^/дDGh؇4;ih+P2'>4: BJ鬒5-kd.>}G[~?(lriZ mt:K F+BԴLA> ȵSV*}ܨsA E-gH_0 ~aBA@f01eW8<1P0JQD]0Z,%꫍/E\퉝ȾW*Z3:?0]_)l[2B0*6.}1j^ndA}& nj[Mŭ-2 1Sp#l0l6B23aJce[lOS n>}HkO5 /FEKz[@8X7`%Ԇhgw7>w(PVfs82۾"9jGΊ$ĘW)3125`q :&~'m4 &S5o <>T!ß1ʼn)b1і (i=\[4bW'%{:ń  ]VK#U>]w#m a*_4/*,pV0A :bL=o6:D>#ࠚXr@ *Ww}9UBE#P+wN{9cXklLք_5LKVY<.,.VG=]iZVB( #o/|>AC'zIԟLӥ{b 10hyv+Z"65W2 u:Xܾ}@s w]Yfaw;5w'vP6O}EܿKसjJY-8Gbez7mSH5ZY3fM>2Jb66wn82&/6c kK3Ù+{59:|<(elu:1 ց;CڦB)j%v C:`(?\o% /jHˤmș$",H9Q+1tb}pgsN|HlcQ-Z`QY! ڔQ7ؚ9P(d6b.JNuJۙt*l[w)40^"tp)F/وy( "w6cTNCh[ V}*څs6J0nD}i-d}$WY['0I )(Lp7s?LpIMd!?<gne`7!Wv_x:i0AG|:u'K,0:^S56nҙ2z9Qɇ_ jIu!,LEǴ#0]@~D/s2ϮbrZAAlp!-/V (1Ãk2imGhv5DV J '",o̞юoq+bD}>dtt\?06&}NpSNZQ--P~K 'dPa8a﵅VfbDa\t&w7o\۸W(:%ۣ߰{;RN6&P0zO1YoNo$؋A!b=ObW=0.RyEu;pZj ilXA%MMY{jV5/-O g!ou:hS'B|6! s7bZ:Alø,P L٤ɑoʹ%0ϕBy̵?{)Lo\E ʕ.\ɵ2'& FH? HtrW~ȏeM{SERܼ{8曂8#d їKB?ѕz<^]^PM!Nf(x] AmqdZR8igjdm3Q+ϥgaϝ}(ArԻ6f-s \|}?$gsTM"jq֪H-Ttȏf\j3s Sm0'eKFݓ v|JaQxSa3/ Ő9.|ivG km%JK̦ JNXB¤iq!!Iٺ.?9cfZ6ɎlGfȠC̛cCs܃Zo`rTe^C,al30k+C'yfC"D?-I-N` A!G&٧>a_& c  TKŨ+"by6Iѧ(Acɳm4/d`ZH_'F.u;ZkPY]SgKsX/e]y_K@Bv1ԗ]Bi,.li%;L|x̓F>ILv}6d ggu.W2~ξ@aNl[E2i6w;8#DݶH5z! biuq1n8s7 ·8u׎t">Gʹqt/.:®KƵ5D\]H C\x\aKRZFb\BBɴGGfF97^ˇ: =7jC!yDz+Ә&u7oCBR;((>p\ʟ =o;-wAN)RF9R::NI %Ք;jwĶ۲[;}z8JKR/McיxvP$I!)@2&9v@=}*Zο UPb->X?cX#0{nl_lv3Đ䓷ՏY ]?ol_5| 3xqyo>R߿6GhG՟&m{vƒ/?} 'z2^RCobU]$,ɉqk)Zh:6]</l-Bljm*y|qTKM9$7VÒ lE(fwKkkG5*qz؏<'jƃX0Ä~UJ}ommr,BۛH!W1'xpcwCi-N$8I2])!G0ϯ~IWzciHˡ5';TKNԤ(|%le+3: #~Sq6%6;sjsL ҳ/ziBi05tl Uc)ru˒j񧨶Рe]^"xإ_ʕIhO,I!u~E#ol#+t=;UyStf4Q A;ޱlhgbAcIHCßRa:{.  WJ^ b4!9v;f篩XڸݠlȴJJm RY]yp$ 1],R|jopFݻZ'c neCOg EGSXILݑ B{!fvȫ$wBnI_*r<"Ng`,?ٚW"YS:/qgIu$#\h! x{'XJws f;ŌA./СL~n,e%9Ɣl ځ맮}1w.)Pz86_V.}1|T vbnAؘ܄) i)A˿W".Rf^/gN0^2*IL/6XH!At!T4p_d*{7,D.?g3<=8[!yNiud}Nwh6vsS PMow٦=I{Mjk[YݖRȪ#ʙLHҰg\~.s޶fZ$)YP" ]p8 B~xFmO|EXϐ, \Vјi 6M^(976 O('_r^fƁ,f`kfG?zO o`` PzSU!@/ofV/tj^( +3W|9`+Uɐ™Wּu GÖC!I]L8ze؟t,F*^im&g]fkF2_YqϞ@Nye;.(vok?ԋ*އG V.&T&ĝb=_5e7FeUB}v-,ykYgo#Q}*iBCB4_2fbxCjb ΥTYg]{l)y/ay>' Z?cQF>M?/S3SRp6园I1*O|lg9!!"B)G]0O8pSpy^V-B2T! ©)o;;@JmbO*tְae=_: !+bJ'o⇨[Ko3pﳆxT\|UGs9u0e( oyg#;(!9wso2D(X!5m&4y MhK*@}i[]왵ܛRnK2)ywɂFF^HWzcYm%ꂥMcb.o0S|qҙ׋"{?Rp` L$cYi} R3SsDq5 ͛LOdgJ35/3Idbd'|f5!!s;(T|7a#ٱnθQ_o;r/RRZ[.^%c{ӎI5IR~5X ɗ͢&̇_/l %e,6dvC- WZ;I=Ns6aGSۦ4S)tIDeQlۚef2D(AO5ȟ{m l- ާi,BCk{/2$w#֙b{k#XWܱ#HcpłL^f=~DtDaen2ƌ] ̕|P%)o=ۢs/M(4NO(F c^[ɫ vBsqEӑ˧gQGO~wܵ%̠jSF]Myp6 dy #ʤKn)Vk% xxSMӱ{Ey{llY~yo!hޞm cU~_KKjvpj 1WK9ӶT86^U2cwmhV:{2LjvѬgO8GˊsyJ軽}QG 1X%X #dz!M=ig\TiAwKUG+8|VußYΈ Xjӫ"QPn( kJ9>,^P#JѮi5rœ3M`sb [{jĸ^crynS0FKKG]zH_FO ߷JFɦee7$đcKxvWxD*;th%#޽'D~96dzY7,1b'Y8\&~Y=GSaq?B{2HsU2A<<›J5`iK)v<.qw@@Y kP15M̤p@ Xbד/\7r(L,Te]]eݛ|C4ø-vy>SƭQ?E'qT`>Bs 8"u?el\Ƈ _NuQiDL6O"}(}yVdn -YΏ]¿5G1.Gx ^V k2C{R8`z#؄."&[,fId{+PwHpo# T]bsZ4r<2Cf`3fBK:1tn 9x 0c d(5at1kA8.>~'o#M{8 Q+mZACIY(3Oi#n3|$`h4c?lp; j'ulg}rG8`zUhlE]0{!w4E¾?DxMwHoB*_.^> eҍň"  (R,?^*ȗQ'+rm娳49ׂy0!Ͼe{=f/!ڛoз{2hATJE \5tk /o_ *7ݏ-ׇni8U #}`t& oA t uP@W\@~)uFנi cchG ښ~%rC0}[/&wY/xurCiZަVv#Jv?`1N*;o9NΛ A.f'qfIu$q j(9cJKOK-jPtpY[ p:Gj g#%V (oB͆ﮋC!>`z"S ;_ILBflH8U$xNI i!1X9]h5Fmr9n6!MhDH v0x·[XD cS˚b̆ Ap O+=%*oҝ9!)24N 3¿u݊QRH:T(Hxؐ qc+ 2K2>=嬟Ls,[@"/'?  WJc'ѬtQ)G=&$ʷͽ#pٸMsޝIrT1)jMD@_tœw{?u?̻h[;.}m,!RL㟠/0o7IimJI|awdLZ ~%nۃuL#yt{>_a~@5D,j u:7{֗i&J87 ӻƋsJvq4㗖VrGr~, .p_}eۚZ#cCh/\j GDއl3BS5mу"iSɥ[KE5H{B-i jŴu4rMxЭHrQδľO$U8\\EYrFsJLz߉?e/#|Kl\3r\7GGB+ȡkWb|+ֈc=JvR4p&)R[U| t_ߪ*yAީQzɾ:,A%I[!9_\s5cزaNv0Kxwo%N:Ŕ #Nf^0H)męH5{jS: "psP+@6^ݶmF@泝Ν:RDC7Fͧ:װLjƔزNt6CP本e r4n5=m҅I%5%-ng~+s[3j[R §QNueEx+ܯYT2&:Iyd2*ۚ㟆n~Esɗ(+IiE rw&[]Z}Z2"Dѧ샵Y1ݏGᣣ*v2~ P}-wF9W ﺟ}t^I .s>v^ۀ>m;O^y~)d$/S9}cOB@|=ijm)ըC-C@*tqsGC#О( oG<MJmo+BymÊaECq-#:RyUjĵN=C iu7ô+)M_bٲO#u* 元%*.me336_^qndMۗףvo͂WZ%Or_ ucRGv~7Jef.[vS8@.NS mPobڗB% IpQf#@l`=Odԕ9OX O8e&gzE<z7'gR}8QZx['hP.`/.R 66)Zu> <=7 _w``kPr.u?O`t <#CN=`qK/d>U8Ëefu9͍n2}gԟJtu_KV'9îvZsH2\/}޳ /Ȝ` S n$^c>]LC4 8^W7PnF'EIÿD6DpύaK뽇;ϕ-=],._nvIr*|h,K<|>N/Y7E+?"2y4z騞‹=hjO?gk-i~h*0v 3WSjSHֻ%<4yt\1{k>`5q9R򱺢7:{ oh[ D"L>Ӫ煓F"0e(IyNTtfj:,ԇCnHldSnB2p->-`zզAux"S)O`|T6|鬃*Yw]cOͯy5v B֓\,jŹ;86L| +="b8,i [uuhqfo~'ĥ7}y OuZYYUAwCpZ,&gQͱ8_./5}2K&Y 2? >0 Gr}wm|v]<[Mr`ۗTV] 9Dy͹wtT̂k8Gϵ5>>s8 y穎Bm"I ҥ:h9TY|~mwFCܷ1t4:ohxG;;3G~}5`$"MU:N¶ӄӓf\o U Ggٶ5=.!t] p~$RSKsq*C9']ih68x&Ԃ:$Q%ס+gl'<ɾx3; GU5c0z6& A_߷H;a^o@*.݅2kϠs?75?͚t$rG {:-sb])Gw3Kݺ:X`S03xQ7rH+X+)yE@ֈʥ-WdV`~^>6T~7e* =@boWW?Sbx'[\V&@[jZA_ sU7*N5O_ V HJqܡ%AZ(Z܊PBŽP4@pwww{׺Ηif9kfY#(Wd\7XuI/M@FpB%<煮@/3@qe?|,uGow W?~iAl_<&iq~[3&Dih3e#k8`6!) ^epV1oK,r%7&kch=UF@&:H ڴ.9TϜ( "9NЛcOU `*2R ȚF.'⓿ˡ1\u|XszRlAE z 3 /w T~]!io]@*~:N~$ex9aV:̈́r*zҾw.oUNam*1'P؊"Iȕ-JE$bLVG궇9q1A}n==o<ԙU|Ui?Z2ѳ f '+l!"Pi7-X3hOקIՁԨ[6~ܺ#sj:/psb'P"+Qa?=OsTG{DDDDZ K ccGpK^bM7(lEAUdwIV O_W1ju,dh.8PO}Uҭf|%Y@Gx*<4:6A zԶ[e۷2g&I)I7{3̓̉SsjM)IW+R™ dt =9QfX />NwW<lBϻ+DZ+09ǀo H\MEc0Q8GOh]zkdD@SUʿM$ yQܙEUnQ$Ub}B1i(|F҅%{qZa)_{hR[I/"C.`GdEfS+^XXΦw=N{B#lnXK?cL p3Eq&at]BUk^8cӰMI"BNi ݝw8qLki[K޺ېDZՖRkBW{Lr693+#ˣiSwr!5H^02oǜ j?(|RMb omMLV+@x8E`BԛUqz2H9YuZ,_Ħ+ٓ䩤w5X(9_SgXqBvx$T[k/kEN}!6zy$tk V㬋 %ԈN&8/`2r*F}q0 R&o,B$y6>vsCSF6 wg&9ɱm9/HL3g'aցgj W9y"[3QveF\?K7\V"ݦ?S,G+n ~gg=^:$1:)ȍlr"׿a>΅¼:6 Bgg/׿e4S$4*SCzJpgX׫Rݻ;j^tJ/5(W Q?v }EgjȕZr*6z@/=6cK+zI̍PW=lM;zqѼrtNŠY֕t]B9r܋ZgX1{+V`nJܿvfNBPwf%3MЅwQxH؉..>!Ψ(WRM"moԏp@I5w˄%!{"t(dtpkv{}-Y( 輆m:;eİ<u>떙.jՑG}цnϏEUg6qw.>YK)-G@eA:G̛5ͧgG;6t[OyoR9,iܥa AҶjRfKusj>+cאA ^6UJcwuy*BimU5~1']{'6>O&[HEoݦ]p槭T7GG擺p>: `9z<=Tm3\W=[qJD*ᳰɳdGltZաmZP՗V5fiC]}"7^9Ǫ7r[CJ;QTL0rR=J!U CLrX(ÑkȵW llv d}}5g[bP?t :Z{e.}kvOnSޙ66V&3 o<}d} zqPp[b?Z˯oqbv!l0S]aWq#avl\ŠC(qpkq"7!6L*u~n4 <7MAöԕw+N(7F$Lb}!E6\3:m05d|bc"QYx©ZjOvjx&R^&xr^ZЊ&'u*{n gfWD;9o\|RzÞ'/9 ~I {19y̺l/"\\W.]x6XB)9 D6N]]rv7Ԯ+pbK2~|ہ"TQv*&]]Z14wۗJfS ?3sdښ ;#e'.8KЇ}~ƾʂx}˩0is׉^q)GOU?VnZr(ߋVtGɱ v*z 9BLA+ նÒWYɌCcn/'%9j(FhV ph,:/SNk}˂4r.ۮy63F:`MeN8UTr,U=&nf#nE ,ВJ Nku9jF ݃4 ~l.3 65-]%aZ m j—%dBc|V 7ě9&U$RM#b˪PM> }y&Ux>=|5K&tyI\j?;pI]|_e1Fs k?iřE 9hS7lvK%h dEM? t|19KS~ ~!<m]Ϲ!U{r!ߣLRsDݼW)*ϴr'[ lRg{sE$L,kVٱGõcb JcfXa.CaPQ=]ىbOBXqk='WVO>S:-*hvbN`0|>搧xZNaksi' wVs͋Z{.[$/cJyoNCIT[m j5X꡹B;(hiRJFLŏyW\S3]f+^/"JaxO(9$>2 1{{n-HW",h6d BfMkdDRlPab'92xMZ4 =`3K#<ӬG e!fp]x8~R15M񄩳=:(pv6D#J0QtBBU> OK䣌s,bYr8`qT>dzh^$Y ~)t|mR`#W :o > { WJM(w]6 nS؄lm䄵g,0F3μ'u귡¬"iMrڭBR!DKfu5MC7ek O%Z f #L+34k37-7^Rw7|TҡzM 7L3=YIv)~A 6ٵ ќdY|}{b潎~3M&^ʏ3qKmԺ1e#œp/UdT o(c7k!ݏ.& Gk6|`!ͮJfæ\EśjҸll)8@@m[w9Gi U5ޝ):?+Tcٍ:{ɛc~|.(5<0}U\|LG]\5za_~x;_O{{5ד89cfja7Ǽjgawy{!UDtը^%f%4| M/<#/!:*S_D>pq;WwaPԖGǩpG/ty;;zK^>BqUzs^J4D(z\6f!DcLy^Tiq6ӟvT $XLи C Y?H}i3S>~?{\E_(ūEuZ޳()= Kٌw^e%T_U21lcN n.:Z[wbb6-o2sUYPg;j"t* ̽{;>9QDy[0ct^ϪT? D`य़EQ^3;ɹ#%Uz?xJ!l HԜvH^PnS%>BA@2c„Em%Cti>Z^wo%GjvE9 %̀.=gKjc6.TKSd:t89Z/|-q,)HbMOL;hڀAi]V n߸RfLcb1Km!R@~h /w.wªI؜b2+:XJ@FGНM0!ӳHs,[uUVe4=-'aJZZMdgTWktLYj6X< `2|]/\Wvk_d ߯LJӯЈy= T,t&YBҸnϑ|ؤmSOu+F*{%uOJ%#,k<&rdx/{lCᅚIDI4dszvԮ6UuW4KtdŐUQlYJ}G<#݁$*f6"Vg[kHda+g9hɇ9 9Vz8b;Of;x,}ga [N%{ڻpnW!0Wt)&eb;oޝgu96|@@C1aŅ_"ŭL(+ 5V]]t&=AW_"HLsCeUO4 ƠqE.A sg `~#4k5={n` U'q}sz<`<%9`2e` Ĩ "yяJtÿ#n(+.Պ{~"Z2=ٗ3Z7y _[DF\Xj2@$ C_E>*'Ef؃6Y,rխ5By׋@fc凭 !{VpM+'Oj`:Z8aB_Ff393G~QѷF U}K _Vt<>|QJ+ߍyU8],M7TAtr+`2m g[O낥gb|mFZVyLtFi\J&7MGuc:CфQ豖s+nPg?%70.̱`WalKTm/YkjYHYGJ4dD<j{M @2^.TUCa|9j\j`0 L]iO2O^ ┄B UJ`~{)ޙt"2(Z‚ me#XƃH╌3N8nI  ..:~c h0w- 6p-z<l^G[E&%N|T,¹wmS{smfv=w%sYtpB C8azZjj dhb7r0VʚjF.%QԚXArm8Blctc;5llZ<+uC9<7%[߬VTӦEs1'xLXȵgÄf$ _ q}߇l/@dsl. t|\A*J6*k~pv:^->?a2o㍗* ,ea MJ>"=ɢ}diWM7,HÂisOfլٴDd(:/)7s-nPpBҀX zƩ.DC$vh3bںv5DP <}`da+$+s9Gݎ(N:cGGnY*3P}q5ֱe|Am'%¶DUo |{[{/ni?{ R;MT?,b͌P\T؉,AJV6$A q j0!I̎@ƹئH+fE-{KrãO]rT@Wn=:M#-<Ȓ >o4 mg\-6 1k 6z|d@jEVI>JL>m6p7:^nFS&z݀m]s$OGp)˖s)my8{[Us+;E¸|T*!\6䥫evڇ?03!omET| ;`Bˬ|-L$L=)/3rXX8N7$agbw_10PmE0۱Z@7ۊvXHϵϧ?`GK6a2Ĭ*F"< I󁔴/x扄/6;xHܢNngu^3)tkAm8!!oݱﲞ4Y5.ڍ iԶ"9{)@\vY-o,a"R hs0:'9aȜ ʧh3zN+YYf掂 uJ(J% vKb/e,)k 3Hqzry=.; `!$% ߛe3z sl Nvk ~QtEva5}ӥϥ;0QL-ܑ p^/-LVIQʑ:r+k3MoTKdH<- =E \b2"|(QXZ#iAP` ]XwU%&:Iؤ7\飨^]8GɭOL>bO;'t{-81vҧڤ{՛Z G ;upnk3GqbNihdLH!ugK7i'qC(}`/ƍD"t;EIj',xÆr\֮X}EpVwKZXWx+ӎu>j L!;focMrkԖz25N{LMwVC&1Y#rj@ ns Nc J܄O8bes*]ƀ<(Ss/<$Qlu^ q/. D=DS3oRG܈?T@i+D%)1$%1KtEҽf+ C~w#|nvYmh-,̹abE'OJT2/-$lhh^;X@#^a[Π]m}rh$oDc]u<:*/ʧ*U/g2[-$uTWKY{k@ 9{Ď)y%."҉?Sd_E.<׈E(sl03Z@54и 3֙;Sk !eÙ,@S<`(bdwZ[0O%63*p^ZQx:*|yc.adV8p_˔eMb OK <#t]Ǹ~r)=Hxr0 7)3@}O3^CC?)ٰTM!}WA'gsL*F^dv{[/2YxhT.Vas,Xe0iPHraG<]=zMO Q)䥪CAGWפ^`\GZkޚ53vawc]g7'k: ٓaD?l? \5)dM-# V{9vsK\7c7U*i؛Џ AԬ{! eF{pLB5_TkM[Mz)k0 MC[9ͷc>o|Ɯ o+Tf BKJFehj+ u_ӝr˅~yd ꮚ8o8\@$݌BT^߼My< #*ru>P)rb۸eLW5d;Ã>|vAU8,^@~Ԭ/|WdY)N'1pkH]Z{rjbl jF6I"Bg7[%bYR 9'3R?h\6㥱HMYi<YAy$=8kc>z; mU]nQ0,\,֬TVF=Lh7'?->LJ%W˛DXgʙ4`?n%ƥrAY x% D~ŒHRJKo)5@Va̜QXƇtpca5{dQl(hV$%OM e09$.Qو [#]l&B[xJ^8k 1=,c?81#x340031Qrutue8,zuQ۹Z3:ͦeQSXWΰ5!G鼦vfx# USsO5wu؇vh6_,tx+(#bpo}A{S1D 9xMn D|T꩒R=SsN~㍍Y ֍] 2@R3/U2AFh9%bC}($bBN\ބ$U .! *|S9'qY҅Dh[;U#+h\Vz],$ڍ%Qٵ-N+KӃY+Z/Fdɭ7 ڪshs#ȏ'7)ߓcLǠ.rlOBvqfr]EYZxG@PNG  IHDR- pHYs  tIME AbKGD?IDATx]{Pgo⋇K9U \̴yEdpŤ7!,.SyhuE\!^' 8@. / 9~K&yv{S Z)yY^NQ.a4iJ.]su-_(yZ'K IXnqS.I;Ӟ(V~䅠Qbھ [4)_ܑ3p/λv֋7C^XHd 5zޢL2QP˒ V'X!hy n]߱gͦIE4aA(tsc_KX@^mkg[OoetF%q-y ^Xhb7}V o!&O4eu>ײAH)ߚ0u]K<ϰ3k-ī!4@D#kO yQ XPjgݮ^t`,YWsOAxQR *3[T2пJ (^bp5;Mof6hn^R(#XUpMق~5E7=3,f,hED6XnV`;wώ`=4wbZszBlHXlZm6Ɣ^)iηEGS`!BX6t,Ŵ>Ɵc#żg3&"X_VPz<%[Tysg'Nq[GŦbY+*{5uL"^Ic5Gf0h)3X 2П3ÅNXD~pX$,Ҭ_█4?%cw T܉r5^t | :K`ED]KH{>" eT\8#t"+NSn_ T|hZ7{Du,ا[s k)Hz! bܖ'1LQ'xQX+2&1a:LXS?>[+IʶEQp5Fc\K%v &k65F`OtEFKi7AX_\d$wg=f8BQ^lPTYLB ?PqK,}%c}/nl֟ՠEee 袧-!#fυܜhb(/jkꪦhn^k׮6Xn#ۦ;b%dئ 8ZwG.>XC鳚i`RD0+@~Ñ55ց΃`1G |!!!/0C4KdRc~MuIIժne#}lo/lX]]G8ŕ~E jA#FUU19ОeS5A/XJt z5^+_v$sťO(ZB4*V[OA^ch8tǀwbGaSDx3YϨVşT]L r4z`ŊU N:Ο"vCl+;l|%76* }6I^ҲtQvv!VA5RX a/d([[\aBfgfI^}c5j v9 /4CӮ:oڈ?s+7&Oaz[:u4ë>~%Q-gZf#Nw4tܱm/ĦaT=8qga"{ ǶmR)jdx X4ܲuWa ܫ-A  /_܉*+-G+iozJ97?'u{$GoIQA_R1E9r*G //\{UMe!;K/IUABCr8vG۔ }YoN35Eh<u?G޵xַe=%&LRVvڣ={6>Sj$[aHd0lU\q,[&9\@#q,ߩ.W&CTϏU<*B0愀Q^0-a31wXq+wMě\4srs'N^^iXL "yjb;A[W&1@v[<&Z\3oy-I| x?eaQ1a swhKPt0c[]Lc g.,Kl:74{^)V$|GrZsOa(qGSY_CԫqO(miΒ2OFB=~A4q4ztI*PlN~X-u _I]Ic5>ղb{'=p\>7+;#*l%WҲ p;WsPy̏];#%]跞{(c#MUëN _x`j*κ\ߊkYR_"]dss"DƿHnAi]{aZR5q2)uim..bnS*>]ғ҉gh2 6.8vz李uLտi%(;mBPHFvD8AP$E? H*ņL,cc#3fwt4[ >shP"Y;]]l11Ȏevv;o0@0`q01(IJ4 1N PB`%UDHJIH_>TUUU< UU(!15o=s<w3_=|gsY׽{m,z!L?q?\P8h =߀Fv^ƪhrDx9QᓱMsμlēO^G ,;2Fu=v(|wU1Ƅ/`ar&J;1ɑ[<mLz"~'ѹ(8W[v,U/0[;tj=N|>iyr;6SN ڗ2]V5Ue%$ "awAIxuAxJ4F0-;l4@x:\gINKHCRhb Ǩ%kʢ.Ukńyl穨IYZYnWU}-cɪ4H zd>!F H;\mϵ@`#dz^<73ɫ^e,URt7A0l'qg26vN;|\UpOm A!`z CkpYR޿,cr&`.m.+4[T|e,1G349I?Te" tXW,H5$ cSɽxeQ[>+{  G)26Sh&;DAplR!Q&_1ӺgӁ:z -cbCOeQ4CM.$F^Oa&ɏRE#MŽw"%,+G,cD㞏n&z$u $kIuǟq\<_zؾS#ߪ*9lz?=qYs%o/k_~iXGUb}cTnRu4޶uEo%Y`'(DNu V/{/_d ^VߦX-/ qO#K5H5XqR ?'lK^A0!A(M3jnx꣺>Ŗ1a!qe~`,l,cWk%YʹX ;,b o}HHS :Hx&ֹ 8c֠tmdz~`a+ :c(4$}YU5J-k| |I;$j%Z1ԓ*kNsܙq<`EL,R#g4q e=[7~E_kZjhWR NiNnX6bu jX|C6lPʞ6@bHΖ,-cuϷt-U/*`HtDQ:5,V& YnVW9cH0u´Vw.a=fl#gzY֑c!(}fY-XLVSV3%Q`MjPuHQΡO7.V$LFB`շ 38" f:LN߹ :N1,xwW>V/Wn-Mqʈě XX0=Whlg I#yҭXI,HƙS!ӭI1n": |k:?I(Xb, z7Kxù?/>+ff9(+kRځUM^\=_ lywE_K]L-^uHD6wn``*+Ю:z?BSY]-4%n|PrtD /móM.vl2OJNk&G#5J&Kٶf%ᚬYNb5*^uW9h!P f􁋡յv=dٹ=3lLH 3t A\ S!X`; BzjA\ғÞR8{井T`'Sc6t TxѧE'Bm4RJo;;x`,#ޫo}ÞkG{-/hc%P9^i^t:e3A^m#B 'pp 6]K}]~,wtWY8dZMV2̌"LEYaW+YRorR7E+,ϱ#oA{EO` Bo[1ζI)ECPr!uJ}6g190U-]N5>gG7Nj)d% En {;kqO8V0A_t%EX5fAf/]C7>Ԙ^n-o@UJƨ .00أeq_)uʚF߁8?粸,rA]J~H~F9v3 U!^zdZBZ@JAnZ` gZ}ൔnW1[nvudb TT Ѿh; AF%bjլ愜)L-쿚 o"0v dAJ*i?𜕩ڐ}:dB/Bz 0sXqZ߳q`NC\h6핁 *1iRҜ X_FBae]=N[Y7NWAx?x:A:w>w,DRaZqU8 f,+P ~jen/ lОVned1 rGt[zuISЁDZ`^d> E.HQWUΎ|o{WcQ,x%54}aw2ӺU{ ñw8mI/^9ky,DGc>q+'3bEo**v*l(z͜wJv Z@CFUGdcZcg6ea. &H+(W"*wm4M4lGc6ffiq<~9p&{yx>{ޗN *;B^ݹZ<fڊq=?'Iѓɮoh 쏍\U<`'w#qUx(3ў+ *֕_џ"1,kD_ ϳ(Q|!@6ȜAJ;`XWL _[Uji E+,jodlF&*IL Q[6*xnr <#xt{,^t5C%&(]OAmz,+y#&T?Dm(b |ǹ=Ȇ42#ޠ*0:՗XZPL- C/VVԐK#Wdo!a9?Q8VC! =5n}ձކ=f`L.QDODpY:szӫFlFOvuv5M$>6${P\zijl&VDZIky ӘEBS`6 󀅝U[4Q| [$8WRK؅ fܠnI/f瑻uNLE+cάִ!(0:DhFRN1"?/=Gx+8V+i` HD5rR_@jkVܬ\Z|GΝ;w#BerIKɦdKMІ\H2lSu0y6# ߯yX}V `q=׌ؖX@ܽGVɸtvjdgVA 驙O򬌵\M_:c-1X؄׏R& [XXNE|Uau}#ԑ>aZm[SZ$)!f3 Q^ZAZOL7̇ \E::?v6d~W ##: 'om?6Du w%>|w>f"% td OLZZ\M*H[&"!{-ӿ d'NVBO$cJ(wo,o(Q_T")⇳ZRl2ScL<uS:Dq*R޵$Z&-UeVyD-plwX{xE/IP4tOZ_irb 9v(d$Q2nLգY+De ,<<2;9XXPC o7>cϻ&FkRmv__yͤ%Ȓ -×Z/@Թ VdƓkfylPb>v!5QŵV\)ơDVW`z. v{/20 ݥ$-.tF9f&#F# fm7VQ4|!s2,*(f{Mu[ hilX;EtW_)^`b9a̶ x_Ք) 5(IOx^d6(Enʁ[SQL^|` 3 <#΁@16StnT]e/c"F9={z*Rfp%D xE+`os˱ ۑÉ/j'DLT;Hn(LQꤛɶ,$դ[JcW)kRG]kAm:Uro*pҐJ? R S`l$!1IH50ܬz) r?H6> ,pK!ꥦ?R]fw(Cs (:(ʚ9$9O4ǟ#!jL@3:*RzThM@:t&*j)'O*]b%AR,QHgoEʌݯ tr2ew483M Jt2cy TE{b[b[ kClMgc>>F 2KÌUI<6՛&X ,VqH݃U8`ikck" ,^Idh+cnYx~ X֬imgKSH@%̑ ]1L+/Ǎ kg_.Sߜ= D2,K}[>#OOԚsyI-_ @&_罹u-_2y:hgòj,Kh!oȫd* H>Qc{GYSi!fFӡO /D\zr?i3`\96vD_F:+sU~ഈ\4ʹПBW[1⎯KE k1.I&HA/-&Gh˘k`a wě"? lv`kQ~,~%4HvZ<|79g3*x؆XgV9W"a&Μ ʟh^H:C DS/Œ`#IR1Y}H‰E 9J uN(MC)RXOY}Y\gԇ+[~ *:"EL΂肚^[mɾ[؅tޚqn?EVG$ ,I] _)ŽYʦsE.` PIgQW qehn-hX\ 0t]"g:{Mt C"EȭuQNZifޫHO05y WJe8 ü|5EpG7ᨆb  Hl%)3OEpj4[$] +Rv1 hk7b"E,$"OH'x ƕ E`ɩ 9/R@R³fs"E(`}-AU 9B|`6h);[GVe~bN@g`Sw9E4zQ ,h9y+Pߘ+8"ѹ¡W"*EV2uT"YMX1r r/kA HӛɭŪ&<8"Elφmid~O"h Ԥb vɮ38.|3b3VsZXvRN\O=+~_T]k՛sav1HC8kYL_k^g`Hn%;\\|E;0?hΜ93;غfZ.Ƕf-&fRFj%&e_"iv#Ig.E]DHDDt!Et]DHDDHq=yGٙbٗq{y+)E5}KJ"kZf6)ߝD6N~d XI9ٱ.1`~r) k3I j=JĀ5[QVޣ[B\Hi]%cu1`vF#`]2j=ynz>)` VNJ"+Bp@bQ/kJ˦L%jk,)oj 67o#Ub0V*bJ8Tޫ ]ύĨK 7cmD1U`\}{ Xټ/e`},)7]5+6ZFB'96Z`Iϻ`]0\U%`_cm쵸 e`a `n=^msѦwH"{ǿG^C D7M?:6y  g@"kL5q); SDրu0X#;$g %lԻ?Ȝ7QxΒVH<<{Hdl |/ԋ K`O";(66Fس)Ô %ȓ$Q=a&yFYsZ'U!r6M [EbϦ?!C~aZdnfng~m` yx2x)L>'޴Dvqry,ykESWJ{$,gyҰ؅[љYusE iwo[m}eڹkZ"湛c;u[ZZ&&'丏]}OS:>?G ibڰwdy)\ڸ?:GIJ)ln!Hdݱ.UVQ|<UX=V3VtטBCaX`x{ӻm.VDJ&Ǒ`ia YHT燹f񯍌4lR ~M09IO!wY) VqHIߞIy\i~y<:D_* t}{nWDU;rC`v6w5tj|> m&Bs=U`&p0^ІGE‘8A,??ү? :!SZH;0Pn HD8.dahX\oTopR p4S*XWL "xYD$Gt@~*+n:XC"эJ y~ʗ%Ѹ&P]F@$(O^4H$iݐRR0IENDB`eXU*xRj0 +DO mTajcP eߧڰ'S b_ޯ5ȣ*Cdc qY 4Ϡw1Xl"`dCNK>r6; ~H\inj:j-3 ӒӊSl^%UK׼I K{\-5XB A :O9;-likl~Tz%Q?. p8*#B9)x/,{UN͵Խd<ʗwuZ9VŠ"'X:/n^Nx[u'Ҽ< ===M.((,KL+//,IՀptRR&~ZZPWy!#3#8Ux340031Q)M+Kg4Ӥ)qlSy)B姤1T8\eTMqFbJj^ZQb:Y罣,o7hK>J/Խxuy4_{XǖXC24D#Vd2)Ȓu5[dI,=;u}}׹s=uɦ0!t&A/#% >o^' l 7=pb&P{XlDCete  keʪͭͭ< & BD}TTÇ3љѕ[|knnnkktW?ƖfffyN7[Ɉke19/=^.i22xiXZtYtj mh@͠D֜ d!D-Ld(·X=0L:YZn"d|xtXzp\Tl$pL'͈i/ cPI(2 `\X1%RE{~='"cȩD0~ƃ%.F cE!ܫ3S#W2 phXdzgz;+}RT֍BpGߵ?@_¯A ,b)r]CSq;n"QԷǹx! iY}VY-ҘJX&,L1d8 )'Xu ƿh%8'BhK@àD{K-1\tWN6)8SκZRG2!\xZʴg,q@.k;PqT8&wc1'1)RrO? Q "8ILE:9Um8M8=cXV$GX L߶,j|#)PFt5\!ZwߚˋmC!iN9Eo@R 0kt!U٦-?93O4st_vO[[\e~xXb&ӭm?"2uZgol~{|%Dwl-sq/qw8RN6)b\!0;Z=L{SiK} j{:>bdI]";0kV/y)4`A"EE~w+4 #.*e!wD^w31̓xóOx9~{|Mq̦)$ˎp v| { uJއ E:h*J0wU9NڗW*KV"RY U([-Bd%dĽ^~u]Rr9ͻ `Cd %xP;Pdy%4^J1uB6E#AE$|S53WDOees~@&c't3+ a-k~ 6x<5Wa6s9PBn]3q=tԅqs3t+ yɉخ/齦L,P#$zf۱ F$81ْ}BeW[N~U/ED!p[5^|-$ K)]-O?)Ojnb"Nj"ۢ_!@_gm\{N^M\".%g旛ge]NJ=E铮131G5\i>Ϲx}wC-e.֜N个ռ[?q'|@ONqyK >#Mo\ iחG_,-_)$AkjT e33- d/`<#.*0ٮ7VLd^Qc Ty17ڃwqHN +"?*i#{^PR>l(J%~W9[~ؑ#wKcO9~U8w  U˨y.BX#$8v+t;pe{;Ë]2vuvT.]9~uB>=~Wlj땨aKHw6'nCAr!sC)vAJ7!.fӻ6j@cڣnξAd!VǑy0eAXsƠXl0\!b+Xo$k.tс7PNlKru;I3%w5~6gHOuU9[H.d/,]2b $dvpllLg2\JgVm?1@w$$Z5@TMCT 4.G"T9w\mƏH~>l H.fNyv(j_I:Z-IϢɜ9Y Z<=e>(.asVے.?vT e EoBS> 0 u =8*Y@G7, ;XӅ}8'3DܤJū\A~|{\>˾ uרTIf r!ѶnЛk ܴSHfFC]G9q6#Pg@4s)vtuƈ Ǎg;a?>fAX <6`[;ƙWM7ob0 hb S5viі@ېpkZi~Q  gU)lf5$?_M3!&fEniKg-B=5Hd3YW.l714g[`ǵc}ƌ(j6b 뮑x\Sq#AmVi2b\8X&o8J `iy]=C"@C=7x: {ɱd)8}-CªZ~laʣJ[W;\_uF#N6.Kf-W)o8 3s]>s4#ۓ56o3`-qɤLЫPiC^0 *,~ v"=?糧"AmZfm1 hYF_qʠئ ;"O $@OX&E9jK_5VcŖ_ē6]Y@ 0{/6pߩT֨5Cұ&UkYX0w_) YI~ww:fl3Z(bSﺵqpli`sؼG06l=s(_ zFW[tP[ f{Y S6E3Cr:vG ۧj|D~kQwTKUC/^܃cw MщsB&aiK*ɥiAfvyf-= VVFe/4,_S<&US\.q*% ;)7#EV@P hPZkv 8!sH&DƀXT;\y￉z\hr eljv܄M:y ݏ"DEG!)DT0 @a_&^#\_$#*+О{tGI_Aí7ÓϱX7oԷ򊔼2få4V$>u8mja|FR( c1ٙ:kFEIrKߪ=˝A=sI\Xv}]K0Q3z/q9.@|]cza7\.pts=HPRPTR hX4 ʚJrMEE}[A"A@ X554U rJ I&MIzn^Vx]O 0 }WZ *t2_/oKHdQ́; m)f`<3/Q*8R5%uk7XW!X"E1[5YKNA!M)Ax|/WuOK;'NQkZ$G?pCi0xxqĈY,xͪ0yYkoU+E$i %IKN EPgœ3ߜunlNTgƪ4Fx8湒>% hwoRBZ3i7X"i@x xaiE-}bY:V:Cvs8 'z'G4WmTf?> f`9HEy=YQ'@A*`~.861{QV540ʝ<jxXS6BAth&dc(qH6{W+pL{Z~NɔRD\J'ְ?M41ddKEsdEo?OEN$֐ ^T z;k&flzDFaFƊ'F7vD% Ѱ={x`_ VKC22r8J,%$@(QFH,i 0Bɡ6$kCF.#]ښв:\q(Y%l Xl9< 4Ħ _\@SOH8P*xmGT>]8I *pngz D-劳VV,Zv%ъ)q(|KÈD8ʘ9-s(L>gBruX}HM Q0MFj͐8#ZCMѾ ~pC9gזp[YR+Jh3-cE4 Cnӌ#Oz! @iU@3IR% uY,EJ9CiPiFe(<%: A(7,b>R>Z҅vr0)#ucyp ܕIS/tՇu=G1 $@޿'g ZCQ Xl/Z,%&V '|Q &{Wı2G=N'xB4x[G&_grWc5 )uFʹhyxWO,rWuX1>Cޟ>,{IdR籪$ m¿!,'bvt0zI5(&i5` } [6kZ]?R%N,Uv 5ݨxQRkj/J$B9? I h+\'@eQF7/8%BêC LنoRRtPҙXZ7=6OTr%4ct[ W燎*w>[JPicF|k!73ZVmE7r LpK^wW :|[GJ5A42pċ!:1zbkVl8v@4vo|co4 Q~Yga4G$fRN Q5ME˄OʽZ_Mh-aTR|=鮱;ӑ<꾸`Lu,mӧ¾:~" _O:q&{zQy)pd\~pt}w9&*[?fcqzpOҶjˊgMXBnmcL@?CT_LeO+Mil)ХƨDoE%5HvI4hSmm%:d44|pt3le'wh!zζ%Jw5^wKA]\V4s hqee kte**"_ &/ Ia"KKbkws;[,q=6KXV+ ynvKwyL$zH@L̗$Ӭl@ |*o1/.gpˆ̶8%Bye5K%?xknT^aIŸIn"mRqh[E>8̹_рfD$` c>%|~Mϯxu ?(hBoD`qk3_/oS7=v ƒFخJf#줗~^髙p9  %/`~^*hyD߶Ga*"~/nኅ R@")Mb0F? g 8Z1<6Ȕ3{a&X ;Lj(R}%-y`ްōm .]@cz0dG'GT+?S>];tƍ6k:,K@AپF[gWWsRL$&BIr{9uZkx$(%"!9궐םb]fy-mNr!z_W f}SXx%JC 뽗*|.h Zq:Oɥ~FiQo/*e,sg,Q_ʲ&+7 W >|D`/sM@f+tS20T,jfhk2'zNC~,,'<̤>S$k=qejÅXBqo8mO7&B:j=Isk'߮tRIiPHA$Y-z^A#{[!1ו+G~8㑄g, Y9ήҭrhl g%8g"YKAyqxCv]JleHfǧ.*H֡jDc,:T`"T%zpV2K^*PI3 *rkbFcxh|Eڠ->Mk:/38O< %[JbDȑcŘ&ݪFFWҖnj!14eZ'BX17I*;U3ch[sf\`փӃm4z:T+DF Co۳9v 5#7ɽf1Ծ/A)=ZEg#SZsz 3mP>!* +{% R ڑcE5D:Ff)mh_x4ޗF |hQbĘϳ$|b*mPmZ4USvdM(P5C*W7>O}~vz}zL5:WH,FpVz##lf 3M #f&э|!@IՍO=jO O1F~%(̻d"C6JW-)R6X[e쟧<='' F`P",dh}UeUfCpI^"Vb 5s腝fX3w:}>)t }sO&1~RiuJUv:FЋ=-q QINŶ6h?Sdܾ2^Ի/LJOFBV#Wit5U/!؄t~L 6CY9pӄFFYЦ.~8Zzȱ&b*%x{Tt?5dp&Y bOktBz9L0uq9'MF+~;G klgcYwL.s\YCk lD\Om.u|5O2&U8A#kt:A9hd\/x pWhÄu<_Xg38Ox4@GÁ6zO9[M8_o|&L4|w>%Ϭ|s<&xK'|;k:hBbM11 1CN'͑G$"[B6ٔ롤< xEA 0ył6}@K@9HIn}sqa TڿV!1y`a-1v|Njt QĿ(I[-zLw>tY2vG Ҝ/e1"~\.縎 x\[sF~_.D[nmg*dLeScoaAd x}d'3y-ҧO{>YҘzoUTwdE7iw۝캢̞g?vբ+*i{/M͋f^ּ~^39)E^f|>jUj<OOf7_oLe]*kL[.wf#;G*J3ptצFӏ^5ڎ=91ղu4R9]fہ ;VXvWٕO"xq[SX;}l )BD QiUDH@ uxHy%nmD4$.%Y0@"uCs!@5fmSĹ(}8X@e]oѭkvFO>*fwe*"pS/|5{J:M~Ck֔43\۫jGGlS-p#Y[Tev|osx9 - gpJβ3YK3\ɺbBPDŽTU*ӾT urכ++/S4{A9U9ǫm7 +ōbǴAP8R\H'F/ԿomP$!QAAA6-Ͷ4I&uc z{ٿ}Ե{Rp=V4,[ۙۂA5YXvdQhԄ#AéX>$,y&4^outV,6ڨpnk7w_nww@U]uJ^~]ڸQڇ06ܸ*@ѳ'AeY IejN. LT(;ӨuCΡh7h>2HjI+v94Jmu(2Oa/j)_0+!{ Q{bfBdϟgOK`@P4\{Bو)2q OOQ:Ow ~6$,X\%Bsp!4}VyLhD^t8gtn#ն '{Yz&baZ5 ,e6֑O{ jaWq/#L=K,,&kA6F2^m@^N}Jtozn{8 wd&IcX,jVR,_ҩpb;`Cyw†bj \%6¢EDlc6 R c\Xe^99ˮ<*pU9yPUE(7ag:q`Й('P cÎfщ7T(5VHKX'^ӘHjWyf#oog OG`]F9Q2g&Cp}F d초*I9`ujdVHjNbcOJ\'CT22_;E(*vEBZK7R>`A%wcAivB%KAs@FCr{?0$_eQ$e;;sNUaڎHǻj {E5K_hdrXrle.s]@-wc$N% ŒbQqR]zW=3$*>A&].Q+Qp#%_)%j$f|fܿW!ܜ`RA$Y7D|ď'I"#CΤ#;jN#i on~e~Y^)3l,yɖJëtKH$TET=d` (m}Qg(>@lP9v7aʈg +(%mT]/I m=d_e+aGS KhU_F0lmvsZ&9vb f8.Vo۫ay]N릻4y3~v c\Zc ف.4W/NW ɱwUVEEZ`jXBT<\nSH/!P/3b9&cUXzf^GS4t$"8"/nD1ii&g  ?ifS7Vdry8tm+#c$4:(eDShPvN"Ҕ]-!Z=3ی%@lT`ʾ7 L" OD†SQ=L'JmhQR1mz;t=d<5Χ9PCa}(,JCE$XeLW+Md@6 \pg^ y+`ed=GۭCy  ~x2؃ YR$Tn1nX,;^=~BIJ酶- Ţ ۲v.!{ek/}<1_ԘG?ԗoUʧ&ΚgjBH[xzəZ|{W``'@ 䬃};!J h 8Ɖ-JEyoAN\XdD .YW'X끕Y7{lڳKqIuJz FbE')J 4m>2NUm/>-wE>~zS+ 464~ytT/U8E!^ȁZ';,Oy3erP3?}[?[H? o9ٳgζ wyoSM'іڸaJ!`8j2yҙHNM?:޵= I؎`-E.F߱mXfbX"r#rp(<"Wpq@$Nt ֈH[D?rTG7SԹ&[GB7zoL(fCE"vvF3=Йv>:h~@p`HvRZ=ҳ/,1`H8ݷDIg";^m` Ky_;{ؾjD\vcSn Oc'LO(ޱp_%&@ޭ"|jkW/Y!ʅqd>G[݅vn>S.dC*p.@ M%RX{Ia7R{Ag eaB8gKw %ۭRφ():gAKi-RZ 5fK~~7| += 5"q(>{SU#B1tjB/6Y,%bo 'Los҂@S<]g@FD7 Zv@NVP[}Ї/D0:WD(,#ht}4qQ.Fl(=ʗ;\s c&_SB+ $I%!L\1$mKħν#;1OHd?)5Pn&;/ӎ;OyvLoi ~bpvn@.IHE !`'ʋ]qXy/ T4#;/n+}wnsCDL_܂ߠF>' 㡜~BB:D: 0kn$"{˜g'P:kqzaX )KC"oJ3q9MY5E {8{{?}?.}Ǖp.ϩvTgGz EA^#E4Pa/~!wc-hx\)f%Tu;OZNroQ]fxbI@I{2MrՆWQKԀ|wJG)U r,(Ԇ8jlɒט\V:TfI3$*bV9ri\jgPZB\bKKBoܗ~s:pt/%/f@K0ٴt[l(`prw)L CߥSMtX#da9KVQfˣy#8$g6p~.ʂ<4}RvC5q֯ɞBŝҩBQ ɷ+i/iK8mUw|wH3X{=ޗ 9ФrF#-=?oN‹R2J-hECUTT8 +Hg!5 /GPAEp0}? n4e;{<0,b2C+FhuDgs/xSn@Uj#RZ$j05ZPB-h+ēt?a, |T 5+XaÌgb7{|μ˼t6LMdAlQ~L]ʷ'3K<~=};20<rHI|&"_Jǩ1򽧟'g@"MWf8IM 2<"杆}}Pr_/ntb&vP`GvX-d4Bfɧp4p\[!o/jeAPPFSv6l#m#|)a ȅ@a8%]~4QKt &0 I129:Sd>Q;AyK@X8JvnykTz6 6%Oo)5p ]jl&7 s+-JySM3~c[U"-=pLÇʄa24>46 %ZA㎋U8K86Z|47ʏH0բdjB=}ҢD3{2[Y f#{`!@Y>gSO0C6[{_8ޝްm|)&<|dI9o΂*Z@&bZ}oIVc^'90z0E:p,{}Lawݏ&WN'=kOWg]vvq~ڼFW huЍFkzytk}58@tc']=Z7I^ ViBS~l@Tel"J|mu6֨!YkBbəd5:gg܁3;{3~mwd0]pC>hQ/<)~olX HK dn}U׀r7zoZ\YX}ԞaMt@a7{s8wcxt֖P7B~ Ku90_Cʰ Yx2"&Vbyw; vGh>t'{V`ߤ N I8mw?]6{;VُĆj ې*Ki_TAy%CYG8CG|>Jd} y$޷an =ү͇dl0@6{Cc0.iD"s# !| sg>/(:~h%qf>Xx}0},8`?G}l(|"m'oSsiJA#h՛ Pсw~ymodcLS 2j}02yC>x Li2h7PosnWCÌ ht=~?=Fw4Y>Z60Nhs;$]ӱg/Y\$=4:6t30TJ QmuafA-3O&=}i-?\ADǤjxޤme|v`6ͤYv*} I.I*ypyD4fr`qTp=WY8J8Ul ]k4g5kX?|U.W2t{~a` )2=0y ,X:HhmߣzEA+ iH\V;fQ[T! XF¾׆D*#+;a!>]d5T7ʼn{8CӲIV&|i#$b**A&r=9֋UcFJs5QDyTw >1Њ܇{}0̕vRR} dCY(V9y5mAL6lj.9e{yRnȩ&L EJ lrBS=a#ߛ 4` ^3y¦V8oϦh6% mǘ7;ێ~m#.p{ao$~?u,"Nc}90D%L֟"Zp!l ipU8@O &}ω*B*> s/6ϛ]Ŀ>;˕C4R#d Q!xU߿1HqNϬ"f>EP|*>lUKN= q}\:V*" Oxk[TsQ]l713Dk` c~Q]W=JGM, W6djf&W27S f((:4faIRݢ9T?sX15gӼTG)6rrLD오lFJxk+UR ,`#+ӻpMp)ȬC*/f7VjsiS;*\[JR1-Cx`\%Ų-.3t~w)*G qdʉ̂a: ?Sx93NXXcBov5GhuM5S'湷ܵLypE)b~|cTfȟfRWTK $8}q~ <`tP~{#Pek1۷?:G~ fY80's9m֢$...;Ύh2<(s0r߯z4z^4 UX%%QםUϾʼF)U I!5M++m`́,qU*%Ed1[1$&C_ϳS[[qFa+PȬhhfQy ,|b W_KCʞVoM "8p@>ЍE6{!?5f ™OrRdqE2[#e:$yw9ȵLRGUz\' :(VlB3N cYbT.GmqD/.VzɊ PK72WSb?/9-qŸ$hIH .hIl@>i1)bWUkpL !|;e"HI+;!Ӂ͓pF IHi^ʊWysx7YWxD+ BvFҏi7eC>MDujM8ކ>4/A%p)z\DdC0iQثOID(ՉA!37 wGQ-(;ހo zQ`ƾDuJ(dPe\/_E**G'Ohu~-5R1"y!GZL{fEw8s 8wnv'FX7~M z Ev~n'UW- `%IM[K; lnf40$SOĢ.Y-2?wK'^98`mRQ)(.* Qdh8:E8Q54+PYv}eYMGm G`"4x!srf #L', v-2w=F&겂}Fʁo_ʃU,)\] HS__k7Fp)HJ>,7lJF}ίUqMuLI/߾5 hB_?<֯W$LB_t!+i$~ŋ&< D3 XBJSV o_JޚU)֙R5 #(EϼoP"s}:/cX჆?RkϏ[bD{*W|D;}hjX~BD (ZbǬ$/6PF} E-K҈BIv +P9kx伊?y/[{k>ϲ`3޳k ?p?||Rc#?x*GbED\+- AT}" N}I"3@FT gJRY y@ϘY2$Fuϊ*|/VeU+aizx=FoVAH<stJKOMtbަKHd_— Fn & Ɋ>Fn)jF2)Wm4|^]]tOqO5|SpD8dza|L;7"cї˛2{a(Ӄ;G؅~@qEM{`Vhюb<o D>RpɮFd٤3qu1KY ~KϠr (*U&Q۸ZƖg2CqUģk29!B5$yPZk2 =M_itarwدmʬQ=_NJUx4xTwH~|w?;.7]Hd-Ҳ}\eC5"=U©D+/ @s&k@˭kk&=J(c;L V^V˘"Z@ ;NحbagH7hs`#plSP &I% !m1dBx="R"7r|Q 6Q>$$e.gq}ss>NJ%|@R-*:@lwG&Ji2qv\b3R=I:b#d+.-鷢s=TČ鲆xp"ϙE}^\`%KKp-"HC. j^UFTrM QJ2y& (8XQx^Y:"wԛc|rO-wn1UHswҸlȧ9ˍÓKE*ObzE%zـqJKk襔:3'0&GݗNK؍}ˣa9*02tRRQ˞P%URci@KQ:DYUO!LhRLZ|S<:VHRRFLā3ht$7TRt9G/ k;}? ճ*NZCiGَ"&v(/!AD߇ SПq":VgS#pAgTһd80qiرqX7@e`#ۋkb(HD'1RB>A"Ĺ h1v`l;;xRX*||J߀7t;TD[!nېA@n!kOsq̦;'0̡#*8(=*7ѶOpMH..; 3!y𵒔a)Eؓ$Q{ַ0ݚ&4I:TLc}KfRR,ۇIq/DR1'\UcNF^F%IBK7x:&ӋƉn; $-\HfQ-qڥMbX.'#`=RR % g(R֥O XPw _GjTϢGB!qRi` SPۖ.}q =AI$6w 3Q_˹0%0N4Sx4 a7ktZh %(  WsX#_߮q/e-,A4Kq'_ iȕW1oM|qzKL@&ԕe"Id)iTcHƜt4S:#vTbٝ+. +g"OF|i1nN&7V @cEd t|L QU ՎI@ST$Ŭ@S”R(E:"7#TH[[FFolS2GKR:IVtVzAͳUH@>F~M !+Agь`yzU@꤮쭡;{>26P1䷝lՏ'O(AY cݮdX+qت0SzB՚g0ɳtďEFGlP>Ee\q ? )eSFQ㟄|޳*} R_L;J&К#cOKׂ'?7NϧhTW]29t GHOg=sg2)ݼקP9v́^9LG0?Tz/@?vF`MY|ovoj LmU2}Foyy?]iW Xk=3q@JRb& Ad'Tq&FʜjbŕTRV~54\'0!&kt]sR|BS/WryJ!zr}WZV~*y`Di5nA!:Eck:`k.dak괵9**B;4\Qr ȿ`=}*e#ua/^Dv%HQӠ-+G9YQ9f*B>ܡ?*\W-1sIb(B{\ߘrZa" g'kR{sȃ,>ٸiUp'=7=4E9H\:7;Y!/t{> )xMOR$VySYSGJt"xdOhuQGqN?7pap<̩ZdҔ 1M3:I<hJO/]'7`UOT]uls0+]ɼ~hQ.EVn r'T?BԳy5q&GyU I<T ?D'!Yvp9m.pFQ"kĺOe|=ghqCfjaaA3Œ6;h"<@wQxM픏GP|H̻㷸GS'̴'=A$43ĶړqmON-?q/L  b;ġ>|3/H=.d!Udoؘ. X29AyHK$TBd~"aAE-XO(be 9nA]ob'2x0˿Q1=<XllM#PCtb$M@D ]Tg= o }xP O,{0XC`Y*L=&ۻדOA_j"@(rWKT>1Jo>J*h 31Z)t<]U .5bwxF#TnF!lQ}'P)CGT*eHiCDde:]lS̤Qܐ"('[yGdCf} }‡8΄j,@ wW[3ulT I aLG% A(/̝Gm`SE:1߇>Ḩ՞蹚%GrH.sfv؍ A?ԎD;#"$_IZecJo_>mL5-'+9lh(]tbI TTڑCC%ϛl t `"$ %[ҋt⫸[GwRIpD7UwRռ_PCr+c񄨌@zo!۵NIe#"$E)%]yHSHf wG,bIKs!. PBDZr6ZNO9.3|=bx]yo۸ߟb ٩$;u$;ϒ{fHryo.I(gH衃p8J˟Ua kVAǶ\E4ëzO!KVXTi.p:!,d +>9a8A"7i@;:ߟF?r.M4(b#3)q].a{#^ KcTP ؁^&'b:coع}tnxXX8s`,0:c,>UA4!q#){5Iz:=uO.\@u(? Z?v"ԓFWjfpL2= &;d+PdJmJ ݃r,l\ S&J\ kTl`"E6>R6p8-7oc #C16XsK-81 u+Y~djpC*}V$ad2_urkJmê4kLkʪidbaj>x0:4W\I*$+$'d5C/y Ԇw[EE#;q:!D$Ñ{«[︷m$1 p#gGu#-h(Lt}@ƑK 8G|5m GbmwV/$KCvz갈M=LvQJ`go3qL_K&Z2(Se r-@LA(Se LA>(S(SkOAJ DZT2ǹ1@\ 5eu@D] IV1Y2`2@uu2QfiPfiPfiY ,JҪ٤ %2Ux>s1?AvjII@M(sk\YT(F6/k2!c%*(S3ؖtZG9r_ 5|*oQ0ݲ(B-q¦3: ܄N-2;[|U=ۍ7d¨ЍH໶l=V堧W3gN5aԦs%E4Hm5-n}xlyFv)"gR6_E3)#z@MoctHAQG_!yb+gb <7k9J7ͺ9#o(<"xSxAQܙnoԔseٮ"/sQu')0|2ktl& (fk/S9 kT+A::TmLp%ERVn'KՑ:n^,œ(O CNXE-HPб!=<DWN7,cxB~Els1o4tωX O)gq,+Μ mW~ vڡ?/O@Le?ڒ/)$'W$7=5I6o#yru7Fō 6lP?AGƖIQ@Oi. xqww88"=>em&ЬD4FkbIlW9G c몐!dJxlҭ~ԖUui^JO0Sb)DXôΎh[ݷxisF( N53Ƅ0hMV# cC@8t2 }{W`L\2o" I^v5| T;:]tV LfmOͅAZ t^pZY slYsa֙v[_EepQܶ`i|1׽߾܇LǯTCGur . mZ], %51.KԪo,#ekW#s=$Am0;\>i†4\EЧU p9Yk-:)C7f(LBi0b@- 2V5CFHBq_p ~KШ#~d#*&wt;J'Z . xFaB]U? j\*LQ.-ʪCg鵕nZbӫaӐb1]3b5^a-pHM}e>^XƕG?Oׂ%sCK䡛򹩀.h[Y@^vK%X6YZɭu_td1[6xL(KZe+\aAx+THvz֔Gl18d/h=7ma[j_ b>ÈWɫ@ +WP$ (SN\jQBu 0f}k֘`AN~/~  $ᰀ@N]o6u%^FGunKeQ.m>&sw)p~ݟE$ eओ2Sq(`A_ZԵ(]-؞fnFcXA)R9/X2+3g!k=Q,qi*u »Dďw+xܝ){#%I? b;8;ro_uUB^oO)n/=%OfUM9{۷>JgjGͤS$Z߅D(E|s>zVHmK/N rJF|* M~[PjD?>akbg)ɦAn7eqx0\hA$˾\93# Uwsk^C[h(z\c;$8V5T=y7U: N䁺0AP2r ֯'o߼~]]KgkBi^A^srtH b2nx8JE!G-#(ssK('8rʞdRa;k$*8̔b*~3:"!uCp>"Dx\.h4C j 5ÕO9 ~͌/eHTSSsupVœeQ,۝B:[rJ<'eM)5MfR+><[0h<ԣ y0|CǷcّ!KfO:<;xAd@dS00$q0ff-#@MD*ӥmgI1} 8JyNpJ5Z<:+o dN\I$aUÍ˵+ɝe n+š_bFy(K kwpU$amW 6g:97hk4iU$dGw8(\/,UJ ˨ʋ8 ˳H=ZB44I^Y>TDUV|Q9LC]<`GI/s]ckWQS,3 >sU8)A^  +~F_^T^> 'Ƽ3It,mdTg,gӡ. (mMB?7!MPcTc Y$QAѨ’),?gH3/㝆 ⶂO=.jn&% JGƭD̝!_KԅֶAn,11V3<ʩ!{@j@MȿC%<1 he$1.6zΝ b$z'tW[]1R#Qΐ>g2P> [PeDFӶ7Я bnn^{Й|+ݡ>޵{^3{ouƜ4⚓fٳ`$:`RCvceL,$}- /9U?(,,?0zӲ|xMp2/!ߖ]K7dOt.A̩˩}f5D^2[ )|;p!cKZ=qxMGN۵ H# Pj A"&|2WTM l9.2秲?ɟ5'7v܋{vOE&jeIQO|6q6kݗgΛ0]\e Zi?0;*W 8nդ(*7F\M&ҷj94xO~w7ir;hF:cO[ dp(3VX5v5Ҷ(cѫCZ<*l dMxno)7)ќ~E!w7Pmp̣`VxuTMlT6'cqfI^%% jDa-4'7~I,۲lL/!!pu( B9= ]g I37a6զғ̎(ҌhU|~jduCvg½kݨkM&IZoG!H nNZ*"9a\d"Áh&,8arn.z@=rx8b-t p{x=)s:|_fߝwd|#p"nQKsIsP^7qE8 m6 |(H4uҴ!ZEL2K ӤU(BBvZ2\}fV L+߆_'5\At-C3%dZu;IBM")M9C]QQ&.7ApXF9AbGRW3<7 |Z;a?܌$U >;(b3/EJ |ACG-"u(6[<\f~P0}~CD][?bM&"CMu_cğp7PM֑#czS ]oVB룚Av~ } Χ.3PdZ-ːw'x^nnӵgu|v{Q'j۰_%W]~<4j>\t:fކWsE WS'TSF{!>.nBPL=4}[{+fo@D]lRA7b$:'3XP]X9}kرaI !U{Z ̫|xIEq;·xW8w }! !}ݥ.6 z~N$~u|f$Y%$ݲbG|,+C)iƓe GOIuӹ8lO>%y޷OA>%4IV*4àW%A4a(T6GYhDq2=̖Ӹh;H{;7VWaH:2Л.VvNѨ8HndL@D~FfQMٿى|7ߪL8q莼ib[ T2Q0zɉ$^0xr֌| ݱ(A  T4Q0t0'bx>9{ `AA eh0U I p0\48Qt>z&L`D菼TFq&q8fT`I;2i>Cݚ:G/ ]u:aDxZCwQ/Kyi5iÈ"GK1ê鎽0<6TH1U^ 4V5hQyZx _ b~YBN]Ts^{O V39`*>-uz!bxLU+|Pw2g }'?PLӉ>X2U1 ``+_^Zs*|c-r˄ ;y)G:4삀!Х(t>Uh~ z$aOchxc/%-gRaQ܊S’ '&ܔI-6q'=KxSfnҼԇt}Rڎ|5[XK;^㶝Nl\D“?a 7S0Mih B.:pM);}k3Z ^TڂVb࿖ל_\^5rAv~Zt`8ȩD% 69 QDH&Q^ 1>%QBXyD֪v1cB}v!WD.*Q^'sVt=z-dvr{wxU"d? Ab |)߱;o[M)F:o&Jil|bsZu;RL gKsgKu.,WPe ʨ2RlhOω7Ke@[TѸh慠&f+H/Fd-!!amY#$lJJ$xkB E~I~M3R9<$Jb s6Bccdem OoL9TrJ((ss U$[ySOzޒ9lUv@RㄒlDI|EZ1v}>wgƐ0ĸӈ.&죈l^Iju%(<آ"G ӔwQj-l K\$x$\9Z0(.*.ƹ^CbTǙvsE'krÕ +QO䊨5Jq45*Q\Fd+~yȀxaI$(+gWuu}Apv'Fh^B#W JdӁyےox 09J>& DR%J|$?:l`z)WNX#U?;uա$WSفM%<|߬wjon1U.R3|¾Gtغurn.k}yNk}.LDa/!eQNxČAхn[4j5\ulP}ۻlvq Cz7KY4~h鎛2cN#qA?!59BB.j" Jx EŝӬB5o_-xS+.*Vw5\x#onPKW34y2xkQ@93/94%UA8#1%hs;i,lLԒIlt' ND u xU 0h(şCaH#O0)9Yyz9 7vyݿy̯.{\jޙBqbnANj1Cڅk^oc5=?N '32OW(-N-Ld)eo!{۟}/XE|Xp]I(6e0M*^Tq/' xZ pu/pEbcbx%X XIKƃY`rfp)2%R(IN%V"oUlK$%Ul+q)G*cINs, lwߍYgRqoCqHm>DG'YDyQJʪDE gȗ%-ɭE0Wͱ(700NH=8Db<\2Qp^ݒ8c(?YERZc /0+*ʀ&]Htt$f 2w(9@" {#& #%$޳-$SPW8h5ű 0t]xc3~, a y7۲t1-(Nnw}Zt$h$IjY4U9-eY9f`%*x^2ຣS+`^GU$4w싥_/6H7<V*j[;sCݤ=葃z:@i~QQ [!V wꢣt<1'p9SSkm;%5#J=jEmjOTjL9u !&.bIg&ciσy4Mfv%k2&B!:?UBmYV7vPd UTÌ}֠PGUȞٽcivMnWd.:ާBILċ) #pi ^T-XL;\CSou&4Ou >ὓŇ&oxMP"oZ X [7, q(f)]ZSv^JikC14+8x]69h$Ǡu>I`:*mQ|۾>XQi}sϽ{] ,[Qte55yy3[ࣱ[X5-Di, tLQLxrt\<%Dzo}]>0OO+Scj:VbҸ&c~tC @lJ TYq +)u O4/>o] C5sFS(r">JM:84={Ae 4! J# ߪhR:k'[Gy!*v2$a/Ƣ?GIB\i.L~xwQVtympۆpw`UVo`ˠfjߖx>(-NTW^5_0t.$N%,SȺ^v޻6s͆=νs2w+J {f$]02)tz6$9.Vk]AE. `ZrXtZOhH=ڜ&t=)  ] I~yw&Np8 # lq62kfp$ ʣJzIpD-^LDI3I*j #H/o?Nb˿PL/h$6YbZBw\\!'cp ]<0<|=5?3y)E-5>C^ԓNXKĘ9wK"amZI];2l?9jj_Kz͞Tjc5pcGj+gGB[whr{^QQsY ʭ}|Y}|mmBˢ4jY !:ʲwN *ƪlX:U>GNzd5"kcu }꬇O?QͽвB̦~i[pr%P>;6ZH6V-> mZ*)U:&J+|?g/]vza;WJ4k|F_YcOlև>xoef]bhD;@03nZP~ j"RMtb4("r8\DEp\L{|Ӡܮn)h|"~i4;WS?)o>W w{wWd|:Y&v󜀝 GqSms'k2yGTE3oji&{Aϧ^OћA2: 2z Dx4:! H ְ˛L@wB'l#%%LSˈRRH+4% ~ ͋͢mk3g]HtU )םbQh\{"!Ы|ss % I*__wTX;g36xfh``fbY_0펩g={Κ2f{z@XƇRۧ-6^ 훘r˾R|U몗pƙ׏"8 9pdbɌE/\ԿZϢںwWN9ٓq}5}^gK^UT55371=U/kb3a3mfSPQfKhtI=YjݦhAj?XI?6:r;R^g J"dp.~ZlL13]A3Cunq+4{:YY0=E1g$ Wp˜ 5-T#=)Qea_XrpRj[ =1t 0+6 =u %Z"C0 0S*[f-"obKؗOVoܯ"k KKhabF!)Írd2r峹(]oV_YxδyBiE9E9%% Z>: >i9% Ef:`&NbĈ[x: luX^H䒳$:,2E.iex-z2ܙ%GάffIY%;"[^n EFٺ$6mAvhvPH9v$r5_\}Ko@)xj7}AVJZH`Qӊğ545$#S~KI ge3?@k *:19soCkqKm>FǦiF'xQJʪD#E g%-ɭ폄`zoc#S1o``@{aMǦx8eP;%qQ~djԧIG8@T TC%],* ĐpG4y8ǧ㱾rc(dNZ0)$M"]HH%Ri6y)۵U)ooZGVMyAQEQK!I`0%|ӻcî^a S0ƖU>f&\`ɛnsp4Yd𺴨-IH,y'C{;NE9y, ; ҢE1='bk+Sط%K%LBcp-(H)6eMe#)$e?|#TJ:ԄKGCS$ hIvC.Mウ#`eYQ+%"J1Y<9z_Yps2W9A-7&X\  " ;m{ȜDy$7E }X$N?N-!7m%1A)-1I5=z/o4ET3&nƲt>-(NJKH2 $(i*rʲrnJrdP{Ǧc1PWٳݻ:]JjtaWw싥,BKO,.Պ9V7iy蠾N$_UBieVk ղ};a(O,:i=d"%=2Zc~x$z4:JQh6 _)4# J x޽ 4'.0$pז!tE !)d,I>GTlznUq3j(A6lu5Bge`m.f?-g߯&v+ SO,8DCب{"I*¼Kѻ*a "j#f3_`oMV̼ d2q o|l+ȰBBר٧MA zHh)EB-L~YEsS?'|ŇWTB ,LofjoRO#sam٧w[|?Vد))邙v ŒLry|2V~̭̱nzX㵔{Ni`?=w"ጼ>'ummomc}~;k>wu^g˨?*`IjQN- );3ڜ)ZY>dxG WeHeT5x_|ut2]%N_ ŠkjG"K9zo9ĹNٽPZx͉8]Z4CQIpZմS2XN:njȝu&zKu=>EG&<ay4Xպ66P$GMghf@bvՙҥ%>kgxh}n>s ޡ12㠰r{ VG[`H<Jlp~ߠ>_Џ}>D8<]Y bc&LOVWюu\{ñ0XĭڭdQvoS'^k{_J0WBP3D.j3)oL) Y[$ Jxmh; U»CP2\NAV]5ҜOX)ΥIDl'C m!ItFs<'|@Ƈ¾6()kW_y'c%#MdF̈́  U#4A^ŠR7vÝ0'&cı㩃Cۻ]PIH꒬k*}Ui٤ kP!Ug%d#dQVj;19 Ҷ$D u3KYfŁwA VA݁5U{.Rx}[x00#69ٚlulk$Na0\ (N\[Y:u9xFCݠ%t)~=9g6c>'骤| dU؞Lku*m$IrX+ VADPQtI0e6I ^ KN MG {`a&bT``O HdJ/Nch4CQyqEG~^!9< Q$enRHh!iF0B \gy|j ETy E3\_İYA!aL~YKXƒKx$6%#鱓c1BGSRsd5K<5Y \w+p(l2Bڏe-k%uv0~r?_ᛃ<tc'ɉg0}yPϖvܜGVSilBHSǧ x z fhje\oGrFx b절adUw9<x^\0u4WMSo[P# o|<|멈_Z}e{KUB^; GCe |jij"$"SP,'OdTslJ颉75^4n!A62kVA4ht;BHL+@Pi+$Cw.{=|n2}{"\FBZ%I'h0, j*PB,j$+ pIȎ}_炉h|t daj^S$Nl4Wff]LtUJ5piK6֙oxnIŢTxdBS\T5 >Oċ0pwrh 3lD9∴wGGQ =ak8rCwM'Kfh}N 3V|Ih#`=/=UrVSe 6vbwBiM6SL'rrDblc9s\Sh`,`=' DBɧW3TSVRֽL{s{3縗˳EмĂ(Vϊυ rl൧Eut1[H!//|I.k R0ec=A/+GL徨;nXcRp_*0fz ֒2Gl˳#$0duh/y^8l ;F7t_W]4}4yrN zeՁ_?9fLX:`s-zDZ%+YMs *ֶ6N:W?$)IAGҖ<?{RE3'E\8 >W?wqGΚ@E' wM;f5PBxfh``fbY_0펩g={Κ2f{z@XƇRۧ-6^ 훘r˾R|U몗pƙ׏"8 9pdbɌE/\ԿZϢںwWN9ٓq}5}^gK^UT55371=U/kb3a3LMFز]}%mZP%la`?T.lJ#깦]Ӫ[Ǟ۶`* { ]8G/S_a: "5bQ"vpM %˩` QBl}6dH<:/<gsQ<\K#',C:zMbl~y乍*O1HQ<WHW+Զdi=N73[zLJ>|UJ8k cM[QAb5K_iX.kԛ ;Cu]Y^p;E^'GFȫsrfQ_--gJ=7$ߣY ,s>L˶ Mmy3fڦ-8<7&Rt ]zK,"븊LYRfM϶嗯sHh)97mّgwM ?ybG#,- lDnEQ%ܹ£Eأ?rAnGΧӨ;\f+$=!,)qcb{\I{a5lqW쓉ŵ:9wSsȐb)v_\=; Xn ~- 1nb:҅9Uyy?\= kdphCC9GtT>ˆ;H&BE33=)D.(<ղmF'patY}{|*w͟[q,%H*_#InLW-\xp{ t0`YȬܑEZbt*[d_e&bbFdח l `1gSOO'ǶaVoSݍcTZOߏ>9 dۣ%g_OHźMq u:xMWLyZ$TUrl.^V WO VsoY4^jhZDe1,x4ځtڨpJK[x5JQkcoր0T¬̱pE|rT4c˙1i0յbtR!7(q-o<Ϫk9aQ̈́J*@M/!qzqFXv88;Gwb<~EBKnP [ws3 +/dVK1ΤoDntJ^mXNw_Gwזw3r#cVp`"BUabRbU]33f]g#ʬ()7hF||yZq;9>#gIxxZypyP:IAB\xX-^HHQEoXi .HJْj"K>'vdݪNsؙLIӴv:Nә4{o,H%}{eѳ?/3so99\"nZwLB$y5E*md*#S'Ó^[$#mG?c; b55N) )-Cc$? _xlhD4qybRRDN.j[;8kc1p0J=9"<+:of O~tI[QTTL\Ut)!jbH Y$B5Dtg"?p C|,R"%B\+e$Aĥ("Q0jv#}$4ց;k`IomgBO)ږ8Ti䠱QTAYefs ԕb`<0]]4"ϝP4#}ħe^8ޭ(  RyT+ElQƿPs` ͫKuQ38t=euy2y\ĥi6k<7+I_?FYJwkh3Tu+j px꩚rn63 OQsT ]al4]y$eaΑF[ֲɁeZ3V3W5ioŪGze+Y,umX{(׷lTjAuJc¡|ZQ~σRHz긅$ͦG%^b2UuܲbReEv\P[79 MZBK'#Tldb|"߯\E}ӾbP/e'rM5"2zJdǙWjxO>GWIQ 4L\Uh\ JJŠ-!@r#7\MKh5E}fφ{ cR\22|HRVip!(vF;,w^MXgE&Cۃp#1ΣO8@to`}g3.XlmE:HKy!mU&CUUY GGZ$摪=m#MህҚ5㑎#3S G`p>Kw3CY|C,̌\QJO(&& [,raϐ_4}PwK!"[â"j!20MLNEC|`&FV( ?m/z¿bz&Fǻ+Es?؞{VձMF`0$z}'S5y)'[S@SرOEXaFiFof;l{b~qvXə3u5E0a(0 =vN<9O$#I"(R:>an FQ/Ƅ*$h)X$c] 6uv3H`9L҃ 쎕e)+\4Yܳs+Ņ)Em!\LIɋh2i31Ij\sۺ x*KⲪ;IqU+%9!"V"pd G0$p~;56>=Fq1M=`1KֳLdfJ.ݻrfoJx@ І b'hWK,l䩩x3 =8K/p,tF@eGRqMRmLhFlATSXKzxkš@D*/qpL_j-EbŠbsCq <и;+$4brʹ靳]X1b-p]LHEb GhJJlm I| ThA::7es_c3YvqmXpuBN~v}IY4Ue[q%Ts$,]Nw2^cxr:Ɨ)Aǚr=.7lFMojkb=+5w╊+pC]ftÿ=ѤK ";2{^xyAɖJ r*>>W*؀N^ Rn 60r(GxxLJW@TG–':vǃ5p^'Wj+[࿟xm Zd;j޵e/]^?[ el YW9h_]ȴˠ\\TbƱA9}+#P0]3>UsT.RYq`3F+$DxJg<D#C!y{yO>£7_QgZÏϬ^tz#CpC;;mdܨp~_ xwo;WJ 4kKz-=|zL<%z= | 7t0 s[W9d'芉@fLJ_+fb_?іI+a%̄r"ݸaah6 K=oVz75[^q C8h}>2 N|7hY 5[iK91I;9@b] DYxҏxeޘ9E|CC}umvZXHF_&6 e[GU4 Mo^ӫT>O0txpr{4ivh<1  GP^Èyw8zACOOU.|M voG烄&e7&1A&ܻUE@* UVv =%z)!.qVV{]{1UFAߕ= WRR@AEm$m}ΎMgۛY9DO_׮}GMHO%$l1E:t.EXrx֖9!f)u-;CK|A*o㘒V Η'rW,NŢ#/H GA)q9P) &6 s ny ;ib+gA5蘐d>+s>Q/ .1U8t4yr-X<1bӯrgr桽l_ nj<9dWETz e*~ue1Ky dC՚@ED Ƅ& QssGh$|,ZaԼ58W Q+dž[mnk3ɱ0=뷊{ϕf.1ߜPbO:l)|j 614k:58|o[Wta G1ƣ/`8 )^'_5W|"]X|MC6tt'_xk L9i囹q$d&+g(;;(g$jLfVeSS42J@\#1$3?OSK24 " `#\a򓥺'vNk-1Yenny(HN,Nvw vԳrC+S'.WWy=$<3/%< (1W?e彜 5y%`@|<& z܂}|\uL!>17?%u&1P` WW?%M{;b VpO?'7F0fi(ڨQRQ` ::`4'O~=o'ڲ9dB0̟!%9aA~!A~H~ .O,+I-*K0DYꜘ1Ygb"rF$-hDxS Y S]2+ vw |)#N x340031Qrutu+(a7>K[W]:a}&@^ǰjn|j{dkb g3Tr34*]ujwlw 򙹉 &}paⴵ"'#!EE% Y29?+s}Ĕ"/W}yÍm4zOZFx3rzܻ܋jFQV;4vݑ. I{ޜD-F XMx: 5*KNd I0&r 3EB9 $7A쌱ٓe JJxfh``fbY_0펩g={Κ2f{z@XƇRۧ-6^ 훘r˾R|U몗pƙ׏"8 9pdbɌ8=~_rT n܊&7)_+ɪLf 8QxjA&f%3|5{_|KK{w}7y69>şCaH#O0)9Yyz9 7vyݿy̯.{\jMϴS8('3 hRB?=_&+1lPl9`TVgӅɽ,x340031QK,L/Je8-}лWK zUkVkQ囘$e|Ͽ%}? TMr~~QJf^bIj^A^:h]}<:>oԯ*M/I-(aZ(k6W3Ki\v2RS`ʢj+LFZmpe99`+M/Q ^zj#}ʡrJsrS<ԜׇxKw|_OPEy%)`<TW_+o-yxE-README.txt莩 fo@>DRzJ2/ ЎZN@ &x ,VM+MQ3srR2JJ 3uRsSSAx¿xl{eP\M wBpHepwwwwa Cp w #߽=U]zkjqe%ޣo[EBxl `%c$oC) QϽH  oBDg ,);d76ЛYLY hblbLflN.W @QBKG+R.$\dm#U rŘj"I|~3FG@PXWPƨ\!1_.\.)&-dz|Uy. ͗nPg.0+Q7T|#@ 4Y46*JW'B{3qR5)w:@{?qܙN- }^*.pUٿ/i%ޱN^jS rtU&jνy;7Y?*Pa)@{jn ޏ\CwCJ!b Dž%s7mX99  8n[r:ޛRё<;wg֔Ƃ%43ЫbPǯd]@>jb| @vK-B~^GӸ*N'|"F(AqPTu_9mfN'(GȬ6Mz/^!''<_A"8jm$6dl{ xµ*ΡEV!G_]\6PeaCEU{7ZIxGgv*o(BnZǁ7մAHfj3xWy{ۤkkPnM'\;06b`oeOӢ휡B{]|:t*S4u̅n-*mdfjwa ۋNcH,a(=<,ĨdQLۖm+;e?̘yq)1=<xvZfsY򑋛BULu)Kf1cP?vl!JWτ 8";~5[>TC2ѪЭ;U=U{T4+1SˍKN!i/MS]ײ/hzH,b vm̽>w@\~0I50}-zp Px?И[c:"h/i/_% F}OF n9ii$ǗX*zr&eA*hn"ef m dI'E׻R3a~IoY|Jۢn?k b:#u-}_O n :o֫okt9 -ӿMC5£6i Bl9'ģ;nbz1nÓo 0G{tv,xr~@ yȻKK)VD6** ZB 4XlJy q<0?l,S3k໓Q:藎Hg3XxeLsXg)F dr79]E2e^(R(DߐL-ËX!Q}I Zd0ͼ"zp-,dATc\NMO.l nRHt`&ҬSk951fKE~GctHKq&(o 9ˆ=nayF%( "(ЫLsM̟ SWo`9f ǀׁAbtd{.Q-q7K\$m->3 pߝkjXM*|z vn|1LBlTQ3' cd۸^<&f59۞GA,_N"pW :/puJf3'%^0ٱwMV FI)?O2)Y-hۮ{1>%~ DgƉ>)U)DK#qi]Jd/k`OA08)$\F VO]zZ]pwʳ1úX.5vp"r$11FO0j%ekÿFyN낇:W;я7܍".wGbCFmA8 T?C]MP5r6:A+8s ƼAx1p;A?ƁA4 Sͧ{?{RGercq/~.J>c^/a ԻzBLMM K%Ǚ&.ߺ] \QVReyeohkjvDgw{&nX}Gn9hBa@bO1 Sp}#!Z}<]pg|PkD,Ï de脧x&̸q_S@3Z3+: Xn+?Oo 9{RÂ! ^e$,:z~qRjݡin@N교9G&^guտsk^hXfZ'Ka)3TFWn$t2?aVkc}o1涵2* $I'# cK!ǫH(DMcv\>OTf֪,@7X:.8/yNn!B lJ9˩ShTQ,$F$!:ۅU7xt*d1zO(yIy :"}i;u[@t=_ڙ5<w ?c r,RV*̕ ~<ރ/1&V%Sj 1MLuSi>% gbaQta MC%8k蒱tmiNE<ḋ?Z+WiTb&),u 8ޘsCװE1Q:G&VKh 4|:W}s>LLX(72>Ѷc``|fHC1Fq$;~d5$E`:ETS4X ]ERA Js͟ p{]E(Gk6Gb?H&2gu}뗃o%.l7!u[r)up68;Iy Df9?zޓ+00"LHld8q?7m'5kߔ̿+Jj:H84STei:*ؙs" ~r.~>0ptۓ:m c6J>Rd1xypj⫻TүkF, T?c(aO=u.R{i_pןhFob2EQߢ;T]ˀVz@$Jq V/H~EUUoЏS=2hJTK!wXiLKh#Y{!2qg+5! Fe]JʿF1k>+Z,(H7Xn/oU r#(IxI5Ԗ'XzճY)?8~$,q~{}=]ͿNUN-#tEc;?` |08ØԴaԙ  &˙&0RNfhh7=Ck"mQQn3|@3 WĦ dH_~u)XP\¾T4PUf۾3ҕAdߏt˩xs g5О`uqΝb> 5,Q):'!{dide {T[ѷ!QȀ~9X) y},}s t:,L%b\֭|"n `3b8ގ⭬s(Gi$6@ hu_S" ٱ7ňê[*/>TNtлRɃhbz/7]̈́X${7ޤqP Bm.Bgbl^oˡkNN_l*ML2ߒ,@O9,wI\~3L{sl~w@]c5DmsntwpnaSw1mU5t @lCNh f{Io-/92Kk@w8ٔ{]*ߢ'G|4YC oѷ5Z15t .BjsF#@fh8Ģ1b'|/ۮ|XVѧG:?b6[LnƧ,˻j]NFW^cStJjs4ŗ@LvõTI qQ_ZrT .J7#{x/KozX,?rZsT*o!.9.Tk'ќY~#d~/J&gy= MFWV'F}I\8%xϿ{էk'AQgnWW32P|ln_\L]$ !T,%b&#H=Q/l"MQF\p:D4Ҵ6pl!\\)糕:K-KqᜒpAJXU+wz= CXs!U؎MmrJhq =b·GT˔ۋȻl ^miυ!.r/׀.L/Vb%rr)G6@e::ilIA".2t%Ggewuy7ox_&}cl#ϗHE,&$"HCr/B4B`4 0Ta:o1żQġ}ՋNVtigא[An{_ {( V+q[Nv,ܜ.X:K H2Fe (s5E&Ј<͚57Cpq1Đh}ne[1 /s:*Qظ Zy|ђ9Keik12<r|kl$CIoC43BI+$D.uI0Fs21$f7ǙNZ 5EDvgӶf>CXE}sJJw!彁_AB<5V٨sc?,s/UR -Pౕt3cU|?9W#;J<9;-,MC:G#wW-2K,üV>w ֟tHV:i R-lXկ"It0L㰊T㿨 t)t!r 'vT9=_[2v,v#Ÿv*QC\eq\!]ªG'uW.kKI{e^6:xc#%^ _7Qȿ%CnV~/)jbUG< JVaTy*{9 Q,>z? ~bE9F2)ﰯTq~4?#+WF&$K |YFE\/,:Zram7'B mHߌᄟV4qxӺܓ"NQhbގ(%!%o*ayb廙)ǩ w-F3 ;}Վ(T/|1t9I 9Sm8grh΄ol"2/x}P1K>BywLl^Ua$)FٿȌ9=P P_ʭ[cYtx- ~R\)nJ$3'`7[Wy 8wPUv3óq+-"sI}ŷZL3DgP bN[ ,"/O%5iO]LA{ '=X<8|N[C$ WJTpOL3]€l"YI|"|gH/3TS#Ku֤pKA^j/dR( d ߑu=.P;CJ\q!WYǭ*7Tiז/#ǎ3UBJ5X;&3[<' 9<{tn^:'[iTt+E0J 쌹ugz␊@c-MiFiFS.NUe?k47 h>rRwx>:VNWMPEa;!ߧׅlqԵ>aIRՠ8+7(5 _g2a5! !Bғ~ˋ9B{Zd'|`Wd>lfjp"cC$V ={Tb[niSvCB$ p_7c_t2vhrej;]fiGĔ:?)2>j^/7zu{=& gVw++?;L~pyϰmwYlC5t3R|3ܫuq c0]O<9tAL(& MɦB{2]}Ų-8b*牌ƣ4N;2V*xH#`8{N.OF Gf[&2n/c+_'l vZ@B5rHM&qx칇/,3fILP 3qQEa?hfa{t.0%z_ϙԖi"ubS[.D+0,>@d2$״  XBn^[:z}%;\3ύrG] |DbA[ړl}0pѫS+׭ς?*ف<6I$1[Eg&~ Br(oLYvn =>K~mMǺX#bU0ȖyyiCfBo";:ybo <;7_6͜촢XZ1Ό v6ΙU4T00A5*qlLV$!hTH2FFGw@I|CdU]b 1ň9*8ud9 GIv?17%pݏ< 瀖!OW"mz6T= .u+U5LD/a!ڇCqtoSAsjںvruW}FFx0nKد-AD75MSuG݆ڳ^tIKN?bޜz\:{R:5\$0:vuVT 㱴*~3E6g^%f{ŒH*3$Uho;ȲltQ]N;am$m)Rvyـ{\a]Κ"Ё /7(0fRe,'?qq]C'43wLY,؋ V'h^Yu"QALƦ!wN"R޵3 X eOEî>(3imR7Bs-^>% v_o}0n9wH#W\\~g9X2ᬝX!N-pt{r1&BCf/*c[3$"v7R[e|b8a!$ɫefdO9eqc3^=#˟-8Y AF. 7C˄xOX< zb'PiNI1SD;ȅxBL(ų1 p[^KpXlS_PA?YG9 @l(:iu^'-kF.+T $+CVlzX,S)XdHHt&L`44J0 ˼8$fIB,g`:DOX#c0C]qQc67 &SqzLbet9':"JXm~q%Zļ\!b PRmu2X$ߦ0WMq jzBߛ\cr ֕lF2-#EK&*Q]? l61 |b8E4p*p+V7>6:/"t 7L(r~O uHm ow9O|Z)ba+ 1&7E R?̄dJi.B_ LŪ˹4MǓ_}KfHRU|d{{Ӌ*iVSZ7Ct4|z˹ɺI=Rx(ՇB`,jC5ҡDzZ8gSj =$d#2F.,pj)?-1)O_**{Dr~>"mս:,"iG$8:2[Ne_Ѐv‡Tɔ2Br&w(Ȝ`8r x}n!Eū8(UcfFy%ݓe־֭L_=3-=>_55Q:Hx CusCh(Y鄮*S[Ī"Ɩƒ7A)h?VSivG j^Vc+x̷pp{[VZ7m!ɉ]&:2ep>Т"b34{ḓQ\Y[8ߔYŒm2h )gρ>3qk{?v7u| y8%زxP7P]J谻ͪ ~{fWs.qqed \ܻ)j?f`dQd0po`櫼$25 oP-4.XGBIʶK 23KJH|,+(f6|Yq>g%Fˤzo‡gezϿtJmnd sMXvfl-7+y*5iPNE|r|w,{ Yކ%lhb)[˨KG:yS6"}X܉xL)D NP@w+#[[X blPcԦOM^S2j Frlb犅1\-#so c P&(P_$\3 SޓN%t:>jՔM'98,({S3︮k@ '0iF `'Mxι/y s6k_}al15ђ5 l\>~z$|y8BTMaJ &y"sOe"JZ:!d+Cg%{*߿-퍴G@jqx9mW61`\} lgdKg#Ub=ȡf%^?^s_%x:5{ }ɱ1!d-@Cah?Mԋc9V28m@IK-aiSZQ +kB# D*I=YQ1^/kU˖4:`x ppAh-h{cZָ bZ_"K_ Zb) YY&E27 }ϯCDq9r$67u]՗_-8V7Z**k@q_(~}Ŝz4HЀ)]i|M'$cg]PWLb.]VO^ǬMiJo H)uo4;2.OxFmV # sopSrQ< y#W J+@dlŇb󰀸F)' .L^54|8C[ZL\%)͙ CU@ɀhmO,X")\͸⫨Z]^}[P>R0$Mo`a[QeUMź60^]Utp{t 2."TQB x<4t]U} xۀh-+\~O%#>yOMIIA}FCfKKAot> J L~P}! ."o`Y&k-@c2/L3@"3a/0,牜3I|8g˹zydy0f\'7pHys\Y΍YOIV)wuO8MY෹ έnI(sd)ʮJ?#\<K"hJ9Dw2ĝb9 TͷOןҜDzP*=ˬo4,yf+G0_TbxWNr4MP?*ipRr%qeVwEjrjh4'j "=m# ɛ54pKPkfz^bF,)pǚ?ujN?v7y!ۨӷؐtD~"#UJjwj*3mӼga?ʥMƁ~ɣ<]IcdDɕ$':%:㕯mÜD cC\@BK֔2^=>~"A`.(6(\zCBhIŌ\˘VC~YGNG62V#'1-\3rFFQnVh]M?az7޷c\+dj}Xfu3d VzFK6 ٭6.(T]#nȘ=Es l1~l{LjtlWGa +YHoPpawx6E%tB dv9NTHHNF/cr3u9mNDO\1F[oCW_j;^'J`=bЗcWqb!pT͙A9u55l!"&3S̮iierҐf-/մ2U[N>f|aVBQNSXp<u4c*Tȳf ^g! 7ƛieioܻ aƍYbb k8hר~Kq%/- -8Yf:F;KyG|}nKA-rRv lړŝNyTh ;eY LJ ,}PX& ݀#8+ygH̐8Ī-B0gb$s`~l-S]5ܦ7.,?,ׯ{gp.OT8vKݽ7TW3\ /rCvG̈́?a4_BjAkZ^m@(鐛6*A&ऴ'((X/A.SyF֕!. r} LQ1q;q2>*-" }*c v9>tg'̾M0ȗ2TZ;9:H'kl A5-@z$ l:V?M;GrDxƫwo%%4"t^_V-]HΊV+Y@C\!h?>0놹E <eBnCOIC =[Q`obH<R[+~pkTkR=a/yrꄴZC毥R1S]ӹUӗy`Pj+EmO`b*x)"w_<",( L@7Aa| z-;-3,zHln_ |-bpp O~Wa^3\q'- ;aBay4>-Hfw{<ܻ E3\9uOK\AʍJ6QΡLQ4~dM;t'ҬOF[ƂJ$ޕH0 jc0o[o @dƅGp%g?h(nL#u<[1dEֺ.*Pk(HT{@ZfzD08.;K k !|ʪh'n|Ykvoo^} N*)\[+Μ Vy33"Xik]hh?}iXv,/76TlÎ6̻SAO[?vxozXc/BFV\s<خv00l\e ^ʐnB6,~rD$qMbjשX ~OK֗ F-In۰47ئ!gJz0?9sm=.*ߨWMqt*@*Sq ̉x]s 5k_ο-gE$diOls2/ʉIJ"e+K״ks^5 Ax=(X _C \>Vy8@}Xǖua ͼXH>Xne%Uq~X}+4E$-N藍8w6VmO+24d8Òx@|~hk 845Fǟ^ >; N&ےc" aU"XR)lT 6gBDf%IzYa_MP (ݙE>-"jYC3\G eusc93CΕ~n"NІf2 s vo1UP SMa`D?gSzg^[̃+LA<q >X{&p8Is̬:y ȑ!-4zUC60q8=GJkʌlֶ7|d4S0j|^`r]\\Ҋt~ q jjjq9r:NbvJc8zÙZIAvF!^۸Ӌ%ÜWl&G3jV}}} a>. p5||\\YQvMQOir9fu..(muSN+bSx_eO)X!a@m~s1 LOAVS$1J[ΎGRW0#R&ܗ7DvB XR3j3c)f`hI@](Gȭo\]WylB:U{a 43Jpzw!HunHK5$ׯE%r2(~]niV%2h qT!oA5LOAB̝Dѭ-qN^jjx03;7O#c@>ڃc< %,zՠgⵔ0:trzl ѩPA1;`^H ^ ?[Ʊ7O?Wx_8fWԀn!;ʣ$ rq򍤅 z,d,S~Is#d^ ^z.1=IʘN@Jtryw(VKuq첫.N.cP˗y͛''忽tOX g}l5եf 11XؐL[?\ȻR:WxuC\f!#V ۨ6/l \Ux7QdKizg2W-`ӭ~U4ܥߝMv2^&8 VM`}$$m6 ;Tswؤy7A'6FKW-hj\Sz;+,rx rfcw͍_' k +Ǜ4*;cVѤY2{k_GwDlMVSk\ )U1Lp?X55^} #!"񙽋Tx%ϦWw_>,Uȴ>~aŴE4+`#T"ӌ}dTy9X? `ientenZ-~{5RH)ߚ.,9!|d叆)^|ixAuYn(|k<$լ艃>vTj?/>#>}?^.S#L5f6+I=73dpSzKvu}-S-$2, |=hIZ{ba&C.e_h}Gy2'b(}|;;7!ǽ@{o]^'[vq';A ƂI-jnuF>Uizii ^پ;l4A> L4.݄4DžvI3{wg&볾jMڜ[{u"- ;& >dX MpG;>ß2|N˃91{ S%D̲ɔn F>7=M};oOKf2dE}s^2#̻]ڲY5Fݦ;ၴ,CRACDO;O@2G]696GdèDKhZ$A@*H(D.R)Rs!g8GdRH<5SމMYvDA7389}nrם05iL&Reu~H2ɗ!6տwDq=ZaA[m5IfuE)#Ejw0Q\0Yn# TҪp=2 ³f}hx6RџWn]#^+H2Oo+%lwv!K?R꿻MX !s7}7|sU=OE[lv|i]N, ̋m]<sp}^ά=| R*)D kGQE&c(*;&:8xя/ZW3kW (.ꏸ6F/1s+wsI?-<0}}u}b,n ٳa7>BȐЁis6^2[䋎uf2J ;D۞T> yRx0P,IQ^Ìe3KZ][} nw?)|h'tRV-\1g$gEdIM4r|=)$7 O&ޅ %jcEV_&M fT mu΄~o#@ XBR(#^w"S(dJNɂ P0&| !p 7VyF 0g Sl_x( BR qPe!8h tLV j7*O4XV,K(}NB$u9ianM,8l6= wٮKm\ }356(-:6>,߹39YͩfaA,!_~בμjb+n ׶ơfR/+!N=- mGg(@3gfq90W Rɟ_TnMEE+G g10p b8oEi_pg0І!|m<8xx^ D=xA2d"=۩LɠMMq'jJCK.rXS9,%NzoGn)C~4mOˆx ^Q6ucS 椥MsO1`4:"@}米;XA%l)y(&=i}| Lpfϝ|D7$ǿBvKb @$%w1M A@pVUWgf~"V2j`QOy&lM6|?u^ H^B 7܃Kabf=6S<{0@L)P#NZ9[T^E3M\Ƙ=yKvY;"y ]},Vfa,^3d 4>JE2>\E&VJY.D I {lu9Py*VOacjHs+lQ W,R 0RAhS%zɯ3مN kʐ)Lo0*=uqWcj}UP&ݯO3AVG}䝤ڎ8HKܞ$9Wݯ"> Ls=`4Nx 6S[/+6T0t6+.8os$DnNX'aw8|YG:Dy&_swg3a`?Ń$0 xp 9]us,̕gi:NTMik3NZoCDq,v߯aG/9}U? #Fp3c&VLTplmmh;jX1ia~oSoxIdm0R\@?e~ILyΣCNAk !)QqV 4+pv\o''&DslIȿItI0%W`Q|չB*=6#!CV'u4D4L3U};`ՏaǥiXQB ˍuH%&Tlj{[tt#:3N9ϯ0@5ɗnkācU6S$=V\ڌYeQTڤ1~5D~:cTAK֠"KK sp 8UXwX[u\kD6ajRĝ w):( >t*$֯>rG7[q{`Lso2>&[i4%嗑<m{Cqm.lOu8*V X@tFlQk@p{~yhF+%o^VVjbyb{oӟ,o唀ܟ"]v6xL)cr_ɏAE -XιK M>w"^_AH"~\J N4U5 @&|Ge8ǭogКTsL -F%]Ҫ:xCK^}L#{"mbNFON!~fľGV}325Finӵya^ƾ /ui~^tU%nїW}TKV% Q&-NnӶ]MjPSOg4=ZLfIZsjLT!", T)sL.Id &A$ ]JR8'*R$B+c.gtZTQJ054;)<!DOdiy/dz~P>]` tV(+oT:W8oh5j_&@正YM@[ k@\|ΟToyb3@DI\ֵRiXQ&H̐Vp]-Y/fW\$ ~;:냇YUmjA-I#y'6IY1 2?PfO@zaW[sC ғiD_H`Ј2wegfѾ2?SqlO63%) <)m8XsO{㛚qhf4@S@Jf0W(R ts/U2Q1khIU=l^mSOSú\. IlOp>?`Ayg* eQ#4:NNV&[G{LFAxUɗ9.,8Ɯ! Gc n ֕KzSt_ U`Iczp;Eu:߇}d~bF6,O'*. '$<>hO5 yLb.Qf1RR1@_ _F%1R `-׎G֥ȿ26S慛pg5y.%Oqr7i -Qay썯fBr߿\djMɢwٗ]ݠ,y3XH3/̽Ô<̚ekKӗ~GqDKu♅^$ JX{s;!-w9:Z}=&ͪj2훓eL7ZXL_EOE^09; QNřs !(? `փvʈuIongW_er8K~5]v0_T\{է/K _pJ#m>aU] SᏐUy])GԊH˩_zSͿU-)x=kwFvw~ŬvOC$9:vu^G!0@׼@JrrmծCs˦rUۨџROfЫ#S*E{43t.]5 zizjmʪЛXضE_O^j]EVX`?MV}9;>n٦.:k1z|N}tX[5K<<懙N-Z}8ټ3EoTF8-x}Y١+K[=_Հj5'^6q1]vH1֔j+BzfL{c{lhAM ٘4ͼ2)Z &W EgtqYqFTYY?]C]6_n R讉RzS!gh_q50Q;-0OCJ@gѪWK1뾇Qz ;=`;MOS%KOt?;9tЦ6WlY/zZwYT}3zJ~u _ t =ygb.;5W,zۥ_oҰj|nOw%1@j).)jzY^సfȏqznV=yw=j]temdsݯO "ia U]:P¾[;~;3ym9Ei(: g̕=E13߯a"gggs O[^hi@޲d7<*ͥv 7f{=p?#g*h;;&🊺+C]7MG J ¬ЖjSX rxYa z 8;ځ 8ۂh(a*٦ʷ ȀRG..LBX4mK [2Im7=.S*wCevƛIFo)m_55} 3GwĈ!&JZ@RSn LWuJ'%p:ψ>+\ޭ)AoU_!ڍE*ز@BB0&tͪv,9b݂Es8LOLI-v `Q#eN\rZ|ُz^ufcUb|k@mWZ=C PAЖ Rh@٠V+֠hUL?G !_PC$w_;TZuc)];A~e/BR}/k[nW<>.̚~LNO5xaOD(VX`e}8pe'xgtTDd8xv:0R@-69_MS .m3v6.ֶ#vA׃ɮyHmU+.+CFb>"2BЮqCZHRJ=l\`񂉻AgXP&Y/"qkGf{]y1#_u_r\+P =4 gE7J9`qѴ9Ygaytn !`e |R!2qmZ*r]AײT8 xu{K@]V`AEɔp4(䎻RHOAo[tkI4T=+kMĘ AUU6 (j^(?/z lYީ,\ h?FnFCF`z qƬ5O=A4o,NIxdE:QN;Q5ECMquoQJ x` "ED+ 8_?M =cChRxb&a9ުɶjzRRS7 9/2niv,M2Lm2R"hocc%`%@/V8yEzIv9eRAߛӝK8E; vܰ/nbS O.M  ~.H  '5.d@NA$pU`}\p[]okgՙ~"Wa{а1;T=Sx iwaj":#>={57}F4/`eoO%D!,s\p[Kokˡc@5L[/v {] )%q2OM j{Ax&YCϷIgbٵxl "fitVvvjgooy۷$el` D bBVQܛ @7Z,ɏ b]HL߬X|"s@ ۵f}n#%`; d,|(1#pwe'ɒg-- (OR84A1O'[oLvg ꝇ^9IDWhA`IP?sXp"}DO@/@ȟՋhof>g@lt#^˔e_2H2Ł pӁ}v@hɞp:OiL&e eEddXoĭz[(ޓM8(eT挾]ja}+{798ryx~!'''rۼ6E78C(3͎"@Dؾ)ȉ"'&~< 71GσGn )ؚ@p~ʕt& bAx@`Ay)s&AG{]d~#Dv툐q&4kpۊkpϤ(؜4vH;K1 v`q./OΑDO}T9R bԒD' %nmso􋙘931̞E/0{s*Y*AD+ Lm릝2ݍYO#`W@pw,J3͕u`IifQD^.J6"$,ӝXw9ŪbD'zGZ-Uiu-CJ*{ *$68V!1)bΆ!wu1N t0FQnAAv:lYH΄d.Gd(zK&X5mql_5X}3xtrpOӇsݺfy/O漏!E0G]-"@dN)k΁Бn[, & #([cMTpRڲ(eCy3ڡ;2$ 4NƳ Υ3]땶xq_#+ū7Ux_"-7(s fvT*&xw`kZ0oR5;i $aܼ!6E3\мZR6DFF#odv]Xɗ|<*r[@·:$6P'd]V<Ŧ2 D'}l/>X1}0n0)!,+U6LK%DOyW|-ayiq!-AV28,JNffy_G3 3a~V.m FrRp>C&޴J ^N KWRE7O*Nt+(W T7Ul] mp\-˫K*s6feqp_~ՖΣxgh hbܦr%N$ Hf|,b4 P[C@ܛ(ҡ%,7.{I;>Dhsn'rqWcuU؏xC=NSt~7OX-^]2Q*_7{O iao5t%C,6w~ ^Xv.,:#r=LTU1\M8$r$py?֧̾zS<|L4Q9/,Y^#]^=Fpԧ+`A*57G}|c\E$/&dYdҲݧCwe-`K lal |9b7bPL 6e³|ī@7 1ŴH\{"P~="4;?7 fǒ(K<)o >RLL L9];_NNϟa5@Gc}w^Eʟ%CeN_a$D(|\ ZR12el(n+nrHsآ.0fYtzwKl=U7X?)6vՒT&B:̆|jd§HEs<üZ 9J_7@BY|bPq" O}+F%-A卍w:f҃/MuLh4\+ A%)'1Ȅ?i`Д|Y:J,C %eޮL9FVlf{'S;͆MWa Ht|oD<Ɵ.%zbCjv"|{ |@L${*:jCȒc.p3Zn])W&*:xJw w]r+SmŢ ShǂrAڊ~TR\xZl(7^G>@UvF9@r4'_Ot{R5\FQ=i`g?*OǠM%><Ģj\]Er"hF賽waekѓ]A51r'"q'G\dTDifM!u$.xBHNOKIǨ 1GӨ[IwÔ+32t@/[ N|#ؐM(w< [Z`t9s9֨()!wY޸m\vs,/ :cix"Dnǒ[,7z6 Hy(PG!zUe0#c[z|xy#.4=#_4c]ch A"GH,I"9BoMMuu!\m|nKԽsV '$i#- #etú%Ǹm7DR{ 9|Gifrl2N4\NCcӖ.$ 39R-r'ȸ(yI6ԟ$,%iHU8Vu?댭֗4:X glF_ 㛟u F$1"LQiwGRMq.1,P)@})劐*+2h#L(Z-TsbCth[nFe70::[*4ǚZ*ƞ/OFEOҙ#;SA!'%8}GּH'iE"@I6S>U(g@SRGhx-)B̍ Ƹ .>,yR2ijX!WXݶ;n> i2㌀Xdt'P9} JnTpKǍ-TdQ[|yUV &}Pjڛ 4K*:Rg7l`N@IvVz~8o5)ɩ5x࿃c4 7`3Kj3-Z6d4XH>2e$Df>D95MJy^c-=qKhj e@"|nZa\l<'p}n˜ї_+|Q[}AV[a|)^sTǺ}[21g'Mv (bXF{討dw#P(tsBbSP3jnV%o-Pn! T,Ge`unryUzw-.qh[Nm*FgoxU a?ܫ6ad)8{]0 @ y *-&7 YRZ w[AdMI $2v0XyC|ou@ro۵rꇌQ8ޛ`llyP1p9ְ0f3q4[PG q|ǔ3 6aL d` $QF_xPZ;\i<>+>:%GЌ.bp  @)!Q(s3iP > Q'n~7Kcs#(pϟG=丏}]EG3aWH.k^yf߾|,6qָ?usUR^`2 HF^<,G/{ !Aa`e7 %ؿ_篡otM%*+24v{:m˰}'&y=Ps3'_⠼7Iȶ =S.dkjp E. uǷ p6ck [(j"?@FfUp$MaoI7u~kő08YzO:ϕk9l5tCzLx-m˙:@΀Wj!R; yf| VoJ0b>Olߍ< ;aCƒ18k.Y9qX཮jɨhFk:WEjnC؎]^;-J9ݝ̪BnV,(D&t7~Bt> E0tU (R4A 0{/Nl%v*t#: r{Sazkko'|-IB^t-%ɗ ?Hљ~]uYq. [`2LjT=]B]a|~bܹLWZC8N1f ߛ^?n0Wc-Yv1n+@ $.΃᭺Bv8,kdݛ7|Oy/GSKvdyɰkBYO@PnN])c*,D3m$iVݐO |Wz3{P&])?'2OjxZKlWv/D VSnVɟh ,z(#z]z YE bbEb I0I @,r}II`Uw{_OO )."ĹXDV$Ns,}?O"UQ(I˱ȵT\C%t,b9RS++Ύ"ö,UGrwldTXc]K 0s|E*'xf-r }EzvFrWyף6Vꩧ_X^Y|u}[yyA؉¸{ ҧa_)qlj"FϹ)bQvÏwWaI$`'T lٸQ>U}x+EyA*=/b?u Y2bKHSwqU~'OzP Nz W_GATU?}}B0cA'G6k՗4 7sk5i>^WW>(2$ eLPLW8n|P}s8$ \gkƇTpK_zQD/FTE;ikH$/"؈A)3(Ջ'ڂrGAc9w.S < I Νv0WFc:y=)xO!9N 6&LV2 -c[ș7ߜճf:Z I*S$)]IMy!sGn͋e?;a!C:7P zY/XO=H  K"ZqT̮X*7pyC Ɂ]dGD_Fм]>Y3lE$) 6dP[&dJ㦨E!j 3_CZ]Oʼn9G'v̧O̳կ9Ðۆ8V 뷶 ?x$y#q>jw9>vOV~{_D*HJC%]I|ͲN;6!i'D+i:['D¼YZE$AAD٤<߂E_H^'QS`IŜZR]RlI#:LlӾIŔ;lG_-ǪiL,COȦqHĪtJ7 QIGFPr`d\ߵD F "||2Bջ_3Hfvւ?h,ӉK/vm˽Lqn߷C”G11]]wAE ; iET ObՍ\rө\V m6g}LE}xll\r+[~&ᗾޣd$۫?XAW6(F;GEDPۖd[8PxM󗓇V@zHJLrCRKlBD.}NoZ ^Gvʿ>P"ul )5_l;W͔lF w^{!|4k +\ږɨ,%-ng̋rv<o)ɜ` d{j(BԎH&3,IG7G6)5!L¥{ rG}dHyPqI%yS$W P0 ((YDOpʑ vu WhJ匑鼄0//WC5+8ER{7>`@LbF1-Nw&@ FYI vY1\AwHF~{A=MFruLe.P2nGv(Q..niF78D-2>Vɱpsz <mwC' f$C}OTء籶#?}x=ӑr ϠD1,h\\?gn .3Xϥ7e^zWN9s(\~Nm҂EӏdHǼgeN"x `LCj}Ex6$M@}bD=}B I"RRFAȶ)=Ke[\ʔ{RwNM w|I$&϶.dƲ>ikuӮsVML&`#9}م$QlIiB"e֥֩Qդhuj/FGA!fr%K~1m{abE`!6"db $(Dp֭-d-ﯨ(jD"cݐu@on?r#q3!4^~sO8ѩ>fɑQMS=r)C-#tǙV*d&3KP;@*8')`Iޡ]_sDi^w_rQa&g>-̛|-L5TZ•oAN>zɂư&hޑ)}TfwQ B=J׸eR+w)x1p>&jR vU*iP7,)%jTHTÊݢ5ߣ󡩢$&O92yLA?_|*GmfOXtѬH9v|sb&z5S1I: vҚ׫{3~hr[J@ Ba=5|ǫϗSN R筺E1wtB Le;˶J3="Ny%m?Z6 0ƫ0;: iK޴,d@.&r:yl>trGw87zGIa%VZ,c! )F#m 5xv04pBdMa3yy֬2ss{A`OODTfIOIhؖ<='q WP⫥L z?6Ekͳd8z1;b"SDb>2"Vt?Օ:.]rm"3nNԼ?<{=q88Q[%pjynZy [x:^T$JV{.4㯛lRe&xib$Ⱥ9#(XBgh.rd?|s施},H-ғl_޴r̥_\$K(m+6+|V)-#Rx sS1=MS-f[Q]~ $aMQ[u+{DS妢! t?.K{kdn,cSJ-EwÁA{VG5򤫸 0)bZ\N(64~7:I\u>b}M4kk<6^qY/$SE%GrܳhԲqWItΝ ULG4^zgri(ȕ 8Uw2hU9=OyDLE(HSin]qZ,d4k$ճz#!ku>qXȯ~mzwZ2I2;My:[Ŵ}A Iil8N·fIHت~˒o큣#fk}tfå[|I4vqy+qNqG!K4p٭L[7~ )NgIěd#O*CEW|vs8P|ftMOX\D]M]rF[vqc-4y{vsj`$q١%uf!o"{zWٛFzryL@4$T!hD]:3Cj1i[C^(RgyO}vL\JN8[ȴY-mNϹw^_83oиI6-c\Lci͇3 ?/\ ^ǗuVJV6kI>e*[ܥs/ښLX͕k,E V¨a;I++p8fP:d1!Ma{:.bjqh7׫(9P/c#3\0x,SX3ɳȡ %a`Alsl) l6-!,R&2` a/-_ƘBNt4{aV@׶s bHjli50%v>b*U2H1I@yRXDR:Eu{@~Ɓ:VrlH1e0.+Cןr V"=ߦِ1,|$kNvd2h7paH} mJ2Ck=c-䮪!ZO )Q]Ө<^4q &0b&7lQ 24vd"V 펵@qtL/2殮 };#o]Y^`m 6-qV{Hkw3hrfrqu;Fe|'K}Aӿ-"qZP8;Nb xteP ܝe@ n;]\0<$XpwoOL^gK(5YL424)/'ݩ(Vd~4d%5oesu  &y[D+K#SW-N` +n01`'/%tʥH.N;mOBpC +"0˙a;ǔBܾI"t/i38dtqTGbe6Sj}y~"mmW5VG ɲzм5C@?'+GѴ:Io}~.a?/lgmqjv=wn)GM(o:Mg8eEeJG6T@a/D`I<~\ @kXdΕY`vΟGۭ 8b)h3tj ৆R0aMeTTN f3#Uӭ|# ebVD>4QhhW7x;+x>-~k4>=v}FW^^;@^}u~ v6gIJMr@лo ');P")Cuvpt]g .r$AY b mnm-_>`E@!Wosgg.`%gkk:yDh\RBn[0rr2@B{-oa>xmD۱sW6FZ[[ ʐ^"=Ѓ֞ M]K aiVVV6u(X_24jjb)󯌾 q> _r]06 @Hj.Ƌܴ7gPƝІus!4<!RMmUb!4 u3'0} :)-0e T@Ç~3לH)ϥ*T \;μEQN>Θ7qgM 39iUf}X+1Eaw2BS^"]cgC# Xc`2 ^ehVw|l# bԥ_zkU殴*wY @eh! N}]hW"! O/][?ٵ` ++KXA;e Rhҋ@40'$*CP}[}y9-z(_Z^/ 0㏪G32?ھi֍mPúM*rMhTWZ*~Í3&O?6U9G%2O Q/AREC:vjM\p(ΆJ *ayv 4g'ٝ痮'ݽ'Ng`͛1y(/z 1rX%ʶ]84tqIJJ.--qeNf"xU3dȚT8U{^]x;U#CЏKv$9DQ,!W89EhMDC|(Jiy[ >y4wmyYXcji)-,d\-& w`{9?zE|0+c 7 GzpkCSŃWO]Ȩi!AW0+8s ¿+`Xvjmd%b!AY2FFBbPkZc2dQJ9 hNM S۶V>2rr=JFIqRd=Ϩ9ѦEV@$sk :NBy|<,6ķBx3AkՇ7*oM">eG]+ Sj?7QlVMroO),ʊB 7 AM1=X-YVZiH 07eJc3~3qɑG^ ùn ^4 yk/RhT;ߏG^wQR>wቭ +9W9=99UNNȋ .I) h}_㮓w^wwwjl`h"vi;+ҮUߛ- ᱠeDVJ*5[֌ / H;UgC?sDecs "@x@ZpWy=x`0 ...IӻX.p44[tB-LTԙbEQJ*Ug⏶A !T e 1x"{j 7{6=~y<,;XDho I 0+!!U q ;>)`UR֔@kMJ\]YÕzdgzl~e[wqˤc'diב2rda z-߇IHv`lYYE@whL"e jNJU?Xs5o^16!}2&$ҭ<:RwN C5bn#OGV"4X h=T"C1X'1Gܺc%c[[4$ r`6!iColn BL 2#" ͤk2:alۥf"Q AiC9sN ذ]A-*3p<\?e<'zIU|6?0zkslWwdzlI\qZ"+Gyܷ,}/#(PPYvY»/Y~=K@\Rc4`eNY!ځ}O%awR ;u|1W8_`Xs1{O IyVD2=NdCQ=8 8 D{XH&.X$ኮ$\p/3XO]A[9:+!.R Xd.x#eڎCS'>B{H&?_t_EMjP'Kńх 9ruPDOf־~Y{F|zlEhl\K;|A>AƫcTpa0-(3eu ͫXԎK](*<:+3+8rT+G, wXVį{zh7&ƻiAMiR|);&>9j)̟TnoW{~p?DՆZP%}9V@MOl?!Lz C{uY zPMLaRض-ѯ#]uBX[/[qXj{mk k Z$m̟3|x̳t;.&A! dheFlqYBηXcO v_58lWUGVp~oTЀFbizOnSeyCg\KXG#4GT " C鯫jKYh"OPp&JS M!d2g}_,Ӗ\oF6 靖LB5e|_NL&>ޢY¦]8>b`d447;Il1%-oxZN]d_44hiK ]ÏAZ`7H^`ցn\ؘr•DpJ J5J1tr칚bHzp#@y Z@wxoNeF$߬.^2~ݨuuؤ[Nt۰J_uZY 챘0% $qXivtzs^֙ͯm}o,(!'\NWt -9޸ ԽHNLt~)Q%6BW/{ҁGcN ͨtm|SN\0aފS5a5M$wi)^w~ZA&U.{76\6i^T&o/ꥉu-_C th &G{7&m}*_7EӱuZnG(V}QpJlRe잒 u2@.|mD7Vյ}ImntH3"tOlRwZKt#NBF vOݟMC`7 9E݆Hi ~;I =OBu״Ĉ0xFbP Pĺ?-Bï01i_ :ubs3`}I~r-z-Br3׮_o܄мM#,\0B:@4pZADu{Ӹwiq1u03Ei4[yʊza,2MЈ>]He~bXNLgz%"ַonxr0 >K\E+ t3WUDkiŢ6ORl@/hh yٟ0qU qh'Ur iWPI8Ɇޙ$KɍI[.5ɲk[!W/j/a.ebKA_A}]1N!/3/ĬtE߃h1ePAhZ ȹNh@U񀮅K[~X^w:%^j@`GLT ۋ @VP% Ϳgk),5LZc}?JZk79!|0y#EPqZMZ{ay~sF}+kl16_9?#OI9צ#&/R=>Yd78`LS|Ю+U7:O?e^OP+r8z =ְy\#m]DIͳt\3ٻ3)_pZ&˶ڒr`+T'oBL+4\g҂ݢpk{(HΧߤXA .иZFj;څ!9nCP4\? z5E|k$ L;@HŜp}l>.<*7a6thXOG^j,AkAg*sdH}f?Àuv A'>_OY^y `ud 5(ӧ!NGGVѐ,&܀O{p4WްS UadQAK8GzvtZd{&S3oTo-\kiLt E!)jJl Sn4Taf|^S6Sc]8ZYZjNQ[g3<*[.mC;|,ǑO0uխ+GG+9Av"i05^MC `ԠIgNLzg nI?n)""&'&F$S12 sX]\tc8 =f7cɊ<}4GRڛIZc3+Jj=i FC|qL"bY-.YSeoE- c''M-'¢VB3rN3nA]kT6RHj> sg+3b;{e6U jkk7!弞øu`/q3Mks?HBT:4>Ǯb_R-vfpuٖK.:|"*QN^>t9=/n$FJ@&Ϋb/=.wȱ \~g ۡ3I-'q=:cTwC`) u9 z!q)[ɩwվxMz$')EmKv]|WC!;AAb1DpGPН%@zFF\glF O=֩ NF.8U`ZtHVsR.ߌcLikj[r*~x+'&:)il#k:`٥R%AiUNf?C<iȅ2?Mɇ)P't?cӊ@Mmu[T MT Ѳ3?V(4R\NѫEŜ?A뀅Y,mF(POC 9aY04=7Q_x%$D/b h4?[ZRy;B+iZei4}?m|#3}M3A!m̐ *Ҟᷠ>}D8Vj}NLQ:I%MyvT%5c\\ԲiF@,b-P֧ݿϕ2[H_o001'(F':-wQv>s|e嵵Po\h5ܨĉ `}sZp`00wR+Ǹ51-t+)eeu*%$=O:60-;AAAJVI R ol-XBP;>L_jדj*QO-B U9C2W ZV]kb9WY b~nDt-{r娰`#ydKI}^3bS~8W瞓-MTSuYgZ-:`蚧^›lb9ݫkN`5pT)z3"vAX :D.[OV27ith Z8QQ_] f~m82'b˕&@ Xu| N]=(5`D!}s ³q̄J_Nq39ghHXώW)f\`G&.I}Yk6:YOm?)X[Mv~i1=_QD"=+~7huKN ss'x+.\1%9eG>eDGdUkn`ppq,Kz48(/Ύmg#1WNؕhNIufv\VNwc??Vav ?}ԖzsPO/zq_k UWuٺ'Nr/WWPnw k4AN|q9sAx?Ԣ}:9NRR,1G޳x7F*r9ұ2˹ &dEgV3ʔb\x#Ơ\ABqdU%Y6)AWPYlEt;rgə~J.t.\ }!'Y϶}uS|U i";d%ϝ8eXAky5iBp*AuXgvg)wlp%#(IeD h0* MB47J1>Fz= L_Lrx NbfwvIS_g@=LZz=5d8&@9Ga@JD)SﯞS[q]'9/F|jp=̞]voP".i15+tE)YFQԌ/6xO6~/1WD#("VSZD.)vc.R~dF}3D |F^8(oNV&}`Aϰx0ןXwn(i( ?t)s^Ԟ{B 'Z> Δ72_N?_Ն%FQSkvc|.UCyUwnPqKy5Ⱥq ,|Z-,TodiHA+BnҸ0ӱ1FRQt/u*^RA6#y~/dNT;}Kh @p hnk?a L|Ԥ<E(أB<Gb"Eg<8kw c(F0u/ڪ$;|p5VDvT$`Py4ήvԞԬTa^1 B|Ȗ_~ѩCy]O֞6Yy9;-DIko;װ'dŘev u۪NH͝W~xxbCYS0,XXXIRsV{'jM6dU}M~+ #n(pW5Xe޺Q;[H o.NW,v Q!0qAO31jT4E;+]e CIv.K"JW}aUU?}&3웹9RE'kE>h [j)z-7q֍OVqDJ QQI?˯{EVv@Ć\ZΕ>-(d4HN6mj"̕" ^+FU)ы#:bt$Oa:@yP5N=zӨeur3.'%S[b1͐#'U .Kp[?x%tvj d]^5dv )&|"b(@fkVQ'e[*SӋ)6QJLSs$ }o\6ܱm@߬&zS S:\tU֫9HN1zkֺ7 :P18=;oEI3j$PoĞqI"z~Ej9U=@}SV n,%ou뛾&0{SM#-Jl8H? ,P>gg'&燱Ru'|J Q<_pd%{pj@Vf/6(x1.:ǭ:qM({,HG0 `g&2gBBGR-EfSl2kB֜$~.:e+%kou<_vo<z#EaaLQ]<߈Þ3\E4bF@j.JA9)9G^ӛ;7H .%%_N7=n#)I\h*$#,4C=w幹 +-Edbe_JJ,RL(<H#yyEIs\;72G5)Ý5-*TAlZ b9@Kw4uӷ­d44oq(˨ZMgCJfxH#0;OՃڴ,o!t։zs\Vg!-x{로. (P3IK{j^e46-'&x'"lT0HW0PdNg YL)I>y">X/lP `vא)厕i>=/jaG2k8G{gB#dx:Vtj߾H? pNr1!ddH9)ÆFÜQ3p?=☬El$i_fO@^'77-wpW}w׶lr@0Nd٫ 11B@X/2MeFk:f4U$R1OӪ\b7>W#JSO+7uCQH9GXAއS;*Rg`Bq(A%gsg(1t_4QREMna ##cBuk2cDʌoލ5Y[k3g_C3jQ9vԴÄ"#vlmN F,.<āҖA\q GoE=4T7Ռt0f6^pg'DkyXVv8oхMumC ;xSmӬaPW6\|;!G0QULJpZseWM3f.zAmug^g[՚0# Z|3Er il}F"ZrһNp"?_rP65/|l@H96uN} t)'1(Ne]Z6~3 xpr$Af &~Q=Lye%ip00Z }Wa \9#@U[ny\͞?D3h[2;wz+o~_ +.S[Ĵ]C-,:~#ANx÷"[Ib= ^:p{o_ۄk&hQe!;#%ILrHSO+x>v ZUU-Th =kC."/~N߄afD<@5x7~P"ojm)]==1{TПӧo*^<>C熟A||Mˈ-p3J}YBiL_p<碅y-̳9mϷp֚'} ڗݠ@ plCԘ ԘE1Ӆ;֣H݉e˜'b4;af tHY4.DsMxw?uGK_\][Tߵ0w7BVٞͬ׊u)+2U\LVVoJ*P; }Ajh qeSZڴw0gRnz _OJ"Yu5c6ռ?\ s, U\N0* 9Ѓ[ONzS!#Uv /=8>@뀅 $m `3T$UKhq(,(U:<^j?Y3m)5~\J1/4{1L% 1uLSR ǿP-Eh$`]ڳj1f0]xhrfGѺDp>i`<^>7eX7CKD TZP{!˗rUJ>ᙽP=@cXg2hrhO"u 'oTį)aq]oH- )qĪ;ivH,OoeEb ɶQӾObWoN^UYX^5XzOq3> 5=32" LM \o:? :M*ٗ*`ľBΠ5R4s%hU, JJLzNyPq5Xxxi"/j5(n2 QF z#\9$c'2Odw4$8Ak! ݐRkg*s)q摒 $OA7+wc;L/#pq44~Fzo'q4,b |+Yx >P}8rp9{߻/ ñoj`Vh>;}'æS=ZJ18$TNPVXwQ'l:Ѩz<# 9 Ąۖ6Rڼd-d\BԑþL9* [t0 ~*ìF22'C~g&'(ah}&%:R yO{#eCCQx\p/ջUVE!q"9#BOd-R#3~йZNOHO׆Z@T%:x"Y ܂5;zTuߔvwом|kXjnA{-ot_72 lR+˃I 'X:s.?崲%m~O| nHIfz5JP,4裪xBWdeMlk7'@m1+}SfԵM eӹ8YUpUc<&o^_C#$E¸6)14O$?XPcYs*.SWSjk 畳H>ko { s=lCEl9<-ng^=_U5p?0z&7̏ޛIr@akqS(ѡk'䂗n@oB+}W$7wZ0=N.6ZmɄHSԒ M5Ga]bu^~kkd3[)x=RuIk9}XԵ+?G=hNY"q.?=t८U @>W;_v,!*i]@p͎  kOˣ\Ǻ?k9奫n|?׀,Q6H2C6? cDC.VC:Vv?u^I"eoۀv?ψ644| lJSh )/(M(IVC~\_, M(㶙]9>ꉫ 8c%+ǟOByOkdk~SOnٜ4;c|Tn[' SLh4jHCId [9KZ(~#E w};T$b3 H%7uv\]t%:Mj4~.ir­lO%?|dc\%Qf7{)R𲪪;'Gɛǩ͍B4^AyVmi*XPBAN)-wwgo1a(Q33ZGdz&:&:ܹxtߐ9i"˓9&ޫmZ09wI}5%7Mc an"1tB%)y]@4dsxW,C}R(6~"˟M}qY3XynQߗ)'ϮN]Z0gYS*ϓG)FI:[@%_x9q4 條xկ Q-WW}|@Cf+Ĭ/f;Yسs铁=;*uUf4yH^NP ̅쬘Yc~Bmn"wݾ>; ߏa]/6QelO`Q'->cTxQшQ#ԴUSxRۛళeNA3NJ(Nz _XRx<-Lpm-LOŭP#ϸ7[ZP1hn{0vXzOYձ, =ݯk@=_1Thy_^`kA9DFrMv+"6Xvqh|z@cI)Y"Rrtf\'B!O#\w挥P YԺCnQv3V5buV'>g3Fܻr]t dRQV BuC~A`Ca_../5b. 21DʧSD 3K_-/,ݳU_kղQA-Mw;mMKrU]O8wڈy*/bψMģ~䐳n"H_g`\%u>gnC0!fPkr$:3qko./YC_J[?iߜ[nV ZyKЛuhAڳq@z$qv׭~`tt PREM'ug@zμ'76kǴWanS۔r.21ypb& _XfG5E# gP=:[źmդ;"|]}\A5s& r@^M># Q/}ҰgKQ;# ?œ\ē~I)rXNJiĽȴJ.I% oزq9Ji9B~ ['׹pO*T57GSDyڄRw[X-BKQxM| {:_a3F  S-JHKe^JdFe?xٝU_幝n#M+L*5͟4KuRu?λFZ+%N?m}y8_ oc͚]Yc4ʖ aPdd W+aTD$K{^{;}s߯uogpK*_bݢnW!Al6u+Yy~Wt~X23*\UtN_(L5F2"E)ͱc5JFۈ߂QFG*B6T53?Z86:q&ד~od^۟#%$ݞ9B/#w_ZU-A[ X c[<*ZʾܪKGu))SzL)MnKl֣sӊ6#I:+k1Idj' _>8=v/8u$BZNkio0d:+n僶#$dsitx)ЖefIL95-ul8!Hd,Ͷ,M1CL %(:(?!Vs;r8Ĺ|pe]GE +5u~$)㨠SΒ7RKa|Un/+'SWK*׏ɓ/BW4qt],8B_!|-qݵu:?#?s 8"bb﹏VK7$&Es07n,2M2v*SӑV8ZT\mh~yW*#+Z1ǐBOn)ԾOpRT;L6G9qfGknQ&ZUu5":54촸 sɕ^'b(XmzO0}3K p٣Î/ԣ7i{x?K6~,]ɱ$2T=2& Dyس1G9y+|Py:ǩkm(BJ( &ʞۘpI\MZ8I6^ Z\P~=m6$u1bb%PkV7L|8%չpM ՗N: HLT\U0}-eQ#F cG^lݸgV0 W]#ψ~)߷:?')yv_ʙontlo?pr$y;!Ģs{-ۃ}y̒ۃjiN wQDkFF8C{r!Xw::iHLI6y=hBw=*8YD2b'3b*5S>s:X hm:K _}B>kxXllZiSR?S tS9=LO,{! }8FOd,0,F,nc=l\PȆYocivgޱ9Vn[1lez[e%89_yw ױdebI^n%6}چ`Y*GT x79?"oOZkEΖ~z[(B)ˮH= x6:BFԅ 4|27IH|T]4_+-}%SIc dAj g)SxX d`[sވvMAamPk N&Y. ]W]zX7B9oL!WBzp|f,W2L=]pOt52Lr8~{e@42~|v+ tHǯ(^E)QCiSoEޯXO 1n?ˆ0 S9x}+g~w7b_͆u( dGmuD U7`<OA|ǎS?ֿZZf+nT\&WuagQb|;&O Ma惲TrsҤX2yfy^6rW2Ww6BųӶkW?dvRy9d7)%_İ%2Fv =z4i[v36LYN?ѡ c~Гok,jqB!U)LyARziZ@0PVoZcO %XF )U6wg?,(SL5V2ehkmPm "*"rҲOțEH>{~kޘ7n(aAޛ`(o>X~ Ik#m:0[Js rӲ(0\3Kn5]RkMaSgkT$D|9@"S$76øYOI9xUϷf1&AHb il -8u2"r, Ƚ<7X`w/ф/;Fby`,Hc0hQr+Hnۆq$%k7}GX] 3'2 6m΃O #M,;vR. Rؒh$,Ѣ^i\d99YF(R}":}la.ʛ;oR0d?qY^=Wd}g3os:O ,|W\ *]_DȆgqٯtVj 3ծT̘Ȏ:Hos|9/LPM%6&;,5rH>@\$73(}x(E+I] d;q]Tu xfhnLolOaِAgx@cSe{.J0Dv=9iAM8[=x+l` wb0cy~ijÚ S˩H=e<$)6]Ω.l iQ)l-U!Z\> )]adeZ(lǀ'䲕k?\z8B WB+iG&=}vkʹۅGd`Yais 8G onו\2QR8 -2鲗8Kr_ma5Jk1 ێ}%|!čM.i{y}@T ':oS,{H9bLK &lCCoUdob}}{gXv )ѮBW*ӡGmqjqHbxڭ6Q6e_40If%L>AZTt[:=;VNMTCo]&HV7R!OJ*Y._}=pa܍d1zU,.8E/iP[+z8D7^N^qe?8iO?w^SX(4߆"ޖ^n5:JNS#ӏ(L6ߺ2ܞPO6"pAXݨbյ8JT#!.õKdpzEx1QMّ_Юo|&;s&Qjq!bq?14 6SADdq1WB8&Qa#^bHWH@9T_3t>"\Ҵp|d\w"hk+x}/k&?NjpaF̬puıLBSqPJΗߺPLzPϟIeMMg.NW\JElXZbi[dkbK9H?Za+֟&˵r>⮎φ$7)MYWYDg~[gC<} gem3&N1YσSX+UkKu@?!L;:!XUPh(AO RoVc<,T5_|RO'^p`hG>4ͷ1'sW1cڞſP--ѕ"C7Y:eQ5T!y7ù$b55jDUTyq]b_z_n4v缔T㌈3vBʴ9n[ǯ`|\0F;,S!зsrό~wD ^z;x\"xK>SlIgL4(h|+ݗ`3J-w>%N~$H&3Xe,d ­8ŃN3R)4uHxWTƳ/`KK֗I䪦W iɿӥ.ҒtXW7sm]B>>ݮg{Vx}'?E9.# _?/4kob;"՟l{ɔf?#F*,a(ٞXrgN%s\uj!i]!WMA*I%>MOG_l1}u^ӁKX+7FlSRI_U0xXVc%zsg*z .2 SEU nj0`c0}hc<( TZMY {pπ Z7MKuWlXܸ.V/?1HpXO~A|m9E]is`4P1zg220;d,lk}2tg=,$aԉF%8 q/*k>Lø6ϊST) }89 ɖo28w~Z%j} foʑf j?*!{¼׀e~X 6(Ok*lUx9]pz2|mԡtcV{GڇFV ,Q4ù^L_[*5F_Z,~P ׹A[VfBGz+=sL2" f6W3bK-Q w @% ]o>N^FQȃj[68Dτ^g[bl?bk7OSGV)nפGnck?GPuK׉O/+:ZZK_z"(%[ƚ5vQ*9ٕ}54f ٜLt}pO{4iu;J.<]+C%|o-$)HAhpļ }JF/.7S\ W!DJNopި/WAk^^\ɑk yѢas?2ֻojכ>') {uX˚͹-|CUKc9nDp?X`Qɚyssc>&1BG WYyEDd'!9!$[X7Bs᭻9CQdآԶ-/#)6!HtYv0)DmI?)aε#h};r ~n!piY@=~Vx྘Yyf~ [Dd9~'(BX1i{ s<م6N*U5KHNw?oޔ,)n ".59V8Q zr˽SQy<',HH+~ {pb²ͤ(y>/#9NZcvٷ)8kg Œ~ KYף ++겯 i GY?`*1ZE^͇w%\< uox@|'7Q޶|fءiRuQ$%#3;drv;"?zUYvIN6p8&^ 8qL7uBZ_+P#rm ,7͔4R,?}/e_B{بL~iܴl?[qD^Iuw=cIr-L~ϐ_Qa$i ї.KHG'd[3hϢb3C9ސj)t?^TZ<^=.Ҭ4`*4x/sQ=\IžjIE {{ح \SwŬ>ʜ0406q6!SOwiK$3`(K˜M%ewjE XջOw;ĉ:aO3 -K[ϷǶ  }&c3tC^RN%˩LUb]"~D3%R>`'Xf# ~jc $z0rRy'Td9Dj?=Q&(dcFeɂʏF^۩/)I pH{& S &>c|uJ,aF1q٨20S];F+p/qƳCHU궘ѱ=?^?H,(Z5Jg7:brfFXT45Ij_I%`_)L=]|:Dbr9N(S(=QX,lAV,% q-g D v!TfM: \XNlI.fM~G H;t 2QI'+@++&`NskXt]/N&@n>=dQ\Kf |Fc",b@q9Te{R 3\4^{ب<eC7B.q*ĊC{KKkR\vz]t#,%p;.K@=?",陯ݿb+h3/s ?*mPLxb|q"xxӭ9Roɦǜ9ءDRK^KVi&r !U-O?˫e^M οO,ܳ{+Ą _g&G,pO0@?ޞY'zo(,_ ,TkBXH`ۀj*WR$9ܝ*hn.3_rƄ2ôk|Δ)1V8{zi~!jk:ؼ3OΊdmLj<@ /s!1\$G5F d>I+ j`#F1`bɶ|r[:j{ SYAO)גgFzzgQ7xc ^8"`&Ϛ>Rf100644 MakefileECIWW,Zޞq+S'&w ȓz-xKMJMM-Bfr奖seepd&YIyF\Zz9)\nHx&tUh?'k0: p)@A^~Ifr$&S=.X؈RKsSJK2&1ir63edv)g+}Ԣ<ԌļX7!$[D24 jrc tQjIiQBfnbzj|rQjbIBIjByfJIBFjfzF3\5sS2T3sRSL%0PԵ"Ae_qmUa|GE$l6db3˃si xtiB?-jx6Ac$FsҼ<Ĵ]R: 99E9)\ @_)2f}QjIiQB^fBqIQf^^Z~QnbX? (!MOIE PH(VPW-VWA KMBSit^ÌmϋORRjrdfF:\?HLVa1ŸE&rCQZQ9yD:XAZT`@iD{4Q\ <ɾb@cy!:!_1YWPj@&ofXbcr+:*2M~$c wFhk"DlKSr2rJB]lE@R 4 ?N ă$yQk;qwљ_ZWꢄŠ*`>D0XsNLft`xUOJ@EhEٸmEMP*-UAEblnҡdX;w @pgu>f13vTqư&ս7A'f.y5au蕾Pz;@ȈP8%iʹPru17A{ˈS> ™2)yIXe7E*jC G"ahlѫ3=jk3Fh !㺄ԜN3:,_MSQ !A@( ~]ڿ[(: GB[jie*JTL>3$Rc3CK~]Z.\V=OO(77)=8)}fgxn}¢ItxSkA&`)n$6j[>DRTJb鏠LwnFafAٓY&Wg?hɁ}yi$Ȝe~F ^{]FEX!R2*1TΪ`] XNjOD[ ԹE!=]Ԁ4aqqt,^/ Owvlw+Rid2w4bI,.'ƕpzPq*W]xu56U3RF<.LMM&rGq9 io =-*)tM#$@Eг @tХD!N bDszRcfRv"Eeޙui걙(tbF"GA#޿m~7~ ^x[2m{&f @hx:67>%dO$ hDk3%l=3,( |2xuPN@Nob7/c@M`QV%F%`TL񀦖,]]]|ƧY=Ifm}aEQZ)zzǬIZZm4kEp;Pd\ 4/Bz텊1&$BP1Ghr3tnۉә̴  Ǖ, ItgQteܹq83m`6{s;vŧ&Or|%K)2,}ӟl^K:@ *ZXBEr>Od\Ck5K~QdN~3Hn? ] a(9Zcr>K+WdY)ԓ*sK<3&2xn~:;&a#߇XDXv܎4I@9}*Bx&,Aqd&Lb2S O^E\,%?475$$3?o&Ljs9\k؜9=sJSRS6c`v exk-}6)g.(())OO-O(MKI/-IӵOIMOI-OIKk,NK&oF9q0,,o_x-Kx?^,v%@x3xɃzPx vV{[dԜT.eRy)T*d$*$dde+'+$(mOQ()j,N-)KW(H-NU(K,L/V(PTMNSp/RHH-IY{n` I@sJz\HFFG$p%街 8QeZƅڛy8U4`4'g6Bag n xkY3PϠ(h{eg7G`0жUu v u 5J)NlȨ;فes2>3 HˬP䴷U/-.ONJHMeT4 lM̼"z $e@g12LdSpq q TрWEK//J!9'51O!%?Y!3$1' BCHx[g9F #VĢJ d0Z b%秤fdd*'&&(!3Jrs&WNc&^xƳw<̼|ݤ"=C+^Q~^'TPQ-R-,HUSPqx]VMs6=b''#8JCf|LLIT d޷II`A}o[ao^o^t<5@BkSo,ײ^nḿ> .Z|u#3ail}L `Zutުsex߿IS]<$.Q SJ Gor,Ht%掩2΄sf}oz9t ۅRՕi$A348鎕Wˌ9fX\cU !WeRYҚn@"@;)`' gr_@`)6JGKhUw[~.Ld6.Ƣq<7FwוL%ޛW2j ;2UP"Iދ`͘`-Âs#aFyY0|*D[I7W$h( :R@TJFg@:0cQ%($vfGT>azl 'A)vBS:3_$Bi4r,8w!=d $nNaB_tUW'LaL73ב ZX ,BZv" .h3zU ZX -Zb6>1 $ T@?3z2ۛAa8fSqx OZ H;U)Hk*4(x`k'%ra*4UFW"n@lC7)'.wpUJ9~ %()clzhmf,O]Db#[{V`#z#&N3uڣ9a`dzZczdbQKߝ3y{<[c5V nSpG*XŖ0FmB[6'm{Bxygu^RiaYIČYȘ7CYg +TQI͔Cq<{!㵯TJF(w`Lvw~ 4ulƍRv)9g,7!DGlxvs֪NC;˅zK._-7]\+t W\>rq LaAʬVjT JT/6Ǩb8Y\l`):] ɽx0=OM?}ioOxuVklE&&y57ƾ4Mڔ6iM88.wk{[κ;I[yZh ԉ B%$~$$~ ؽKRuwޙvvMW_"7 5ۗϳC!1 ꙌDE<^0n {5h_X7TM! kA$ L I:Pxp.`&(%ltx<|R2S()(&ufUaIe*I bZM7ncsUF܉? :Tzxu9cRMز4EM!Y/YLhL!ς% Py Z^dFjg[6A3!p&,I@!d SK72Cq`/oYh).Q!1ɵap9J(֗0B8\և^XC1Zg;DTN,x[ 3uMgr`bh2:0Nr=t6qm[ ʳ__F&# JAt3ȤB.7S}M߯ ۧm ~Ԇjm6VVk*^ _ rv$Y׸hl#sZdҢIb%':]]'b&gj;jٚkVGdͥX:QYy]@<)$S3BҎ+#bD'܊oCUb\U6˒j&'l'xWֱn[[y19/m菬NŴA{[??\Uӟpaݡ&,,uR}k2H5VZ`7'떻w0{ɔ sLvƈDf)g 7I x:]wTY.ɏ<֫=)n{X_ x vC1д*lxўn/چ -y=8K)b0vX㟺ʀ)Cݶ}?O䖢 >YSsk~IÜM&F{ľad4x)[jA^Jxօ8;ΜV O^H\_V^˂2X!o5W=fl3~mi8q-~n|Hijsm$mksǕmeGΝY<*L.V `r Yvx^(hdJ"wqB \hB}]8ي{V]-b,.|i܄. |1~ҭR-ug=8T-mDr9j+ X0\7s2ەRP qVt78rh`g8<.G}2e %>~>C+DiaqL()=QQ޺֑ o1eρ*dv%O/2RxVOldW[UQjiǫΒI?] ]ٲmV$\;ve TCBp HH '8nr}4YUC]{UuөX&:ΜLGO'ghx ` $ j&ɗ4ղjTȅ"-)G;.7j1ZlƆC*muF<-٪ +p,+$#id'm47y<Ĝqȶf,IZ5\Ӱp:f v[)/D]Z O<J$kjդ\UY&DΦ_@YX_49WM~-~ b*O]+U!*TcS&ms M6!޻_{o8Y{GmXU;EB'j.og7VQ!tT.S+ut+n.IԆjJ洔i 1r*ugJ_MqFL8L -BɈk(Ɍa#!pXu Exzܬje\M}@ء34W"-T7< brB!ل j{K0XgOBD.&lq>Kw1M,7Fʫa:+xw_ꂬjD)Y| m[|?/ (F;{~v?-B(CK&BdhѕXz(E5bVկ(2{]mjDgNaqFdEuu3Z:5*͈h鏛k+/:itd1kk JfNQ^(]\,byL([B>۶^+PkUҀ+i8bmXLUBZu:@b::?|t.@il,2R3' iN4t61uo8{mPT _$+5J~\,:3jqMæ+A@)HzcIe%e onEސ;v7gyﻑI$ujDiv]z{,醮ؼװ(3{UTFL󧾁m\^=+ȾpHbS ǏŘJ\UÙ(q-rt9[RIcQx HyiRx.ǂdU> a5R2iJvjSa):STUnޝ_\L <[$Yxz59 0$B X0''[RAQ@!baβ͇z{hOC[9R2*D3""In[ԬTdR0b4-t "Kk ]_XŢ)91rdo@ǔzTK?Cne)c.(HVCX7f؇.hwP@(2M}DHP7Ƽ ;Ud.m`={oiW?$dP 2/#BT~EXn#`akҌ"̠,bc@dWRvJW﫿@`> ,tF )%MFF[5rOF|qu9E QŬ"M1rLPe 1˚u \5xئmȘ-I A5/>GN=N|aywYv{̏/bVtL@ْ+lNs6a.}aYՁ{nnR ndn;<']kg zu~վu[ Af %HZN(+zlyBYޜ/ɫw"(xeKaiYrYC]sLkE݆ۘуA>3Kt?-H]#E?K3fwy}~OH/TXi`^~gRԙmVƻlaC"aUkM©tu1ҬZ#Cu¡0AnLFi>U_ad#uCI Yݨ,9]HgroK0"wgN+t(Bu]y'<|S,ǶzUN9Dic]"6sTK)Κ}|/ao,'AkU 8x@x7)3b56枰cŧ-r`哜f[WO^Rg Ͻ EΧֻ7}ꭍ$y9cIˡLm=Pvu2l0?J..#8Tx{i# 5'۪Nf,uȑ|<@`4#cξ9E J9xi# Fx3SJ2t2R33J6ۯ" P(xi# K7'-E x=s6?Lɖ;u؝4IsN6OCIń"u$e[׸/rrw37Ipo.pw|Z=MJ,Ki]Ϫz:ճֳh=qL3|<]g@<ӼwvE^IvvCj51/EVc4z@H ፖ4~珝|gT1SvKNJU1U] qXjX2WYRZ!P5pXW}`q0i]IQfiYc KsX/18CԫR3R=WQY 4ڨG" ?F%]ͧv"}Sozvz:5?0Ə uRptbRb0M`d"~>L?]`L2PV';\zOӷ%8&P@hZjYh-\}'%C a6whyzV \#tPRݹ֑TE nDuN^/5RCFhth~OU@ߡM&B,@%XWI8~[O~xzd֚TJOb#1g@1 gt9==]*lT~.}uQ&g 5 ];pŀ?2Vd]jty a;k˜Ȥ?NR" JPU$M0ro *Ƙw0Г'JL/t^KיS\EvO}VGq ""rC3EUehZ*`̬Ԅuٚ 4_l W` KE*XyK0DB"@I_qe=EyMhs&Bv 1F? R=B"R ̂;F솴=0A!D7`, K&!}Ok 9Y"u#CV3B-ɚ؟ir`<:~i}E@ 7/[h*PYv wK Қ{~ܬ~0 W",t͘Dq*ǭBP:v< l}O}PxlZ2T- yC4ξ-F0`Yt]<7BtuaK՟ׂf"y4&n/Ɖ`d"6h ` wz極и ZqBpP F725 õykcN% osͩm7B pa&r^Kr7e|К儻͈8. 릭Lyn~t-F(D-kn8=''׿{  C4G"R(Phk7Nm`&׍ Ycۼ-#:+j$%s[C@%#w Y6z;Ǽ@f>31$TS9PC ,/}zq؇-@ݻnNk/xT__񿆨{#"z >Kb"1%V6aCwN;:M~ hyXEcn{QnQR}8m`Τ iQҕ!h,0>D٧yӃO e8B[NҔaWCUڈ4zoSr(`` VU4$2[6i1Y5 YmEKj,/4/ߎܖ,WNWDmފ2O[9}!03(QC`d9m.2]ʼ1z\ &p"J]sՇ/ӁߎzOB) eaRqHѫq6i|ǘ144 hr cO 1%"tm-FcG +"CF1G*1'gpv)sZYG7 2+Ey(3Q(1ylArjE}etOTFagS^=z?U64J(KMF( z#XAaNE˦PاPܜI2|WQZ'+, J6AF: /xC|MAh.Yhh4jkf.*I6(Jch PM2lGMN?V5AZ$-8Q\(eY#"2"˜ZfǢ1#SFw%j*W-l_ꚫ|1Y%o :IBl% { c$54i> hܶO_楫--!a?PL Jfl5\'j"|ӾB/.aF|uKyYo 6'(kK}  [ߠ&J'Up!5 \g)7Pܙ Zcqw>C!vUVUvêF#VtD쫗<9MP-5&9/kA `OcՔy;7ZCt~lj^bog@d43- 6y_WmNJ`+1:n{. ٿJ-a w0TU9yJcp)OƲs9sn>QG dt3)~.eEy6rN%)NByYX;ϵz-AX]ƪ l4\/]6U}K"ljDj),9`W86lK&%O5I?iISLd^ xnmfHϻv@UMSME/׭-݄an%LexR$&ҟ/_m3i3q銲&i'΍2x/$ٍW.(w7Ӯ9cKBs=><^ƫ k7:f Cۚkҁ@9:R 7_l\n.QFimwq.RSJv^C#)z;Ҹ!mЙtӝ-*J'Dڻ"4:VҡrYXb5v ~JT9T+9cǕ;(8ԊD 4?HQ~;TЮ@H9[b;³QdB=-6]&7@by$ J[)Ei jI]C5M%{AopJ6Fv|ԝU!d՟?`ܬRݭ']~o2XU)!UO(HG;_|׺TƕC},I@H5ٴ3]'&v|?6^ӳ;F=& ;L䊄HLg#P:7 {CPgTrqrws\%n+r5ntPJKdFeSL fN A95⹦P*;46ӡ4g=Hks٘Y_ҳ98UmVcb!ؚJk^*p m;G>8|M< DƛF/^~*.RgY'>ڒ Uy.?`ѷTt?Mn.QYlԣCu zM o?^t43/=].5 Iv"nGl-MGk䃍P%_)q=W,suMyQ>t⽖S%g0TBDUC7{AEq<6Z])@A™9[oÝd 8Ns3nD %L D5&edXBdsWԻsO:9+gݼ<ӧ`wb馷uQiH,]s ɶvblft.c,(b ճBc' zA&B7K&LS<՜y4E%hnX'T&ېiyxO%˦SZʵ\Ɋ J*a]ꌮ.E'͹jc=0+!0BN3ȅ!&`RaԐXatsn%ܯN1"lVzL 7itFE8x;QsPit%w%豈; w{$:cSM9B>=vB&A񉿞LhV7p$FfNŻ[٩ذk=ضsWvF^biDixdۜH99uT>rj1|Lʵs.SSW:#܅rua_,͝m͹K{s #W\G=eo]1vxtpX&iy%+8OWrZ[K^׳xgr`p)gQCg@<_I]c3"D\^M ƱFo]!':i nlrԐ8ۂM>d{ 1O@^:qFǭtI¿< ĈD,..WQÞTUt&Bz܁ f,VZ+HSM\@Ǫ]O4_G"}&}YP̥wrI<E# vh.Mf< hWM=2=K1f3B5=װE 0*z!6eB`Xx-&09B'RnV/ h&R}Ќ+5Q^A)1˚6fx随d,<(ű-/Tjګ>˶l8IP4|0XSe37ˎ_%= k5r Pj%c 8.nzkEys/cF1KʤI5Aӳ)<[ Ay_qA`9YKWnٳJ)i8xQ r7%U@ =uBR9֡]4P8h5[D{'^85Cv$0Q;>{u[x}T_o0&ⴾdUI# X%ƾߝv]&9wTX×󫟋%Pg)'Ѭf)n-\5c#+:߁JA`>(kM_^Q[[C8a*pZHRxnVD]eR v7?`;W2BCeeߡ!AGUM֯E脱G$tѻMJyH($RqRG1 )m)wUփƃ60HAAYo[NV؎U$ԂCj%N}őx 䕌VvNX̲2R»@@Ѿ~R:݇;8lRG`9 ,(bƦXUM!t.(1 %9r/2l[Ah՘iS|`SJ f2n,W}ã<9ȧ z<^qI? - ? 6ܕƚ{"jpJ$q91=![JXq}c2<{w=QZcډ51r,_Źs_'5n^lsGa? xXkOHL~]!UI!! YJ  ʮ'N<^߾'>}>=wf̦ⱌhp9:> ѵr eJmSEA&:Qڰj0&kjR[Ylp*r6 AWԤAK?_u^Ą< x w XyB2 6GYp~pu|[ P k05D̈́u|QqSš'Uqk $\dUX^(w|Hl<Ҥ>PK6|lG~};87ws-;)pQkCG-5m$n\ebsN>x{jy;ki(-poͰp&O=Sߎs)c~4'o0/ M6`27W[v-s}h÷<-`|{͕n-- 5.cqP{D|6N.Gi)S(6xRan7/+UFҨWeVuKn~QgQ- ̛b&=ifu^3/h,p~Zۢֈ N|wn;lc5CƒN .fXvAMn6`Q`Ҷ0u~5K%ˇS /]NW|YPZB,(SFxr 7ܩe O=N+dÖ.t6*KNd 100644 font.c2M#L-0@]At+ ,&vhR.6~pN47 >oWj+j%c,< :x;w3d/@mݜ\ݜLah"+,Ey)E@FAIFQjb̿xrSJsR㳊&Of*?YUztP9l3"2x}=KPT#TU[*T"NBH4&^Q)(8nN Nu<j} 䰬^cia?1d` B]s,P21v5ά}Nǒ펷 5CNϋx0׬0WJ*fU|#h!ajT**T8H&t2-ÇT7T,rZ[,,GYB6ԯgMa5vGo]-o|DXY$>~]SA^ȃ(TxȠD`sy1>ZI%voWj+j%T&r 3EB9 $7A쌱ٓe tG6xc ^8"`&Ϛ>Rf100644 Makefile1"]ՍgK1:b!,`֎VMAPfo\oZ+q4 xQn1V~* ewVj(UҢTB$E⟕w&9Qx p184(ͭ#{K^_@Wtk{A؅w$ YCMdIvI;UQםi;i'4$4?<&4I3iϽ ,HD{s.IsWRhA<-r#3io&DIP~! >4G#xtry5ΐ*euqJ䔷e㸧},L$bB*єR2NM]|ޙ$%C]JTCN%"K %bʤ:Y"O$N 2aȱ.MJDl9ELWedlSD6 ]JRDl qz7!ULBT-ixlPrs("fBLl^qX{- 2=)rsj"f?{bEb0I:L9C=^Â&K( fɢQ2;`rnS*WZw4$KbPUg7[~fzj$YS4E&[]v\فɜ)k*ϚMY')ɳQ23&/S#,Pf h)wO1M4dZ3-dQV{KJ$*J zC0l&p[$ïwf;N?hs֛ R׍BK/΋2 !sퟥ@v> %Ir{դ<$*岰9Кjv;uMq{4 $\}P7?l[d,0Z^DD%TNJ[Y"#PO. wbfl ԕ`6\G= {8"ZhwCU7j^ =g>8VıHW% \2@K>u] Էm@[D . UdZI!JEb >=rZ!'A]u` xdQgP6M=5'#iQe<_܂+.0n 8kjub&XN\fjp'xBnALj-+F?hg*Oj[pa O ?k$-[ SOfmv#I)|QJ{MlCmar H)W{-Z.{"=wojJeSsG "ϗfĤ1 OG82Y'"X߇eLd#CJ$Ye8ꔹKnE.usoeJ"#N21KLG&ݖԵ<;Wyr.7UY%iUVμ 2zC;?j9^ ?n{!et=!N'^Eಬi*inq-n 26B|^z+VS>l(|J96LU*$ç>Ic 9~zFmzXȘ]du4Y CG#-yu>Y>>^( ObfZvp.Ba~uz.>^r Fm\7QzXS4]  үn_: ,Vt^8 c?-\ 'F|8k*9z\*Ahzp G285 t:'R:&\*Mdt >۲+#Thq~tX$qx(SG`pUXz oSڹz=gtSzYRN%s:old 7o쀻 ~;ej5?K<^8M˩x[;51G6L!a4Y.R&nٹ1qbX0f:MveMP81}Sxkfȳ vA1Z} ~hkgm*oX/d**dC:9Ou*!V.!M*U!6brYRE4Qb0Ә?3sT"HXf a&M\&PvkK.GI~r@`.LcaO1+JqJIŋh1i3qI%lav|+d^s{P‡'^i]D£ѱpt,1qfY&,+ˆs$f?kYKUc="%, sVYxKg'9΀D=S癃{z2Ptizh< NLedLSH<^*(tLʋT_Zj|^"3_Vf:Tcs5P\8ʋĠ .>ӑH^9ɜgF fD|SSFƢPVC?ז,TX$Sbݿذu7Kv86,;:!G᳉ CsR̮wmU1'!}?a/o3vWP[.vr9Ɨf$K}]vvo,_0Uv`qol+M0pJeyYNqJ/ {1LS=#X s|; ]|i؀f$L^6# A6_V1-v{j̳MgÏ4oV=< }rpz]Ų&_^o?Q5ol o?,ߨ7Z oxsVPL^!T5q8`` $X*}V͹§o9O]8/ٜ Ay0Cdr, Fhawls7xctFZx^88~m!˕ff7?<70Y@>< VnzCe^۞[x&Wj4,6W)R|R_xD`V삶[~6}@ɹǏ{1Cbi++%DcyE$e Rg.JȄ "۸]L=@U n:^jG{t z+\;߿Z{7z o*6[~RoS,"͠EP8 <#pS'eL|arq.ppsxCiT|酦|)}3*MzYMrB4_c +^30eGTkjID]1}'a_5B+- cXñHdV2S#Gװ+[E_/~1#KrJf!/єSXh~S^1ҘkEĢj% 1  sKtm'ǧ㶒AWmCHwhhilϊ$ɩVn9XȭnMEqxRd1hzގ|bka~-h_b?'h%*Cpu(|4E-ֽGc'}e>YTwӻʈ`b̪ }NE|)H(k+Ȅ{kXijBUt`w=YEf77M]<Åj}4&,u8jjjm;?^Qܙ}s)DڹU&ؒ[wE:ܜt,xN-s{K:喂`7|^mcZ>s+|Vmۦy[2(ރ*5$_kNY`, X"tb[Kv2ova76*By^REz.Uue.%-}^]Db̕F׈GV]L8l]JqW`uBYv@y}ipx1^sb&-Rve'*fBP=Ե3va~,flPEh'RHUAr_D6} nG{MhRnO/kBmu.WΑ^j̴9q԰ֻO_׭NZdٹ~3כd Ί4j6-ӏ%%1oIsߤ</=jsM8 ahi|ӃYNxF#0=Ÿs˱imY,h b<n: y y,0]-Ȍ&4!P !^+ \poF߲ %kyd x3">a{pM/,!""3d3.ׅ12d-nь.eq2 ^tV=4O۝h.> f>u} ^Yh4OՉm9NEㆱ7ht- =a-hb`O˽Zj6x<*A €Z.婷(`ZQVN+ 82BmY/NK3ή-<4Eke2up[Cv3VTQ9ӹUk2. E+)lc}^t3t$?_͏3ErĘ:#$@^vs4l.E?xxa,2L8jQsñJ>V4+Q+HBg0U#ac D #L厥V)ET3|x"9+=2HF3RljgP.Y>d gȃ6_DlHWZ+Ť1z+F(a0b Ѕ$$%dNc?WCyZD@N\NћtGN C}"cYF쎞7 oZT1H/PBIA tbKʭ|^SFƔGl̒A%PrJR+\fO)Dlw4PcLWvZSf.NvƸ>=Qa(lQ.jY&UH#(coX5h$&Ʉ@j} !ȍѱPZ߾%`Z!R}i*P.x`M]5%{‹dyENjJr[$)ZЛ'rPL=^/[I y]G)"~C=R3DDL벫c X}g-fLYdו#IrA1GLEz0VZztcOnArx$x8+xI*P9ؠfУ`sg󨔊&z8)U٨m{tljҷTq\Һ'eYvW$ ~C#lh-!oD[vU-``'8K4 g\o=h`j,&K~ʥʺD6.5{]MR)ӆb r8UwjV=(jz\cT5ztv&>>N*0_Qf4$%һ 4uJ[?SU$ԈSL:6RgRi !;bV $%yeW`<1ԄDAjGvF8%ysTG?""He.g9j-uq;)*&جR7q!PK!k܉idž1[ǀTSᷞ+/V嘲)"m?a׺Ls2#\dh[#蝺8v1+NYp[֧¦{^s*E #b@ ;u$V* 1w9>gf8% "Q+9 385.;b?\Vr>UF~~i^S3/WPE ܜyZ1hf ӵQwR΅r9U/[EsLi]),a_vlczWC^x *׫7Y4]fư܏RJti$;%wy. 'OpdS#bb#mD`qXuP%*q`gw]Ϧ Z- Z-VˢMݖggO. T9@ߐ>~)z~(M*/&='TMzN6ʽ{RanAZ|w̓hG%8E+9Jar oM6x\f+h_GFZqKdv3cs5 DZԄlʉ:ayf댓K bN/V^e΢t)4utx,a2H((O(JgaWpGSQUSnV5nRdGD~$c[].U*h*N܀\pVVӵ"w*N>zIuQS}ItWf$ȷ ,>=aR|!Jzb`L|Ov#j"jen>-N,c$suw/[euZ=3ttg\{jwqj [}iw[ө4/SalVs;,{QΛ >a/ _`:ֽYy(x}VKlUUvƉc'$vԉ8SJ4Ou(m :͌4 !tі JHg `ǂϢ Jo~^xf{=wgw5x-Yr|(\\(rwϋrQ(D~5U TJ¼\LW$V,-Il|OdJp&, ggc*b1FQ8ļe/ 9SVkaִO{."K:<2 "qJ,aZ+[Ú֭.{r> iNJjl U23ӆ/Q‚ L&.]*20t8Ș3ntE9FDi )"( Nc aA֦NVƶӝ7 2eڤ#mD69:`?u<~xj4L+*Uh*KM"0L?s&Ta U i&,9Ź$ ISC05Q{5 לn!zl휙$2G@Sga[J7ΖtC(U(3((;>t%5'FkW Z <늃pUp5e2Сi`258Jb2*c6%़ ϋ9RSK2WJkF 6-$Y=V)+ç{v;NUfaE EUp[EuglLZm1ۭvA#ύeOiRpyWa#jZ!Ibr蓄q*U4i!8fBSPc^Ak($љ(H-`$}bTC)ST3HP/m"<涻Mts*S@8X6^7 (Hy Cp8K2$$ Z[ b. )YCMdIqI$OTE]w&vxidҴ4jt&ͤ=. );E{wιUO*EOl缒Z||G JiSd&I N{[e5$Jzl I 8CVQ׭)US–h|:2 >oDSJPdxpfl:7+v[ygnbr(N gӿKHg'Q58,QJDJĔIuD 3-I fc]G s<4ˆئl<-n>!BGVM2 QQAI͡8h 1i y=c(\zhI΍>&b$32 xm ,$t( &F@옪mUN#;@j>Ӻ!'YKGhT5݇Ɲ{ u|3Fp#gr"Cm-6ղl;jyYS9)me:f@=y 5X3cci:roi[đF:peG*^m\9ck``OI{t\r`%( 4_@M}fk Jq'T_t0~1ڲ^nvhxo.GTmFa۲0d&+$[~;`8"868p("|עҿo-sKȏYZ0u >|0*|iFL sg¡Z&PDP,i|l$XsQ8,\2rͲEvpNuVml^IdDSI&&#cT򩺖0|*QC?WOV¥#kV9#JљWARo#|{GSkm7'cI()fW,|JZƴ[\+<Ӄ[4BU @Fop -ފ-:< #vFfĬ Ӧ6ym|XCܺa>62fWY.$4MtxsF`HKf`%,}ⰰ“Y֫( >۲+#Thq~tL,8<#8U*ѿv,Yx-EOa\3t:ȩzYRN%s2old 7n쀻 ~;ej5?M<^8M˩x[;51G6L!a4Y.R&nٹ1qbX0V:MvyMPxd̔g1 by~rw7w72Kjhy!vhJGEBca&Z*~w19a,X(1 i̟9*aR`DYHik}xw30@&.P(5y%#$?G9ZWfoXD8E㙸0V;|EN2/9=(W϶g—D$Ů6.ˏM%r;W{__SygY]`|-ۡoOPԕ@5&`Z UdaN8y5:ph5luEDSךkkG7+[࿮= O7ïl{fwb /ߍ7otܷoT-7n9@ +si&Td8ws``ſO ,TL>t\7x jzTa.l ۆ 993<KccëZ}M +$}귑N*` ~purbٍO+Mc+LwV*+737𽕃P>x{ɕ2 3Ul}JT`ǃܨ~s{#|Մ/햟 q_ PrncG^PA) A Xs^}YDԙ%!2ᨀt6-0utW-n9Pn{WZxn/]@ðJ;wj^w[w7 l?~}0_i-HaE3`N=ĉt Ӏ>d1}8@ \xP_~)_fJ bb^V`5׳ʩ LfY/뚚CQELƉuWJ p,& H,5t 'vҤ7Y"%s oj26@7fYsXc@d! 3ai] bVYCxV2"m(6 -YQW1c 9J-bu׭S4O"Mo۱6Ol`r3̯8]d_e:F#taԺ(8~C_O'U]2"X^YOvԩ0/ ewMbpvm 2MQM ޗNG#IKBc^^pU b"WVevöZMSMYQmq'K;;s4E|^;Jd[r!H璛SoݩooXb\R3˵mvq]tLX+>{OH۶i֢#J Ss˻2?B&]۟&LJm]JPxKFh#۪ńCr%Vxh1 #JBDAbOǢ#AZ8urup^1c;]4vZcN kK3F<.ads^E5^Zn^]EY9+{I E'1UBx}W+E7Kl.g9xR K PCh(i)*KNd I>icIwywZ?W@&#ixs) Z ޳_Qa͞+ |xE-README.txt莩 fo@>DRzJ2/)$$3nxxtR &~ Ux\c#Ҭ0&`lIxuWKo$ItҞrgcK6Z ddV^ {sjOQ׿Ϧ UQ]eP֒yKL,H~ЦwOYWt}뿾06SGwn$s6Iz^HekRZGH~|BܹsG&ݬygH$Ԇ+3p2.TPɑ|J$reV/lc=%iI~-n 6HqÂIT;!zXJ!lR6%T|Dd풨K嵚sbam+X  +X8*&vnϹ~=\d㮘L"]Ey(1![#ϓ|L&;,Q}>Ra/esK?k~Rjtm P6om%j!gҙנL7s!JygY,loRuޓ@9l{t M B$jJ]j@ j4NXpcuuF'p2 `[&8PrM.,\V6]yu<]v^4Š֛>(4WzSZe!GgOs<~ć"+xgcA O+c#oIpvUwq?k]}Ą| ym[`w+_%= (ʲ?YƏ`d{`ϰm6eHn;k  '6n:ND?47u/;2%_.@(y sAwqtYW%Ǹ) I٬$QN1Z&-ec&eq>yx](KDx#i@H藢= o&_FTduPXސ39 Hљ\]J@nT271UTĘY"`.!z 0j7QsVvGy79uP*Hwr Й@" iyr]`99^ūʱmܯ.oX-MO  i=2P!;H7˓x77/n&.3ii\_*nke wS* ZEU +{y%o)/42il~yJ@fC>e@ ͐RɤHsaؓOώsyi""ysޗg/*?=\s=EN\W_O^xtiC!_~IBNiBfV^~BqiAA~QIjBL zغ2uRsSKSR2RK*RJ* R' #)V(N-I-\#-SVP0y#Լ-rz\` y% %ȶߕ;׻J^Jl6ؔW=` 6++pgdn6L}XY2c7c81fxUR]kA"bITKM+lBHQ Dgw6{w3fvf4C!BW+'Mgι}gs}&NvB,0tgBe> WJ;(!W!cg\6uD s!Gn EfY.Zz [N }[faلKyP3:G@[h)<?& `t?z܅x۽F|*>jpuאFHߔdIc^HATDٷ\H B{|IH* 5цs"ZaQ(ZW`3nm<Ԃ& j"}N*Җ8ig-J$ U8CZ!΢, mU4&z_B+PhK9]pQY..Da_="+GJ7ϕ;ʔ5R(̤`7Ya\36/!d@g>` 8<>>_D2O듫{y? xVMoE"8lH"JJMPxwlO;Ɖz+BB…#GH \H<̮~xw|w?;QJOϔI3* ʕ˄ T oU&+79OhZrwWpkwVBIO:vvەf̌F$;J(ZIJґ(τ cIC2oPd"-\~!*I(A-3<2o8QJ&)=2r4>y$O^z^nԫ1 ,vN Z7Z(MS:%=Is Ek)=1kc"m,"b}JXGOrdF'Gd`%`?͆34H@nbl[ۼj@aB ޸ȓҨ+-!34eZ24>ҚpA%-MZœ(fƃ@*\XkP 8l·5_F鵷Հ!ve^ < 5%BYeyz M|\}o-Rˍ Xg wOM*TT& |$_ICɊ"[0q&DR)Z8OLqd ڢ9yLA3!P$,H6_[+}e5+c[ƦIg^@]&'(̂5.UIBln\qPG;)8H ѱdm-^0%Wеҙf2D˹_tPl(C#(v M-(K!qhɀ/gr¸b]vߠ r*t=Q?̌qKA+ *'^7YֲYM?݃oOz;jGb1;rzi|nGM\{wg8Y)ePyU ɘI<>Sg+Tq{Pzxm uBL]h[O&$=TF!ƣ>9f&RgLQ{%AX26DЛDB.48ԋf|h.^jeQ򜣔J*J#OsKyPf,.|ci ~! } ej: _WB>Љz׶M^ruKUyCe"NUĐFx$Gh2Х:\2vommw cXXbG8aL|ԞKas[k4]k7Oםfn[TR7蛥,x}UOoEW ]ЖMک.EPҦA)!#@YjvBBn|*NpC'[yovMx{_w}B#1"t* YDZ>XO^I:w0-?Lz_|joBfl$x"&>4`9fJZh/9KCq0fDVlxe5Ue`,~?;RQ)1Wc@p{ -癧vv1k}gIhJ<#2CvE0JPc8MJ@$'&)|hJ脗&=3&N 6Q 8M~( $뫀aoa8rv Wh{H/Fn_Oϯu1pvEBn^&>rm&Ҝ^Bte+)9B3Щ8m$kk6k7߼q˱#g2wL"bDL#Aw֗;+7ߨon=p&WK/(qMPƓq`/vQk݇HE L{1-I C}KϷ==o, 6H>ӊ"@/x\ԹTz529,&zx1NPD%K4_H@M3ib7@TPHxe!r :K8L=4]nr>R}:M>1A.4uRZPCV(- s+gp$9\ÔiVVds^VX#c2ؼ=^m/sѕ-gsIDu ݌zoGBk`kTw}K$@ Ss_ է:GchG?琠xKMJMM-K-/N-K*-N-L2󌒹s 2sRS;UNx7Vgz ,56LR)uXeO &Gx7ۑtD=OhϿ1b,6d٨V*(7b_vwI? &ExE-README.txt莩 fo@>DRzJ2/w+Am,q9cC6I &}Sx{qZkRZ]">²lj6 6x{Bq!2OLKWP-VHKIM2t@AbIWM~ŭ9rx}A 0E9@7ZHQvLtz{S "?94S(d(@uܕuS.JeEv_%C_^Q^w2v42,.nтWۊaLӏ|S,x;YȊطfd ϣs?AW0򫞺n%0Xr 9o:yxk!RQ5'?1E!1'G!=,5O!-3'X!3$_$#U81/%)bsb%'&xo0W2JxMifLuS}ڪx#mwzO;@S;08avd=nAT+G  ɚz9k 6Eac y XX<~UzT)`%J&\[Z KIXa-ѫa} Ѹ}ʎhi8QD*z-4A<a0]N\R')E2%Ǜ|41E]t{Gz€_袜p6tWq áj4*NG MO\ ۭΠ9`BT]X22Zu3s66{U6^QoU:ߊ{x340031QHJMM-+Kgp])O~/=xwUT\m74&Hi=k#!Hpw@!˹sz{=kWY5kpUeYtb./'r!$?+iN1?FR>@-('y H$,^qaPE^3@􋳩 9{U- Q^JQ7$!뼌k90%h"%I3a[9ae=}9kףs﯈LNG1Ny%6JU\*PŅܿ:p~Ӭ,uq۳TN nUsw<'&r2 V75Eb 0]9Ez.f|G~Sm'Om,us?[WcCNͭ!lLד1^HwDhO{kun6ioi®X^; y7cױA~*Ǘ~_;lNd\v1 0!41t($Q; O,F(!ba!2NX$6-B FO4GĂ k_&3#ɂ^1ygOJmhZW3-?94́qvi!m+WbiYհͶh+ePSgqE.n}0͜=]R#wEZ7 8zKm6W<^ވ mE*ɣq:Lv$?kEΕ"߿aP"qyibStiҴqޝ-xo|gӀeBI T`f} iՃϰr`69<y`VηkshO?| m!.N^{ƗB D7{KΚz eN;2Xʜ6fX ңJnn]#Ktd/wFIslEﲹHt=tP}:iˏgGm wja8GMԒKnZ _Y;Iԗ5\kBP^t' k>ZxzsIX8Yi%g{cRR.V8L3PEŭXoZK[%mG ~;,xNUUZRwৰ|/ZqZP7V+6ŧ E߽@ @:;eS{̟It+/_=%$4ht,lM;륲FR? gjb4G߂ C_cC!.|iV7Ki:?~~'?G|،0JM&zZi@*3-^p2U0,+JW}{dPN^юhlKlWJ|=U x.\qAaivxO%nގMfܳcJh8 'Þ.0̿Qޓ͝^O ݌iU֠?j,._JI Faque?D Q`|ôx\AUYAU2[$1չ+6{bCOoBsvN=E d1|n/ mrn>a>cW^¿xl(D= &*G1uovqmS2gI=BՑ 9?2e̔e/"utDo X=las8L "fT@2FxpVX\\-Srx,ID~BB' Jv꤭EK-j,S<"Zo.'T>%z/9,-#!hˬYzG!pZqwi"#F1eD怟Tj;zL64qJfI?.;5<^CXoru;j@ws!]6b\a?4˕![oxFزkW>LY -b疉/7 Ѳʌ6HQqU8{bwDhYYʳSvXrgb~$O'IT4vͥyNC;N@ gރM!ԑ 2OgdhP. T|k7GF;X=5q׽|N¯KӹAzMUZI=%Hݑ߫Iu{-BH7`?c}hHCWyACLs] 91K J?j}g6۳ar\ X|*%6O᥉3Q85HͿ&vI^*ʥ .k,:AƿH#кS9OX:Yo@g]ÄVu)n3ªj~&QgfHEmRxȷ!t;2= GNr;Ě?LC1ͤ%*E4uvY!^O-ef^lpUQxD3֏mT hX g..FC`,ہ8.@aO), BSXO!$'T(@&)fY8!4D<Y3Xz-f^.$|#NOu!a;C ON# ʎME@R&SpfƬb+۰`+τ!{&7IjHiDJLEIYe:;$ |ZPX/]tݗ&hV;C}yy7=Hʜ0MkyΩ3]ݤ *b kM.Am%DYKI4 N 'M?~e馍njHg"'v;.&R ' RRK2 ϯddAw+4KkbTf_3pQ"BD0u"Gv$kcP*fVևXRs_]oV"dē@>ӊK/`BQn[ArX%;ح{1Gɖ05V.jQmdeve d8~1ܓ/3qhRe31#@L8f=N 6ş64ldSBpO埋ތՔlvvܮ|7 ZM'!y$B)$ sčpp'ǔ3!/5Ş-'O7:UMyR3V?bjYU3%+W02vĽ繄 `AǒV|z8-/nuWs6ȋSa90tb΁0'pl~4'}3mBIĒ O}@Î@!J<z$M1sK'UmKsG :o.qJ{F1O./|w[.qb=b@M $NKF<5!v"?Mw',EaBKpEMJEXerHArJ LB*tpLg@ 'Xo8a 2=Ӄi8\^ޣ\{a%8U$x!ӚtV WCHЩ$3Kmd *+eX~rqؐ&ۯ!]yϽ%iosm'\ Z˓АYÔȉ')wu6!1^T)"E|Y4fw[:a)b`c1ˑHPn&<:~A> ㋵a|%, uX@eMM4u}JfxY#B\ 21?yNW9“W; SC-)$|yVHPs ȫsT˜EJﰙZHC4"dM8`r(q.-0յJk|yBqE_$ڔz!:3hx,hVØQNP_Y z>_ e ҝbDMf~G8kRT:ꉃ,\z‰yj3ͻ'j3[};O)90cmw/%-XBڿE &z9b56e UbZ*{/0UܯlSjCCǓnFI&&ĭ"}2n̛!"2X.@Cy*:,r. ;4PKBe7njE1:} I(^4aDQ!/hRwncbEp/o6yN&!,`cxꤗeptE".a,P YS8%d@>Sҫq.hl5٣zqsu,uyM GW|OR򧩤 <ڪ]nb񳽐wYg\495QO84 Ó 1..Iq`L5뤛H`TU3(ߛއv% Q("FUD kv9 Ƣ(Oȶ9Q@?gΞiBXc.0%F7գU>g-`Z$&+fi#c1.dX$gWk]yvMmkZuԗSOIF _DN86EC'Q:m/.եZ=knX11{8ȴ(+KEwmH)4Ox9g} 3IܬcF0񎞍O`U>#e\686x!6ZATbE}l'z8f RFL l؉;uKX 9InX-u+) WJTU]LImC XPE71x{;`X}*r*P v֕FRтkFx|m)QߖxYÐw0b%xta&i@lHrY҇LbGpH+={5^B^sO'NrvV|;^楦Bow]9EkaފX$k_vPTXZ(Gtk/hWVL~΍(܏ olG~K l吼U?L$ z©^ ~~Y$,b"#"FPRMwe&ڃXﮁ(dx}^ >Ū;$h];V Sj@&rxՈoHMTB#q/.|Z5!d=$5[+ q_+vB+ŧ3c2lOj=,|vw^Dҩ- &4y7' $hYC(2` 0Ypami lV,oOӐevU|bo;b(K?QrxTMn,d[\%d VY Uύ{,lqH[~v՛2C{&w,j$d\UZ` ޒqƗ.?u+7 w ZH\p)pI1щ׻Ϊ|6d}'15'i<-j.A^Ify//kK]s:]U] &<9~]赲٢;0u_x$3gKkePlLSxa0ON"9W*[|6~ކmC*G~|ÿ+ QKGBk(>Ú@tD&CdA?F~f$2RR}S=F4# c=w=7ܯYZ?5깊 ?gHz=9m>Gmua-re6c=&K\Xn'b8KKg)'@8a$vNJhTL#H淖 k\>?۝Vr$jf$$,* 2I=`%+dxm}JSD]( a>ZMv0b.63 HǗ&~fU3 R { J?,>-!gwMV[!~IEc5 pVJn9hZSܭ Fx2ڵ[{>Cu[uQu ^ :Q TI`KQP`y DtȤDX4'~BBiS&zMp^y9|QT5r8)I{.\QpPTyUz:7#؝^_)b9mp_%ߢ+F=\vO u!TRQrdJ X\I C{6.e+&O" AOy-U?!drxZ1[<%6"%<(ѧ8O,6@ft!z Fކ4p/o;7j}h3NM@iQ4O_', :\^c uy qa"Q /8<0WƖ\aPΝDAEtyĎ5~V#۞f0|!2xcf#vr-Y% Mф3jgr>1:}GcE>/# i q薰K^WSA0t?;KsOy _wΪK)P9v@X@c AEo΁スSм S$J45'lO2BVC3kNL܉hwwwXKD |bcΡJ(t~^9$V1FS!EЇMcSW#YRO&bOlBu`)&*,E@?9Y ,gV-+|}ӿcYt0kl#Q>T7DSv+ǂ8GVhȂХ[mQb!~L!K1CP Y0MtQn!YM+$r#_\vuM&񃈮( W֦xqSw.<3>טȚOuC5Yaa`F~Teh(KR86-yvܝI =qd3s̐;z4jy33zhZ?0;_%m" C5Y]>U؍NLT^;9&ϗI~o\\ljd!ӛe/r|J AhBDH[|?GCF`Byݑz%׈ZBƩ-#eD+sꮯk}ۼ}.?Yi\JJ̖i tmd{[u- VLމ)چigܚN1PK~RՐ _9-$mK-HS`IzN- 1\l~9'_&k̥?0I,nA-נic|*qLmjp{VI a1[9?ʑ_q ,YKVYOtg\1m <@}d\ȅA:F(&aA2+9BJ6|^2^걾P֌)gcL7BT'$u}=m36e.m)lQrsC(h}{ kc1'0EVku0ɮゔ@'7F yWnf?,'caΚ1qYOQoO6ʷ|r\g~o坬-շ^۲Z;rr0TLa?KeЖ$2?}bvMƘMĸ4BKDW+䤐N~Ñj:#yg]NeOT݅5΂7!hŇ9Qw_/h[(U'Cr1A1{NдMg+覃{{ 5FXOם8>ߔӎ  xe~@Gl=qow@ nb=Q}s\xD~j 5HeteXa9gSNW1 13*c*V;n\ҍ) [Vȓ7Ba#ˡI߮+8;7UPцC'(L<] a R*-!(3 ɡ a+:**|mcU;'?_씍׌.UP;E#Qߋ@P? Eq3Ph}dzFq|"OШn֣x3L۵=KcH}֭3=EuVpŒΓZP,F#`"ON< a:F{ r}_eGbn8"G)!%ψ9O_!=.!{et Ku>ID5)털'UeK {V 4h~"h>mUU)K]Pך[ iePa{M]A! ȬIwΉiN {袌HN]Yn9ނcY,|:>XęOpwefJ;tNtRVVtoXKb?rIߓi\e*" OuRC5Q<9F2g`qW{~BQDl|Ʊ~0Nʳ@wYvfA8_jw\lXU9ŨnjSfoP xA4D3q`!!9~j0:t _>K;yѺnu"Iai:E4 !4S,$⓯Xr~Uu?=(c?#sKu|Mo:\pq Mx}ÉI !LO&4c}uv/|zS}^B EJ (?9T3lK73*:|w#D M}{jp`lFnc*PB)V$ Iw- _`׿Ժv$uG$hQqTEKw1F^2`տA BfE4RwNAwb]Ur~!XQW C4I.Ffo]K@p;kC՘#z kRL>.12t ő hAhD2p28I=k{ךzd5.m&Px9ΪGEReېC" ֗-TJvrrFX]2v>H41L }y*KՍ/fo`2"êSQj}hw]Esۑ"V 8;у9T.!W)4h([ GEQLۋ7J/a{da#=X^ rbzURcefi[ӈ1X6^Zi4:E2e=^S~Ar%$lrN oxֺ6~>uuw/)_z9RTfqZ㣁DD QIeSM 4(ݖ$RP)8q[rE5t"zuNr"^GIL`<4j{<$HY-|i(x tZI h)UU4n'Ӝי8$RJںCEF3mo;܆?D,Izqg RUŹsj m;X˝t'ԮR(˴)ab~vsmt]>'6Y{BP",,cFpUmò?ɿeˑOO9r>5طإ^~}{ƩӅ@zYwUAGk[9uj)۟ͩpoq>joK7P %?&$P$ZMP 4ry|  p5{NpS7u\sŶϼrd5?9"Hqߨi@oH]d46le{@;5u!˞4~ERB #ziYis8[~]tbNhvI#.XP!8s+N,f`͉/((2ɂ9q2H FSbÈFnhDߊ_gJ}jV ƻsGAjB(W#5n E7~]S 뉑Y*$,X=!U@RPW WTB'R"580 ѕRA1E3qFRY˳DrSF6t6;dAL-da f9qU7_!0byR3𙰏8ul{ɛk,qCyw wA( 9uh5/c(hY6<_|7ӡCA>PG< nqKbcIJi7mMs<d<79k70rmӪ  ĻVr,P`uQ&5l;2L}(ΥӖ/ڇG.XSORoj̈6 T/qӉ}cvOUV4g! RJ Q+$^Us_7Ghjv ٪Wa])J &Oɚzo}n? ! }ntlƯ"I&}4TM(#vL=D1 ^N%= ЌԴk2n ʏR#e}tp蚃ayS y(PҖ3$$eũ_tU$X [*Y.׸'2Ȅ(i;1'YH 7jSoM^֬b]?oh9OU"Wkہ]5kQ`AɕN衁W0{}P͓c> uXQ=klhnO+ݴ:MErzjF]*~d i_k8ϐrPv{om/nvm{^r- yy>Yw+: w7 Zo?ΰwO&x1c<-rRMpPTʳjYRgm6I%hvK0jK.\[?/DiҷZCzS~ێкDE|KYrpT8rW>!bdqj+Yu{()DiBjӓQڎ [ZSP +aW&wġKvSJsvGrM-:g| 쁨sGൠ3K|QGuz i^jX6fTazv|T*bki}JkK'jrtK:2I내_apqCv)2 t!۠]Z_buP)8zP0DO݌'[4L?o4nAr 1CyR/O2і;>p!0/5$;Bd1w FU !Q@_OyxH+ 'm5hXYe󫹗ulGC/?DF/lozнx0::D70fC&hY%A _K" )viwdGff|mM`IRZe /yW=FH4N2m8鈭QiAkZh;Ys‚ݪWO!ބQJnmUtÜ#.2z&Vu/nu=!2l6HLi]UqFݟΥӞÄPO]-KKv"˹[sn%(^o(lÂ-+X6'%. ~=ny.y[AB0{ :hJSF8. r73Zs)>)*VE@DDb-D1>LƮ Y[鋢 ؙjkЀtwI0+ihтP7@9'  a$H"ABHDDJvFĢs; nc{ܣU FǛEc-P0JvH^^,ֳPnA= v+"eA0r' 逋󰑍#Xʧ 񪿼 8x-uωЕm4:f%wFiH9T+c 艹|'2D[B{(ګ(;c 4 ?P&GKBIBYuWa!qۗ[iբ tb }GSj63Spe7u2+q$ =}~NeS49n!cp|$-W\n~6ژB dŕ:@P_ =?j^'ZܔbK߱Y([H,|6 fzx8\Z1X#ZXyr.ୗ?}(3_oӧ_nUnڇ~80s8@}3 ea^Y}u77t\D |T̔UeH+RcD DB<:z6PXJ AtScs޸m_oC/PԢ|!%uۊp+Twh"b 5iq|rd|C xq>$bVߤz9B8TN>D^ *"L2P& yfLmIQi)piIJ L^ T2BjzWݍW'/Jk rK1{g:`fqfAsʧ};r]~YϨѻAQL1 I2aQm.Pr$/iə^d1Msad>/V4/pyX;Fܿƒw*XGuh$]&'Ưh˯>nZUm<*nxpte÷ 22Ǿ"e:ƗlOڢ 8R^ R)7yi/)Y< 5sh|2茸CS "Ih$NN߱p)u>fBYL˵Sܷ؎+_IFRiZ$LW 3d]pV^N3~u2ܪS͂zhVC o>Rm[ݜ4de 9L d6f?0( %қ* kq@0nA*D{Hi/إu^A;h:Y&C)}C7nEG}AwXHѳt2- %rI] =V%]`#Y=atuK(0/-NKݔ_"WZu4AS!Q`ꉓ !$Mp}2'̌yM;q3k'Ch;6r >&?SF(%TRӦ$=\&S}\c{f*K*.U?(c"I̢UxϭF8YnJK1>-rbħ#2pR]Wvl]l3ʆQWBL^U.JjOc{;v2Jo4 53KIKN𨐬ct$[u214GfЗL< TA"vt w &KGc$qXyX]zAgqS/s2UbśB]m 79T99^Epaf||*GwB|eFDM(dzŬXD@Y*"]aR#8G;|ޯ]>*PF0PK&l D.Hl(%ޓGbG`z\5'-. 4YZYPHB>PtCr.94 檞p ~ ҷr։.7Ք,0q] %5 -dx4X qAW-`%䵧zuYeDO?zb v $wq@*|#:Wnd7_,yab#SEc?vyzk-h@E[c?O35Fd/;[E!<uCmP%فEWyڄ[i{Ȉ:, 6*!wI׮ 7cg7rKo{Q 1ƞ6$_:VH!kL) Xz*m} w$H@/"Y.KJM Xf:r}lYi,!yc1&t\SGzMFЁm$3K$!-" [o2gh#瘼A\?S=;[e ~ᅪ_Hl "X7ږ!J8)x\օ49tMA 1q@iWee7k3MB?ow0\>,6Z٠#^)Vs5#Ysbq74!rZ zBw-ܓ2j2m+˶[}EOJ,Q֝3f /ٛBv)I& [р sEk)k"zp__$Pa1lI`ĖC`3?k;&vO1V4oCeoaTgVOy؏-uϚ]E& OH%4T# ~nK9ud\0 ]<%r >מ,tkx}@K?܄ Vi:l<Wm^;t8.)Y p2vl2/O@ټzG&I|?:Ch.S.<&&<3s]"%.=[=N`w刾ChMQKA탧R}-b⢷kA^֧49ɞ4Q&L0e!s4jg,aK(լ?|0cQG_W[f,mWđ(#*dCAbo;7yF{W ^:-G캞!+|oѕ,Z`}vK@k#85 :׋>cg%R25{ XKrnYٜʏ]g&9ʌD_ BDB} ^/ gub>b~ݫ x=YlX^0e60K:P? j]w(q0尟u3!D&/< E1 7.UlҌ#"U81E&Dk2mi) Vۈ2 {pA`~Np|ׂU9 GHk`vN3Y:i1,LT}i MSDSO[K" ^Z9Fb$P"ǾD0gwyݵs}M{˳~fۨg-M_c1Tj̆ '@˾AvHLLn ㏇X$*`t rK!?2djtڸ m ?B0X<\MY ,^gBMYh@ StQTBiY:Lz(P>*.MUہ$[9 t_O"M,)^(6ݐwnW'hJm>ܼP*Y;Y0=8uo/?oL`l paMO ^ArxȈ 蒎o0"*"{gҰK0r,ONFw =uM~^mnP`ˊ>O+寜%^zg \q8_A5xԧбkAH\:(B =F!d*]e]L{r a>Oh~bCnl~ӓrߨ^>mnCK_v_f_2"!~ NkPj ė?(5&jM:Qzi20 >5{Tc!cIs7 4*UF;C*bAX$ݘˑ̌\e5<}PF(=8x˕knm >~(3n Zi ë^މL+Jx0UKT|?-P ?Gq[P=B?`/-32i5MIB0x?~{|MvR1prdvpBH] RJ$tZsDzF?5ǠR"gA*ljr(mg.'e*3O.dc3 VGi>BEP`2glޟnJnnؔ/> ch@A[T@t ?0An&or+vzUi4E 2B!˅:I湤 Ήhcز+ Xvd6բ"vHԮZվf 1*\צv" UwSE6!Rxń߄AiHT7$pܻņ9Kgk״`@q> mRp.ԹtF:lO/DɁ D?+#A4;4mX Ww'oo?V"`v@$#%)ƞU?-U{e~o} { oy)X? pDA\*gj @%RA鑙=".Hc9=^LQٻJOXǃ G%<^l{'MƃAnȔٝ+L d |?eð<|'\'1ݺyK>-n򳖬TRB+RBQܺ0*~zMcj)Fu(FLN%? .H=d.Dwm, ty64iyɉ;Z蠤OBA U6FŜw-̘ߖ(h+SX8Z;ə yDV\WrR:΅Uoo7y4^8쨈(A%ü9-e?r#2 zz<N@2q k8hǿ ĄDSҀUq|8ej<^llyցm þ0b.$Vxٽ$sK j Z.d gKQ3_rhx : AK(%2:׃7#Fv6$qMk$kFl8;qhuXwk u-k6<nj֙a|N.9]3װv6Rgy:0|KQ+e0mzji8K.9ZhH5ϓAM-lÊx8l>ֱQKZ:8mX;,%vihStXO-Rj}r3k;)6 Hitj5'OZ_E69"w;r@ Ka?PߒuiCq+z@0E99BmА)֠Ӻy7[:T]$d bи['ﳩReS/TEp}8&raE$ǎ%,@ %VNZE}4& r &D@\ۗcƇLNpd?Rm݈s?-0zs7,TpPZ~L<pkDc!qgf5ӍIEk$[ܣ9Bvb_]U[jE{02RyDÙ9.gCԌbGhp*g)-F_2,P k2)P|hMg@v!:QeOR?v;n|sV3NÓj餪P>H6q؉YN?of/~Ҹ}e9xif8H( 7E6}ٰCXL$;AyXCas6XW|f 6;:HBO[a1h1j-Pצ/moiSk>?6vfb1cYCc 3>u߫)#O|ZRU>X{i?Gv˖$T&TAeyų^d9X$5{ScԶ 2@!}% ]-OCa2 Zk ~щ=YsdsX,DД[k=bLZJAj|#*ʙqSjJ}$P y{g=MsؿM.mpls(\Z9 |hu!NdCw ֗H)]CBNUUCNfE|F/4N0Ίg 3G旰x"j'^A£K(.̖>tYj x-Q4T QΟw:؄`RIZvů{ק8sy_}6u10+&mv,043E}tOe[3% .VD>7G-pkagT _Y SsQ܌U|Ȧ`YHFA`E!||-ep*Q K ^n2jֲ~K \S P&3*Nu at_8o6h>DNԟ 65T=7UE<-bHϯpB"QѠ5~mU0`mj~$*U4V! 2nʲS+8Q2^QO'_`t} Ш$wXqOfQB@tLFM&RSo?N^U.N<-G&QauamiImN` Dfwn˄FuZ ώflߺgcZ ܿTRhn 5;wIv3?ZƆXp8NB"dd GF&Nb'Y ,z&zi&W4ruS2H4=;H.H0c};\иE/}6F"KmHuhLi§߷ܟ>̯mw(ÑqMA2/+OY ~8&>JjP#J++U&mfܳXu('a`@/‚O4XGR`W:U$cTm AܢP2IH)ڦVFn4e+0+_| OYF^xM-/|"7L% 5줩:[ooe*}[*]%s N~!/zLzT_bZxz37BDԞ$ae&9*F)>6&%`\zigiKEhvfw$7~3(sU2\2] ]ذ2ZMp(#'D37ׅ}Ie9*Ì c<$,) 4Y:J]PZMB}1QXS]?嶷}|<\Hމ,9L]{ %U0e9]i>l?FipPn(ޭB?`XJ~|r)~د^NxMJTV[G sRWg'3lQn(`ɡqD (d!M+(@BA \8Umfn vpD(l~KM }7 \a"2 Bnn(M_tp3Qmŋa$sa^|q9V$mctDKrpī()z2LM)ۅwӷXw .TU~:iP˼/{s93$k2ɗ0Vf'k)Ks||rߖ8~bkS}gXH8/YQ;r8L 2Z?ZeyMoc;Mt-hޯ1n]''L?~ T&w@Нg ˘?0\OxRz}<Ѽ3aaf.k܆{1/>/ =?zFJR` _x}\zJ_@,|4f:эK|,*Tu1Yw(M2L%N.esZۢmABٗߎ14I`"-HZsh.o.$_+ K ~O紃Q;$+8:-E^>7V~u*xr97.lja r< l*8=&~ ;HeY?Q<,*BF^EXkM^FZUUaZB12xoX"^/ABCփv4-20.~~Ky2IDZ희:Sc|XP k,kĭ% $:z(:/" Gʺ8҃#üI+׮ [U'DWh6@ꗰm-)r;l;l\FSc:\K9{08廰'\9oXWU%1^|@\XdYH 2Bt<(eĔ7)?" >z"yFWX!qr6,_v%!V>R(ډԢ3 "q3M- Enfg]uvd'/.xy/(MCZb2_)H^VV@}. v㳞}`ՔOtS5Sj.@L:j>Ew2_8StXwI(cS7·P@f5a}\?0sbuj4]q$'80xʞNz|ڼod||' Xvv`wr(*PB#Q7,+iL-G"li?L>c ~ ']`hqZZT#.SD:O_fr<;tג߽ ,T4n_b|w!3M8oKiSc%ȐӪY?# )}$@(zEZƿnunx|_ݎ{ƽZ:8&Ev[$!<).cAi cXu1Q'rXLN.E>G6HPOIe(a}6V2xkqᶚE'SmIL#0 ;MazT*[{ ,Zٯ諸!<ܶQŘ_ ؉萢 1t E_tζd/ ՖDBh9('TۋraN o9Sw LqL3ݚ~ H_M6UP&c#ms ʄ~a_L9$TLuibہ,*7ej7$(QAL՛##=?],%QsmBG#{"@yM t.<,^!0yŁhVG5NS(: 9jrba04 $>y~﯉b'幟pJjYe1l/Dp.+N=X2Rg3UQ4t S5U=׻zb4/KMiS_~BFT$ڎfd|GBmJ 4!ȵoؿ+/ĈngyBm ?ծU//\爲pBK,$1EvIr4CAzqG NWdl0[7ubCr;},)GfQ?AguHP͇SDdP "$mNX]v!n^P_s٪<8T8.L;/?Velb(,';jM97F/]a@h Z.t IܯkF3GMF B<LH"ƼȵxIRV\Vfz#H:P߲ѣ1@-58H܎O̓ D畚Ҝhu(~Nw̾.OtHup#R5`kKs0ϥvS;Wܸ~h}>HgM$2P>+9PGq%dr%ԏz?q9=Bft[l,1O›XҬ1 V҃;Otqi?ӜtJEIdO4V6(_L@.XGB"}'<$Xרɖ1)Q#pTJI>Krn֟@J<{7P1&.>'\`܅h"KIuR7Jw s+ ވo78Od4, aI~Ku9N^ɧ5lkP$Hhɻ{`)_Y6463ܡ᭶2~&c8WS@0 Ļ2Y*>Y=gNߜhxbB4ȷUƊXȍO'V4dmʋ8Hr(AbO9W%/5| pUY*ζm۶=6'۶&l['kTsy|\u3ԧrw)} uد A(WG0]`c[Avڽd_Y-͊bKz+n SOJ""VfdD\Y5! ӕx0?Nȡ#1 H1Hm;\Ho/Ov;^Yͦg h\t\lTa@37};0ǨIG\ݥ/"84D%˛!?3sVu8ϔӜ%gNǃ#d1 `ˇõ;{/^"q`9V杊@1Z . Y>bxʹ\:uF(0D+&?54տpf|O+FUc5hÐѳ1_В;o%ej%Cb+^ ^(_2=o`jQ8fH_fo-m-ѣq@מdR>mݙiIE%-"UơbG$S(لHz 0v*Ks-MR2MeHxW۲2q:adq ^ 4!D6EIiIV p\ Jdj ¦iǣ3F:ߎV{t$̤[^jbٜ9JAkG5A!xWk" `BSYG!Bv+P;:MMGZU?qfxE&^D閌GS|8)p OfwVBGM^7{߯J)N R࢝E?d $؆kk'a|-șp DtzeQ|飧Y0R<4 YFjOǺwbs*{-?􈔁|j>ΉʪJG)x7$mgF5vЅhNOid%zy^?r |ƱRWg :iң"Tp=k^>Q߃Š" IWiFېyM]tw~ Ȕ I &uf8_=8ƅ&iCgfi:?\RAlʶ!>㸐Clqb-ƒmAI(UQE"6T [#rPsV75HSXꝅ\uU>1PE4-bĆd1WW̏,r/Q-.yܕx !@̮[q j>(пb԰af)\򔮆?J#C4K=$TP`ϳv(ɶYWD;52Il˘+uw^DOڅG7ʞ)f]D ZBZy!lnF˩ut|s7ѭ@`{(ߢS8Nos AgH  cάyUQ2uyrDb#`JI4:0_A_ٳ(Z%ԉ&t:xr"Хʏfv*Kb䎔јE(b=Hs. u_Ocp&iHXBghz7oq.P4JG ƹ_v[G'Sa;("){?j5K=g1Kq+10aO׉$JCe}m)ύ2ߚ9i| >$޿g$k*>R?T\F~JIRo&)%3^G y/GYRǰZ9GkֲNPrV6Gh өҍ4Dq_<^Y>f|~О! lcƃwW*ׁcx)i)`cY~E&[<ݷ6)95%3A3$W HAkJqTg&x rWFw;c …vQHX\ޤCͬ~Vƺ<ٱwu7:ƣwQK+YLecfP@^TۮJ* [^c[F"kTQ>TbPMm}c#&y*;6 4 ]IihUT9w`|B2(&=⑹v"'dD#$?PA 2S;'(91ݕx7, mzAO{jVۈnǵÓ|~Jy $ DVvaDBW =N`VoKDfö‰v`r,ҕ (]=)О@?֔KZ* ~>Fc ͜>4 9gsHǒ ^Q@)[&h:IRv6B9%R0[Pl&6I.8ا1\XO;!PrIRiU*:ΥJɺ ڪ.9pGz׋f|h]⛡/7 rs%bIPG6V{m%&8(#®ȵkF(j ';tI-Y@o")d855KDnCGrH I'sw=~Ȋ8g2)q{G(0U!6 )w2ͺwo#ȂWG@7aFV! Vp?vΈMb#Vl.H+{}GEy II12v2uGb#{x:, nV'D&_\~?HԦPܸe["L>Ɠ>#ߖo.ڗg¾wd }Id+%Z!$CdkR#xD~ߗCc_uƽcFζSC!{#_ L윜a涒BveK>_o  | sIT2d}ѐ8w]&n܆wXG>x 3b?dcW]Pdk!u*j#T) 1*}JQ6ov㽘KzЕ &s%|&x bi9{%O!E"7{1H_F U7/|ۯ69jO;Dɱsxw?H+kTEKPcߦp'uC)f*eއq&EMیB`J@Q Mf5#c@*!Q*V߼Nl,c v(`B{B_w߯IwdMYƟ}FO73ۃ3*EZljzٸΰj6FfZ!AX"lqf'^ES&c)r==Krct"DronCU{ w>'s{ %IfQE>F@RѸO;`DB7R)ŭP MkTDW9ѕ`͙|- /Xu6RVlM&E* {G " /kkkʔx5) G&IwGt͗bGW^Ze:FoIYXEn-ϔhc7fJuP"|U;)%gVI r^m]̅ޥX*ښw'<07LPwa%ٻ?ƻmn>޺+-ox6&P~fϚ['uB neGJ`d,y' Ũ6[B@˴?(?|6;dC"sCJ; 1(wȇ6aѰ]ɨIiNF-N"+md#zF s"~xKJ4 U9$̯``|HoVbHV:x025M/=6ujn;}2):7XE`m>M7a-VItBb3(ThwFY C`͞]LXԊr*c,5vu%1r5PY/P?YzD-t6A]C ʣ"5WLuvEQ"U;*_oR[{$38QoAB)2=8L%."gU- %C~Ni^ ϵJץ2/K KmU|?F)2ÂQR;C)gBf mJ_CÛ+SXoVb?-9Q(X7'>|Y]@lH%Nvi$A?<|]G>V 1 |P UO(G^Np*EeLѯH[$ހ6REhW7ko"; ? [Qɚ~h,(3Lo ogA Fd&VygšP!۩pcl{O yIRj;?2{C ~t%/NuD[[HC=5nZ<~Bn5'Pnx0rV`*5 _xalƳ/:h١Zxy5IIqP`H=87ӗG 2E\Вowc/#}Ok$,!ԢS`ƵF)Cl#qvv݅!i*#RL 2f&6@l7Yu-SbhcԜd.euCqr6 +n͐&ʻ`K H9QqR\=Ċ <*;*92PhSw˴TDQM H`G^)rhCL1'hPJe[$gx3\3 <(vVY| (z1Ne*G[g߂:i~"K5#ԍ}B셞f(&dI܌:Mx3J~:~q|O buqʇb"u74~/Udjr7ȟ.ԤMNdWj1ߋ0LJ_)~Cg#!pN0]_Q))W0ᇖ-KZq16@+nVɬzI- 6ɲ0F/!a$0ԯQ,"WDEY׿r),MvLx yyG-n exG7O⒳G 9"v~ Qvо^?]G+Y@7ܿSU~a ц(ʚ-Q'}YN)9*#I{fM[ũ|ŮI~V}i8 ѝv'DC έN9u!vBMm\o뛷uq>o_"AJy\moı9o `q1 '<ƈNaE"Jg*bKdA-\BMgcyGНe̻jd!񪤮sؼ~k[Q$Rܘ/O :م '%׃׺=ߡY7TnӪg>lא++oÎ mWƠƉTr@E"ϒ] EqkyD$wF(\&pl4-YE )O*#!ݡWCWt!q=9RuuUSuԽ1&T K$\t.r ! *̋ݖɸxBPjL3ΝT1 rLed1]SЄ Ԯ?k즧E{ILQlR gZ #4 ҄=d2>՜8jQiZd_[bIVfŮJ;U3XkG/Ϝ2/It/M]ee =SZA쫯-7RQn#^o)33>9JMŮ^O@`@ 䮜>o w]va *:KV-jxgbK ERB8s1L8Aێf:%?4N撱gpr,FT݂oJDv K(_'<_])k\ӈblo%Xw6ϋGC'D~_(11k]]y[\ǸAJpCO!e&)FĜxVډXPUE34GVhS#8FŸ{H3jNN^y=RZW5\#; 5lMS_b{vME1ȍ(~v43~=w*jl憪NHG"e,M0jedkkS~S /A٥ VusYz0L '̧^[C8vQ` w /zu[" 4?86/^yKcCQZA\4Ag.1b&tV"{G(GƸby3jYb2eՊhw}M$R75Ya|S?wn߁&\Oc_gh(_/ ^/W,"u|?~f Vכyqlܥ8jp}M[>y;i7Ygu?[!sOjCSC t{:2y((efpDDU 'dPaʽ([QP("G_[KMӅՎ#ñ[KBf~ڌX7AKs]ON.io.CӎE15RB~čw&kuxV]סJWԴ(~oeLyf} 'dM!"'W5 SP dATHPM7DA' Ml@%tM* {u&c,FfmKSGBF51<ooh}ehSɰϹZ?cH͈wja G^}[olpC)nQee-Rs+&tg̸_D^ xx^ ;.t̋t\y4}"a̍OU.x^:m |׿|~F4FҥfϴSF#calJV"N 2 .ʄO,ĔKtY>C _. %ןwiuR\hϋz+*ܭ.Г we|;:`6d" eNn17~9oS> ' O= E],W`{L:ǧOL< 98M3&$JiBBSO5B uŌGJ#2z4K۷f&dO&BJ{lr-n@vVR뭿}({fQ2be"}\5V;Np橗.tQ} )DM0HY)>h£dn.CZF4.fȳzKpBjBurȣuЮVs:EI6DOzD\ƬW-QS-@o. fN+Vv{sM1Ĉ*&i 1GK2S㡫J_s+Qq+UVkivSڱ٪!j{w}`UqיO?z}@,tjLi-In.#vIoQ. Od>-ۍ@jvH ߗ%ƅo\Oj;I!PL  u(@vyDcb,/m(^*݄ M8KxmYp`4]b2(+;^/"ИpEE 'vPKP\XMUQE4R~<x̼6zi OENm R GS/xȨ ~,fH04/A&Qq)5Sd߉K:h]3K6-£Bc ߻ySpsn+$f)jqfWK]Rd6*W:,'ζ{ܯ;T&XXryZ_{#L;zmLowcRdt?E܈ &TQk+Ղ2[xz_ˢt mi:ƶ>1a%gdxpZNSt2GbWs[>Qۯ٨x&n1@՛y~'hFJAyzT܁Ib{;}WWpfFPl0~k$k| Y/qM Zr3/$Iዡ4 Dj򻿦]G=U`|CWpoӴAx:txT6m7]YbeŏSئ ВZ24FnDM%wH]o ⏍n]vĪT#(p#|GS1*gC0bG02~ vY I 3ZemAXI,0ȜOטP}7|o%Ek0Н'2fq'0R!/M]]A5Yh;F hxB,fH\nlP''Ҫrй<\~?~OP@"|_C8r;*oqUa\L>/D@Ipb/NRUb!U!FeeY dB}DNDkvasŏ2l/@?huOƻz0KriD-wh1xi=&UAC\L2iL&%P6o:7n!b ˱8xGeb :U) KQ{f; (Ҧ(DQz6[>r@h J"AGe͙~,ᶍXp:pẵ[&s < SMg#KT뮄+PVhf s}8$R/!"QTF'&m߱ KVº~b9'. ND cS$G/QSkA`cBňN!+n9igu7\(vQlasQ搬Rm)#vJP׊?)ɴ78p\ =7Z|2%.Ӿn`'EM%e}wKx~?A7800_eñXS1'B0IcG:M,M@sL7fuXr)n{YJ0[#x{,l`rj/P1a}"gcaIp6yIBA{o%_T R`FZ0kVmwołXq;Y!jC;lZ}!'o}. p!ϵ2}J@\dr&N2 n4Wu*01%3=plccj9|8yN;opNG,P* ND PkfЌ|:1O =W~S6 ldOFRblr_mؙ~0uAc%M|wC,|fA@x5>ڧPM[ٶN)IJR%ק H;{t2YPjѼܢ_#؇;h,_ʴ=D'H=EP;|Cc={o}ė"WvfQ, $ zT&3 ֚JGk& }8x,j l,ȡ38_VCõEɐ$1HƪMm%zHSQ)I\}LC|ހX%+ϨYUq6rֱ, K̮8 -M@T%\=4[ e/ cb4O#K/y `A'^~Ɨ7nی CI |m/PӲ6lءrKGp&kȩ=zY ޖqa TkX#Wk,iϟ֭z;}w|ZKrLN[\_>x+^_45, .J|"V6(쒓XQ G6FW%()C ! Y Xќ9@(K"!pghvIf,/=XHL |9})(@] n~dSEXZG6T^ zQa 93NIFVJ,0jφybYs\&Z#Xb 8.q?vP)UR"5RԹK3e8GЉ3`4S@YP=\0Kխ RmdT2?肃MJrbS XZW&26;Xs3 dUN n闾W^+ȍNyEIƩ>g%j;%֥w/ PSup>ߞ>>/#Ytǒ$lvhq \w~7pQ,W 5a̓˜}}e%B20c? UYj@)jO\=yup*73>eTF+nDf38J:@Q/rX#u:}ã<μ Vi[hw qP Dau7.3ݸhulώ8uEfS0oÇߑ>T/hb'M톱?a8BMԛI8ޓy(s ]7̄C2'$59XԥJ?WC(M&D"z*6U1q[3hɁuɹVlX:ũAΑgQڷb5Nm^wyߺz;p雂 ۿko FoK5Nl%``z$}١<@n8Jpu>vѵ7ooNNy&.fU1v;h65D̔1)>.`!rNLEiH}J?9xeS-=f%a\ѾSu_,R8ԲA \0 w B=sf 8S|>4兏˯|[~']m9t?v޿%kLZ _jf''?lPٮ˒]uo{6fhlJ!L 9_Ɵ }~kuq7F^E)Z56iLRF2.ffZ,OЌ یSsJs(,Ae[[k{`%gu%`!`)H;ewJ, eH|lc\X(V[𺮾p v dܻnJ_q#9QFՆavͿYp@xyqlH@bu|:q} ^  q)Uc@`3 H;**C^d\ s^Zb5OHeHp5_ab$6%%śyEɲ '@ -@ '򐗼%@Oy F ($bH$JȢV$ε/U/8) hHvwUoS3s.+K)+ƥ}>u]MU= gM$(7Fɩ*:D I5z[HIAUbv,!\4LN1J9 !.s}>t.<{?qKkm0մLazDåV.Ȑ$ jlQ7ga@eU2 ,bPJe%`7#jޝ!w灑 BJPoF>K$㐺ؗ Bᅱ(|: f:͍FRh0ZkPxboU|<wFXJ.8ARO@{+X#`*ɞ+}qJTK 'Í- mTd3`{wkdHun˙ Ꮉ?yZ%ULD@(cc ɒr,@׵v%sa!ˆVژH ӦS1N#i!1cT\Wc0D#9qE\:L<>=om\W*`A0(97Bʑ4_Հ[mPB[uIOswtESSBϚyl™:w } hf0-C]qm=?SOCcG\ &f)…>td+ʼS=pPmfY޹ j:`&Wؖ_ӝҙN Y" +y+vƞ.j6ga_p{;Udj^KUIGobPU % `z@=<=Iu{d`?(]Yԏv 5 GW{}*+LI݆ CgOn$!OAz {f'+o兽QVة K3[Ůw|,; E.V<X ustGY ul7bJžW!.c}+v \rQ)!PF?p}z%\an @uS|ab?>W"D[^%ZL8w>Kڹd5H fD:s `fQt:1)-MV 4Y+x ^M~}5[L gy^qĚ Cfc}hcO>cSmsǯ옳934M{4WXROa2swF])StYKq9mF|,bpzLbkEbe68kyC\d mI_r:~)Q8y uu%^zMoʄ|u9ӃePܕ/H`ff1"k{&%g .Ʊ>C$ ++I0JJK[xx[g$KUP0yyq S$+c,gCT*YU\a9%9< @7#` SC"RY.9"]#mμvmˡ@şxV"J,@!yJŵD롺R\`i8@؞ľ]ELb,DKYU @0m xX%6\rd5ZDєV S#8_T}qHbmx<6c^;ËolakCnޏ;# Z JHd},ę XR gN`&>4*Fl<8޵D G|_d"pm ZewgErYA:2u2y)H94J'"S#l,ՠG%)GE:P1JߤZ6$ 0[웧Y0w p ln]gڷ8XB@Ei&?u8F 9G,J Dկ &A֕Dfb]^1-„܀DHP;B;M JhFe2mB)Dj#Po̔c&KOOtyKOlj۽5B3 %@ӽ>nKeTl [zkS9.LT3Dhc 353483J3=?,@X"0H6e[ԑ62or<ɭÑ!ʘ ϿD6 ꪑ{Ixw[#%!]j±[N1%%b(h"Tm3INmk$ & @㍭?g#߭ߘ!$$(2@\dusVBkc6Tzԃa-QYͫ:Nk(C,8fa_3!)KɰR٭tPK)m:N==Q5,&ݢ11'i>&)h ]|-Ca"D;`΀SȈht c1d-BP$w I T0%1;/L,fxה͖+ثT9qMggYrp#%TL՞N3k 4Ņq# Yfd3 VU*[qx֒fG#OGi ".12UeY?y4ayu w>+b8F N1b 酭$3|@i &/Dt}wѝ}SҬ7į}w(Y6RV+=-;+ D"͎bBR_PeVen|9ɹЭEtq'!\~+^#*53l@r'nb 5.<ח RD*}nqU7&3] C%4 WEmd7ĸidtZJdt?TWf !/p̵c_oׁ>.cڃhCsu*xKfv ny٤w'B(@j$ѝ1>E ``fxWY U^GOg<<*N`]l'+?Y$f1 A@f C@=>02, Έlztg92ӽeP>G :BKDCOV|fc_k<1tMRA/`049YOFqep~}k WbkX)*۠FJf ¥2m wѿJ{\r rEY K~t@ @XdfQ ䷀[ xx )3(wr1(]V&:j"WA3t4.`Ǒsb_*(o# m2te!a*H,D lv9⸊lM[q4az2'  b  4lr]}>t.?o~ӽ4*UMe0sX"V|L$%% rsb54XO--N«.^?M6xXQ$t%d`#1\!bhY}益~Itߗ4= `#1`@=Dg rN7>wlsW SAey\b2L )f xꢣFT~3gnq>/DEl:ғJ5v5YJJpBV;hiʭ`)o }O8G,1׿KTvI.9˜\0Bi//A;E_s ; lRt.t^Vݓ2&Zп3幕9b$st!=pv뺯b,+uM~v}[hNcDZ,&xz4pmB#Ss!G^v3o<ώXO ר~G$ɶlSJi&-uf&h*b 6"Ë !}*Ujըeop{t !V0"$,)0_N9[#撪U2wgh7e)[DCQDmC,/\\ ԥ'>_|(z9ђw !G8,rzw>U6͵Rd $z#Eb 8]K7䗯`U*Nƕvc 1&-y׋LN<AaL)x:6`\+'3q4-3jbZ0ISϙA' ,1CÓ b>{:}f[lph$MR:_mgi 0}.@"ǔmRtX $|^.s? I/qSQw(7{IPrv&0tzx"k"?jpUXq٘az<2 @}p8 vz7> 9}Vl}Fxe:q"%P02'pO %Pk'>QCvngxKWǗu {mmOM}6S pV>%E܉}X@+ΤIu C~lOoC_COp+M8-EhN99R>%G+r~C-KH^7<.<$owh ,Xw0P::hpV$B*|@ ZL(ә6i.Xy[Lyye[{4tc؎~Gh \K/9P&vS0kZ*FMwx-$6*ѩ9_@$ű[XNӹ9:|y d6XmH1q9D+Y(0 G\[Gv; ħ,dBh5 fĭ tq{oH[:25bj w91R-9 $L@L_a|S(i&8A c `ׅ`nP&J]u_݄/}B/"o~.^.a/CLWޅRw gtV%K]ҬLe&hP`֎oX,Jځn< BŠDI'ѮTpq`M2R1A^a@! tj^ǂrNI-@QH!wŠS$A +`%' 34Οs0D.&1u9'ZY;_8Q_T2S]pƞ|dG?_m_l kNSۇ!pni1;n&c_GE%9I6O"4?;M04y_ʟrq޽%@ᴰ!sOvbk|4 /a#b(OՐ*测:;k~+W5>9ޠ:h XA=IJLi<(!mùm.rcw]\zV4Zg!4ؚ`Y&]<HAUN{׳^dЫ>3`25Ӏ|!#t (i; QWL*|#l_uMP 6WQWi> GiY9,(Al-R %Cl?{\u뜙;s|\)R(Q$%QKvů"i揶IOEiQ4HkAhI. (E&iIq,Ylٖ7I"//l`5#,{^qs.uk]r6i6{^`Ȣ%&X]26Vc}"Yi@d ˕Dvc\;P1r&&|OyEP:ڤ4eEf`BY( d3faqsM/?̊HGw\=aP0$ʶuGIy%Wr8'0;`l{2r мE`&t4I/tȝnR4.-tz~a^y`Aw-Nj>B c"re((,ȋL0;pq}۰$2s@!* ^9oݭn_Iv|=4h?4Z:6>4!D$W9қ334Z#2wdH}}uۮ*vm(`(ȁR~:OHArfTf!dz v?w O~j.QW+7@@YƵ=@Qq}L `k؋X,q!0Ǚb7qOwv1Iu L"4ƪ8*xJsH 1Ћ{뇴 JHs-bd50=M`k =\'3 q `RWy=P͢ø"={&yD䟒w'Ky /hq 4£>mxe Xn!(o%d$P:K98X&yR+4T2ksV!LVD+6.cM D0,ب 1#`i UAû>u>xtG<6&[v+&^!< 7ft3]?Qn=6!@MB3P12\9g>q*YY)--UCwtlqۉIMt*rǜ#x4=AcRډp32HiC/' AgzžS}uvc}ڇ,mid y{2);8}9 {&y2KR"ֲe˺I+@ ^ #YO $;c6%MW vflfa ֌ мE`FRJD?BDm "s&- 9Q'i3ɷDfsQ8|h@6kp2z`S㷓$3 eH,bbQ\<˿p?u7/`>(x*"hn@D 4aJ‘5;s! o4#h}zR;0=/tuv34(@glFJRpbL.aկup k# (Y-,-Y ]&I(-h,pc߫FC6rQ)9//c?d^fJkzpb7!$ f'f #`bGVhI\MxX6hXw=Z_fKZG#~0n'@3n'9QbCVSvI "nqv|AOjU̘\"V|N(_ h p%㼻Bdz/RYԬSzU.)g8,2k"qǩ(/=mqSLv85 MI',uSRFC3^<Gq.NL'WǨ.Ep̄kg4 l z}&ӄ|'nC6 ;cnq=+~Co{_'_v* +؝ -M5r6 *>"S\gw7{;yL;edwhwY *Y_ͷ Iڋwse\Lȩ a5@npeQIKs\7;l\L?^ ̃G,<=q0I2FLIvSiH X1@frbo.aK "` j4D !!^eܸg>6ClvФ. r &. "dBblFXЕ-76)-MI|Ƚ>t 0/RxUsA0he7Y AKQe8͒] 4ƪlLI2rR+D+L Okd/jB`j2M h@0 Uedg1P Ԣ5 C+7d0Ky쐜D(apcFM`ё &|Y#DXk=GWx5=Uοo_a55%Jh9P=2Y),[VM)ԎF2JeQHΪߙbh> W>J3W tJkf~57<}zI!&HO>. plyš6L/e!0-3[2B)/>_%,CtXo6)kE1襹3(c4k `,qi~ẹGBl`v`i ._|,J/M:=E et=1Lm0w` t`=2P0 E>!"˛ :v@Tel1Xk`ǟ{Ѿ[0^t8 -ۍm) kZz¨Xr`TD({C}I8oOyyTb>1fmmdeý;Ef5Lr) ;9[d6t;c]?} ͑[`º nMӴtz*5&g/qT9`\tlp~U@ƹx`f14߾hҫ vFR<3A ?= ėO>ڥS>(sw)QlKKbaW (f M&U 40Ej\O\`{NdSB*6I_mxDB"dcOcFuY@TQ[&_CxCXFL8ŏnc2-mvlQlQɓ \ϗUےu:"o)EԱ 4%ywqS=d*#jzkM7i(+opzҏ3Iy,Ud%(*>ToOٓHLxwʟ…C7^uây`ihhz1;SDJΣkղ =BEc\t]u͍l~}gDZ:&u6RI](}`;cw}VG;W58qðl1b3q˄~{;+%53Sk &2Ir3r(w~bhQcu@?q2R"Rdzvzf^_,sh1&y[`WIL-&::hUėyַIy/蕙22,PR;o8t_<8OBТA(OJpLT3f:ҁGܧSjkf)B'tjy˼-<}CzݮGBKtsٖ giw}p$v`Jn%z#v++IAm4`dR;'OQYy+ *^qf\t=3 TvT(mUKWx͓pdzLI?CkM^%F JAC.4FR&X,W_(uq|C0?1VecSSMt\+_(f>zk>RI`mNָU{M.wwZnmFGc7Sy07M:h Ic{ )X5v]Jfx sc۵zkf`MgGq& ^Kn5N:IIRfm8> *{V~M7A}3ri_bdRȑR6H&`%Vlɪr~@{`{^xQhyefd8?ȟ~1]z/GY4 jlOs U~D|eŤ-2U7;2jb'PZLVFYZXs]7 1cj>d1b?K7X1؂no@#cIKR̖Q5hy2 4ԡ} 4Jx'&"֟yӋT ;n6 tV$TvFc_IzM T *ؠ6٠qWCc~_ӝ?,Uz6,ˇan_zi?[7>x|{~u~k]ij$3a: s&c(ʕ]̆8w4=N`MȎAi/I) zCP"5;ۅҖ_&ƯmS:'h9l1k]gYEc+wK*|0.š&͜*7EIyYX"fsU;׳c_.MckW۔˛b4+uCH'Wu1E``4At$ʫ&/wjFbP-BxM/3놁t>@W?s_ye.i&siO[u{ߋt#]B;Q{9p!E|pB͜ey; mF!\š81d5;Ǥ+C#ztaژ}B\ ٸ6b/ݵ\Qg@xH*",@ƄKљp}I' 6@ɿ&ثV;~Oԙu,\'Ǹ齼ك\y}7Yȩ-,xr/Hax|Å& 4́ PBʞ/~;XҔG`l$s1[ 1X#1l6hٿ"0Dwh+Eaa ֝@ (HYml28ѐGցX3=Ik]M-ׯx@;ѻ]̀hfẟJlhnN r |3q?/xcn;Zc M)j3afc!M`5:?E EM`뭔Z |3[K4,Wy/}A/pHG{8d`QRvlO3ʨCf_,kCZ8"JFsc0e7.[FZ Xݧ#yG`2&kkŞ4 cdaς w-xaۣZR[wnWVZvUUv/+v1N&n@.R!xx EVt+C;"ƹ8NUuNSok $4Dr؝Z}ƜcEM˘u>Pi dC${HvmK= BO4Gw]8Lƨ =@z2,}=iS}_gw<巾^+p<0/zsd7}陮++WJt>v}= J`"O9?LZ~,5?iwObf$ ,k:\qҲX O}X4cPh&mh&LL푤`7CC}̶JR3.L3@IN[ӣDȥ%R #TP=zھۿqk/wϿԆoAy.0dn.K ym$Rʆ\UsW*5*z h, v*\" uu-y϶@45"EUKV*1l- 󞂆?LpƔ1g>2փ{ϷNwУKXSA1b 8l*IR5-]q& 4( &] v )H&U1?a&x@v[Ddm,%Րl~Cۧ"}Y*JXK t]TA6@^nGflWf0fKj;Ԝ6_oO[Y}X0a؍'DTf,.G`,RX4\vfqH Y0=V|+:[}zSF}1.lCDjĎ LI7OxJJ*2൲D2aJ) PpNչа!10TB‚lI`(%,>~'1b n0=Zwͩ N;Ѻ*ۋf-:L -V(ǝy BZ@UܬC2:ė?9.=)K(=!ȥrPzX@)y."IAF" atق:#dk6x~g'KT4 "X&(9=n _vұ3<(+P 4*5ŗ~s&1f[j4gէrgaR:%-=г6M2à?0S'p $%T/Qsạ̊́nqE_H†*ɘGɠԘRJII8,DI8lJcPZUe%|CȒN :ަVs_ߺJ|{/=^cp.]d GU*ͥO,Z SJ\{1=ANn}b9h h &][;ifoI'd0jH_4,{Ic4d4[XKjuLSv;oZ_58rz5&DM0Sb /TJ]QguwXkRa#M!Oyls/4+ykfv Gh tF:˞<[Cn}]| _wv@2zoYqloT#˒YJ9K?Ƴ}-H~sf94YMR3ڶ  $(7f[WC.AyO;p]QI@])f .@ٰ-yEZ7fp3CslSq`3Y;|"vfz<2f4z i-eLG<1MoD/wBUiAO樘0Y<υwJ@@',~KcUaARSsmʋ2CUf sːq*RnŹ(p.\ؘ@́ u7Ŭ"V@ :_ʥׁ-ˆ4[p !ɛs @|_.*ߞaw2-+Ax4IqW$lbԣe#{2K/+hjhHI>XfbZJ0( np1ƾ7Wڟ4z*Iʠ qQl㍩DHyts篾r`/S!ZL Y:|)Ds=2Y٘IBh9@)gBwW7?uunw$:!h]n3 %n c#LV +5UU5"c<14UV4 yTZ@c{tPgT ()\j_\wVg͞^@F3& )]vO1zQ!c}f,B0`z8 _z~qS7=EP(=2kS'S+f!s"׹(yDeW{:^Hg"N_(Yb05;,񽋺iݪ,  y S8 e "X˂?, c&鳕XiۦcOݧܻaN+I0ńJ7{^\+OG-$vPߢNS!"Зճ1J%v"4 'he\\ 42/+鞾"0uY0$R:W @gK}|h8Ð+'|w>΋/ϭ3 ᐉǴÆZNoGh x!,IG5au@3OnI1/!<怆2l+gF9O2~*AJofb*@<`Is}~[_Y^׊IO8 E#57 '!#Fڟ73c qYF2mJYw?6]_hC'+!]]PTUeSZ @&'4D)dX%C621&$-DX @gx>~6N pϪa *-|̒Mfq{~ŧ)XNqǨu $k:>S̝M^z˰ugUlcH Vb̑JҒd q"r/$3{eMft]O!MtQQ؞ v &o~{c*M] $act.+k 9jr Č+440íKK|ˏ`3K>q]5&F'$ЛpǼLLV"+sychjQPel $ՀB (sȤHҌʚLI^]~?1zRkDZI ";$](/z-vgRøJ4P^4{= t%j MDҢ Yd% p_\GLr1$A*2 "Qiɬ쩒QFZ(GX6YfE~Sh2ʷz*B@n=IJlW,V< N)+M|=}@ 6kKهaĎ) avP{7R˖j)/1ˆX4=4E3=Hm1'1OV?GTue=P>ǤE1T" *g4( Di$*pGͭwɲ>Xq&T^DZ% eJY$ Z;GbpaO+] #g ,N{sc=ȓD{03aM+5 䞓kMuq 14ndY6]gf,aIZgtW ]w.5!hQ2]A(1ܻeu]kn³ F)a_*Ѹ@&I,O_ҘV ARd9p<Te,fG0]D':4@%8g3LyN_pm19p[<#φ;HU%="Swkwܶp(`fF@"bvL]w%趮*LȞ.l"mGo$-V jfTk#Y(߀#!bcb7mK)ƕMGjjG,#V1p7 4 bW^% &NkD8|r<˙Z.:1AB2N@2'NjLsQ*6O@Opwq. WH\*QŚ$?__bw w6=Z?&RNo >t39%5TLi O ò%2 d|8b@'=Ds9v"PbdB >,xY;wO.t+;ԅm7<3*s v@5 _^c,$e_LS@CDo.H{lY z^itE A:!RҤ1(p1F$,|ED9]VN+Swb#C2R,ا) #TZXk}_+sx%  (/+@s!g{~~K]~Wgrg6 0@ fBxS 0c -fQ^Ll-o;/]8&j|fQa;/<ʧۏ6C|7hj{ }Qdi]*)#l?w&33Qc{ FĪXȏ&og{L3M.wYM},H LwNN~ &\3VHD H+ 3Rݮ[}9L Nd PRDZ\uߟ6{{C7_HH1oA.?˞En@]W6B#[uO뵧>nsL' DMC$Q$E&@g$$ic&nh!u@ǾOym>}ih4Ǟ{ͬ8䊚 @8DR#d1tNX| gu7ToyzS.B,7 P#PI,}k؞`P1ݹ?j?[yBϽ…KlySh)^`ȑs?Een5?p6a(FLM'&  41nY0iLc hUI&pR/y~<:c]8 /,S|2b k"w%9~T坝n9[feHƝ1O냃$ Zb,/P@Mi~&T>.( n-G+wdK3nZڽ` m4CYiyYq]a %a<%}([]:ځT!b| =6tU+- E7C+%n,`%/=yIKONWNmsWO]%(#Cce5fQhfBPm qHFRL< I@2"#ez8#}#ÀU8WBYU lG9^sjvݿcD Dlj^c>3No>!& `1d'i X$e3f&Hyk (+֗,GÎ}@b-(;^a.1<_ Gba.hfr_J.ؙ 23tM;uzfHybKKO q1IqH_@l!1At(""K,Ifo 1n &xN(2w\9;8T8K"؉z.da*$#65,sSu~<"آa6i M-=f+~~sZ ҂f~Y|j_8xS 6~'Чjl;|_o؉]ӥ\`Ø9*3.,!wAnj7VؿxH'wj`MD%Z,G>1M:g01:@#VUϟы=,PfL9b NL{Qf6$z/uieD'J)7ce g`\$۞3,kľ疶%cKsHZ dsS)䲺t6бUQ=YmM-JK.Kkyy6 lu.Δ| DAۙmY&Q:]D1 up#)5vqƣ0Gpuwٟ{asg@.`x!9.Cb UUv|z'_`o\0CPb?Q :$eV2)1C/ѳ>rGՐOyx`ŗO*!f1`´z ||䂳de# t ?(n>m- =2ف?G1 <ރqWx3yC!lQRY ECYJiy+Ѥ1THr:[Ul(? Pcu ֑YG8GQ ~oL39fƟĔ}4I%g53?kgq0Xq{emn՝>svu|֔1e,J=rϜI:Y:+] t%HRF.5yeJ4!Ԍ @RI5 F ~3=``<5'?/(: f(%qe@I3PI%|G~kWu!0423 "ؕTG)(xt`#\DNJ~sV۟]F;E 8Ǒ]g0aB顀ҷ&ތz33Rn"j   T2KrcD /γyPq@ !@tY/'䟳@ȉ)i޻zx(Z}mϘzuiOƯ;@j;L~>̄%i`L_8㬌#t0jrq€E!Ebjt|Զdb]^)ɡ &B*5 `Z>6iL㻚)@ 1٪}`Ey8ɜN5X|$13b.2ùW s:7j~(ʮڂAmSJoxN;咳.B&`ikP6w@e֌l[$F$0RHj,F 1#kh%N3(飛( ,eP[1m!j !|/rϿ 5о4Cm~P%ۃ z%v;Kci/W0TGf4FuAI|Uz ܬ*gQ1ƓnwL-j8⽩emИⷮ5F,}{ H~ p#ZLuIM&"ȬY,9W7ݎv}GՎbW9r|ïv+{T%Q$/R; ̊ӺFGm{yʹ=N0nex!(LL čF,ܕU4s@ljd9iLTFR]a*쫟X(ws,NR֒r1Dϫ6+_X.\*݆b9d %)-%Z.t 8#7Yn̔  {j%-T,wKrD!\s㣒Գ9Jx=هݴ'8Sbl\@%w Q4'3J3_F:)K<מ5fS{HBNЌ&)"58*eP(3фmO#6r1o;>q[YG l ub@10c-H;sߑnUj9M%Zkڷ,۝t5dU8-^--fɓuw}[>:mt8J DB R^#]"+Oda628Jr~ɌV<6V`S)ZF&pY ,%cXLPynR yO$>M"G;X7@9tεke8@Cq?@Ts16Ny Im0;HՋ_z_M8JSlKdENڔ414Ds" qc~8Q], ׏ }C1G Ef,| e`045ЗTL0,K=4{w6)A/ -vv'򭻒\DJj 6&ػҐP#} P%Vmcb-{]~v~c^"dB5&"1y1Y"3[졑h$F0V0y!KahQsVJϕ6pE^,K咹1]d!3J9ڠ0>p瀗0{8_[iv,P_綏r/s 0G jĤ(7bߕ@KwOC|.3?19$fmq@`oS9W>sy23^h]E(k6OcӘwhl*BO> 9&KU5BV#ޚ-hbv;@ 5iJҩߙDjm6do`8}coc~,/+< Md:4k b)G{gȗcrތpECɌ~FH1hdu5l7e'K2;W#Poj{.'sw!`P.JJډ}Oc@72YMN`Glp l0CĤCK ^KKouR|&`*tS]|ߞȩ%ޘ(>[1yl?˜AMP0S%"iոk׬pd¤sA; 8)R.!7}cKlG @hg\qB}{8GrGf]k-,pT_\E\}5Upػ EY03@(e{sM۶iF.3hMm>xH=c+%C, $c D'Kr324FPČ@ Rx$ࠖl aRKg)<2XZ@{s뼯o}Μ3 gHon)ŖdيK\=4( nhSH[(ڇ}I"hPh<@)&٪|Dl˖%x3۹콿դ=Fejҳh UP <׸S_MbUƼ1ظfFnp't""`!<;u@48%',ld j"0G9E?`~3/r:U_b)yc(R^I^O0]܋1=pƘ;@ vB j0H3tI; n&4ٶ9K (nK΢/!z#6HdlJ ZΛC`'\GD쀉AQT3'mL[YnfiF{(|?8hH!s&4RbdKNlLnݐ8cY /lO˶moII>Pfֲhg`Y1"!"'.hS Q^va3awGFS <9en#4 BVD=[ ĆCam,|~Β!K4(N!41Yh[w< 6wxmE1,':K>:% f/2rjPTI(;mGLy?<&cP"$ Zۜ8vꎇw9o=W|'h0탙b)9dqI]SoTֽt-K'6XFc\1d: ^ti)4m2 I "(HlYIuV; 7I%gSms@>Y84B $ |9s\Wj`;1%5(_e+o {gSC9aSpW760%m#I#9,cD ǶA"]qMu!"X*%4Y4Xͳ Lp$5PJ v Rr6 &*` 9F Fn~ѐ;:Ll,rnKv22XA3gV5Hf{E|_fQ5 aXE C˒&Xcl #rJ}# d%昶=_޹ ]<[ǧɶ6[&jkfl666M67۵ٵtדuu|\؝0Y6xaL䣧Yʝ/gsc*R6_UAej*"WAt 8&`w»Mя|pċјLAGQ6M@|Z1Rob.ȣ@cK$R@{60U+?.7 Oޑ>LJP7o.fifО.5^~CҮg$pgX;a5~ٟ %ͱ;CX3ʹfG slزS\?"6GO5< uIROm( ܊ƚϰd $7 LU$*bURtZgg*}#K|0Pnϖ*rZjhBlAO Z"4K@h,g 8$%. (BN{^~OV!03^t_ufmtm}h7',Lwɷ[޵vGu_Km U3ה ([% _P`L*m8w+=3j}-Z ,;ҤRJ'l،cvWPGd)?ុVPG)>Iu4Vzrj{>|I);GX#~|Xmb8L s;* kR%ĔmQ|?:%ey1;b.Vy~Q<&cr`x]pD5X nJ20r㛭 ܁W*%Oh/CvdSzp8(eXk 㶠]Yۼ dEsʏWUVϽoIhwLčkc9 %A`0O]NOjg*6ÿ, !7:bT7W>mZO։zPpJ^fn6qNZtuZ))sNߴ#jHocpn-vmql@}8#TXW;܅GNfANBX5 \-1R\ qKYЈXuLNTY΍O'lec"0 ܍CS,W+`ַZj{WBђ_8C~֡y7yB>l"Ii_:vcH' WO5%H+Fp/M|^ކ!PcC-QTA (/:wd @ ^rkn,eТֵ2/ qS~c* f65xj5LX7ǔ0dW0(nN[_ǧ)V?0"גeCc(K݂,>_,$mDHM_7`B σդA-= X[\/A ,3dIρ!Ud!D(6{7y!jt4%d䏡qr˘3 heq< $s*C#QjШ0}XhĒ&RDي DIƤ#zԭ?4)H"Qp&I%kA ` rQo~.Ec$N'W/| /gl?k(V\;jTU6#Pۘ!--F w^᚛TlDEqЕ< L⸪1J¡Rfa ϣKzٱ31؀ d9_}̋BGIZnZs'~#/>svq|A4'A> ʵB]P8şX{>}q|Ra:)y{afpނgCEC5ya ax#7t ~B8w'E3?/l3.u.}<a |m-)u &|LomCO`BbJ4yx$7Mҏ8׾ 1]M d;Qv3K~UӚlAx2ÀGQFt\6Pн.PyUJk-lcC(O DL?6dSYVLdkPr=x༬{rc׳\+b&}Iܱڅ4! epfּn٥\졥eSYLRMG<ql\dsS0/󓠗 FŐP牍#FZ;ztax@S20 75|A:1yn`cBX80hi}w\=ͱ0QngF3:?LR7>1mTgjmle⤞|>wX ~ʑc B?. V#`}AIn]&ڔyYg~U+(~*%."-@˳wvg!Zoeن?=&B[70j%y>!<|k zSd @'j:1$ +m1m]>~D[[6g!6Y|y\w%"):X-YȾ׈P`hSYlIi *7le6%w@k޴[gXsIa P-3`yՏدf>]*A64=]WR6FM*qb|r䢤F?truREkdZcN[:dD2@cxHJgH1 Ll΍o/)5MF5OwqxWmV8ͻ\L((O٘eغO+ 6D_1鰒"v:;~|OXA`z;!e&1sp37K5--tbb В>g=O2mq?٢?~zyo0.^.!ax5GQog*莶nT1boMkڿo\0^Ln`N6텢dudCq7.jgj.O 9J b/j/m7%~R<UumA wnj'鈑NZ\Z_deש:Zs'c~M[݇?^H?>]W[p#d~Z~ћ"\M ̶l-vAX ? ͱ ײ,exP] !nD*(伐oV)Ce[[ig`s7 x Fh_j{E{IXtc &ا:&k\.t+ !GUt?ۤ<"챒tX$qLV ȯ>gdצLl*mN 4IIcL;k䞓"e{=B)"Y jt^͏dy5?w~mÙY7Ūh!.7gqT 웇$ 3t.u%_,ۤ @RVǮWc bgP*O73_NОO0Xq-{4PU,λj=Ya8)n2x"w sztf%y򾚶Y/*apk2`Wri@#v"`_j )yn~-A 6Mnqz+kOTn=lzܧNa<v>W| Sڸ : $y~G%9"eP:;a-xIar0'X?4U!-O01<%O_b'imqǕ V10`Um m7ʟ"lCE!ƕZ#ip|&^-.b~&b Ìu{"9{kPV"PA'65hV˰n|8rޮ]0X݁o%q3ꔪ4kۻ|244x{F<=%` ;R#6BPju4O1Va"͏:`y|ս٠7ĕ"ԼEQ%f(9R5/P$L)0QdόeD\dR U p)Rf B;d_7qdpS$9벣o\3tF\܍{OLuYc㤷ڔ 88ɕ-8ޛheH@({hKfhg]B's{TNPܠ$[ː3w ,L?Ӡ `O-NԂٱFoy536Ny#1t8V81 =4+ti;d>P|B|::$F\fBh2jA3ka0 Y# [H0)+ l9 ?Sx']}WFYLЖ ikl>rcnS!o.wh} Ep6)g@i_ė#ܮRJ*21)+e'P&aag% i, $S@/ŝK] I,4J׮-Yk~c8@$SY]s8^qU?^*pAڌ HI,0H[ڂ> p9.7`⶗5uM*r+ M.#Cq}˚3b0$>`F 8~}_6 __̼ .{jL(rD?jŃƍ-s23-><B;^\\gvPhTɓ(j*+0,=y!1Ц2|H[;R %W0:>uxp»J~G=Kb~:YT ]N`pQخ&jެO1#Y)M-iP͛8?Q-uđe-[@#_ݻ}V!b$iTĠPP6ۡ,-⋊Ŋ^>Cqٳd`|L5eM250DRgAXƋXe>6Vsjek8 nqPLa&9FcG;wK ۤ<O+)7/g3X\yQq+cl4ْ7xGx-Y=6M #` }p`L+%\Ԣkg9QLaVnԝ?5,BiUyT EQkO1g[uG #5$k XR@j.9C.n3 rg3}|ڎ/{1Ŷ+\F5 \1u^v3/c j4Eh٥jCg\O[E$vTݕӿ[e|gI0PQEK %&،!ʲ)o W1')t_iYZvQ xߡ7!(T %BF5Ŭ(s#9$hBYrz?߰L)%@]G TW/Y5`nYF6iA*s6U[X'RG>;!?=߰es)_.zt'&\7/\!凲UGqvSAܨ_4VzLI9 Bwt ')׍9SW @c5ѥ7[H3pFo6F )݆8f[}%{JaT~EMKLʸdyMZ 'e$ZeUdm(w1 ~@rVo`3q9TdRQ2ߜJ`[˱daITabYo_m/ SR^L]'`o[=@c5g FFb N姅0`aDQ~6a ǫ;~ϝupQeH|i߶pHD,JV :.P8Z$ƌNѬCObG]^D HVcm#[b}zs„JdF 6WUyHPXȉKaRQg a$W8U#pm ` fj=2.BWupʨZ4(859[Aue9YK/*9mT=I]hZ$Wc<9 ;2"yZݲ3Vke!g$1cY S.{-ʰ. N qOWBt.!f@zݥ锨SG?hm=:\7 eo]jN`@Y5Kob+ySs@&hxTR\wٿN@"7F9L"GR!ׯ}MćKx$'Pp)G}PX'; `~=ܕ]s2"qâ+NOTF4 mAR+eC g,!zP7(nxcbfUbYǸ?$IG-~ޫ߭*M azM\V7Yç6Wˬdqܔ/fa?;hk VȵPԠ׸',t"1J``XM0IN`ЇՔ6XoPt?_{L`1LUP@e0Oj>ڸ/>]!oau%hs.ҡ|bߔ(f\Bxc\-^-X C|m1V :ſ8d G)ls<0,v1rpC~pubq(#Q+&KFXw8\ԯP|CьG ̦N'Y`RK3.ƺ<޷ >n%êl~Ji%޶v|XCi=ID@^ל-u8n|] XW輛LG(To<-­Ǯ9gصBUva0 V|~Xi2M39Od|·m{Y>DOF'k ̥Qˀ2RfBpJ3s;g& "':᫔DGJ +0GUvRq]|Dv`1 ίo:a 2ɴw?)zc-!W?#Sn.N՚mĘeVHEb"R{|N)xwP07t-56)=/ok)fH12A$ 4!%.| 9 bCJ8Lg0b9 y#/tJ==[f\rFE%It6$7r038kΉr3 @l’Ӫ[k/E0!?J.5ip9ΛR@4Dhnˮz"s42C*$RmeS/)v=eH5A 'S.Ws7 77(Rto L5lînvM-6H.yK2ŐPKȱ$3UR!CfpZ,<RR7e"s  녩Y[C?+khf.0N4m9؉7VȎJaTEm*_>uYL (E"H3~Vz'Rz:п emd)ӳ)=ItRRR<6"HNى:̍{Y\dvN)>-^85#\mCV)oJ'MX \z4uݍ^X 8_yi%s<)u2^YHs z K~6R"w)eb?c:LaW~|ɢu \`.3cD!8"'qfP*"FMq!#j[]'#ccRŲF.賑g'ad33< @.^F,>l`D"7PH#%&߆>19c$}KXxCwkTB@@<Ye+tQ;RF.>6E;3 .{6gMx;vĤcjE)Ţ$%۔!oD""#tad1:Pf,htu$gl0ʔ(s,JSȀ3'7֬Fj(";c}/, ZQ?  U !1 ' #<+P -K\jpH@uj*5#Yq[ +y38 Ym5K]/LyY$;_X(h#EV>ܞliqՉ}iJ43٭V5w<#;>(ZV1,f8ã6a>4om05YOMRr \`*O' y="#"Јkr'mV=<&Fprc+f@mlW2UDuHdSWި<(.Ʌ|NzP bg=XSG_baܰ'kZ=YՊE&sAV4:`azC@{s,y)k 6?\whZ.Nz?o⋧^1I].]v* }XC\ctw~p*i66AOfN)Lkjx~Y|c󖧜b|Xb_ ;S4C6k[be13: $AC4 ‰8J?߈SgI)` TG˂"t6ބnS -zG?Յ'eP̂"W?&$EEgTgH=Y}S##jG%5{>Ս'N (+:ɩ]46ARQI$bPxmhܥaB'ok3H6ӼP*J5j+2FAB=kq 1B#ԐN+1x(]em$m8?mˁm;9l6, ŷV``ր>a,h @)P ";ZDZEx|]j!s K8s;+Ɔ'++ oOM@)ǨȀX |gzݿHS;(LfؘKI ,Y/|d>6BYb jnU MnCrjZjx&aeIy.Gl)A9 I&J&sGLu3&Ay+f(4Cb(6Yڄ@(qjU59y` hϘ Ør筳>3rFDVs"e&Xgd Ks~%vkP-/s@=[7چFyQųrT"Q+ Jb :AHA-|Rl 06XDj DiI{[;-% X~aLОg$--hX=x8r>R( mN oW>X&(I5 )Fum5L"}#qP*l@g er!+# d"R =`M4{.h{Y4 =]?WQ(\q:i+ei{k¡9Cjs ,А@/FrFӗcɚb`oLh)и 4zPхZ' U̍Sm7N:s lu*< d߰(&JzTdg %pi0{_SUUB#Jn^!5! 8=YoSaخQ-쒷- ~BalrXZJ=0hd("{H&ӛ\gǝ>qI ɲRfVZKEi8˕Li6 a*[ŔFI33 pY,(IBawK-7R> c*u~T܂\[쿝(aslb 8"$UzkkH>Bm%$TLCrD 1#ld!0B 3UYː \DZ$KX6 bZ)Vj޷%0r~PLE%ew,j!,\2m6|#b.)4"J Rp,H1!v5>u_^`S}&XgG#f% +SkuK0, z99#o+2aJjP "@I1wxqlr 9^SN>U]DjCUVb%ύ84괻2QEs])mmL|L-emޫ"oafG*z-h-;~DfSF7p'gܼhd[kA  3Eh$\"RV/ELٿVKZSvZ0qxp?QG50my98 p\娸6j [,RDE"Yނ仗|E~o}w*zvKL -na&f"|3_$z)xqh8if*TTxJ=h/VMZ>lA-j'^{m /6,v54 ݒ4zXMеj82r!1TD=QŞei;ӞD{*G=+PY-$RK^zDlQN]HJ|ap.rO=`nr7= Ԃc"PvV#I\l%jM xINJ8'.K(Hp7PA*QpM䅃̰c`JhZ_yQtezwmcj]6Mdb3X"2?Z,! *z,hP\RAǤ[*jD*\NUe)A+! 3Km@ShIy=ms N/A6qaujh@*eHeT7Nf[/ J3C->XuOD3x5ը><7 {_fAzuB "*-璀Z m)%}ZC"/~9DN8c7PˍR1\q+ݍ*Q,<ùo2T4谈8brp7D|44#l1r:(*Y)*EN[_``(6`wCH{\ySؒ%*4a 3Ϣ#1RO;| AP &t\zyl#O$7y״5Pxw˙s> >\0`]Y v^Yɭ-$ZԁOF#VMXX5v6V}I9.760\L7\T*~ιE߼|2 z=l_)@?@x(c@M1h]kHI'nfKZ4J䨉csֿZL0,"J"XzpbXrw#}xzܰ\`#X>`J}G_6P<3Jg\BAHCEba;mΠvJܢG0Zb3:wm@ɶU0C6'qFcI{IE3JxM:G4Ki&f9&7h3DмYw o]SQƄfIW @2 &M-2S$s3(ғdW!Lb}7ll+g_M@ ^QJnKeyo* ;S g"R+ƤJXLM}Qcz9>6eDtVM\M]~jw_׎/s-Coݣ2FB Y߯&Y4EE[`9=Tc.spMzyޫ_; 4ˉp[;ʃWjLH%+άZ .{gT 4F67&>yhS31e$6w`|~h0^< ͼ0dF!3k 7+gn@fɳX7D$(-]FGۣ;6Z@@e07"{e+3gXX>cŒOY̊7{o Xz\mƴ]JX^撓@sJ hA%k1˅ jf7Z]]pH=L[QO>F\ ~dsC>e@9(JբDbfk,3,yƭߤ!$#oAlB(ѐj" Жp]g˅YFr>m I o>\f~)&M_Usnsaȹ[;RlYmSc2F d**rZM4[B.Tخ{ţg/mBqy.TacIڵQ " e?3kԁpa !ࠛ!!ZRa=A~TI˞w/ٸx bzYa?'11"\5i1÷P >h6_›nS^v -FEPWelnDؐK-_&I8 z`^- Mԟ,{yr?F+7ʁ A0+l#SKQKF]2P[ҩ|^uiR1O)goS,;5Uԃ9MKg/IO!6?xk>[peT+;8h8IFpDȹXg[k{nGZoE7_/a^y{DHgĵ|km9a:f+bTq%r)h&ޠbxӖ( rs\lb]Ђ_,*4\l WJ^ƘiRk=X@1Z"GznjiWHT9af б4( j8 BлS"4q#ЙO(ixt^Jɔ噸AmР[k9_rPs!=c- * Α^8Ͻ,2궐1's 2<)DEŠ!)T >U֡SMM-5~սȹn*%"_ٴEtsBBgcޏklℍbmiXyy\Х߭e/nBl68 n 1G>=5=_7} VC[ ӱijɇ#A{bcTm0M-']WaѿHyp_ba!᭱'T7$bp6@6+ƹds/6w _W-C>=G^2ߴy1t٢ ֽ 7 Ԕ<=Fy<DBgu~$c*b$\LN{m ɻy]EL F%W`BI?+Aqz;g"k )'jOPx1L{T%~89uYN~PDΏRVm"$=穽?-7 ;el{԰=Yd]Ӈv8|8;L#a8v QeYM +AR.П3; C_5uo\(\drF6F)4[`|쬰;C?_y5ݡbPil ogy A}븟X9HbiWث7H)8x8N|ZW3T:s^%ؔiP"ޡpYr>TU%!9f7]xwNES:;-JڕNu.j8z8xQOvCWm{mO.l?bQ~wC*4j "aeLs.4y{t`4KU:qO0yVʛg38Df=JnG\`x1GGk*$ȉ{/tl.lqO3 dW( VeWC +L19j17)*új%#Ҥd8 3Xm?qҦ0UYiJRȝad}:٠@{ =zb^X1Y0z,fݠf.@-y@+Ynϭ9uyS70Y ut %&$Gy,<.gJ ̷s֩`Ed\.{Hp'uZ(k%?gvx4!U*2UbhWEA6 \c9M:㏠;?W 'C &&;圎ʠwp;ݟ-#6‰SqS ſ*`4ύAG d3K] F W|WR~B% p%˝l#z3yS틹>F;|[#/ Xy0ͨqP3Qv]dDY`:@[:pZ21ޞLFl* 3_Y}9Ttfj@\US2 m&66Q`kĈhWТtr-HY5Sn"fE؍'vM='NttzNF $I}4꼳ܰERW*sÃEݖ;Vٟ80gf3 GULs'skvS|gmCT}p̛=?!vE(#k|cRCŗy@4{ߺk_f 8Kgs0[ JmH;m6e9{Q.o L:LQlȟQxw)~aFjIiFhԣP' %"}  ݍ(z8I+Q̋Nc@㲈S'Bj#]'U4q"4-`o$jA\oxcn〇jgܙA8ezMC'ԃ蔷݇(-zS=Z2,2 5ӫU)bM5zONaQdH씀Ӥ'/5#&?j0N -KImXh&m=5g:'a >mRjdE,%t۝8cNk^c b kBm|ӋZ^S%29NKɡp/*L֒Dh -oG5x_FH[,A9٣ 8st53@r&A 2IHln> -5.-ο ܖ|ʑ:ҝ8Nu_&&/_:j^9O"vм:qVVqCqʄ"lo$Oqm?OYc'W9huTbO,tX Bc&IdV kvP1:\Aj~ikũU­{)1 j1 erSaYn-e cEBn*wMjuʱ(qkhf=baHMU~Px1 ~cJѪ!Xƙ+Zc-DED{eO#6܊C|=\4\<+uGrȼ?8n>9QJiE.'!XspC/eR)ÐLs`2Xh } EC ZWǕdz3Gi[.^zhmΖV3=bnAc;4W@ J*tkz=źJp1 Xv"Ư^[_!rcphR8PZGP.گuEp lXǿ.[IdZ[$0,['#Z, \|&Nγ ~ A2 Fc?, }N\Ԡ(dTg.o/]4hy`" "7cхUn2+1.,bjl,DB*!v" ђ2.:B"1 jzKԵH[ci fDD^K!0,=j\ܬebvH0G/=bwPVs*RȚ/c#'ۜ7_Ua:S8vi1ۂuq]ΡJq}?0Qy7:UY\F('U&Ođb:uez14ީd3ʎp|yM6ԄMݿc@Pܑ8UF#e_Qd\O}BKyۚSHʈ7(5q]4H`ZcSti$$C,V_I68 S) (Wd-`ߞ)15oZCIp@-kb!D*f:ݖeqU T+#nmUX 4pX~X$30WvFhjG =}afDv82#N51%F"S (Ҏ1='̈́k+}%݄oAo/*:Nzp=)z H=LGU(I,_p8O蜶2I8RYswiy9yD+/ F]nP&|G2H*Cfڢة'tSb$Jf\Ô!¢Èg;Y6xy!S6`ɂAё+/iX|hVzhshRѮ $ugvesvW9;b=fvi2~x[!z82yQ7Hҋd1=&EBÅ:6t6+pMJ]J?a3bSjCDvUh AzʘaCO(j{#Sm‚ A4R89>\fԯRj|4vFyZi~;X~$kg}Xe99iBp3;eԴR=RXU~0)<ņ6I*/mdpB̀1G*ŒݪS?ǧ+o"*2$[+F PK>CMTF,HE5 S oGS|uIҜKƁQYГbaٲOŦ,/.c6d=FŞÍ[H!6>4@ȤZ#D_Xh 3ɴ]k [8=im2` 7T#/mZo GCJNd{.%QFĘ%((Tl%|yĄD-%YXhsLYG߳#޲ǤC童yрiAZN ۠kn̫$usr9.* /\6NN#*fBz/"eh&D8&GO޶JOn9ks[+KU8CcǢ׋% \]tb ggLUb.NQ$h/^鵻tloOWG/'將|E+s銑)cLR|BEC."i,AhԏS$? Mͱ;@y5 {_TJ NAHCd .㺁`~֨8 =m&5o؛=>#ilGH YGW6fk`PT,".CO>~-Qwdlޖ` D`1*L ^`9Vª/)$4N'(g?(]%iT0ڟRY|ԠckD7Cg)\۟p;|{ZГ`022ve5"U,R|$DBHay@C/ʅ$D<4 jeؤa?Z??W3le7Չl4<ݳsAkA篋u7\e`viN׌zBjQKslL<39kt.Rigs-J=rʲ0Q :qՈA۷ikM)ik9/E2(cyF<:L@\oX9\&wv wmE ʵ ~%붕SˤoAjً7An9h 2f[j;]`[61.֋Ow˱ft}ɂ{} t%念Jhs.aQ&rLQ~?v>noeo$7+][XFԂThhDvku $Hb04Ko%Ýkʨ*iӨh'0T'nz3y}AWRBy'zI:$.+1w]^ pUfEO)Ջ>$88Xݘpv#5EWz7V+F?$^ӵLX x>~3Rb_z W@BVcIVfbM r٨ v=8 5o_hxa>L $[An*/?G dO]4s ׎dO'+!8dB4X,tƜţ4Œ-|;ݔ'+oK[m'[oLR|Nܬhᵄק5o"^͝DRzQwяHӴRn\Z'-C}JΕ3]h7.Q]ɂ~y,` L2" ! Gd (9c6Td4,7`ʛλ`kS(AjYHh_HwkX*S'g4u3 [+[4~NUޑ[œٟ!dӟ %bAЅjoy򼷑^`חFVPn=Tfl}_guܕ o._!Ք? <-u ޑdHSj6Ɛ=?%9os*R/0Tё|NŅ΋o&ah=7#t0yboFa93woOg} .v^`OrJF&Iv+_Nx 0b[㛖3P$RBKю k\r|R%EƤ$iyY1~yHũ"TSl,Go^E>";~D$V#O`ТO26NM_Clh}xn-0wmA'kڞS1 {j}}k"3ިVUgS`dJ+轘@GXXCs e"0FD 0E{.=NFI1LG{P,2cH0˚\|%̈(NdX;f9@,/3r|UWܛ`HX I$>$ї˚!jxkf" w 0dh j4~ xevO0̬9(*@̱zPQ~Y&sɗo-e aPcA.(uߡ(eB+.PoT+]Ĥ WᡫX׬big5I+Ǭ|kѼG$E;K ^zP̨=n "(Ye</s&豘i 4#淟*)q/)0,Էoz#`P[OG-\`U+Iφk[iY7 ~(6=q&qyEpnDX қq;ׯg1{>Si#gH}\|0X\~<Lx'}Rxہ`dm7wwkf= gd3^HGdT!B#صP3vx7e NMXx5[RcO Vcp'e+=A 7 &T3 5L8 Zť/x '\#\6cDWrd SM+P9j+'V\,t#GB@]tAǺ>r'_jБ(ax"C4=iy"dC/(1UIN!B+(e#>5w2 膵.K2Wa"r8K!w/io-y۳.O`Y@)f3UM=/!`D7TZ U!D\>n}}9#EEtgVcBzNN{ =hoAHӋucN 'f"vq7Q;xP}Qw.N( SR$HA~b%Ru2iHo9x $5`eE٧4f2\o4;5Ah? VxPFB`T ,UU}U"K=`ul޶WxrWMߪU}8|#z۸:h=r[)uNKCI &v]ms"#9xp0s 1"<4L]^r]Q!: >pV_8+c+~+=7H%sL_1:ΐ5WU iӊls4ei2͖3ŅyQ7@'MCP$_ -vd"Ժ]eG8i"#BRIob5@lRu\}K^Kl421ͽ鏋6b8}m 8[Λ-y47zc6@p|0#f9jQ!r@|xtXs=8m7m|NjN#~ӅSK!БHJA!* .+]wʗ0!`vL;f53,ըa$`ԂE.ӓ,B?]eϕ[AyL mQwA(<$mw'sJ#k6 ?$M̓٫i{($fW!ȩQWpyM-As;b)Ɛ>FXk>@߹M¹,$d~,? îDd-J#X8q}B3%w!tS{, 0<Ŕ ~h$Ujg2F?k&!G]z (ʉs"wa6\??֫A#K3;5k .]N'JuT aq%O];Oˠ$,芮@GgQV6DrrB!ƝdkʷN;+?r>3`NMk=T3 _,>*r$7W;af >US<5S>VM`"/y_ Sz7cbdžK3;8X\ F1=F2uO^l.bZK&;If@Ƭ9g@迂eB!*+39KU@Ir., SE}@MIa2&5" N6D,\! GJcGĖߥ4oT *ߕd(pd}>Z Fp.k#v΀w7vGx*[12ճ2 Bqf5VFs ×ub԰$A< 37ZbX)zIvލa :0&e.ʍig5OxCszP60NRǸ=[.Z7h8DDQ 7 Fu.#[|f{?3i[an/հ^;R|vkm=UQ@Lģo]ٰmZ",phPa )x1ږ],=WedF%JF;Q?O@(pQ%%碉A[*0ei='Ǣ/E[V)(x):)[C6?uqO fG.w$!ZSڳb S Y v:*Z,H*†%Z1RC6fXvMU%7oإ:V.W~-; BwhYf: \r\-*ZOҔGXRRLy@A,~ǨT^Q0g8&cw2]4@^Q W5z;,ߩ%d^(̓iNe nf'ql ͝gk?Y ;q^B)&rbO"hZWu슌 #n8qsDa{jj^iMbS5..A↙ӻ ^B0\Tv |^#LNEK %1hߜppAJcBX@*Rr/dO/%PƂt@cɫJaS}%rvC}K!z$'T`Ⱓ2G.J.jtA.4g=*-ӌoRAҀ8qh"x.Hǜ#꺩&od&f[+{1p,J<byWSEMUi<6(x̃hq0 ٽV 8Tpiɨ#R$U;BvhO8Αh47͖W9%r2N)}a9S퇜_KX.M2nf8CwhiwӤ#g&vIr}o"/A׿zC>lO2KdggAJjY@9HPLjZْoP8ĺZ|X[z~.+v?8^=F/LOs * Y%6!Q9okud REY; C~2Ok]4%|wS0H6gA3%‴#:#u%:uN\Lg_ ,B\mv]ЍiJ`ĒSտ&63,ѿG 3LqQƥbE%Nw3MǸxπ^'u%z_&]xc߂+HF=|$PoiȞ#q |N!9~TCt/( 2ߴ21D {'WCmAqD &]ZΒ#ml1THWK?2+S#V71O\*eykt˭1 F~|?f-I~;KS[Aw$2pnl㣬߈PӎvS3C\rq^?iE.hek vpe u=Cp/Ce=i^3|,dy:[^ o/8 Q1xZS*em.HDkhp?"I;MG 9gv3딧ԤFKͨӂN6 rԋRy? [jIRU1-!^qP|UbIPFpXPzO)R6韌F-k>L$s'd7w7+4! y?kM&ZAOPs^ M ʲKiV 5C\iNȶ^\e'h!%&pn &PD$,'e{Os)s6',eE9lPo_ٿ[JY>Mѥ IZ'@T@?EP7LXhJAS^7Jm @3\": +k+t/jmwuTU[ $Aݝ8PACԡ" t7FFy}o5c1<Ϛ{S1ŜB\4`;䁡sDApElOd ̤~T\|FF#behqCX&^LZB{B{ v{Ni6lGO~9Rux' Pfp+32d SPr7EG嗅/2chx+&fhB*RWOyVחR)cs..QS//>RPfrf-%u?r.mkf usiQ m?h(3{e\8B>N$~$m^$&Wd@!;FFnYy@O{CV v댩W-9V:z˄>[UO[J^A6l6@v@ˑ,-H wd *Urt_Em\ԤiV )fi̪Ò(Izar3xg%kUto=[6`B;;.W(<%NnoW_hqU&'qTb':;SR[/2J*ki@niɒH&SUD|^cSӺDzh&NsBe%F̼[Zq7|Ӑ-v Yy- b•R^W- xyR\$l<8ب;bvu1Pb{USCUE_4O]#Fj惎iw/;IO8ny]BBy͢_)t1'ĬAE.FNJΠ%~TX-x~..@N="I2;g|LAA{J$yyJnq!dML32!h8%2_4ZU%\FhRA" ;]h1/5£M {( :K9xg}i=Bް 57=c3A^biTSu=ր2J]V ~כN-z2UdO9'Y &P`;NɍZӨ@3|9T@ X<얾8ygL]QҴY@"PkA o_. S;`\)>(w 4W Ry#gO #r## _cP0`((0Y C-s?=s|B& 6~4s,4RުkNx>LeXΣ7qz߀Tq-=%g;9 =]򩎗.Z-0u*b Gplr? {Nl1"/H^Af6U?&ocbEI#zAZnb, #]qH>sY3z2daྣDQYb'VGMx8Hf2e( !L w:iѵE]L` \s FUB7]8};IW΄QD֏cޙM ƆӵNoPh-*Q>jL\TLMc5?ue?u!CatD'yAV@`g~m~?*x:X䤦d$]e+HȂJE.;cF U:G'-6Δ9YYA&V]S<-_V ,$@'7)$n^n/ RhԕdzM}*{EVKJȣՊHU,"|c*I *w AbtmRVӊu Du5z,*(H|>y}K-`Qx:ng̠wJc(:/N@ߒGq_U~žou*l9ڛOV0$|)ÉE~$! A̦BN9ThxΌ{~^:,/Z\vmu%)ݎ?c) *=.+Y`1 ;| \<]wCY)olz\c>}dfs{ w#m ٢JL۹l(zA/&YX3#q5L T!0j׵؋,FG,눶[YG,=xh|x;/Z>J;6>ܮKUɘէb ܏~3z&`=1Rgo)K5ʱvFiImX /㪒ɄV[1g {n]UA*P2'm&-ǂljRwc*I 󢠮-uF W_ڮ=VUK[{(79Q){İQP;SG& mD"%ef蛄8?"S$WƄ6aDN~'Z2ISL.Q#MzY#PHW ]]l$&fe϶ /<1 Ď #E ="[% >w*>V%~8SX,U-9 ߲rVv:gh]K RNiVrɡBNg.[(xub1,/{gƶ,?_'+UBd9cWCbu XJ;NjLCiό%IhgP 6)Zxjgry@+]Hw샅#CeWqJ ]D,K' 9 hMɴI0+ߋ[@cfvD؈ 94K6b>N\zU1g3i(pX-C `A.a Q.x #G}>NFVrCCE=JwFOQM8AZ=|lk W09NJdLS2=2\蹒#M g3aaxҬF['y 8){ *9L@+{53m<$vBr$G0%5vד :T1 LMw{LDޚ~jʟ8F#ICM!v% 80ڃlBu]~z͉18PՌoJ׿W#'읣M/ܯ {J_Γ XYF܂{T__>2ar;(755]_Ȋ艱̌)]wp"ᓌOHRͤRS@Dg\/" CCnDP.JJ dc?@& I8&wrF vW +C1"LݘFrHMUq:T\V,UV0ٯ B.R<5 _gLB]8Bڮ4{_0z>ȣ:~eaG;őإD) D6$#LID=#it7V]o $.*\uX|)=MsUeg"w@3ZJĥ%)҅] >s"Y2Y#y&OMXBnhXy|1 #ٺ6vIIzrPYi+͗=,Bz3}^U{.}"o~̃=)G 5 |Pzv!!ٖO[:w[|z(ӈX[I;LUqBQ&+l`h$eG%J)|^/HLnǕkFyE(,7]Z=tL(mFZ|P$h偓%8]sESb![ZͧtåJ2+n X'̊: 4-7͆?BAzl`U9N3M߽k +-|_kHA(Nsmk?,JwKՙiaiL/ߢRfTLG*ďfax.Q8c b(CO^~ OUdؼ[=B46fYݏgEڳ۰P 8'n=[I~X0܀?*6|jZBoķˮћyP4fe7wL*]ѯGX]H|~h>/oŜi=1叫(J6ը +<8وF SaѬ*_d{3ʹ;̬{8Mr^Ђd6Y,-ӢV %gqګt0carjA W`:buE${R\AFA;lxZӭQTv3 2(qy젥Y1T [ ZahACF[C-3 CM{HXS2w]FhMl>>*LXz?B;VF-] }De`΄H],)Vg(i$ql,37GA(?КDg^hXĿj7zjܤ\?K*sw zM_ZEaF";n#)6VN\@ZX_qeE)`*1eɎhJ-Mp?;h9$Βmy*6Ʊ[4~nT˲!=9%D|侑~jY!+Gz^&|^-,b]odU  ;W qͭHMv/ݒ*®W _ȲV@0PƎ_i.PӠPubo rx>buhӟ@%0ze }H O[2Eݍ$C\ \ܹ,wf7Ϭ2 J3l>ܟipkB7mdrEwrR >r\oXd9[gfݘ+Z5ƯW^Ġ;i{tBa Hpӎt~H|^8bYՙ澤؛fdSA)OR;el\lVF-ђ3e;ҕ(f)FE[|-*?Cnfc ]WD/۞qZ' VH3:4:>Ҝ9,OwEkÊ{`Qboo`*Z,>P=|9ۦ_jz]yk8tz`t=vWݲhaʗŃ [6YBZ:ֶ-XƔ3/ܟPZ,Z[)kb@@.`f_֣S[} Lf֮ uOaHrk^݅—y^s(xg͕{dñ}UWK '5 ?>Vu6]`VzA8Z]%D r7-O,s ]E]0;f,=r ob<$hLP˗F`v Pn%·?oWY 37zhJ&PӍf*f^J7`ڏpDzI?:pH 0Mig eplWO}uxe =BGa1X֚JgoEa1ְRR_ɋ,V?nɢ`bR)DG&n}6ׯRInw*F$>I SRt5 `v&=,_xm0`Zl0CӺxwfɋӳTr!Stm:n\w/łZfM{׶- Ȟ}`N7G˾!3x ~6KFfi~lp}pk0YI;<<¼@>^5s 4FDX*v) {$8?S- i1]YR\f֬g.hJJ퇔 )ʊ Sɡw.*\|ݯド4׽ٞ^jBv@}nqd[H4C㿿ž=W(<,P x%1 +$HRJ[R:!`4(J{t}W=%;. +-f8hXQB 5L~lc`!:,P\hwzo+ۑ6M|GJ<۠%u1 x340031Q)M+Kg4Ӥ)qlSy)B姤1{8rgƙ{s$Ag$%3ڹ~se<ʗUYYjQ ÁovSni3B x} 0y=Z' i*$iQtaevEnlENVR[!ۄ58/s|UyD7F4zħ*hb e4?ǽn0MtJt0up ",a.2' ?X-6]L_hEv}-~< ƇYaDHiK!Ԑy_x[ɼy:v=M}S=u z:\ P_m_og0Q H2F x+LQMTR hX[oiNI&Lέ(?9?' ̄gdAOI L-(JMI&eV(hRJR+jo0xXmo6_xۛOf Fo8{WHF QrkofHrZa73/qΆr"a31g<MF&a'ƿD䅩O*<^|)BT2 +d2'kHAr nY=L]CˉͥPh6!k)|tEj?,y8P>( \a",{Vae e(cMUD"ddJÁk7&w'|cꃃ/r V׸5N&i-xT ?VI{Pw^8H^U6zc/y]qL%q%ˆaJ.rN35 =kD,EOu~8s1 n*58fWnǒ Fϑ|$ 1k&\OP&d }ɂiƠgR'aOGT2NK:2:-[҅ DdhC>/lr@[ Y`2*>(Od|z8},+ eh~tTh/v_ (k862 _T1V@10RD>߰V*>(5 !{uN̢LĊ׷̅/"-To~ v쵗OP`~U*>!_Cb_b0?dIPEP$po7A9Q`whsYAV1H.W`T8Fe ocƇțm]3s@']SDn0J7dZMh=croGOt>98"ޫ②`^_JvuJm)2-z"`.f,rmGW#@J da;S>6.]I͏7dApH;}?݂gw .pwtnnɽdCE8FkeCrho\p;L_I,yЖWR4-BJB\JI.+YWɌ٥Ҋ!\j~X;`{R5c쪚W6 d/  !ys+Hbaƫ  _FzpEA)6b'wxP> <,lX9дM*[Ɂ\ks*ߦIx2]..Otb"$F6iRT׼,V=MZsk=%z1$"=Ef$u'߂I [Ee«}֛qTU个r/F[fb:OK9[HG.EaoJȺ{MfLgU@'[-j4MR {\֢hnxM4k"qB]TC$s n!$ Oܓ~Z[|f ^$G8qÈ,؂tӇěWJYif>JVÚynUoĆV==>oea/-Z߱<7Q 3+gIoS`0\:Svz2X )xV:OҖ6Y#lW-(ъVjY[Tox0P&(6ё9aNG9SR2Ml%r8A],Ivl(UF2| `&}R8DmU4o6@G'X(%^6rW#3E{*ءֿ3F4E-|n-VaVi߃ ;ua]񍠹>:Td2jyah͑uy}ձ/G呙QE Ղd7:KbS=4 q3N`o˷--EW8NI"HX-Hf:Ten1X!P0m53YV{WcAH9cFߟ[#cDJb },FIPz~jLRZyn x?9Z8sհ<ҶW>^H1_R,Lߨ+L5]o"P 51A#GcGJFin0r]n~mJ<ʡmͳkrd#_ $p q+%jkK_cPҡ3h` /+v <՛e9 r=gV&`:PO@u0~6jh |*;l#ATe;~:>^. e V4*cl 66NGVK=e>N^I%,E۳f2/{a?w𴨦#2 );FPKv[VebJ.(aϸk<~EkۭMKdNq81߾5c^5]UAv)y4Z['pk&Ɯg &}0^RF(%6-XqoVX9z@µO_cw bK+EQQ1Uvޓ PL&EZAP3ȹTU6cxA#/lr`o:qPhrHߟw4Tu}B ' svnpo{+ !dLHD5LMݜ5;:ràJ3h-FYL Ys`zt$$aNz$aXU}5A.ݍ|:1Cޞ[soٟ~O3yB|H܏qBr mIH~Gce~ϐJ )`r 0>Xte 1-q\"D)ɜ0⅞uo|hN,)I$&=w,QhR"D'ޟ\KsUjO08Z~:x+|Bߘ%IAj!Jƞݐ swG RٳgelB6g7U= h ^9 '(WźJ'h?a0 eFZ%uB]YH#:QJ|[-H )p,d ;іh'?y_ _bZ` l"^vA%䲫Iپ- C9^wM[\ Xרw ւZ+Z#o CYQ5,v,QHKF@+o*VOy[ tV]W*)Cu+v)0&"S H(Tԟj @#|L5ybXȜ]}#!sDjiRn Pu+CBeSl qlfQ G ݻ=P@bq*b!^);jy[;G&d H(ygj_#Ch_ ~]ZK"cj^/ͦ!B%Bt}h\@ k6E//.!N`1z ȬL.)gka(=5chݟu bW}[zDaJq=j`2mD ZљK,ɦA$m_ x-oxUPx#oz <Gb0 ٮZmPbj"ČixL:wۜ'X-A Wz21u3pLR`KZwCZ4*ԬFh w/ЎL̟-C?L{c]8`oġU 4sFS Ǫؘ^ Uy+Qg6*DbF.( fbt :m[P7BT α: Iܻ{#4͟ ‘"m\G 8YeFg]^rwڇ>0P$Rf\;SK-ɹ#b NQb>=L;rcEzzg*V`麶K OoiץqY\%oWL@:Vw_P oǺPٍMD 2vpEsng}\[3sCulF0ς_꽰mœ% I@8A;P%Akݻ㷋fuȈ[Fhfa7*@⤅Wzg1f1 +4Hޅ5X 5"#VKJ~B yAr($ݵ&$J)65$ |<7Vb0*N`G2c]ß0#Edޛgh",Cr[~a(u=|}Ȼ[)WB`C{ZuןHvY aX!6xLGڄ={;y9 /&gn#PxV5gy,9'g(eL1Rl"Ҽ< MԒҢD3` ɾ|JeMOŃBiAJbIj ` rTB5|2 JE6ėtNW|@@VUN//$8(O~/(b~2 E6bc*-Nݬ"ɨpwr~N>( J l 6>M%o?J6_M P}};xů#6}&/G7q-]sGߓSHpOqgD3R<-bjJPnX?ag8?`oK ۺl}_^}qaTZ?HL&a=G%$_Jx!gr2^%GB/ؕA)Ab:iТ9ªXVa|H L0"! [֬ŌpU*[OC(330ĄZl#'Ԗ:G`b<-*}nEE7Fg!(?C@9LFoV&P JQ\v9#ߌF{G\WE34V+Ƀ>tYFVHTحIrA.f})qz)u|~ѕldN&>m&Ow~ʬ.Ppu+dfpkE^d3|;>i,{3L55 Ԅ}iy:Wbp/SյDl 'ZQV{hlmi/ Vץ>5_v|nk}XVk?,ŷĪJExuSMhQfkib6(4PkBRHK]6/mA IO "$^Ļ "QPfSMoy3}e_KVI҉O ¢ ˕6fTgTTF*l)~є=qC8;#܇am7Qe E2"nQoE$f[+ I`›AB:GUqKX H㉨LXqNe rz-V |.AaXE.u&(*д|nˤ%u{F 4H,Kˊѐ>UyRa_}fxV((os33VfxySDA/=$3=/(FN3Wn?%UP5nEC9Ub}H;Pݾ٩i9 ߄߼緺cAh In1l6qr)w?>/}/WIn:vx9 ^(~{=WkjYr| mZƵrmWA^_x;ysӵVewjXݕt+FJ3xx-JA E_qwh"#.%UI;թ{Ӎrrُ~vx at=rS<?kנ?0S8쀗At)z1ԋi{i=!4CtWwɑ5fk Ncgt4{bo+.ʢy,XT s_DN,xKeRƇRԪ)%Pjcs x;ys9͓ -QS߅̝v*6.x;ys)'Zkƫ(Pjk͞,U[x: 5`gư*Qnfx%(IKס0+ՓGw xJgG8ǯ6/7&.x{ g-BJSK* RJ2sR7(%x V'ճBI& _>K+x{ 9)Ei9yLl,*YQss Wckx;ysBȎS?*4:+ |B~iz,%l|x[ųg9FOHJx340031QK,L/Je2UOIU?T3tv v+(ay$|`2nuw:?T71;5-3'AP:ZUtv rutS6IlR4"smݩK.hJMz.G:m>.PUIyFz j®G,mO-31$霷ә֗J7_uw) Tafnbz*ЬK%+n6lod 57kw޼cnm3TIvjQ^j^Ni"37>tlQR}*2Ofg*i uDRYR TeӴ^|ҝ7m5}umݾQx[9seдIRX7r/obvjZfN*CטīIQݟ+5)-у rutuMaءj:_ǾЀlb_HϜXh4qv79+61Y1R7Aܤb'f0߱簯9yE=M(&:w1vM%T [\*(GId 3c> X{h)tlɽLF"1g݅u\NdqzL/EҪ%?=wNL.{+^JB%[JjNfI'x9sEC9Ub}H;f&& ٩i9 K>+s)Uxۦ&7tF:ɲ֩)ZB @%3^uZSOǺ{n?|t^uoh`]S*7r.|8y"H@秮*-sK.~`仌b/&l>k:'@-MZfo-Ds߄U, LEfq2PŔ/3 \tZɯUgxUd04p0Nb;?ryM Q81 '2;^)8!)E@.7(=!lrv΀-/1ckxqe*X/l8?ي%j!x9s ȭ[5fe\;[qM;LLm .x3 ]^òR%? juqT%eeͶYiv40000 doc>*sCs@"100644 font.cgS x.:U(CV%OF6썗Ȓ RU7100644 main.cM?4Hak5" -:eUZ8ZxyssFb^zO~:ӵVewjXݕt+D5sg`8Ȭjg-X8lMLW֍Fώ^]cBZ~^^2UkҾ?;LGUE#^յ+F#A旹&Od79bk疄~\ݥP33sS2XW8(|XRA$StҎRP%٩Ey9z9 oeuỠr3Uej]֯WfcÔd'(MoY'ۛ0 `HR=SL{Ԫ"׹$BqbnANj1o:MU㒿 ԌĔ"=תƆ3]P*l ɗ^,}E!^|9\$48j C4zd+&bkso׽Xdxu W:z $8Xx Xk6`C_| hQ100644 main.czZ7Лz'-9;ms]K?11%me .~i2dx;ys9'/]nNLL R.x! Y G)GEHWmWU/x;ys)Yc,[Ȑ&BUD!-?D/A0`݅‹OWzXÑٌ"'E|;Ԕ=]iSd&&S'Z ;'{3ĸG̞u1E7V[8#1%h:)' 7Gxp>_? =R"scv6T)0],|T$;W7;yq?~akp[~oP!|vb f˒l:ɺ(z~ncx,QdfsF+NF.*-lx(Pdf HN vx{Tq";Bf^BnfAnbdEkw@ZfNIj-TF^'1(31SBLn(5dv[6(ӎW}& LSЀO~̫fRKJ2sS㓋RKR5|tJR+t t3SJ2t2R33J47qfͧHvLb/2SCx[\idN= ǀ`wxgG߀\$8^ n9x[TiC Z\*px;{Bw;f$>ԢԊ\y x4/xIvĒ̼Ғ}? B R2~>> 55\ H xEu6ə<&u821rNVQc2Ҙ|[dr4TL̉eb؊RKJ6ר13@2n x<'xC 6/eF.*?k ^xkxQ:‘Je\~ꉑ& PAxu W:z $8Xx Xk6B *#FI|xt100644 main.c G)GEHWmsUIKtgE_szӓЍ6 AxkȻ!es0yɪF96?6fbU ax: Y G)GEHWmsUIKtgE_szӓ^xA^(8$>(h.~ x[[s~ׯa1hS%LILNK (񸿽wbB/-g={yiuٶ懲͖dϿ=9ٷYn7oONbfeamlӕ4y$-"47|f^gw@Awi&dxz1L.9|2DֶׅmS륝/kvN , əL7n'thOOlzlYRDeb6-XA6ۙYW ~"mj3IβB1$/"LĠ ̋6BF];KD,i׭~Y wY]>T֮mπ8叿ienm~.pvk PT򫲠4owFU9x|=3wg3sG'ͫmi>Zg\ pl!B)\gcۅ @XҜGM({=>U3O3Kd:+ΐ]0_&mw@첦!?\)4YMk6w #fTNgSӖ.Ҭ\9*mi A% RUǏӡV-w-rS'}W4{8E+]LǍi1=iT+N: t x.W(2rw}/Ĩ"cB0KqrW嶵a8dawQ?}AwؑÞwWf='-P~.cR~8t^մDࣇC{qRv]X=ُh=?/\ʂ(D)v2-h3T,?wP4~4V9LllÀtPӄ`P l~:7 =k OFF-+IW *L9nS T(mxW{cQO($ &>#`k+o,`}h7yMr:XLW]&yW ?p L p̛wճ'ύ ,CZg"d6]oBw?taϳ$ V(_ NVіNu cvq+5|T?~ezzq-cfo(/NϨ"}?s IJפn{<AYbWx VÊ<{ ċBbUvSۉuP>pX,Kʫǧ 4U.q 9ҭ.FT'Az]>4*@X( ˁ>ɱ #”ɣ3b-Vk% 8^3H9f&`yDÑ܌싷Yqi=EV76Oo+/maהNr3)XOl jA fź<%l54ߧ+,`zEJ/sܿ@Zѳga[t>5k9ɏ&e]zIoJ a-,7W̎Ɣ;b8Ʌ|Z{,TO F ,j̬14ٍ=(js HU[{rRژP Ov1Ҕڢ<:\./qrC?ej.L( ƃ$(EHKH2=ɒ(jɃ&xV@@([ʥ5sG q> IdyS`D=TA*yaQNW7y}^?~??7М.1}\p_e`<8U E4Lg5#UDs0zu ]{ fT#/I/ 5~Z\h|]ԍm ݍۉjԃbޘ5"zJ]:Y^ *Hg+[}Ǘpi$'P^-1PklPeUL>U "_%ۏ_Ni7t/ӎ+S.M^;9{!CAļR,ttN ?|8>cs,1\:N(7QQ0w]O.rcBH-<}}Ň%"PS( h8Sq W<8M@Y |.&bn.qw< 1[v#D1,(B҇ɣ< g>MQ^-0ArxDey}$|L8`+kznz@JwZ뱁P!a8YiDdfW"!@7հ\NX'?Z:h{wb?Lyi ,i,%J-:UM,L,"JF_ ==. n2fgSi$xWKoWV CN\f3$ P("0\'SqM# VUբ[sNR sy˧8'J*~ײ\Vxւga^0/u(1 '"㑐"em+!Giqe~@=IƟI=e@ofձmIB`k&f鉘زϯ{Seq*/HMKÒs'9SDY<8Y0dA+ pCM >Ǎ`u^'qU,~?+a y1^`HubRUR bT}V}&Iqv4S!* sjH` W^刱 dͲ7.#E07@U z<~<97 Fe&>/OLdJA]!ڲ|X6#z%Yd>jH^(9Ċc9\ a* ;Bē҉~^ua:̵W{!y`\0 &9wӣ{63hZ!.RntH&nVWK5o;=ߊ(,e7<}}AۛS+Ih_yhM\Mtmdvx B/PCGb;L鰌O;$W<׈=@h\蓦I *mShtu:mxCk2OxC 76`BU J~,W100644 main.cX!)#*=ӏvmWJTnxj ȹY^5%axS W:z $8Xx XkAo^'VUlsms]K?11%me .$xCBH7Melua_safe_error_message(L)| )7`PScx: W:z $8Xx XkAo^'VUlsmWQwx\ 767o=v!uW100644 main.c %D>j{p6]\msYhO8ST>ǓT) JxO AudDt7H葖IÚ_0@NI6Y.*6S1Z?100644 main.co%AGamR84QJ100644 shader.c-oDĐ`R?xR %OT}wӪ s y{ަ+ʵZmv#O%]V6VO .N(%Bx{qZ1_a̋H^bW=w믉 Jnx͢]1\]`2)a1c0P+x?rT'x&t1͟X+ Mx-ܑH input", 1); aB69ׇ x340031Qrutu+(a7>K[W]:a}&@^ǰjn|j{dkb g3Tr34*]ujwlw 򙹉 &}paⴵ"'#!)E  9^;-'hAx9 ,Ʌvq6(ʀ?YZy vmW,GHxR %OT}wr͵ZU5>w9ޓmv#O%]V6VO .J'x{ti- 移d((ijZs)ArFbP$("RWPWQ(άJ5uTStSK\sCԔ7OqN-&x9 %OT}wM#O%]V6VO .-B0xi- 2R5Rt2 JK6[Mf ax %OT}w.n@x;{\w;fŒ\(4@Nx[ųg˘6_c8z23 <yx;ysB-)tNP8YWiz,kVx[ƳgtɳX{lx[s{9FT/3NcU/-.ONƠ|5!Tl4x}{9Fj7x;ysC$ȩq;_vE6)J'es™MUx[qӂ͟7o[:gfUߙ/U_x :}H.:;mCx[ƳgtVƔ3X"V*x9 =\sv;zʀ?YZy vmWA)vrxR ,Ʌvq6(Sl z~V_oRmsz:-F:[H֌(i 'ax;ysC$ȩq;_vE6)J'es™Mnx;ZTF-{YGWjxƴ ӆs @P))Ez`JV!3/ qwtq Ҵ\f&U_j7"ɗܼkafv$ xQ 9YcZT䀖G`]`Jm Fv ɳIFN2Fɩ (!"`x;ysB-)tNP8YWiz,+x;ys)gǵ#gCyiV~͞\n{xk!es0j#F.1VRqxzPt^QHh1ɽEӑ&n1x;i" 6h8E%xQ 9YcZT䀖G`^Z[w`3*eWIFN2Fɩ (!#dx}o|sIx &Yx;L J5k7hĺyGT.6 *Lxk .vCʛ+ᑖZq)2|$|Ii6P4z{r0Q<m0Mb$*䒨5#41 x{:#KjNqd&5!,N~x{qZEQW^Ь(y~%j^Măjܼ Dx;iT J5k7hd٬Ԯx x ,j L 8'fΙ [xҮyf3fm>vԼ4.^ ?xJ nƷ\Zs *sgS x.:U(CV%Okw5gAi}tȪ?WV2JS}ZŒM 5mvӃT -[Vw PTHk[frH_0vǵ5]bMt'TfO!KCN)Pxk=PϠ(p7>33 AxziC,FWnaG nx t &u욟56Zq)2|$|100644 font.cgS x.:U(CV%Okw5gAi}tȪ?WV2JS}ZŒM 5m0Mb$*䒨5#42ӃT -[Vw Pz:-F:[H֌(W35}HDXq*W?-Lۓ_0vǵ5]bMt'TfO!r@1xk=PϠ(pe2L\ m=F#j-?-k \q ݧ/?39`pUlmP@Ldg.Ȓt ޭL)KQd0pxQ(륂)IoJSRsrJN?10kgο4y8TUnbf*~=6^lu֒WTdba_.:yת3<*28e'Rh׏@<X(N-I-fcr(p:_$N=-P33Sx9Da a攳s,hAUQS_jnm~n ⒢dP~tTPlR\OBU+)m 'Lz.\UN Lwz]V]!#Wf `W?amnzP2IERfI1P]LzIw^ސoI"PUũE9Ickxqe*X/l8SVX4YJ}ʦh0z7=&'䱗;YLo JgӇP5e)@]O/t5^ͷ(NDQp?N[h vt0%y4Qv|k}BI%C~/CR?cR>5?<|Uxt ]t &u욟5q6#PCTȟS?5100644 misc.hMb$*䒨5#435}HDXq*W?-Lۓ:e8M1zsxu 6)7n{H ˆ 7m100644 font.cgS x.:U(CV%OF͂dWpbhHak5" -:eҪ2x9sBϒ=-6bg !hP© m,xC 6썗Ȓ RU7100644 main.c.ly.1[W*9EnTd-HWQx9sBe 1rtmk TSn=Ms̥e/Zob ) zr}՞|&xe cGAp–>y"y Y}}!ܻ)eBfnbz^ K^*hdNVjI=UXm/y:LkIΫuZs3&|u7GjqȬłMEUd0?ɤ*_-;i ،͛EMek=\>(:~V,1`loxkͽaL! 'xA ]q8+0ŭ^C֑qL?z;9ԓ$Y0Ss2!X}9Qד874Mjd100644 image.h)*"z5L{/cڒ4#ίnq?} =HR4QJ.XMx9sF/ xT:%$&~=6^lu֒W(f'%3(MoY'ۛ0 `:IEI+L/}UxZ{4h x! 4=B_fҡ Lױ\HWkxk̴ӆړknfՙdHogX4tWₜMj. nj܋U&k/֘\#89adyKK2n~x)+!Ex9s HjY:y.15l` gH x&iiQklk@kREGl~;f_Ex! >k?>;5 ^~Sx31#5''AQ\[We3MLOeX4 O ?)/HLI-bXr՗mo98F1UxR ]`P;M˂^qO䜐CЄE(T 8$x%B/m(HHWz' axn ]^òR%? juq2%eeͶYiv40000 docPszJX {8mm$6썗Ȓ RU7100644 main.c9)!?ei]$HWiA%xk ]q8+0ŭ^Cֱq 0Ss2!X}9Qד86a%ge[g-j<_Wވ{se_Z.ZlE8HW.)x{qZU6H/o]\kρ [xtt2ӆ.l|W. ox[La"d6ɦ!\1c2;fGv? x[{i 6VXOo69tl= Ex[{i 9y9%zv^3{g攖lgⵘ}}#VX]G;BF@jRRRR4<}BC\}6-g1#mx}4ӄ؍70,||#~G +Ix340031QK,L/Je2UOIU?T3tv v+(ay9g=jق[, V~71;5-3'a~CB _|96Yz^5 WG_Wf~ V)ZTLTE%9i`;_) ݑ&E)2֝Ug0-:~2Ԣ: PH+)LbPMݚ6ݏ"3Mj?DEJ~2C@qռzEpWhɭυZ4hH? B5H=Yꏬ"aG 3 Xvc*LEQbnjRiZZj(HTn|] ݧ/?39`pUlmP@*}??uPi[rQd0bQ7ည g,T*N-K)Md|;Ĥ B9PUy@VnoܡȃCB`BG<ko0ŠXrW~fN^+ >~5 fIlqG>Z#P70$s rR.m?+ُϚ.Q! uDO&03`!G Rso[ |s05%Eɠ80ͩ֡~!=ؤ.͹&EWRYbN0=\ @ӛtCF雯@Vp~V'7-oF+Z!UE e%yKy&SR(O)WQ)MDүi5?Vys~l-yU&lJMaWR68Qw򁉪lJP 乓$Y<'5)~>xsC7.Fk2jocZkMl$xs1F,"x! 4͂dWpbhHWcxJX,faT9D&!nx4i~f^ZnRjbnjBqbnANj!) ixxrn 6a+`UOI/暼KrtLxX' n%$;y n̛]U&pM~8\5)@Dj6{53Nvș+5"s^j@ZaxLV\-7y0X>Ф"&qbW5dYɮ>:K}'r\):#_}0n6\d Ob xQ ]`P;M˂^q6O䜐CЄE(T 8100644 font.cV).HZh5F6lk,O1100644 main.c^or.$htvrHSC]lj/4Rل:e9N^'xn T'OWL|NMs Z[x. &ndʴe-ms &x;i. RRJSK4&P3M抉'6xt 9Uf6&HnF1MM&F5>3xP썸F6ZJD׵!QHu100644 misc.h)HT2lx{*+Ais)vq0xmMo0  \W@$$*)DJ*u+_~L|vIJ#'F8j\xF&*ea^`"txZJR4jwڥxz $UN@f80 }~QGݽ@j|7rn” Vf~AZ.[>s^ 9 HId蔊J<Ն^)rMb!.>)`3^bUk0 cj&}>B0t:<)'9LF]Gpbn=mxx340031Qrutu+.N.JM+(aX|#3w~6K? !SRrJLsIU[$e&_wT i%i N3|_F}/6?7{x; l3צ|$vǗ8VW7"4P x31 x: =.1rgdžHۦ&tǗ8VW7"\ dxX JAqG2ad$=/X iU[:56rHnu` iQ100644 main.czR @JJ 'jNt=Hsj9͜^-‡WM1k}"[cF_zV֍<@F:etG7xu O ueBcO*UOaf&$6=.1rgdžHۦ100644 main.cI;1 F³HsPrq:yI7ύpЄ81.xl 1Z/CbJZW7c3 O19 #AHsf{#muB@W*4VJM"eot):ez++ {xX 6^틃W$򗑨X100644 font.c*3xP썸FyMKE8$tЌpW!)^hL.3HvӃT -[Vw PEvPc_Aܫ WSC]lj/4Rل:ec!x\`dW̙6KF0j\/ ix) ]S\abZcyKus<.q6^틃W$򗑨X100644 font.c*3xP썸FyMKE8$tЌpW!)^hL.3HvӃT -[Vw PM-oW2<3тWSC]lj/4Rل:e cyx\0`>fL'_1y6g0z,1; Qͮ/&l>`dδY)Gqb^JR~%, dxV_A1o>sɻͣ`L~xS Zt8+gq@D9No$=.1rgdžHۦ&M-oW2<3тЌQ$=x!-SZT4[:&Nד=&,nKx˴i;j94xexT tqC3L8Y z$?[6)2ײ" NIHsy6Rϴeus[Рv$kx{xq(~%O;D=~]uăj>GwxiCTWֱR9+I c Y[qnO7cvfnRUo xVWasɻͣ9Cx ]xZHJaƸUȨ5q6M'R"I6$h*100644 font.cZȗ?Vy+G7SݖLv$Ojp퓒;eEf鄳\ΓIR8>V!@ʸLr׋fm100644 shader.c)0VVL; ܰdt\rveEiiz ӨkqxT  1;AFT3{&ҳ%vVTGLUhC&B7e Afa҃AJ$tH\!vcx| ]{a}Z3$NoCFqdR_B;YI>%YڮX`+W Uu/ͥ0T擒xr3蹨Kx%kZ3IRǗ8VW7"=xu 6 r2E󀛓:=y100644 font.cl[-;B;"zǕGكIzIvu+yqkXٗ8x 98Uf6&HnF1M100644 MakefileJlWRޑOb$4DINģ$ip"%ߌH1 $pQ}WPVD)ƇK%]tI0{/=0oqvR+T2︦H5ZG'+jn7Im/A/uUZk_Ђ!nx[9sBm܏Luߦuf&& A.z) ;TZrS˵ &0; n#T>q"JԮ2n3{bI7;Nvg4ѫ xJZׅ'ObBenɅï,pGi߄*+bSS$;(/5G/4AVH{џt{ko *713踞s\N-q:_V\S&SY T娯^]oW Xף$ rj˻W,ir/#[e%]{L/EVZy8I>1pvfHj&_` nu=ըoy1pЛ-'[޶bx%-Q+/2~{S8 &+p# xUkAƙ@mx[ XL 6guPupvuUW04I"\ PfCK'zN=I|rfW 3:elx;;_wC4V^bnBv~AfjQjBi^B^brBqIQf^:P",,y#r9x} ]!I@A bmG(xqK Bh^,F$=v^HvGAujvi9sNb:HB4M͙Te&WQP[3\?O@Z :e7pxِc.#5Z,x{Dq!2>ux?hb5n0PiYx9s>&awGY2-/^K?mL-x9  _~qCb[Q@Wͮ JV9Y:e GxR ]!I@A bmG(xqK Bh^,F$=v^HQP[3\?O@Z :e/!l.xV9w+ͼҜ)Dx8 GAujvi9sNb _~qCb[Q@нUEGxR ]!I@A bmG(xq~(a<؍G;Ǩ9Hͮ JV9Y:e:k%&x9h 'ȋ0mޫ%/17urL x9 ]!I@A bmG(xq>J2J] RHWIzx5ܸ""|@ NO_GL_PUSHPOP#"#&&u1 @>xKhQim4Fc6iMiMjjN}UϾHT4iXky+(oD|"bAaP|R\X঺ݪ$iB/ws[ U:8J0عN&5dn9#Ș@YE1Ѱ $FclQc z\4FΒ$x'|L.E*QFIOL;SҺx^_-!Il*&gucY˓r>O_>J0ʮo'0#,7[XDrW fB۬s X`bٖVXixnmŤy9<ޥxinUY>Xv?380x;2Om{ب:H4ovԨb aϠtdKU5~o^\u AVG9+|\fQTBr=IPhwcz5MNu  |j̒zrq+y1@Wmoxm%⢰sNNp²MSL$6!bk c__q/cP>~T#Q2:A}XT[9ZY4'WLrn&Mx\OEsqmn)2Pl&&\ij fS.1@̄Kp%&|NGzK'jBxZRL5x1a«LdiFCւg:vBߛ,j>۪ʷ*5~P=hx=K`p0 ibk9"mF(RPf[w~L$3h޹y)_ zڽ (ѡfB<\u=_σqk#"pU׵zcX5sze'i7 VmG1̰qe&uKD\ś96b (vZb:9fX ,1,W3q+ŧ5{?l3*ugJ%]Z"fMWkθ-ą##L!us$K]$9D JˏZR-0y+xԶidF.7Cmx9s yc-l9y -H l~x žy{ dxtq@퉧EV|ܔ6͇kNYyt cxF.  blue dment of 123s3Kthe G4s. It 4&8alpha is an optional value. 9" will 39%*It also keeps them updated if files changeR!_aS#pQOA~x9s?wYNku'>KS۬i!!kJ3E7{03qHi.xiV k2R2S܊sSJRJR3Sd&+Js)>LAJjbvIfYfjQjdN7im_j)@ Aɕ9@ݓ&q 5ǎk;ɮnBNz2g')s&eVhLNTWK'=ILOSJJSSKRO -N (O:Q(,Ѵ\aI iLxT O ueBcO*UOaf&$K`^EgGxvQQHsPrq:yI7ύp- "v2x: 4lZooϋHsPrq:yI7ύpdD2x[ F5&LP,硵y' . Wx[gӆ> z;9&m㜡 qvь'p0Mivp,>)/XON|ҞwfN86,7ik'oY@%&j;hZsqA$rRRJ5&LP,硵y'Ah=l}xsgj-x0 x ]9b;X-_RRخ2100644 README.md%6UPk$քq2HV|5Đ^֣k%YM`Βh׹qw5uzdHWk= Rx9sBHטīIQݟ+5)-Xx1lUw859Yev󪡁Bnfq^2oۗz}vU^1Pb_ғ*2"f|T \RG鞵٢{ENdYms^=Ծl/L?C* x9s7z' '?ؕ2Yqi-_e#V ;&+C3T [h#`4y7><[ZjM#K xwӆdiG7O`(WC3c }}ʒa,UYY6qdl99orhsNiۢr @XXbbd&L3R4@45'5/(-).)K$2,gi0{R!7xk6^)qlzmҢhrAKͬ,]7!%J\ Nƒ8Λ3Cu6c`_XN``o}=wz2i~24E*WVMUx&=Ʉ"EU*(T& G*4ܬ2ZDS斊 Cjq%_r(.ͫSFLʦ(yziIo%_eO ^e%|.1ys4E,֠`x}df$"+W])Oa:B%QݴeM[\Vg,S SV7s:Q<,_ɟ<݀ Io#9RUsu4hí{5VvG['_@zD |BuTXPeܐDaFޠf~H"Eځ{ KCXT /8:3ʁWU%tS-+Z1g\ĭGQ2}[v 3ʜm42UjZ{`,lSOe oewS'd*EqCz6l @z^[ Kx0|ѾMGaMd `vb) 36{XL:g6JvYjytvUA\]Mbʎw~Np^ٶ 8rqƌpތVU8HE!bU<+sXLOsu ZyJ5eךy4 b3>?##$͘V*bHqy ,I3JU ' I!ۺF!t0{p]k9 Կf3\R/sYxdY7!ghq'3?U p1ad},"/ N^[6@oP>4.Ʒ`ցHi$s)hM~8`3LL-(e"LU΀:L^V&[JHzynߌÁYZeWOdSɉ2(RF+8"\wŧjчsQ' VKGLѥLn [w7 tѥIݤPզ~J>bZyƖ;1x?)/Zlk;xXk|rg^ ݄O7~~wlP,Ru,5%Χ@ܫAJɞOGݒ!N`/tV5EJc4hMUaFE`$6,·%_}{cHm;G&5 Mo}SnpxdC"2xp6̌<Hh{0Tb*w i ! JjP>MIKzM!JKC)M٢olE| 950pn$`Mi^Ȣ!+^R7p"e,8_~oOn/yzZHV)H _ w<߬\!v̛ӂ>Kqz;#fZ!i mϋ>{I-C(| Y#@6U?RA6"+P EC9F1/m? RDB#ʰ:%2b'Cs);xǃO8C-R8^ zbheOB_"ˏ>, f3wmwN"oj{q+o{;QIˏPH{3 NP ,)(orhD@z 8JH~^ŋXds%ў#m?T7)%3T}*C((R@NsQ@ Ĝ=~S `=\8ߥq{X LV@ gx~3 Q(rKJzn ty#j37p [8-ҭ TD(7<ǀ l-0&bO HQj*kHҁH4E!`5qbZZ.W[;Ra"~m$@b@`Hb]ceG6<MADMkؗao1pm84ghxEEdЗL]D : LȦA$X x#-2G@ע^+ ̸=__w6ilW,ZsYeZs<;)Xȳ ] 3t߮VwFp!_),b3Г nQPjlܛ&__ B"% +K< RWhԶ矬1.>WLzފF:9xjg3ӓmwN+8@Ţ~8Tdwjt9(yq `Mtܺ^^>#GAS\aW з\@zR&Ds+lDa>.OiP?{#+Dڸ VCZt)ww}E.eO7S3E `B\$-ATv@Ґ$mB Pu^Nu.~6|?y>+`G( Y~Ui-_>ֽʚCv3|˷ZhOcm<\} a+^Cj3Fo_1'/_JF)6NPtV VA $P=uO[ԣ/ !DnY%A P8R`m?q g/kVnCI؄ {ewn #E6 /:RQaIR>v4M:-TfK J,Ӑǚ409O߽ݍF$IUSc$عo ^;S 6G*->B?az1fːܖY=gxƢ_4OVe7)BB`M&H3Ҡ]+I';Q o2VtuAȠ nzDސ_fTZxt!hEɿy6H _xr ,>.n>Q f& I%Xz7 l<ȴٚ'srvͷE 9#H!%$11"XL&(gViijZOk*_PZS\R3Id2f sFd7Gpl~crAa'[qh姤L<%T`srDe_G.Txr JzJ))y y y) %@2&OIG!/17U,kWX9]B(57 #(?'9#3'E]51x{+wx9sBȟ$峻[G3nOEN=kmYu ݽ8{ cȭuw#kso /vAȳ-l~q^ĐO[g^540031QMLO`ߨPs`_[~~;6Cd&2Z> и /r3Քb\DlSj=h LIfq2PɻvY8eU&̽bB*2m0_ZUz =L"f |8MN#Z *0"ٵJ®8ltlŒ H IxX }M`Βh"ֽ/j9͜^-‡EiJxyc1Dɒ)E&dlϲWSEUSAY!%?Y!9'51 lAxqc1F5gxqc Sx{i\ :l~1n^!;9Gg=Q9'ج#i4d 9'0N^r|ւ̼ \&1IQPPZœRSR J2&['Np'ܓ(55Af.7Q 22KSRKJKJR'KMfJjd7O/,e<)\dsf|5ԊKt &+OK[ȷJ!_gxeOk0~D ,[p{,H:MBެqy7/RBacO7BjUE?9M&nQ un%< ԢߒwNj[hQ2a@ z NA |E:1n3pdPS⢮^ye]w/s<^-[ 9!tJ Z΀% Ұvdv,ֆ ^8IgS}vlx;ء0!db6kBL6'0\ O 7l(xPhW0idR^^ Wx9sBȟ$峻[G3nO#L*4<{"7V&t>k LLr3Nzt0)2ajEVPoހ!o®S_ilag16_`ir1Q &g?TqxVkls8nni!mY(NjˊT][MHJd޺ǰN|- l@؆-l: HV`6JDs9޸}4j^sLHݪ]),f =;{OGb;ޏQjV+ѹ B|jddi8y>fzaoMӂ14=?.LM񒢬`b]Ʀ`٢9-y.{?!(C>J*l(ڹHc{R 6x\H.$Ądb\ vB3SgcTBMD_b "6 #M2\F2(cX;Ǭi|Kj_%extb4}YY/Y2گDX3CL **)By$r*hUs0Ga:9 m#K)yĢˁ>uc+De }6{=u\a7d Ѳisۑ Jw.nIRZ4,i) laC(苤R[ < ` : ? `92gpvȫ6z3Qm0t0E@brqa fޮE\e}#X;yi] 1Mvb5>9W>M'>bv,*Fl_F[\@Q KfNT*[uKZNmw/$M%Zn*-mc;w:>bEY&Տtm|Mʊv+q#J$e*2Rdy88t=UWmO iB9ΙΘL4ÏƟ˳w}N-[,Tx(ߛ_?O.\< Ͻ_Hsa$sY޽KW띹l,}}Z% cg`s#MjcΣnlr1l.?fT#C4!98Qje%/_jY-P8sk4nVӱ3S3FXiزANqVKiʚMz܊T34(0),m` *,+E"wS)ID/GOiT SKc֗*AzWx MxaC ْ.Fsg^} 3ɦ,U\%TJ~pFe`\=dz8zfS{"b#m /j24䖪(/XॆyRI!F+0(r.̹ nu0oo/:3;[;|]nS-eNӑBjdԝU*SBt xiZ ߋLnDo'ymZ:x&Dhoj8Pz'Uarꚓ+'O0vBssr\RJ5&MhbBqIQirBIfnjYbBI5O$'T_` +)/NMKLR1! SKBhhnΛmTNMx۴o-=A,?E JJsR4|ttL- 6GY2姤楤)M~`+#b[SF@͇:!́a0&ex:؋ now = glfwGetTime(); ׋ @tBY5!Hx{J Lz>9zv\ʙy9) 6`Rlb%n12o^)oQ WDx{:idU=*Mu'O'dTZ_Z"sS5ulrSJb$'ۻ,fFw~!Ijxt.hEɿy&fL|Kx(~/  x{FaC2\iA!: >>8 !(F8E&ܜx9sBn+WlX"T_>yԬ荅z, vx9sBn+WlX"T_>yԬhC3 WG_Wϋ`=mEiU"wL5WZV$U#En^;{[|_K BMh!rgC"U~*:;R仌T$jrVJb_ӱEWJMKfP8xA5Fᄏ;hU LEfq2PŻvY8eU&̽bB*2m0_ZUz  yԬhC3 WG_W'y8}ϲ/׿:'6qZHSWRbhpO;c cȭuw#kso /vAȳ-l~q^ĐO[g^Z=Qաw-Λw̭m*N-K)Md|+&[I{q'^BU&f%30~eaClΙ []`J2JNzt0)2ajEVPoހ!o®S_ilag16_`ir1Q &g5̮UbN_vad+T xMNA0ٔ(X!-BY)*?NI&/:L7^Aw2_~L: ^Cj-ZdM(}{8WFHqVLE_\<xSPOO(ͱ- xYn8}߯ PZƍ/lMiS4ALIE"]w$Y(G19gngd8 tȮ@h'/f/%8$}'K" yٴ+rC@h)n)U:9 [r-:^(b|pT!e1'lC4Gt#)f\t~x}68VK@0DEO*mpU@SlODPNG_#HsgWf/%t1BK=FTcFS+-T1 N9H?wsbyHMjzgڴ,!OdZRH F}9' :Mj9F\ K>Ufg='toPSgWS )+Exzޝ&+Wj瀎'|PF5A$LdQۏ>UP.޺"_݊~ eA0_W݂]AL\njux:w0'OHI Urħq 6D~<*˾=WDžRT}SmH2Q 0^@ 2}_n]D4i_U BBXG#Bh&M]D,`$ATn R i\ 䴅f0*$ @I=Exi3 r hTLoDbM@"f5Hm%`fѲ򫩹XT,-TIs#I(ڙC( zScB"lD2fN5SbMЄQbŶ_tNߤ#+shxRأ S l6/{$ɕyg73g&owc8[m|ԯp؄3gk1H <ߢ8r~ Oބ|mc8+F%f8tolyqA:#Ĺ f7w 0gu*}SXl<&onjBV&JA$Fm& XA.|Z6%vsЈl Tꑨh8W'"]b[ޏZ'D|VoJ /b׺zU|{o-pnd/pq~0.*QpL`à=y!f\ʓgDZs ˬ֥Vy`fd¾.Y̰; ʹSp5L͌'vTʎ( d$lG63IuU縯-a|N*CuQ{R(dֈQ~uzj zFo휔ճa>|L4_tE2v_LnPeq| (zC}~=ӓ/N8_鉩onznqK@ S{ ,]#T E r! {aKTQ" dQ u4nۭbjg׏1Fp/Fm&-ᤸG>FpP08EWB5w>^+'\nqڏvR"{5xjlC$[f^Zn6W#x ]9 D<X%EG[100644 README.mdqGs=z/zb$4DINģ$ip"$YڮX`+W Uu/ͥ0T擑8ߌH1 $pQ}56y2$=BƢUu100644 main.c %eᯭ2sݙpK:tHv︦H5ZG'+jn7Im/A/uUZk_sO x} znoᗚzE?ue{GH+h$]9-S_"+3&\'GN/~-~D6(˽^B-e}R 8.x4*>fnIx{J {6R:/x{2/jB@N~bJjQB5L6Qa1 &q@ydA̴v<`vRn=:2X9W -H'*N,^E HlGn^y'?Uf nNfl(`>9}2#|G'cy9S8ys|ψMV+:TxIzBFEEɩz ŧejTM%[%==)P1 ZX_q3a #OT@Wx9sBn+WlX"T_>yԬhC3 WG_W'y8}ϲ/׿:'6qZHSWRbhpO;c cȭuw#kso /vAȳ-Dl~q^ĐO[g^|ѴDTJIkw:(J)yz />\vwwg-*,Nx;.5ʄ7_l\5YECzK Z^O}bb'2i1x\ gy/VS55<=x6xk VE)'ig pݦ@c~( ڥ$»z{'p{gZK p _w{K3F^ñ#oe F 7o߿Yu> 酢{F(:.qSp+yײB XQ,hEdUn+IKյ\=M BlIc/> Z&ď!Yt'?Ȅ'ŏl3!I3(Gk6dbW˺ub؋'T~d}q$5e{hA-;\-!+em՚%`#Ȏ ky48Pk2+N͍>c[.:9Wo }ew\ f<vi!\oZnPy !ߓpTdY< zIﴁ͍PWhҬmD޼OU$GZ->4 <E<$w&.˱ %Q<2;1ki#{bωyJޠЕ 6/%&{*ʝdE*ˋ.d+ 6RvIVED21Jz!:*WqaGLr*#ݓCva䃮gfJ{`"bd b1Ȧ܌LI=CB^AiZ-Ydßz|L >fR]FLDQ8 B8c(e=(PB1VTؓ@9Ǣ(PGx%xقzcǁ w@I021HCfh0 H+>VBw$1oPK 'm4zeD$y&V@ F4`~o:Z"zyҞ[8r,nB`OX#o@mqz_iprk@聗L:" dR{ŷs$ca;C5 7f'\TLgM kQp*C΃imB*%#;h J+uW7fzFO7X{Tٹz0X'k^\>䘒8U ]a+Lxo<{g.JX= (t) cNci ~P4aK(ӷ}׋3ח@]`s*WI7Y㥉YvEXfr]堏[P</ W[c!gL-}ˇ_d&09jP3yc23)m''='v`%fnewal<9, #%(nWx%hH~|+4~v_&dkGepi}ts1DYO=wbt݀E%kFZ+EGa^j-`^.8WD ,-;p3Q őbIA)*i^Qurc2 $\;&;x>T%3 %;rE]& +tJ02ްKQfo rٔh bQEkLQ9:NS?{ O>!jIğl 20^fv2K>hE: ?IE,~8ު ^ݴS[f!0{@%jYJaDC`2UP5 $xVMlE&MI;M\ݨ-QC"KhU6qv]ᧄ<8U@/\ZB*7H*cy37|~QzĥoEUv7zyO 3ԵuD]%ĩJʹ o>}T5#cPMn#sǏ$S M|iXZ6:u=EE۰pWꑬK-G7~E0j/]Ep>L}lqEpm$ }N2 kN-[1] K1\럆/{t&>'ns.=pXd>$zǫeI؎f/w M[Jժ b'5 wKiFL sTx:cCn>o:ҽ0NtҹfzH'-/ǽ=;OdΦ3r)>rbfx'|8[.Xnh1WJ-"j*~.糛G]}ÚYwR1jd/éPF?HM9!QĿƦ6薩3m˼v\|8nOբgӅfu|s)|z>"$.ذ <;}ASPĬ<1nĺCNӴ&YxI#j1?ȋZcKx%{˘ 8ZJ.X{x1Zt|.$Qcs t%Eү%# ByVЕ0W\fkAO;>w@TP!3 ]Ţ`˼(BlZ觹Y%xzP;8/k)W.yXlesƽvO0[uKG#߱EũeV:=lIƉ,BdLz~7DK =!=;lAgΠ(jC!"/7HhFw%ażO~klyjUK+caXG[D?e-ȮT30|bkNl|Wۡ%v&mZwPpVxl{oN'0`f"SSmb'h=N&p \Ct"׌s[Xu6E;1 S塒f?+-Sd>?~=5Z}yMj sI%jTXg{=1xrZ,>ea0Y߈-m9tV,:kU%e&T:t@m-;PXW|-Z䲲NЁEπ=z~:ӖYn= DE(`ٔ"0qwbND--n-9/Zxh;ZW'֡Q]l=@})+2 蚑pPI"$vkE,Q26㨣/ld'X O00A!ӚYaҊ)P^NceY僧6b!9M.l/u VyN5eM hfb JT923\j2b:x *Ij5FPd-7}=QOg8aI |i $Ʉ%T\qIxd&aBx"٩y5m K)k+3"JѓHzAf~F ] p<S\B^y U) K9(RiSUثé VrmaS5ܤyڌ?xsxcq ҇82s.$L|>y?@|Hj{0fУBi(J+E[NHs{ a4aqڰ웟Im3ߜ8"< w`}7+'fȋO()#,,LΪ ~8-G8KgmQjoz`tp`CŶz&ҾQ/ JWv]\E?7*]_Ut4VGö~YYY]sS4`jz2'0ðs$N r+ecSBHVAiZ+J;a R+ʾ@։m7t>LG tu{|hhHh B(0F|IDkux'mB)bGjS}q4_@31bYL\nM#N޻սFtz~W$pKqvea]-QO%84xUl._>mjQՉ6| QT3G!O*k pUIeV|~譪ُM.;Q[?#[5:Xh8}BZ&9?෉_d*?;~kk=߃ءXOHUgEjޙbM 5trCc^~GqKM]65̞BP_#$m+ꭺ/iF@C8YemNt; # /J`JTbx17TM#`h:Ɔ#oġ63$H_8b6d.W #][5$6O a uajdN'E7ZkFnX]ltrh ؕQoY1pm:4WzCe2K.LaV"v(L Q̍P4WJx{t]zE/~SQ˘-1'Y1[l"oZ3<Ѝ`z욁ǞvH n+ ,;KFz4бt22&jm@-ط#VDAÖF^^_y|~L0}9ޏq=.|nu睜Io0tjci~8,Y? :tz(t./9c>8Mf \.t iCE_=Q/"GA.1JWWB 8ړ:v/$ Gws0fѻA:Jyd^Ґs!OK<5`@:\ķg1L QxQݠcgۙ6hԊRɓ &!nxc LKRJr*J2RR2+RRRK2KR!xs_{C|f)EśS Ӽxko⤬iKe~p]hYԉc"Cd:N~(jl293L=c;Qj(Pk2 rF$MXA,Y HXo&QG~''Xj~J4T3&(yqZ3+Qǭx8zR@/(f{O97[ME2Ku;6R(c#=urG w0AkZi8mXksHmߜ3pDxH#ص`w+Q&̐?Z34NeQarVwo~4~.Ƈeódv{#~N,M׈ & t"6%Q͔o7̯7TբZt|'! 0/lu4l[׉5݀Vʖ"K -V <|Αx8-a> uǜ^ a30ҴVv$U@GtxhhaL E|XO~7[@(aX'͈YnSZhL6JU7EC'dLE|#]՜3Eg\/ݽ a٬S=/W͐o ) ?Ӳay꒖9ZrWj"G8K4j0H%N_+[1ȫa펢5#r#KDѢaRܳb[7)n*.{W42f ai+@).t0=DvOc?bHPar񕙋c% Oz4б4!i6~Է#o^FAÑZ7@}z~ly'IǕm{8HBg4k O&Vqශ!g$?,ph PVsG1u@,72p \F O^y(H"Q6tS3JGg=6: ptwz?gOi0#DS ,|\ȫSR04UW2]0E :\Ɉo F4J{ ,x6 ]9 D<X%EG[100644 README.md""SA.{>xUyEMUz݂5)4Epg{.LŒϓ$6y2$=BƢUu100644 main.c %eᯭ2sݙpK:tHv︦H5ZG'+jn7Im/A/uUZk_'1Y,wx'3/-_7)517kMFY"x{i´VOy)q`z8# xA0 y~1$UOCᓵ^FqNNn v"Q $WLV;]hFV" I-{'s i3r>*4?m5$rpA/{,=q{JWBx̴iOƹ_vG+})鰼2/َ U2xV]lW:?O]'v69wc{7m78qRBbOvv̝Ν>PTQKU K*4K#JA #5/URR8'ؗ3;sw{A (otg(5Jӏ>x嚂uB"pAs*g02t: e#@ 𭰑Z 6_?~p-26]7 mGaC7[w݆\sJoj5( WayfzBN_jm <\%fjD|GǺ!Y8kL9y}d*̧%Kw :bU8iT~@ԹX?]Z3Y쇺xlBAuN`?]`zX+%Cg}=`P (.XLo1X.v-lzGBe '`PF#Ayr^e_=RADb{fՔDؖƉqIJ?G9,Ydwz9P˂co?ܳfΑEpelŌ?B1MP*04x.Fn=$ WB,μ L -wt]BJN=7PD/ T͢,wࢌ}gkf{彷B26GGa+v̎y,.P&g6>pN ! .jѿs[qd诃JH #P[5r^AU|IN08{k&Rld%gW¶`+uA C_eGř>X  ډd_ř[Υak,;ν@'X?9h175 O7S_0 <5\A</^FU 2ܺӼ~*Ϯ͡cē/LeJQWzR~JoOl<'@u3Jܻxk2n4$uA(ed%`)oqX[Dl99|Y"T(ٝ\^pXIϧ~lXCr!/N%BS: d<=l9ɶ9?'TN1nqj7H[o V$yRR<>ۘlHU܆zx;q <,.e> mX$X3sS7G`LI-]ؒ=vg*LV9SXW(I-.V(.HMMQ((L,)VHܬ u"xMON1+HC ҕD>{m|ׅgNNv|xŌi0W2  Ab1Hqxdh'l يUEx"2Pq~'}gN4oDH#:Z 9U@ \kU;Eϒ 97{{2U_*D!&Ӷhցqz߸u1nѨʮ%KCh,nԴ܍l6pxi)2O]TĔ̼RR2st$D/hVx{J ,-Y6RW4MxqcWA^nNVAjfs&e&aYxkS;bNchoB:\p ,d,iV9Юdaw笴!W,_8s2xSd<:N=IgggC]Iye$.+h@4$dbtȜ>^P^(ڇ=Hk$iAIβyx9MUV2, >cw{i '3 `܋"bI9x$A9"^Q e)h'y@ur1S]ؿ@df,KBX @גdE,+qB^[/kKF{cϦu.82u8ԗxV_+qZ<G CR+[YӨj+Y-k-+;|Ӏ9kSN8}8L~/qbMrp\X>.) c]Ta1APWtdV댡e B* yttŶBSAXH$(4Yd)a%$1vRP>$Gmc)Y.}9qn]?[,!a֮xi:c'^l;Xi+ ӸoӢ6qcpd%K*64Җ e 3An8C]rVQK2y ed{?`ᜁܮZm 1F\\NBnMU͖4)XY,! H$ɠ>98&SZlj($WanB3`:P@>[Iɑ[/[_DnWޯY=ae4@߅q5eU 2,qvu4 ܓ(@fi_D ޏ3`:4|O:Hdq@ %GRJmی*$rtnTpVM;^5Wh_`)Z31X8pVeͰn6Jh41JRP؛* uvЧJ+9+@HN,ryҔmc|\&PrӵpINTwIƁEp-G}`u yPKI{i;#,(K֖="/_ƵXEɕ/S B-CR/f +BDbmvg1LFbT3Ph02r(p6)'YAS8+Sʰq6j9vT+Y8(Q6N A^?\LiH0M R<'vېPY…%WIqI%Ӭ k=P a8_,W9j%4 LH9=Qql{<D[PT]wјLAl@ 6I>;AK32A)ݒ% ^d?H2-0 M[  : [ Rq}oi>@IK(\vT~4b![Pµ Pg+Xv<q9T)O* [p^]OGh IbzbNbUeH E UH|$95Q m}%AhfF:1wLD,"Qu, d=Q )TрVWU"V'K UyK.ofFYD0 ^mHՖŠZ(bRšcw~~*oΧ_%k_"-U`Y* 8w_E~Zxx}=\%{ ^ fVd;}<-O)_-Vƙ-D<{O'p:pe%[ ZBaCڂ1v,*@"e"0KƇVkS7:f(UFnv2`iTέN߮BRIF |iWGhXJS:LlTE>`߭ڭ#{ba$o OuLa"K''gX;W~(+cK}rYagƱ <aY~'>|xE*K/&  x1#iϡve;cW{!y-bz0B>(yQw=8M[@P:TnP)rTVnJ5w.5;u_Hr ͍-DW>l7-H~Zu"Z߮2 RLFڛdJ"8̼*9>/?>SBL1ֳ8/zSzocةhYP/*)2135JEӱ萺G]˯:5Hv̶ӏ]Y"(F2E)M`̨ b+'aY 54B 6 0xk 8Ayr,*f)1}-Ҥd%Ԝb-}ɛ'd-O*MS(N-2Rj&˳$d&+g(ŧVdLe\"3y, LdՕKTkbd~VYH7ox{ Ls0ndiۼ7Jr2K xPhPpjY"XM&qt(.)K6 9x[kBz(1M6bTQ9 }/FYt-ǔSfCͿM&P\aP\ "*dI9S((L)QHL(Q0RU1* J `+ A,`l}u[WU:tx[sO 'ɣ8Y}`gVN`16 ̷⺷xXQs6~Wr\=%M:2bFc1LH]$cI;=?^V~Z8'cHO,$ =FxLA?JZ'{Q3K*}.fgeQʲ, V9 #TDQPѻ8U݈fգFX;k'ŒgΨ)~!$ax zqwԳ'sF|B;a׾S fV>_&"=DkϪҵH"6Ϣ[Ξyj`HeW0 oY"*7V?[d>$(ɜtXrtA^ nɼOJE|,aG ժ~v4 hlSeDqO>/$r+'$AzR|]_⤶6)uIL{9 =N# N%s&gO A-c%KYa}iAތy̷qZ4e0sdzPC؉dIN"B\8dRE>=5n 1i8&E)ыXr\tP|;jDg=wOeJDKeKf-X0brKdIWM}w2[}"(`٠5%Iψ6LzXEbAӌGLW*GMTL<g >HbCWp8ܩnIL}{Zh>׶0-@ LG_NqбQj*#&pz:£jBW 9KSe42ŏxr48b7QJkSMtx޿)DD~U_FA c@3 Jk¢m?o..4+~TF\F?v'  )<"KhBQDTZ"&ygܼ`7}sY'M<MI,Pǃ,sbW,enhFj(U4hnhuUFcP*+ l>!jU@ ;(ĺWj6ѵRES C.o4e|{qgp3^>UacU~R-[n)-C2 4dL*"*aK`ؽ`2d79<Lz~UkX^,4[,toA\V13]ǥ1PR{]shW5¨W ^@cU4)6qr͞/197q|~P5ޑ)ŗݛs4 >NOp C6Uq}g$z*Bj!.\ATp3!rFMRbKl I:cfv~yӽGW! F&܃9JqXeSpf>՚.ӗǂlGkls/q@ FGGYE,eU8xw\U}#M ,+B̐*p 9Ns! im)-bUzzyw?+^z/.zSYlҼ҂ĜTʂTb%x//17,&4Cm*GQa'jYx{i w,UDN`۟X*%Az[mJr7 ;/Yӫ?{,8x340031QOI)Md!c…[._8 xW[o0~WX&9 0Hi>L{I͌iU;@RZU5|;:K"E[1APZXd♃YOE*xwYkB>0Xqe,hK(oD\hD!=r& T8, fŇY6e҂ipmJEs<#|8}a]q=`_{HV9Rh1=t\(P35t q>{ |T%GG!+ٛTnK(OW7Y"69$!z#K9cc he.I!_}MY|y3zqM]#: 4<a"[Z=eƟu`܂-`[j`:Ix;*wHf fyfYfҒ;l“9&撟lCG9ϵpso>(D#/$>371=Ugr \^򼋱˦6'/[~z`x[s 1)go'ѥ\fUjf <=xùs:okPRQjUF\y)i\%S|݃mt]`U4LKp+dOϩ묐<9YuM ٩Ey9zV ^\ũE9I a($^UZ_jK..L+-/QMUP3B<$C!'3/غ hBn>NT RHIM̃Z 6f14/Aq&ilx340031QK,L/Je~U\EK6ы-q4MNMIesnz|GZ̼Ēbtќ黼 xt }R9_UZ_ZʶJf-fMz7.-?($7!:O7 )>~NߵMBe&q~.XDZ'~{=\YNN>i&ח(Xy /=wƑ>iPEy%99%y yNxߔۍ<>APy%)`=TW_+o-*-N-J/LI8~y\Q0kל_xKhA`' ޑ:wG6"ywZkg_ʎ;‘YKPw2 g xM@Ek+n$P,jL+ ;qfYEH3;$wz:.Z Qb9̑(DZXǟdKZªp %tB숦f Uk9Qq:NjDcX9$Xڿ?JxVMo6WE P!A4Kw͘"rmKfggg;ua(i^7o !>Q5e|?~,Or$iU$;NNefԏ|igztT2R}69Vu%oL_4*w6օ;_/ʥ4`$iJ&ss< g[8iD{픥 %cS  $>WAX(z~mAԫ ~1wW/IzSXxz0 O(U67<;| 3D!?A/Iƶ2 ̜ϋkG\EN&u=zc`6TuR S-v7Uƞu\Ԓ,45h1|U4._;aFR"+Nk )Yj 1۽̉&n/n1'o%]I߷ VG҅ :;ZBX/K'*f,!4c_mf\qOHӴ s"HE+l}\JZ_'ݞC* aAb ik%%| *TavdCf0 |*uW%tl`dwB'NKEa"bYWABN|ɒSwxݗ}L2G^5Frc*{DY$ ̗*R p+(<{kK8wgE.3H;e?"kS*rMXwӉԜqi* .c(WӐ emHL뗜V\#CBxڜx` &wӎ:>@*~uJ?rۼ?])ǚRx}wזG(#쳞^h @hMk?Ԉ_FP{uS!#pnTСZJZ 83%mFr}℆g}S W!,ע}TOYhaDgx}Tmo5R%%**$z&^{]ǻ]Xόgy<6DiYzt'Koyd۰UX-!(z):iVPsTmлdE$(A= W<(սAVnѶ#\W 7LNsC/|#F~#a$eu&#v-Hb D=T,;ZC!4dGzjRDqȻMVe8}%Re2;l=>q܏Q}9FaS}Y68p(ttb,lx 9Dr Ճ)R% 3 q~~N?yxtku1 1],Pfف1'BRY:c.W 6ҙHH o)B&ɴ]M2ﮪ87엒y\+&Ef^&i3ֻ~v+>yVLCP<a88l6}+`i4R6SgQ3,Q9}rx&Z~=sڹH ڤWr%hN.Ov?&'U|UUǩQѶu[(ͬ]_ZtU>]M߸quc̨]_^]IoZZA}}\{ ͣl^eh?h%b]3A C*7q.Ciy|a̓4܈0đv0{ 6)qAU%z . x\ysF?EG^ qʵ؎-'qh@4D;>@R]DFxLY2MWtmԣOmߩcQ֕E3m1+W}U+SV^-VfcL>ge)Whug{m ڙqjƅq p \_ԕUq -~#EvtZ]4Xw;tYfٶυ FMչL?ps*jm2..D[=ԅnli8+` sC+hp~ښ.o3t_8][{/. *E9ٽcV~aog- 8:rU}æɺn~o$Q՚4hL_nڪ3ӳ}ˣ>=k (/D_GGnpۦ-u]5c{BM]X v wn~:g`"{̌GY)/_`.bAKmۛn6<[>1'rE X2sDk3PRS^"tXywٿQhtP_+Oȧ:ܺ.,|/@A\T(Ew-43GV(X<.aBhb v᪲nؑ{YUHU@7V L*ٔoyk:~e]EM:ȯs/Khz-w%*ꞸufޭTo4W`R&05pG G'4gp]dm^943k۲jn:u/91,'%r47 <9pؿC+"6E&55/y(+Q-voDDeݦ@6Ӳys'B`Yvjxj@ZMVi늶e5%6̑8{Ύ%84)vm(dQkIѳneR/LGlSTDo;sy^aEDb]Wi`vlmasZ_(K4#zQ$7+;lֺ]1ۖ"+%:YQՊ`Pz޵|%2G(va\</ԎYuy]ve;]/UM(SjcAq%xIs}MhL C=i*1ϔnSх'`o(+@pOQd*z0d(4?^=M9̇λu24k BVuui?ƦrhE (~[/nM˶،߿xً߽M|2j9 RܕW<ĩd|XW$RU9R VM $A;J-eoYEbp!hea'6Cؙ 92C@x^$JgT_m۩98ci@lEGkf.?XP.VX ,R{x& h?J)%dlwK`[yN#sK9 Ben$=kCxRޅ ;wܻL8/Z6%A: qူ7U3*we(9/S0a0"S~a'ckAu4DpnG'LJc[@6/aMrNywd WL`b$ rNݒ *fiO>GtZlYf’3#p*$%,-QQe%m|D@M'$97y -`YÊ&цS>&/,;Jdge0i׽.i`ON}1-:RibgDZl- $+pfwY)$WZlg=g7GI# iJNCS3 hD״pp viǥS[ v@F6GxIvt2J\Ϣ^MNf| Ÿgt`LWEf֍e݌ww E_9r+pd/ IWUKMif|rEE- Քq1%iKfT1d2]("(NDRj43P/H~Q)H10T9E`@@BrVCZ*rb-"1c\5̦,"h &%1m"Z{+S<8;JFDJRXST _.!~c^C^C'+I.6 ЙX\+jᤀIX*;5W`M@7(R측ou%V[LDLnltw&X.Xʟ3!2ac1*u܂:Ϲ5نhF BN\QKx 2!3!L4X]]mq6<*wwTwv0{-fenf% |"H$^N8O3J!z,CtVvʬ{yr>/ڙ).fCS.#|ogfp;e|C%ۺ*%¯ѷ&sS's$V[jjxOģBS)JӾ<~ qvbT$Ef/ztz@>@%BOCƽ3p9 ISCsi.uO?(§͸|‹yt멒b]q pL`'ey!_$D (Ň풓]"bćܩ"C4V{dq9lpC\>}͸I-Oqemf=w @':ٶaͦbBI sscA7R甛 C_Я/f}7ɦF(K|$9CgBB@kOaQy]l''/RovH=#<@`O$:xKҼrؽ[OOQd19%Sk!hQXgוtUtxBp $0"DYd賒5U.x \YT NwFnG}6ajn 5GHFvC@:z.%c񑯥6фa%%̆ +0M, @C*xSl C!"lvV/šɧffRAtdY--ZȭGCB$rrғ*N[S@ g(I,Y Źֽ[~_Fzɞkd=kTWTZGTc`uCgnM{CÈOӴf Ӄ]YP#Ӷkc nM013q!}t)_vmI"yRjς'7mzqMЃc8~>3.GAR0̠T1hq kNDw@IӐK dm9j\-0G6anphG\L"8aUC1O$љw{1b⎑|y?~p"~ % <"Y_B8>SNbsX-ڸУ[-A[GX .~:k;/4P(XXDgntwZT@Pz$l+Bl*I|)TE:Rp%$SSf)up* X(NLy7TvϤ/x8K4ܰ'LMŠ͚cNq19ItYp=Oc@h50yXIǻ&0U0HMSc+S3~| v] ;>yG^hY]a# ~Vu3A;8qctExs{ĩ(L'MSUXVCFA${/]lpTD~_0?Y5k^ַS:'s6u$8Y[MQLm7sƊ?y\4 EI|@ )<$dsO'IPR|Ǵ ΰh xg$-j@'e1O xcZ X'2rDhHҮueXL+h v&ܯDwiI5EUϲ0 y4u82 \Ȝ+̌W,~=-1o8@50>}q$uĻ8 㛙+g^7'ZP'nS'/Qtw!?5Jyæ/TwPDsӥJ&_BMhD<<_$g~K/_嚇&liqj>$?nf=Q=C@0X h csoT5@,^cwĄx>ly!lԪ$KP3&%/#SZSLMpjbVt!m([6h.) B=\ä,(l<S3w`2# 5r\yu;LI.sg 9z.V tpV-% .2^iS¼д@ ^p3 qDXҗ6% C1p\awHzόƧjS|>5Uyu8UUxF9ỠdDu5ƎwO@Ȅ'ә|8O tp?Ok)>Ho9*9`0ĈImh i tjcj2}=B7s q>8!)p\;8-;TˍnMz9I亼#SVadxib4.o7[n 'zH,iHs}X{٠xPl* 4:R}xX"v1 Cq;iH8Ś[nP@Y(JSnJےLw (rFx.}i==tb?<*l[4"WD7t*Exntv V"{vi8AtXkIn=|["/8K __\<4OBr'onn P;>,,_WCb][vZc3 ͫM;hTV1O_9HP^#gBV\&k#6I=3$D8+s%c9fxA`cy|CQh6?qaZB(2nį2cD7+P, .9&yQ @ͯNH5eE SNNLۈTx ܨE yT́$7]kkk׹3'{AT{[0ľSRW49Jp]}~!o`Ű` q| CTi~ҿ`bt6#"a"bͿz,XtKr w*kN4lZ,&a%;1Iɍ>h$ͬ'o|Ux둸'a[bqqjQZqHm| nx{&LpCchn6+6xSn +VʁKYE"߁PA@Uv$nJ[3hH@*hK%-eF&Rލ\!5ҍ ]Ņs%jCJʈB'=̈ǃФ?"N5@YS|+sx4rZlջEV&0ZGiar`ga"yapZ.Ha[f8 ;\.}f3k˰=8$Ϥ36 J빡ɚ'+:$?>%-K6Oɑ|̋V''@NAGk9Ɨˤ]l3 es~x: \AEɩ 9)y\؊luB#-(5/9k*u>͎ͯM>o1mul6OgvOJQ(K,LLI-1y ײԼԼ"PrS$G{Td|Fb^JNjQBZi^rIf~BZ~BIFX^ 593-35E! '/17u_'n)" -,T9N 8Xv\x[sl&Mo91էz`ZLʣ x31Ԝ|+] ݗb<~af+Q3sSM=FSikEOF &zCRKRS~zp6~Ju-TMJjYjN~Aj^n l-~}~Bեe0D$ B}n +:;[ӏCʦ_@e$$d,ɿ)=y|\R9JKSK3SRA5W+}t%B,zm|x4IDA/=$3=/(33UMs]I/Y~D/q[^_x{&HpCchj͒N̓c8L r*&pT(-Iw x{6mĉM(=qk]m0 SOYxmT]h\Enc۝nL$K6E8m M6 j]%;{lvdf3MP|8T-AD/}(>P "swWޟ׼/233R,:tf^~MeG?/Dh67kk^*yMN(rwyq0.aۑ[11sc'4`+ T<OH*$p5DP}CBM55^\6lz[XehiOW'7 PǟObwe`q˃`O:uEze׶YWj;e]聽_87k7}s*gJ<.TeK#N߬ӵ_뻎M% o/ |hvd`8rJ,MBl~{Ox6\=}N؆J#OG/FHF݋R KO݈|zoT/`ԸDn5 ;:sYܚNyľǰRx| ]WUm\mݺ%﯑qxbbc^U>Rzc1z%ǂfkEB uXW"VxR ]xZHJaƸUȨ5qE`(դr*!qӳ%;eEf鄳\γIWs&(=ax[s w}Rj\aM%ͪ x۞ߗNl%Fb| xKI-K/H-(+.II,(pfBT,-xyc¬Du=K3sJSRsJM '3s@x3bB x340031QK,L/Je0oZ/rtBT&fe2i7vݷ&sHC=PZÖ^KsH.w!Z {yQf|3a&zlϨ}*7^df&Q0֍bn;ı;FZ,z R_-Y]:jܴii埧wfA=Z%lv"vxA;,/AJ5%vfRyeE%) 992jn%/(5Ufr#}bYx9kCd^A<Ԕ<%MiydT7[ڱ>=B(\":T0(];5tߕ}\"'tUWub-k]4^EN)`OG{e-x;y"4=ߥ]?r|ൈwM4Vq.o+m,713hY9U(weu '{0DɼVo/}{|X249BqbnANj1坍{nGJ=[ku!iҕ7g$oYyF M0Mw6LRO!h/l+ny"o.g=Д#ofyu,Px\ 6t+\mќ~p> Q100644 main.c[I:j|La^+"-S>aQ> %Vca!}&kx: Pf9dqtlO+"nk|6$JopMXࠓa!y(x31b&yM9Әvxg$1V=!2Q-c]ީ[]_:x340031QOI)MdHqٛ e]}qyp x340031Q)M+Kg4Ӥ)qlSy)B姤1QϤ7^tP5)EziE y;g7NA=6?'*+K-*awīݛNf %Hz;oyxqrĜԉk]6 !xAO0 >6#t]`\*N8 U(TmFNk Eʓ~N۔;ckr>T-yݧ=wQrUiAMTXgʂjU6OF8#Y=%񚮩FJ{>:hgoKNtE~8؟A/iIDzhJ8$kO1E dp-dT3 4KtB}|tSsNNݼ!2KPy,`yl|xv *=>4xTf8WNx@R[w +..Q\W ds05gVp~۸#F&jw100644 vnc.hEr\*}Y8@""xk 8Tztɥ<"pL/YC.7 exAer T6d ukxɞccL>Y^'M xSLKIMSsR23R<̼ĒT KAGG!9?D!9#HA+#DG D(5=$HE3Prj^Jf]*Ax9 8f$udkGo]ded0c=gMߒdVVÓa!S mxsg,f#/JO*Be84d9 prw')%s7/`Q^E$bd> 6EEh*`cN" ɫQ50VK6j3]2x;g!d% t9MNno*6bΌE $xmPJa1EjMFg2j:d2?d ACbaFE(nVBZE˰E7t7ù;߹r/FoS!Kf _0>#I wlmgRN{Q |K,"">mT\X""'ZYk8zOY\E=O?YC :+>F~L( טV5ݱKe%[tUdj@Լj¿dnf|0-˰U 5zR+{:K3^t^h׏~z_F-)bM4>jU,FVWX}#0'5#jŲ IdC(X.2l]˓/5$xr ](<Gh~q04Vnq6lt)BNޗцS I100644 main.c9ԙJ.>?ٛ+|+0~¸1bWСӈ'o-|sp11`kS\=3#+@Dox;1c3#60=d>9xsg;hA,>2x[iZ Lkm`^TQ\R$mlჸJ\PA~(jptGQl)Wiw֗La0->!A>Q řUi &:G? tsHl6 גWLSOIյ+H,J+R}Ɍ")E y9 99) y %9e9 J[̗lLiڈRK=xSKr52JR4Ƨ%h(4j|5j7΍dE퇐:pfehlΛ|ocxPh7ycf+s-GxC6acM2)cRQ100644 main.cƺ^*Aٳ+ 3 xg;hA켛_afx[ij ɜ'q:nCm^E.ܒ<%ͅ K ɅNL LbY6ϯȊ,ٴK)?[jVF0נ`O O?w GɊ!~nA>p 2Db32K2sK2sSEH/$,14U,85YVRɅb (tB}|47Ϟ$c x\66PgGv7=100644 main.cvʼOt9f$+RB/ U)pewW@D(Jlfx[{f7ɋ<$'xuUmLfO;CŇ"rx0$NORKE1љ"?,.KKd˒mYca0fO˲e6d¶,&&˒=q֤Io>.v݇c9r{BMw ]M,zJe:F'P -?wg(ުerg$ yk}Uu#CѾ: GM<| rolD#.k) OrVMi&Q\$#N#ݐq `^4 b} ︭Dž>=rB!p(+ ׁ̹|%>[F6u־Qk8CUg۫o& E%Par!?b#Md$52RuDSXsfc|꤁b,,>_i}2֕C[,)zHV1ǎbS4C5/:)W:u{E+ 52SSn UFp@,MsOvZ*x:p~|6(F⤎}F}#΅ ?Vbp b;`i4~Uz.l6R1$jb)i&U1?rQI)||#XRUS7M[ ᆚDANҌUq,8s8ZﶃQ*C/qgk/ɘ*cdHgꝺxq;5@0vou>Q o{f9+q: W(n1͐F9U'H3UQ$hBs w^\ uΣh'|$"\PfmUX)i*6RT!g+lJ5:YhЪg  6Xo\Ꮾ2\#66Usx0G2M =сH(ZccV%W9_yrJUfBGG:ǂHp{0N.nЄhI6йlP= ZѰwbүa #I} {Piy2(L؜epeyeUzD$-L=;]c`,mwfqk):.{9QLiuu4[9.nUdZ6: UWZ H'7tm~k^ot$Y6gܮCi$1.Q,( 1Cӂ"LdBLdnnr1,eӀdLirGWcyHw"3ɸ,2I')DhRH*i2YjHʏѲtI ,u\ jDoth\m^]yWjвvrhbن {g_:x31bYMsf Rbm2i Ĕ"٪5D=~ÓW#Ð?G;ܚ+Ti#an8x*|Vxͧs33sKR+JJRKsSJ6}`Bx;3L  &瞜ζ4~ lxvBmL1<%xYms۸_a9ʖhm393˥MN?&! 5EP6q{wB$.}Z.-c{Q"4~!Oz6k4/ P$w:W>>@&&6eR &:Ғ=&CmCSzl/\Y1Gw E%zt6h{4zPL,kEgj$wRZ>^$/{I2Ȫ/Vdwb:3^ 2{$ETY.}qš.i^wIfr%:&6O⋝YjOSI0jC0L d&͠$b3_!\`IV\٪oرn,^M >6)TOy#%nʰLɶ\*`QD`um0 pMo;D"\~e͏U/'Ş1M30Vt_X &.QrR\"ca-|R׶̀?8OdV |E&4Pւ(8EEiސوzVƢxĪIl8M`9U\3o?xZxJVRn|ȉK'ӟG MP6]劥o\ttdXj)M eP ca Wey/dx89ތd lriGЯ&W!v+@@H {M/rt$jp 9ΣW=Ӄe:#Fm{;R/)rG;R5T$F5=/{닋F12!w_|%eӒ (/XpxF 2eW[ !Ԕ\iհc}Z>*[Wƹl}J٪UeP ѣ*Z\D(nfEߙB  Dg.ŏ 5>Chth•3?Pz$m"@" ~)*Q{X!ӑ S喕[! \6EEvævPؚsЄVa$[Rt% P}<,;DMAO.ʌXEYtSvR8^!dO4Gb~k8@0`0*$ q.9`~^1#`:2`'"+f-k\Ѵ6k+vo352T+ҟd>'D5*GFCէ^r CD._{jwrv {"5WEn¼mOD :ҟzGSvyI^Pw{Ad9dwF3o%!F mC`.;nbBL:=x b%3Q/zԦZCqPq͂lPxghJzm#S4C١m+Wf!7𲻘1C`ltP[%pS6I P|%*f Q2 ӟ|0l'y;`ζ'EԔa (B(o ֱz|*Xc/91vgAcY28GCqa.;$ݽݧ4M"n /rhwX# 4Kq>t}#G--_ZdJVn-0sD_l ixk<1!Vu 3 {~4ob4 Lym}dMF <n?[=V|BZQbnjRiZZj^_jjV]軷=/*MLOKf,_Q0teھ2;e,X~1TonbfPJh)sW3#t%ڢ nVeԇ v?g hkjab ʼn9 ٟ& ))xomVϛӶΡJk_ȶ5'Ykhּ)715ڱSt8#G*ϵ˓eYQ px4WSk~+0x)Lҧޗkd1}(`WsGv }kv+0Z~¸1bWСӈ'40000 samplesm0ZitdC 100644 shader.cBZ?ID㬣{ZijTy5 j\4#`lZxC6;7fe= a\pɄ@100644 main.cPy'K u֧.h+W 3x'Ql{Ҽ̼|k. NfbxF|h"36q-sтLs yyI6diR%#柎1&*sksrA P]9YoÝGTp;i.G$#Tr()K֊ A%)i->Pd&d\o174dGaəEt0`asr'e`֬q)t98Oj 2 jpP3}ۜs^8N{$O:^Nkٶɘ~;Y ޫmEsF5Y4[,;[ff~JΞWRٯÞE ^l mxkKܵ" M9WgŪ*Ll2o x@*PCa,?(_;nw0링cF,ó(0b*4iNiE:} Y_lYFYCբe{޲4Ypbie;*v L'iǔG^9 ϋ*,xmQkAeM&miIɄhBi%I٥TЃ?"%=x) ⩠Eax{o>ݳ}m{ִS: v^' =Pq:G<|V*n`RN,0p\K Dx&6ǒN ~ *u%KW*HIc-ee#~jpyL%C_3S+Q7+5h[/ !f!!6Xu:$FJ!!.v>4 >|o}%y>찚\T۶HMv#̓(55 Ūt#=idƳyut`NA13ZݒZh0O ׅц`Lnߜ0GSNޙ^i!9#~*ϼr};Go. .8C`4lIzatNxi4KjՄdcµe/J١x31Ĕ"1gjhi>صv=?R 6x340031Q)M+Kg4Ӥ)qlSy)B姤1l0\&8K>G%?xk0W}RUqԤ> 0loV\,e&=Xdlw'՚{% _re)o;W*M+kEt'WI\xϕNɠYVʑl661k8Z;7dX߄IֵkV uv'j==,^*YzE=9 q, Džq@P!n>$ɦ0_#1F9E.bݯN%֟J.JV#CniO-vVs#O0nJN6Ĺ>rObT.ȈO0!C,:SfT+ewY_/XzoΫCKS v :Ƌ8/d$H=Igcgoxmo6C1;8t)[WC7CDDdQ)j=_$RH"wiJ#?vN_#!?w?f^ܒ/_o ECp-;𒉶 ݳ5Z-\(hMݯN;&U+O!yvkcyqFeMnp^f}W̵ R2kijGDuM^- 6ƕ@ Mⱦ4"%Cyfi+^fbÿlBM?z惔A*ZK1w 2jCke&͚ ;^~nwt ^2Վ5&jQOGrg%bi+0ZW&+-OUxc֮ǵx6 l8lR]4Pr9OEuQ9/&SJ=Va~%Z?{{]J4Idh2E#v_x:S~͏U忯GQU&e61(2LrqŖ"cm,|THpR%km5ٌN+_^&'0PwLkk"܉Eik`o?LDX+cQ Åu/˖H^uaȺ~=Ѻ]!WN$Sg6(1^G1'<#Ӄ'ʌFj3z7ډ>WL=OQ!ߔLU_!ĶIܫ{g`ReӴ/D5c5L1Q.L0^@˛J {^DwC~k./YM޳M>8`b7ph7 H{}u/[䟙5j^d;x?'у%*LJP#hOb3kR!z8Q^^(ِH :AhлU >/ѫWKk~JB= obP@"$!@α#r'D:кgRܱ#Xa2q)*Bk.@ڐ-PJ- _ 0C"85 0l)JI4Yi QSRW"rFTOS]-9 Ȏ@كs€PPG%?uLZ09'<"*f-諣\h1ޜ65ގo6TP%D%JТB.hb1T]%wJdC ! ڌl6%=)o=h#]sϢɠ#59wM=Sx$C")AHM (xh@o0ֵXLNQT߂@-V3m [j$HWNk;{k#!X Ӽ [Zu`flߪ!"+zGáodaj WաR`S&Mmh, QK(oØdy+D(ӟ\S@xLw78鏂Y۞Q:Ą1tȗkiVXuXq1$ﰃ\!(}#% Oz1tEiϭ6sgx{DM ,*t8e7ǚkqa&v|4S|=3N4tNs1~ϋc[AFxN51}}3W:i*9#=aFV臺'2 75B4>yJ>$.\*P-b?r:ef0G˜Ⱥ $~zV=Im>2+GֈBs4sMΥ:s`HӲ,BO˔L Tjnly9-9m]dRr|5++䞻?Ŗ'jŒTía OǛ6mbD+V lr $~,wZ-G 1I+敋ap {`ھEJCBxp]AF E&߿&D&sJMnu-'I{ǶnX2_7蟐p~E&^1"^9JZ]6G¦H\pA  E,rJ- {9pŲt2psLd yx;qcB&~DZMԯOߙTzVnFsx6Sy˙\Y63> 5xVE?f6eiy#ϩ[{mĦ) |?)T0rrD=9yf6͢ '|lӺFOq+xP,3k FL'3I,xZe˙J* R5|t4lm|BC<}6fd~e3'^in WH -|_HjCn9 6 22r}x!) VTo'))<^x[,_jn̟E2J RKR+`2'fͩ<̛{9ߍ-!xl6<&w<}Wa-,&h?zA!P% d“+v҄^(a0RTKZ]vQ^;#K1xxUn@}+b8MTm#E6"ԲU[5 eIF.\ Y ϶"bIL| #Ĺ[8Cd02 ")A‡EJU+XkwM&xD8mnJQ{$q06BKQ<}fQw [~9ԙ2,d̃\W!,KE"y |de2 L_xZdQ ϕr*94;m7xlFHkHZn7tx~'#2m{h7mD糖[u[<Q:MrJvuy?w[ؘ_ l-bwdrnm§)r"'mwl~|l>7`)x340031Q)M+Kg4Ӥ)qlSy)B姤1(552xqFP˪K] 0,nx̾!Q>18891'UV@TAW(TW0Q@SA (m`4YI+9ɖq%fM+5/ =x;vJe˙J* R5|t4lm|BC<}6fdfן|MD}gQ ~ *DgQw 9ɝy94A Sv[.z n'؜)`;p&+>%sAIN>è49;y3'^i9bԀ\Ĕ"]GUY'wmvdd0E|x{ofIw(D$عxV[o"7~WT[bD}ڔT,EzQ h$]{|lυ%QT!ܿs|^,(%c,*20Nx2[LNԳ"^=Am(I '::q*׋bTD]-աngD3b%1lzI膆D4  2 Yg^ƞȭZ5j^1/'cem{2RQ<z$mAH(xm B:?2$t6@Aۤ+I穈RgxzZ)b*Fk66 4zmџ,o"0֘Ma5х7qa$[g3}ڲ>+m튶rGɣHM)'lu@s*VN[ޓ܏3UA lgT@2D %Lh0pU"OMShmt˫mt3ia,|@wxf>&r\-):փE*W`Xq]mT4oPx"I'=jCHhWS{ ~OPлud_٦o¯nG7MCK7IAzzͻ\Q<|w;ҧWo._ sVXY6@7yqCvm#O}9c8@\=o6 ?F1OO@sKӲ-F^^o< ?8{>F{_J}8˭_LsͼZ23xkCG 7VfDe*_xl6<&w<}Wy߄͚M2_r_&+v҄^(a0RTKZ]vQ^;#]5nxδiCxք:-msx!2Wm]Ͻ䟳+nWx{iCx:1T >piw+RN1JWqz,mTd\ 1vx#@3Ww|v $JDГ#"Ux}kY̼ҔT̤IJԲT}(crmғ)<[њ  cxo9 0B#MV,6DHMbM 8100644 main.cR-ffZ1C+sl'9Q6ZMW lFU\՜ȓ#o; nx&%};FF.)Hx#j>+ K3x{ifKU֖,&f۹ VxVn0+)ȉF>M.m(riBP,*&*IV{ds,yybBA_ O_ uT^Ţݳ^+~ц"2V x 㛺wh+{!E2v"TB]9ȂC^jqwP(omv[bL%M(b(п\HzB++5J`ѿWVD?fVtxe ߺr8m`51L[%F -dPހhe*C({)Z.vfJmkP.vTJmcw )j.VIo z).<9(lxC Ty.Br{TLoG?(mr^ `+(Ϝr\n27p6xUoHm=*8~RlZ>΅r&eڝ=~|H?ҩzz/ l4X1xOGNU9t3ݻ }n5qN>ɇ_;|ع$-ܱGSvN W8uKweL*C9ѶXI)86|b2}f܄Qz^HSB>aC+b?-`h-LxmQkA'_G#tliMPF+"bALRnҢz&<&ؿAI|AirQRPʌXb;w <E{qW3G|?6 20l,I& O9, Bgeѳ3%8pUlP `>9_z-wh<ȄK ]G e4]*fq𱋠>0,| 4Z^ 0`iXȩHrP/Y΄[Hq Ėqw/xh A"ll\=ug$)LA>ǚz,&C0: ^BƭO Mi|wVA~B֫oPuwN[Д15j"t@pjχμoKһSZBXwxq9˜6ht\,*TB"WJ3IFBSN0FVޕO$^xvTddD 9*3:&32Y@7?!bF[TtabTsvMV!j= յI FVM-@\OFl>lVJyS5Ml(ӱQɨ)n-"uMQ<OlSl ^큪d#7@Gi9vA0z^B ۪: "pp۸ ׽BooN^uu/=[w*Ս9ޘCjx_]GDI6{lx[1dn9IUF/3&Mvd؜t ">x|iCj2|<'SaV yx{δi0fu|,yz*l7;yCypd)Mޜ⹅is$ ٟ $%ɶ8 $9{:QaSCɗ36fl`2 wIQNjFAbIY! PPPWTX_`Zl&bt@tK2+47 )Q3YX/Gkw{`l4`<5'gjEf5 ,zZxFG kernel.lua" HGf`fTWBh uffix - pathiTj& x&100644 .gitignore&rޟ  1~~&75p"vN:q^q\/ hltT¬JR.ڟ { դx56 k (k#}/p100644 main.c_ (@?"0P8z2#c88 '&(NQb?tśLWX#esxx[]GDI6{lƌyipeRH>\OӡH:) 2[!]R\ZR$+EiRoH>6#@QVC뼈h2 7Ѝ9NGnst((C ;@@=/;;Pu I07 $k <0y!w_I^TDDU|-@+  k~YjmAb:\-ާ3RJ;Ǽ,ևF47c*ӑSrWOb`wy d''pV'popWi`MBv,,bƊH0]ї"<=c*6[-B!F\7qOxxXjL)Qj{@ӳ.O&yp5Vt_6eC W_DJ*JXHk"c?*I4zlͣϿ1}U|zMG {<$&4&7H]ڃKJX!#K3phUNr'@c/C"$#dY \Vv${Q X'Wٞ\="K玥aB\0M7'M1zYDsl|f> S^;i/n"#nTxr/dŇRΫkE2 UHX]ibT8kkIT$^mpt^>M{/=1%吴¥PXW i?EA vx}՟3_C/_ ~L8>dnϷ0mTrY]8))ƠDt8IYkKT4e)Q ,RkWuPm|$'2VRI<̒Y)4ˀIhܽȓ"%\5SaKp/7//~[]HK_W, Ҟeó,цcq0,v7 @fa_D %'ʳ|O2$K^ŕڦKf MqmR.v>o)u8i̡*"Kmlok<0$yfX699^H]h2 70?m^J&elZekJƁE-GU:58çfh}'7 v:ϻD)7 ɰÆ i*~rd&K'I8bk֙_m(/G` WkkuژhKHA0<.͖xo'׃؃rr5%N)5zMRn@Bǂ'}#@[n% Tk) p\`xn4vI,IEyW첺0D2 Jp9-#!dBf'+CyNiR֍lyyut?(S1t:is()̒6?H5 F1qZ <[ \IuoS5jZB}b![PvRkµ_ f(w۳,y8OQ%CX(xt~Nt4]w e0`H R %!Bz?%'Ur*\N)G1/D/;E"DueX@/Ӑ@ܥPE Z e7ZF,TvU,n`c;$"0 >-AQ(M@Ӌ }Ԟt=/!{չCk;ge(74]>fel6\'8!@4" {JYq~oTD'[? /+) -&Ehtcy.Ix 7)%Rj{S3BI_=ڱ~*h ,TA>Gj fYy^99y:(6Zj: _)nW 7y %n%I])e6hrc>O g*˄>ÆkI8ZA#oԭZYKCKth |vЌv Z~3A-gmcӚ+@xT s󲟱{ Cb +71M6qCvVV)#0JՋ}2?`u܁@ȅ~lSx]c'Hx1%)uW.54C^׉;6R Ys⸙(Q2cfuY"|3)#eA,gזB#g3NC7"MbfH[%N}C)g̙JV'],UYo 曀f5-J&ՆÚ̋ϫ S櫽aB&}مJb A:^k^0".'[Dhl {4t)1auZ8:JEv+碮+$K!Ɂ%osn!:lDx.g[uDWd^n[qr}Dx5A 09Ńll(]B&I~MD?f <\Y^+?FAW3nk:XVJsʑwU9?ճpDdBɛ f9Z{aJ6~S/xJS]N,Vx[]GDI6{l" HG  s -> %*s (%d)\n", path, data_lenzj NWn"~h#/oe DiBecj\j2k~p*Dx!. 3sF_ ÉbAtckxmTo@VJ(mRTHHAHvq4 M5P!$:0BXvd;$!"v6B&"(X!VBX;;6CN{o4C5`٦Bӆ Z">ab/=;K!퟽Pg)2*4;wm)tV X8JneLJuhWZ+l,Ct-WM^~0 [,`38>cOS9A ѦTj) fy Ю@iu9rȊ\gޯAhc;=_$g6r Fܒ5,aڎrZmcAT|s>VpEy%9P$HO5SQ̡尪v0bwE&HU14oA"1W5IDP0NP%%"DW^wFBI=ӞJn 5t }?1>ţ&jP \nZ(}K'P;>~NQ{jxn=<&n7Ϡ$AcQ"M7ph]2zòqi`ujKX^, mEϡ#8+OdN:i$K1!9dƿ L֔V""o,K}9'HѠlrY1;/O:ZM^V"D:Ak( SI\ D^~YMާ$sQ<` ZAVaygI =@멇6fK+Cr<9sw7X| G@#T/xtqŽ_60fSR@y %E%z䏼by89&噼C@b=iR<9et@RR&%ͩUl'k Jo(h(ZWF}8)Gu&b+Z4ybKEXZ&ߕ0SK'KOR\,3J/l'3gO*FTҼ\&sȫMRG/RP Z)(*8xhjjNnטPNl"!.il//-F#c5&;ʋnr|AxfVXylJK243SJ2t2R33J4@qjIi$=]B<lr !=WOwDd.BZw llڰ1q+ު4^E(`iK"FtA~ )N%)O NU(I$ҥ37,7I"*:Qj͔Yp?TpMf[l7FHyĹ>8ZJXd[W%Xj`;[pf]nI7R_ VKd2pm{JԃRpIEd& -y,KT |U_Q=E)7]zzD04isqOI 6\7wǙj&:. TSб%ĒbtRc ir-bzNTc\b ӳ 54*H(IᴟG|f`,u޴yhWҰ J`<fB yEAmy̹vt/X UC$[ũf[v=ik`4\F$$cqx>U"!]HIXT#YT G*GiUQQ/ˑ{FB%&C! V[{Eo~o2Pu8cnV1{(O!/x%zDױaܜÉjbJy#;|-. oŚ^מz=on\9p 5ա\3y`?"+}bѰw\ ,uxkdAʅ%/?%u&0kdN ^NiB={J〇-D'FW%6Jxtic+"x&;O-994(?D!/?%u*`?]x[þ}.Q׳Y&t)d͞k<: |n0xk 1!pbތf*#x:df o$/AR@!g-IOcεOXʞq&NxuSMo0 Wm59.E^bbdHb4]%6SNJՒ*߿_^^ (IZR#I)IYVUmE.5,^ږB'fCo[Wb,q}a)BEY2QeZP k{lp j=JM2,-<7l램|̺̲)ρJ  Hd3>x=l]*j*qv7XEe4[oiJ[7 嗱0b؁Y:+e+y {t}ً{e.M\n0>aǥ=Q:qJ-DZ aFl[ȵ6H?*Ehx{s)Fւ̼eM;Ox!Ɩ]R9^@1Q0x[þ} \& }5V/d9> m\xx&100644 .gitignoreTx xo໥[Z`&7dFZ LZq<6Τ>Æ17uf100644 main.cxտV[&?[xC6I{o%(~&D.bahz100644 main.c}q7ܴ?ph.唂yUxJ/KK-/N-KJ3J  xm[Na^Ögv  *x4iq&ԢԜ;71{IL^/;y(2lE%\'t49 *>YEɜ[ Bz9 a*8=V˜! F œkYLfbebن6f{"J9 % J: \ %'+`+.)I͛UyGAN4ĢdE[#M.(HLPR-V)/KMTXmi98Х yi@k64Mf:ߣ3x340031QK,L/Je8RhTEK/_zv|ɦ^Ꙉ"A*|1cd!sn7ԤҴ"Q|8Nj :bl晊E+CT$eU4W1t vDM-?UUZXTce{s,%>eSgs4WY rK,&TL~\C̔|q̌(=׫Ԗ_(`t^}Uxr^Om-xR6q B=#rQmJ3ɾ 飶N!|k,*|d"q3\ 6{;#=\%/kx{vmhf_ɼxXmoF_1d04 (8Z(;+rIY/q,-g^wgf59ssD ӘC0c{8 &'8KSxy@S5DeDBm3O""=dQ0VU\ ߲ S*ʊg(#40a3=Hkd۱,^K,GJ%Q j'ܡ\e><^P$+9Bj~Km;)sZxBDthyPN6* *"))WVSvbw Y>wJ1Dʼnk*.>g[q˕g.HDKk()iQcV "!g2$%"G*2ڎK˹pLְrX3sCc| p{9țsʶ̙bj_Ϭ#ut,Kfț+ә^qnٖ{r$vr XkMmÁյZM4bb"\e0ϰ4l[)4 GY9]n҅˥=3qDs,-n Jqe\DABV6~44wZg\~Tq۰?[kSñD ]$-.REl'!ME\֢i(nMnB)j`E~$NwKXknnZgžq"UI 1+) V y%iRr\</R ~<ںwANīD q8HXÕ¨<&X2I6R\}T(;6D4MθĪ͏LvWiSRQg_33\s]i;,$<+=Glt#97o_6be䯱HpV)M &1mb*opgp?T8)T9=8$$#g$} 8uTsg?t>{c~F,U*/k^;3 L6|,5WjgP8߇}$Nny?7Ǵ<^x]O듴TjhhhWOOqvg]k6"m0 5-2kjvuԾNYL&b_(`QԚpv㬰]1<&Аpg8+^diosS'i?9ʿa?>T AS%,(Y?nA! JTò`{ ?MY2Tg**M?yJ)Ftu6`^7~C2>EH6Pebиp<磽xA7NP w x'rjњ㭏nJbF b5/-= ͠%vVvӉ "ƴ\b<*S?;YCnY\~ѐ; ƲJ=Z܋6÷djiUrE~d"}t`+XbIzQGx2$lǏX47UMSuHV">"Qe$kL>2;2nңJsz,IVhbJFဴ[PX.R ;$//;~8g)j8O*~̂bi.)[,G¹q'/|;JE5?K/#E4%Iς^[ C_ fY 7oE&$j+-[$d4 rgd6B`ѢbR$pǟUA#v5v̷$]Tץ έ'U#Y&CZ4[l>؋m+m)$|4q@&t ,Ҳp%\5SaKp"K"iz$MQ/pù*Fö40#6YEIcCrg(X8@nW.sɏ7J#v_/~"&bZ Wi'7㱴XCJc1A}1 K] ?o /u %ggʳ8 5':$K+m3JsO6khmO"T|ٴSD=85n_`z`]L=?K⊉+QfӛAl^V4+bV0(D!Wsze̛GTgMD5UdxX!81ɥIL"Ni@Wcw|s9'g OSDǦõ},`$ mҁU,S̃\B=Irߋ#@SxzDŽʲdoU|%:J.f5[.kiY[F):W=T\98c)GIN* 10b)Lʱ`g&r~8lqv3G]"kɊaȬ`ᜟ)IV,]yi\)LVgf}GwTS<M)^]7-4uƘhKHxaxVqo&Wh8Lf`IB. HXֆgtaukܭj-e4pq  ӟg. N$<-Y_?LWw8Lvw-ޒLey{~ڱ,``v+Koב?fu $ZdaQiꇾfK5JT xwPN?\|p\F.^. "V0l-C_@j22 T3_MFaT '>3M R!;H Z)NG÷kKbD<=s:/7_ω>9Q sg.0E5j*Ʊvu98+ÇZ )qq)r3t6_^={M34slÚ~qӛO PI69N. yܿ Qa^?!t YpAOrV,#q/!?%YF?;y̴ׂbo6%pO|z;^䅨XxipZi#j9pbu8zI+~c^Pr W[Uy9FeJU'l'71x3cXoz0=JԧʊUve2_6h}.Ix 7-%RkG_R3BI_=ڱy*h ,TA߉G_j fYe( rPmTG5M6~S _5@)$- ䷠AVҌ޹+OGsyU8TVyX66߄HőԆ$]~ntE:K,8 DE#̀й{i6mkD;z׌vXE[D8piZ }_<*хse`)E +71M6{qC-bMW)+0J ՋWd "9 ئ,FSO^bJ,n3?Pl>vtm^رQH̸ OޑS73ł?J}jXHEӱ_-u7&4Kbnv/s|8JHSi^ǍhHp^{(a0д{maWqz|T˅5;FO`r8Mzb.qwsGO:zYݏ-E̽H_s:9,G%QUqa/sX7Q2glO&,i 2 x#YIyQ)FQoPU[ 9B˴Wk${| =)Fʻduos@MRIY'd 8'xm *'hǩpCdS6]׼I׵ޢX̬^]}@֕i R /k(9SɰۚESj&͜~Ϫ n hWز_dRc(>ɾHL=ڬK>N y% @Լ⒢ ?>$$UAGh@j^Jf!Bx{z>T[_KAK!,3%5_7?4'U!-H=O/X$똒XP2REK_kbD xVL sxSLKIMStqRr2R|̼̔"ĒT-Mk$9)(: y% E Z%"y@SR2Ӹ9.x{vm赓%&33jnbTde]x;´QQiVF>zx;dn|b|7 oWx̶mQʵ6&l)% Blx;¶m`Ə|xr6KgYxۼ錵r(Zw*J1H};#=4r)6ץ:u,x#a悖100644 main.c*yFfdS9o?ou52x96-B2$ֈEp<Ƒ9tQJ3]s/GJe}1kqdLl=xۣ=I{C9< !.Wm`xq6͝B- \x;t3F ͻY>0m>~qN6*eRRR2JRBR+JJRʤ'S`ܬ0y&_b\eʧǥ 9A%%i9i%!Z: di5YPCx%q16ǫ|lkU(4/At6nhe3=3x!}29q)TSⳑZx;vU&3-%5M)ԝ=XVA7==%Iaby63~d7!$xq{ )L+Lv`n9ur!Y\o#kW0Y!SLYHG!4--FOVHo5;KLd ɮ>M> Ď/XL2l& gdO?cK K TT%֓zn#>T?L\V/g2ciaaڡP ebߔ'Ouc;܅p3 C7+f>cܼ! f7̓5*ˁjsSKB2sS5STRX tB!HI3Уv .>!jdP+*M4sf x=kwF+&IB9-;8ŦȒ$'fsxhq$"uHʏ<8Ç6{jZ` `Ca̙nrMFcw0E뀳7QpQi/J8 IO(*؏2?xe $3W!QK=c ݖ6a]RrL_:7I%_zt*I@-[JhnbIoLy$YPdB#JPi%M)O;=ݵ.:̆__1mI * Y+uXi,l(ZIvtI{"MAc'vB E;`ʎ|rh3F{ AhR.D1ٜ|ga~A5O &w!%}Sϣ[RN,w+(܇P6DjN{a O 4Ym?UB!${.#:œ~0-?e@aݳd:\;oMS퐦+:qHi! B 0%n+3 YY%E}%i # g9 ] p4qk?bjǻAŎP o؝k<]nPj MT% !wǻ}S&C9glɯSK[40#?+4L> 4=h%{`ɁܗJ4w{T x4vu^H 0%B)OBA!vWonU(X&usK?bcO/{n*1,m9i$@2@:GZ6PPeҌß:%ZږTԘe%͌hs <`uYۅLIqꎚd%\&!4<fD,b쎦GI~L#^YI+V!G,n:G[~)@4ԿP-BccK( G3~' &ᨄM#3Ռ~et L`qWNPT;)yg7'DUuX]㺯kF2ԇϗ ofzojі䓷J$~O30(@d1Ynq)~Č=4Epʯ ǶPik ]%*!} "5h`am]Ò+IzFA >QnLc}[MiXSJ\؇*Z)vhnD^,"V#tZ. L˳+AS1ތJrrFklcIY6:hdoAIf;/9<)1b~A!9hvww5I a`[Eؒ(}O[(PJ"cy~QbQ"D^HrL`͑iެea%-=ٴICT&RrVEH1RE8JJh^vQ#u0/܈+ `dd]MģRnn|(5$kz 2X4]G0c<݅zX^׷"[Jz*7*QG1Fj&2\@bruAUK+$`c)؇DXO]S~ssc74 t8`HprLV|E2ջ }OW{8 F %djLҥw`䮰\qv1)};G?ch:rt ~}Q1䷫Y Fi~8%P+kWZؚ;En3x ZP)}N{`+̚6aKɖrpZZd.l@7ytLr m:b[̆]J"iPIy׆::[LP6: 'յވGʶmu I?N.nS!pk9"F@_-|cܠXhD672u#={80jA܉͋ǵdsw֤Ekڞz|kT1n.¯IXL} 'vHIT+ZQÈ :d(#h3읻-#4-EFu E"R]w´Y 欈fMWvhh33sPtx]aZi(o@ɽAn]ox&RO'(uD_,( _EVaVfnߍ[kGh la/;G;=xn&bK?Z-8I$\ZȘW`^IăAJ^(۴|AXR>>1xƄ ȷ-!8eW\3 x>Kn(g6ݓ \V+=^6%LBS!b[N#X֛ |FsoreeZ>IR-_- NnVAYU]Ӕ/'֚zƕkm'qM~$5VF&2EN&PX sX/ FoyzXBpjì}Rcphۍr5v$1yt❎GMl aUcm9nҠAԏC;0"SqT#J ET|v7"b3$cCK N?+)Ϯw6^#DahBjր+_A )oy6oȉtػh<*&PM|SB4G6ב;<, (ڪg*KBk9XE6m SxO4d^u_}?:lj\T$-ڂ>zU_ p]3,@A\i;TԲ06#GީڳqmRn-Kd+Ԉi!6wr2/JvQH2Pcu2Kɞ]%P&G=h\B1a쨗-)\qP_DrCDR'X0Nz t_Go.??S>^ kP6ÈE-gt4> -wyNL{/X;r֒z[K( 6w܏`f uAͤNŒ CwX87uԴjL׹*^|7p'E pP7{^Lhz(7=DA\cx z\jX&A>>E?Oa| Gl[ۢS8 4BfɭzGښACc5HE-6kED`1k͒ pvgUmсc!:!åi t(ҡ<>IRk Ǝ|j֑8|J/@-8(, M:j}7_ c4tMjKͧAWEfhg{szl%Ǿ-h|k-Sjc2ţ| 7A S=p1QhO'7_ ܉V8nc.@u trE{-J>A(?KWѱ=~iKPWDxK<^)y*n1+iQ.C~'Ba{5%afuv1dx mw}B5ct k"_g ۻ L~t[EI7w`W(c JQ2 S]>vD( xD+v!w6&`,D"nkej|TM"eRa!+zzۀl`|xC[6~ZXE{Rk100644 main.cltԞ3ʳulnx[両]p*|#ijx}q) ̓=M'dV`620ؼy.|N Yx6۬RϓZY9ymΦBVz`̼rYI7&L~;yz\ (J-)-S0w+lsx6mU͟! x^6 1F64k`^>J6eon8Q*h 100644 main.c;V]!0*pN6D;%lxzu|+#P xx!k8'%qrKJbIʓ a͵ҿY;LxVMlEWMM%MҨn]^Jp'Xr4n׻;CQe89T\"U' 7j9#QAH*B] $`%|}o{󞿽nևˤf)"i8cK}ûKl,!'B6 ];9>胾IQdFAvJ[:q*Pa64 "RPZ!$844{PCIn4â5!QR!_br2 HBϥ4*|ι 8nP!kM'I\*){Фrh5j D@HBU,˦hr,@{ֶX$Ͳ+[j!{#~!vDٯ#;,`QڪՈ-K-m:#2N ) merP7L m2,8! FI2ܮ,1:N2wڨMY"NvZ8 N9j"EtW^SJ ٦έh@z ̔Un9(m!'(&ЀK^wFe qڜV|_kXZZ\qh?Mmh=!WQjYb h;^J֧vllD7cn iͥq%*˥1uy=ڶ% Q7QdI G/RR)ʓi虮VKT(?4,RY*Vri;-?S|rI̟ΟH9qmhޝԉi/(-WeN@0d\%P<27V8S>S/P\MFa(1^q]L?A7 uC"K̊ KT̙~D;ΰ wtLGvnבt"Cwb!ٝ9ɛ;Ik'V7M3AkzM{,[h`' QA-fwl)IrmVX 3,ra{Kz~:o|j ^I>yq|YbWPTS($,3xqǦBPpϐW}QN{ .}V4Ƨm{5mnRb Le'*4/ز<_>u!dž%ݬ XCޖi &Qmڎ fc'=r4~W\6f| K۠K\}VeRc+T[ ګ<66rAiwwF,*fhxOyf(z 5o11'aۅÆܣZ{$) _0^tE v^=&#đ]=M[OZx[r9 7ecd22ݬl19[n,nMᒜĜdͧ/kp9:(Lkt||^jyqIbIFNibYHhsQFJZy% \ 9%y%Ee&: j@yMkDyUSbt "b73mNhff87Ms4wr9ek]X\` tt5LloLt9dx;~2&Lʙy9) JiEIiiE0E0lcĺٕY$?>371}yU' LΗ)+LKMQ+QHKQ(IRx$C5&/PQ(jZMRܪ 7'#!&Z`PYR[$$3YaP6fl~IR93-/%5M)=>5?uCԊ,@ZAW!/\S4c^0y@5PZ̜T *.ԜTY"@f^Jf"` 55,3%5?>75wrg%HH,RPMSւA1T-F~XNQ[ xk?8=RR\\B\}6?`!>ylfE9FF+}"̒ ļĢԼ". H+q h(@*]2EL9C\m\"6^S߬5yAr:/~xl6Ȭ^|,@y`S#(^J|o $*8t*(X%)eP=GMj&WFUSޙfԞVK<39*x;6CY=x\#n$.e** 9>@ /Hf.e.Fg'+3NfܺYɘgx(.6Q{>9\\\&3)N5 7 x)bQM ̔ ͏50 o ,x@6r,퉸5z ?6J1Mzq uG;} &7V;BjfU51/QZy=@9hX NC7<5tw=$100644 image.c+Vbͮ=֫Ė֓&W|Iכ$W]p # E `A$#xTmxvu¹ͬlL\!?x(Ut|FUx2JҒ62chVLc>y6sd-f\wdM`='&f{9txA@@2̪u9Mę3ّː= 5er=\nq+ xSLKIMSq rRr3RD2JrSӊsSJR4@)%: fFjfzF UZe%kZ (JML! SR2Ӹ;n x1C6SQ 皾~W;SuUn[߂!?3hLVZLIMv#]p9L x]6a/AV5krLsJ1K(K[ yb1$ qW''56Y TGw r100644 main.c{x^O$QRyB?3 DjZP &MUha#E:1xq6R=Jʁ y}ݑJ1Mzq uG;} &z6eon8Q*h 100644 main.cLz9T?641?j2xve¹ɬG'gl RHIM̛I  7x1'l։y2JJR+6k1Z0$g$mdļYcO|kDHhkBVAjz.n>>+&feLcRssr&1FL«i7*#C1(Sl1xfxfa,%Fx9+Fʓ.~= ?3 DjZP &MUha#ل x;re&GNL̸5  v 񾮾 &rKWZRZsr56/ff4Vz|{Il3 'k(:ƻ;(N.YH9=bLgljxrof4m^ǟ{r6f,4^ds{6fvaNĒd #[CSzM8iB`+L(y~'F"" =Sdp2 9iNiiE?s3ORi)xr! W%&?XpMtFcrV [xfWCgFwGNcWHI+N- M( 7Y0p!|/x m pu=V{17G 2{'jL9BÔ &xh6% ׈hVyfSMJv<-So ԑ-|JQGWu0(՞J(6W?3>>TрP^u #ؕ/]x;Ųe&GL&Odl2C?+{8or$/ԋ<-3հmK(}^˟niɿMLI;׌VSb(6Wzm9VOPyS#yVÆO['RXGp*HgWE mQHho`۠ zC6/oQ(P$eu|h)-G] g.{JJ&\OHDo4Rĥ87@tӆ釮-}=bň;lw3|s?LBP(JĝtobQ*80*{މ/$x3\6}enʢSulK̜9G)~&KV3ZP֛Tm2j^o͗+[+[ZR= KN8O]V=g~vh|J}zxZg,ŧ$vgnDʚBiX`܅b)@$vO3>Ȭ 7/;}8/+x rMDkFǰ)ɬ#Xp]xVoGW%($G$T$ip5$!ή;N!^*CQ*qhsRPqS/=͌ Kݷ}W,0tlMh_=ajŚnx0QQ (ŵ3J}ɲUR [y o~`X+X&[e/Lz%[] nFE *6\<I.MC'UUQ9 ҎPQH:ƌ2Js,b MG)7 y)ŸzZW }!:o+8)L爽V]C"n>ZC#cվQ&*5,#kF Qv7BWҏ{&Ӯ0d:"U fmYpMj4>bHsyd-YsM&9ARodЧ Wb2w=`O;Av"yЬ4bXB_igaheT7L[&"]Vsib fyf>.1H$!NqI\K1tUaeA;YяzN5fV7=Nֱر'`@uСgfkPr@l5el; FE rι9GB*@FJT$܉щGޫG}4 V7F6V`kMֲ+٫ŒQ4 q4)6&\e g?Iw7aRDyU#J^X;%raJ_,0 eLt BӼ%ϟ"LdVMh-xa*޻'bo'e=OO|];֕ntLem}G!Y$^Y~rXaxD.~ł:L|{9мet*%&" 5}p-xp<9`YުWulۖjl IQzI. Y\Wno-ߞ䩛k }aSQ+q*foJh=L^`\],%'}^-KF_ T.ݽX墲4_,-oFP'C w:w~2ANtNMv{Gtn)Y1=_Nq<tGn)o;I 'vL]#R̹4w{W|\𣖣;;=MuV_mwدZ)Z#Fpu&ꝵ l޳(ry=;5؟'n[NGt0 X.*qFuYY=$vD ^ Mg]<-UZZjAo$G1 1" 4nMh0K(fq֋z-+D-5&`PpS׊ ` ;0Oһ7z.eg}YyGʵ4df2)DR|~݋?9B9F'Kқk?_댆'?^P./o^~]PFo!&%deEo^W[O8iD󁦠gCzL4(`uy#%5ʪڀ/)nm+[b6V*oY& Q"aDD-, ZvnZݭARU+P; w Wӿvš_H0HI9#ّk#A <^%hf'zHa00B(0JkN~` EaF ’Zm^5+x{hujCd'gd+"6{ dR?G_We  p ɟDz6dM ?xCC ^GL/glew| assert(0);,OH@8B]SZxB 62R=d/X$100644 main.c%Qwu )4'83a?$* lx{hrC*:xkxa㆛< @WPP?_Ul;VͶl{7kH2NŲRs=fGB%bHxv Bpln:dW] rnf,f1&HO (1YId) E̼ԼԢĤE%Ey`Y]̔ EE'm\ouߤř4Pukhj*p)@$rGXXrJ'5ͼUC *d/H7|&ȴuZ&z~OkٲBx7o扼ħZ^7a|o&x340031QK,L/Je8RhTEK/_zv_G矛{Ԡr3V=q=bi׼28UBUd$glv9Mq㓎;>xq{Z@d,smH!1k7#-39tc56E7t <)6XQ100644 main.c$d:[hfxrE?$#1!xUk@fVkRͲA*,R\h i2D$$k-"ѓhɋ"xәI6֢М}o7y22y@zuTπh-x@Pð*},Fȇl6M3U1}-E(Wk Wfs%(இ %zʭeKfzDaΠw'rOާdqJC}&C2rY<ˍ0w|GtRc<ǘ$ݻGǁ1!*42 E*`rn"(VJ\Tz!K 0@b&QP8PdEam}O1G8,Ԅu4i搾9I)>^ie~̕sӒLDžmn-셁ɕ';t!rM< ͭ.\tt쏌oĐLEn UN%f+CA?t,/.%H[hr\j2L~ =[lb&!rh<c6f!k'= pQ$y5wf}Fko44G37$Ôhz6LnXcC|]nK:\ l# 0p=bf>vEF7^~$Q{T]^FnE8rFhfh#0ˈ;z R UZ䯴J5jNղV0wmѦ6w܆aԖb={*AL/QxBT\IM&36-=u㴴֙LuGJ\/ X4lh/q,:i>T|R>./[?eO||?Kd xSLKIMSutwRr2R|̼"ĒT-Mk$%y(: y% E Z%"y@SR2Ӹ.x{hh,!̜r[ǚK @ċRRR [ʘ6ȴ,FH?AxVMLW, D"wvbUZ\pk\,4jZaa,J=Cc^Ƥi҃v&=K65ЃMzI޼V1O턗YõB3 z:W1h p1hI5ηsAz,K!>[ YMOcq/'vTL-SYv^N zoM+IKa͋ືm7 pjwĒ?{9&O!EaUaWX At xBgtl,*:7JMmHý7Ԡ8jٗKSse4oڅH@IZqqI P'oKXi56P^7 ]*H(D6ƦqI8uD!#drVJ[#ZLVi npNVɔ8932:U:f"Ҩ M319L"qrIA9l6;mbl*D+^`MBs15/vlviJDtlYUYG֐1-Rd[%k !%npRf(Bh 55VFd?܉ղHM4DZJNl/O <EyT\4™5y -fPZ b=ۘ׎vrlYjCc}z(<~I@$ (Zn̼~fdo OGLʮ풳P p,a6pK785wgd3o^|䱰/NX*4vVEf <7fqWNzH4V?eH4/rf z@ rQ+ /! *-̱ceMF[YRi׋*;J>^ɜxms#8o3ekzYEYX5 '-5 )k%މ'>O2\"tx' VP@;p <4aEs;f|a5g׭:l௹3t/@*}TcN1-/A2-iגncOx#p1+l~vc.^'o{;֝T0sքr5lx[ݭa=泼w#gNx*sL;@ij,}xm4pH~J&d)$&wc)N(fP|#•+2~x[zA Y6/daKHM.-l'a7YZxrP(RZinaS ͥ99%Ey>: )28*UZ l& p"x Hs¶FED 'aT0X~ZN&> SrK&KH(i*TsMa4C=,3 [sK4  C8: `# 4>,KOKрA>RZ^_ԟZ491J{r2dgy%hQJxrfO>.HU4( %J470w$i@@A,@u%i)@ي7oecxB 6/ >07F 100644 main.c%oLo:!c[?$Llxix`n|"dxsq 6?bbc,˶b=& @⢑T_ZbgVidhB'gɮNutX6[sl Ŷ?8-ex340031QK,L/Je8RhTEK/_zvn0楊6Pb̥F`%㌛oN;6n-yq,T10ntx6|cLw=$@N5瑐W=uq7j34$6 xwo,_f^B9QVdr,XYXE>JT3'˙m`-ܬ"?]23%5$3R!-3'U!-(7DIӚkrj1 /xq 6L̦f+p)AAQf^IRbR~iBIBZ~jqL@;ɱ&V׺NVgm`!&O'1yC0Q_d@8֛)@x340031QK,L/Je8RhTEK/_zvz9@iMB;ʓo(`fة9칷%ˬ1*N-K)MdxQ>Z 8BU&f恬"4ރys]{srY TEiIFbq.+ۛf)n):`qso3xiD NO2xUO0~_q+TZ@&e6E&vG3Pv֔QiZΗ^&EC(?)9Z3y*гhHg (Ky%L$ϊ J6ŞSϜ,W`&MAIoy"֑ %eOa_0/P%IJp!Ia8XsRHl;T#˶ b߆,guMEz%׷ͪ2.Q3`9VM0}m[J濘H{afL=0N #Rg8?< SAODY+Hr"aV ߩLWZt*4t:I$#eɮy}s0x89}7N%ǾUq8#/..m=GsI+QE}~Dzƌo"si\0` K^G ۹H6ԍM;ZW" w.ى\:V^.#h{#ZC3=p< 7]DױX? {M``p p<}U0mB)pP9wav ᬍ>Kpqheh?x<wjQ*713h'sO2T(^n6_$#8C/YJ}ʦh0z7=-UDo_xiD VO2BlwxnDp,!ETnx}TOAPQP4C RPBL)[HꖝmlwT!Ɠ7Dbd:q17c"]ZJ(L{oݍwM˭!b} R4-!\Ŋe%Xpw3-k6Yqad6E# ,(P`HZ8@}1vgƏ8ɛ%t=3<6j4$rY̆80B9pk̺CHB( el:3bi5S#1mf3Dc|vvi1%35_?h!mf={Mg2ӳhLxyF|5LyM(9Ez!k)!0KCuٲWG%պ_aR P?%`}0g#C0w]o_;Vp'Y =ljuњV̋v :1P .䏪 &Y^%̑W@D2)'vA Bq< Cf Z+aD[|v VG7,! nvtF&L]B ϫ̆Ƌ.5<=f~dLh]>hg<@i~vLXuKF ʿn#yΐS7Ε#jWuFj.%bш%ƧԤ㴤Wr*FvIpĄjG!a VB'sx;qr 3RRRKKR54bB@f^BAB.%(VXCd' js%i"(rU=b*HAwq t qtwq QPM,ikkZPac (?+5$3?MKʇ1b ,@8t5BI"Q9&ݘhфooMse_ :Wtl=G!TEiIFbq^etM`n{ YoxiDVO1(3xnpEoCpa~Fl[Ҽ<ԜD 9V `5J zz U"6{g{lSxXo\ۘ&.QxksŚNR`fwM&<@iG#K h,$FcK+L.kuy?v$ːeEx0=+!a;`6$dy\whb}dчeة)~DB30R.eIG9H#] ?R>QCKnC8@hSmC$jH>eĻa ?Ѭʨ*\+jcJ4=piT\xd?/iF֨Oȏ/yDh{n Y0ԇlT1Ni1X0"Hqޯ|GaZ~gE_"/\;ma!@_N %T\:D J9HBfҲ;oi"SD M f!2X$srJ% ͖~| |%yhNC ^Ŏa(Pzgp0k¾-$#4TN!MG4o pL3+Ȃ|Ys˕ ?k!G y:Đ˳ҕ_ScϞEc# Nˢ*Yf"f:ݽo!SKpaTxӮv)n JZQV+WUHl8xS3IDWeL`E釙;UҠ墻E}p#xŒac0VN=.sAЧ 8!"qX/&I_'PrUb,Fkw4( j9N^FDzQ tՁh&pTޞWֺr8 Xk^&-517ƶd0s"3׫$v%W'4rVbXu$^ Rx4 j ’0CQ6w@Wq5V+Z7:NSJlPfa|AZf |HzW䱏Nz*ۙ=:2:À< Qj4K[Zɋ|':4 J419F+\1yJdd=g$dhpxE57'KC9ǯ ?2sL ˸0WfJ>XipNsk4ynG$;u;dQt_ݦ?UO--8-!PQ&RyZ#nvifW  .l렛Hhd]#F2Tkx@vm(v ^e#z' :;.[q[L_ޚ+!lxKu؆zUSK(a Fp<{'P~ū/o[z9ܪ"FQGRq6^ oD )l芆ꊋ{,4p@@ňG ˵R9k vl 83[NWRbF<5'CU ةj/ea\ bSsũB؟ӬB/#o_h揧-k&B6Ήx;b|(ǮUm/X-a4b6X~x9c]h5/5ӯjy٪!XV5UߩymdxjanɛdoxΑt%G #όKv%ψF`42 [{j.<}Xoc\Vk`6SM*|<7j6EZhyW Iy2WSˊߨ%JZ$i#-D[L _ZoU u}+רJК *Ԥ5b"tbMGr£N-E[gB"T&<x6ƏB4q1r&O|p1O;85i(N*u6W&6ZX//oa_Kgv5_SGbZ@ /Pi+`^_lYޯal5xkH#/pw5OF- [& ןwQ9=~sځՀpLLzki8_yp|A^o8#` :S~n:M\'.`7%a30#= hxM\ƭ-(/*թG_?v-4}%+@Ն(ɫ71 03~7ij؟v R d }i&uZ>S(K˭#g(!ǟ%u.j]E痗#NC2DKgo*8/Fdյ3qE9_S(8ƛI&z*UtpiN.;j6./عMK~K0-yL"HJ[LS<]7IJKxku:;0IŔGpfǙm5KJKSR RtR+JsSrRRs6c)hфooMdntk=󉬕nu7@Ud$ge0X\6KIwO F隸pdռ'bBU~[P:O>#HfLx[Rrx2FҒ3W1Ngc.O|F4D!/?%5XA(LGA+/ZA__817U!',5g?f+akx7 WGg &]̜b0=9[gq5Ԃ -#%%Y)&{HBb5آFB>H2xJ/KJI,IN-KJ3J ƽxio8{~A3v8Ngv1,Mqq;G[DBdɠxH$%;NwX-I( <8Ow DiegX͜h=ge%0b4q?iVθ_%)$Y5OYfQOAdK_K9 Fz.SPoEWrC$)Č6`F׫ Qfe޶[zυMbpxVU hGz,WhTei Kʪ6BFi*mmtZ8.IuO?rƛM%. 7t'dA@Bqyt56QbHiP'<gX$ 'F(=@͍d]NHDgV1ȨԘPb8#dF|F`y 2FPz'q:cOO4G+2ޯFuP ofzj ,_}i`F2MoA2ílG2?Fl0sӦRdp>N~^ ~5Pfqv7Ez|2SHZ=ʁ\ j%d@;Ȣi"i&.b!$NiFNg*QeŶ动ދX ɟd05Fˁ!\ed.cp, D(ߌBۈ22PϔAX%# qe)4RS%YhK*P¿Ş?7}50'IX4VEf,e<3of?B ڷ~\F2:H߂aNپ&U(ivD^R.%OP.hqpNn{%v.¯^T‰j}Eʶ& RG;MRcFĚ65tUˬ_d|pa\P tft @r牬Ym6>GYY,ZB" H%*AYΨ `:3] @Q^Gѵ,BkV"RN=+e֪\S5JX`̎L9%8DQ ah}Fis@>)B)/PQTfѡ\OWt5̿V aMTqRefrt7b+W < զ}J@Nw@^&CUzK7 {xh-@UzAL>S6?2zoCC-Y?τ4%F!Tܗ fh{`/medQao-M6 +e 2 ;B #hymw|/mG''mX#.&/$WdLYzooAq"PыE*DupSz4~Qİ<`pOIq,Q&, I*6zuDx~lmEIJ.[7dX2g#x2蟾U [)̴j- V/]Mf5W>π_?:|=nARڊaڱ^"Xxi/ۍ g| Oa;[e8JX@`{p@^}XjSFrS_izD?}SY$0Q? KQ*DUa zstM؛/G2Z2պ:F3p! /]?Ѭ=Ք4D |:d4/9)Z&pW^* g (ؒNl[678AdEie/&C}6 ;]  /z2N#?,/(J7K/ǔL!p*ܑT럝5ŵT*?j+KRZtot"|4a9ǚrjpY^,"4\=kyhTzR85,7dGLcWj>g|NYI_=y8' gO/s͞> pyg3ؖK[yYXŋ *FvWLyh~ŀ)SȆN5zsΞ:8»K^{༩:VY7sNjZ{ 2 ˢA$(<>(.!gf 2OYD3٢'d?\fN +:A%!T!p֤Iת@B\I(O}|߲ʈEߖegSs{'YĦmNhYMa)ll$QRZ*tޗ܊TVϖ92h~¶>GJS&6l6 9  ICgZUM)ּm]tq\SJ% n MդxE..xFoLalF#`; f% |zr|G2yvK`tUm6ᄐp90OBr^ BՙʖB-f(("OU88HrłH|^V~vr  +^1V$eKFfvx~ N5d+PDܛۿ)X]* w*W*~fucE*Z)[ }t&"ha\.Z8;S.qdԴq.-rW-e:rƖGu!a2O9 ;DkBJ֔jiQ0/4mkF$nϼ7&En`jCl?8ƥ铨 _Tt Uu!e:TJ-M\;Zݜ$h{qʻ_Ozog4z-gz}Sy<)]Q5l>c[L*NH ő]ne+BGj8B-_ɩ5pcg؅!sʧXks;\hլ*TOCb-uXq $tSn6 iCD:Z-*cuMZkRouvmxq)c4s &=YT|ZjxBx@6Q!ϡrU?IYM100644 main.cA817X$Hܓx@6pD.hA `"100644 main.c[1l> z1_$ޅVsH Ex]{YvԒҢw۸Xv2=ւ̼DʘB x#vB“KeTctrJKK25|tt 55',<̀or_rr]p(@dED'gl {kv쓣e' Hl֕`|TG E__(58U!3$_!%-/L-,R¸y,G9&?44 #rU= x340031QK,L/JeH̙uو72qnǛ:77MNMIe}Ku6J\W Up{G_ӑ|ߏV$#8C/YJ}ʦh0z7=&'%?ۂY&?!_HxJ/KJI,I:͵ xsvqt/-.K)MI)M43q@tsRRJtzNZ9WbNBzAnf^Z>eũ쬩⠠5RSK//J!9'51 LYqq*)h# "/xXoF uTr׀}nFݤm@ %Aٖ}I:=næD?> g>䡟fl^4$Q$w-ZiN$x혟!>1if5~e(Xl= CKa;-SĊϳF>×ůa2x ?Vչ}\_.GۧeW,Df/͒ SxalF"Lxp2wnYrqG3FasΞ$uءpIzb<8 ֳ(q{Igf!nG]F=c8Z[$p )c!0}fh42A'< 'MIFGgO6b bPb{'n-,(%7?3T=w r [ YYqԒ*.o w@nXIx'!TK"0=VV+̆2[Yz 7^:6gf}yqqä؍./ JrL4"<R-!\Kw8:gU뫅}vrrqu~iyQ.4u*5b¥˄B-OvlqU 2HJ\w ›sF zBFe"e +AfLLX?TК qA+ %0 G.Eƒ AM;hkoΙv8 NQ(D0X`t._-r!3-'{\UJ1 fz}iaQeZS9 $X@<:k:! 7xN-0|Zl?ًSC4'K-GatXF1u?߈'[XhLbWʰ#)O!ywi9L+Xx8aaŦ٨d<ΙMGzrCގޚP3RsWRe6zE],<U&g\]\~ ]U+&,ÂʄFaFVEӬisE,O "lM2G4%,(T8š4L*ڑlǺ*wm(( myDU< bQ:dҐ/0J80^0R/y))l(o/CVVZ X9OdX$FZ\w qhҸp0LIaL! ~֒5wfshEuTExys u[{fJFif)]VKqi]acں[γ:kϵbV̓] &&m QC{=q`<ȜBgopReQ˟_닓ϲ9.{vNrZR5kOihF ŌD-K̘X*0VN)$ RJ+=Rrx[)R .=/VtjT5wQSH20L&v-?T5smc(e2cn4i$K5ȶGu!WۙVDR|ӯP";M+b ٍwqBg#>info-beamer-1.0~pre4/.git/refs/0000755000175000017500000000000012452774240014140 5ustar nknkinfo-beamer-1.0~pre4/.git/refs/heads/0000755000175000017500000000000012452774240015224 5ustar nknkinfo-beamer-1.0~pre4/.git/refs/heads/master0000644000175000017500000000005112452774240016436 0ustar nknk7bff9611592f0eb9aefbb263104abf63ec33564c info-beamer-1.0~pre4/.git/refs/remotes/0000755000175000017500000000000012452774240015616 5ustar nknkinfo-beamer-1.0~pre4/.git/refs/remotes/origin/0000755000175000017500000000000012452774240017105 5ustar nknkinfo-beamer-1.0~pre4/.git/refs/remotes/origin/HEAD0000644000175000017500000000004012452774240017523 0ustar nknkref: refs/remotes/origin/master info-beamer-1.0~pre4/.git/refs/tags/0000755000175000017500000000000012452774236015103 5ustar nknkinfo-beamer-1.0~pre4/.git/FETCH_HEAD0000644000175000017500000000032612456161610014532 0ustar nknk7bff9611592f0eb9aefbb263104abf63ec33564c branch 'master' of https://github.com/dividuum/info-beamer b17980683826dd333eb811d3938989daa2e10906 not-for-merge branch 'glfw3' of https://github.com/dividuum/info-beamer info-beamer-1.0~pre4/.git/HEAD0000644000175000017500000000002712452774240013624 0ustar nknkref: refs/heads/master info-beamer-1.0~pre4/.git/ORIG_HEAD0000644000175000017500000000005112456161610014434 0ustar nknk7bff9611592f0eb9aefbb263104abf63ec33564c info-beamer-1.0~pre4/.git/config0000744000175000017500000000041412452774240014371 0ustar nknk[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [remote "origin"] url = https://github.com/dividuum/info-beamer.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master info-beamer-1.0~pre4/.git/description0000644000175000017500000000011112452774236015445 0ustar nknkUnnamed repository; edit this file 'description' to name the repository. info-beamer-1.0~pre4/.git/index0000644000175000017500000001077012452774240014240 0ustar nknkDIRC8T6 T6 S5Ih?lN HZ39 .gitignoreT6 T6 }5Upͯzy; ChangeLogT6 T6  YߗPVSx3ve'3} LICENSE.txtT6 T6 fG/[*!,MakefileT6 T6 B̋X?CT#đt README.mdT6 T6 +˴,NCj5ʢ~bin2c.cT6 T6 W>?fbMmTHpR*cTcontrib/netheat.plT6 T6 _>2ݙqcontrib/oscproxy.plT6 T6 $&|T-dmcontrib/remote/README.txtT6 T6 7Tk@7TlWW,1Ucontrib/remote/mouse.pngT6 T6  ͘cAjcontrib/remote/node.luaT6 T6 :;2xx N*#Vcontrib/remote/remote.luaT6 T6 QH֜'Wrncontrib/remote/remote.pyT6 T6 zz"M0V$contrib/test.jsT6 T6  +?-dTZ}6}doc/.gitignoreT6 T6 F[DfEU &~Adoc/README.txtT6 T6  W~Ћq口xO}font.cT6 T6 !. n7Rvefont.hT6 T6  BQXʺ\, `7 framebuffer.cT6 T6 Jc4౼W%k$vqNay.5ջ3 samples/green/node.luaT6T6O}G[+Bdj1samples/green/red/node.luaT6T6fR՘17_Ϳ#samples/hello/README.silkscreen.txtT6T6K43ꊖ]Dsamples/hello/README.txtT6T64w\e&ړsamples/hello/node.luaT6T6GݗK19#]samples/hello/silkscreen.ttfT6T6|)~c@X^U^samples/image/beamer.pngT6T6 ݧT0 Ksamples/image/node.luaT6T6KբF·*'6Њsamples/parrot/READMET6T6@G\CAL 5kYlisamples/parrot/blue_macaw.pngT6T6ad:f@ޛ$?p[93samples/parrot/node.luaT6T6 Қd^뜷r ¡samples/shader/lua.pngT6T6 ߿P5D[(@焒samples/shader/node.luaT6T6 Ǐ'KZ9|09samples/shader/shader.fragT6T6 z<)HwXJư?^shader.cT6T6"IBd!"Ym\\z shader.hT6T6%zٕ;UNTHla*struct.cT6T6bo]77 md vstruct.hT6T6Xp#KI޷\ userlib.luaT6T6y:=٦"-Lv2G\uthash.hT6T6 8zoRgutlist.hT6T6+M80 `s4I0jvideo.cT6T6_念B۟8*ř{Evideo.hT6T66t&3<1w͢vnc.cT6T6UY?L|vnc.hu)}u) $)1_info-beamer-1.0~pre4/.git/packed-refs0000644000175000017500000000035312452774240015311 0ustar nknk# pack-refs with: peeled fully-peeled b17980683826dd333eb811d3938989daa2e10906 refs/remotes/origin/glfw3 7bff9611592f0eb9aefbb263104abf63ec33564c refs/remotes/origin/master 58eb19d49c6c846759fc0d87c2adb2ec2ef951df refs/tags/v-1.0pre3 info-beamer-1.0~pre4/contrib/0000755000175000017500000000000012452774240014000 5ustar nknkinfo-beamer-1.0~pre4/contrib/remote/0000755000175000017500000000000012452774240015273 5ustar nknkinfo-beamer-1.0~pre4/contrib/remote/README.txt0000644000175000017500000000121512452774240016770 0ustar nknkRemote input example ==================== This directory contains a remote input example. The lua module remote.lua installs new event sources for mouse/keyboard input. All inputs will be sent to info-beamer using OSC. The client program remote.py uses python, pygame and pyOSC to send mouse/keyboard input to info-beamer. You can have multiple clients sending to the same info-beamer node. To tell them apart, you can use prefix them. node.lua is a minimal example. `install_remote_input` adds new OSC listeners for the given prefix and dispatches incoming input events to 5 new event handlers: keydown, keyup, mousedown, mouseup and mousemotion. info-beamer-1.0~pre4/contrib/remote/mouse.png0000644000175000017500000000024712452774240017134 0ustar nknkPNG  IHDR 'sRGB PLTE#ctRNS@f?IDAT%1 Aj"! hDCLc`"8b!q LOO~+NO IENDB`info-beamer-1.0~pre4/contrib/remote/node.lua0000644000175000017500000000101312452774240016716 0ustar nknkgl.setup(320, 200) remote = require "remote" remote.install_remote_input("player1") remote.install_remote_input("player2") node.event("keydown", function(...) print(...) end) node.event("mousedown", function(...) print(...) end) local mice = {} node.event("mousemotion", function(x, y, source) mice[source] = { x = x, y = y } end) util.auto_loader(_G) function node.render() gl.clear(1,1,1,1) for player, pos in pairs(mice) do mouse:draw(pos.x, pos.y, pos.x+12, pos.y+21, 1.0) end end info-beamer-1.0~pre4/contrib/remote/remote.lua0000644000175000017500000001460212452774240017274 0ustar nknkmodule("remote", package.seeall) local KEYMAP = { [ 0] = "UNKNOWN", [ 8] = "BACKSPACE", [ 9] = "TAB", [ 12] = "CLEAR", [ 13] = "RETURN", [ 19] = "PAUSE", [ 27] = "ESCAPE", [ 32] = "SPACE", [ 33] = "EXCLAIM", [ 34] = "QUOTEDBL", [ 35] = "HASH", [ 36] = "DOLLAR", [ 38] = "AMPERSAND", [ 39] = "QUOTE", [ 40] = "LEFTPAREN", [ 41] = "RIGHTPAREN", [ 42] = "ASTERISK", [ 43] = "PLUS", [ 44] = "COMMA", [ 45] = "MINUS", [ 46] = "PERIOD", [ 47] = "SLASH", [ 48] = "0", [ 49] = "1", [ 50] = "2", [ 51] = "3", [ 52] = "4", [ 53] = "5", [ 54] = "6", [ 55] = "7", [ 56] = "8", [ 57] = "9", [ 58] = "COLON", [ 59] = "SEMICOLON", [ 60] = "LESS", [ 61] = "EQUALS", [ 62] = "GREATER", [ 63] = "QUESTION", [ 64] = "AT", [ 91] = "LEFTBRACKET", [ 92] = "BACKSLASH", [ 93] = "RIGHTBRACKET", [ 94] = "CARET", [ 95] = "UNDERSCORE", [ 96] = "BACKQUOTE", [ 97] = "a", [ 98] = "b", [ 99] = "c", [100] = "d", [101] = "e", [102] = "f", [103] = "g", [104] = "h", [105] = "i", [106] = "j", [107] = "k", [108] = "l", [109] = "m", [110] = "n", [111] = "o", [112] = "p", [113] = "q", [114] = "r", [115] = "s", [116] = "t", [117] = "u", [118] = "v", [119] = "w", [120] = "x", [121] = "y", [122] = "z", [127] = "DELETE", [160] = "WORLD_0", [161] = "WORLD_1", [162] = "WORLD_2", [163] = "WORLD_3", [164] = "WORLD_4", [165] = "WORLD_5", [166] = "WORLD_6", [167] = "WORLD_7", [168] = "WORLD_8", [169] = "WORLD_9", [170] = "WORLD_10", [171] = "WORLD_11", [172] = "WORLD_12", [173] = "WORLD_13", [174] = "WORLD_14", [175] = "WORLD_15", [176] = "WORLD_16", [177] = "WORLD_17", [178] = "WORLD_18", [179] = "WORLD_19", [180] = "WORLD_20", [181] = "WORLD_21", [182] = "WORLD_22", [183] = "WORLD_23", [184] = "WORLD_24", [185] = "WORLD_25", [186] = "WORLD_26", [187] = "WORLD_27", [188] = "WORLD_28", [189] = "WORLD_29", [190] = "WORLD_30", [191] = "WORLD_31", [192] = "WORLD_32", [193] = "WORLD_33", [194] = "WORLD_34", [195] = "WORLD_35", [196] = "WORLD_36", [197] = "WORLD_37", [198] = "WORLD_38", [199] = "WORLD_39", [200] = "WORLD_40", [201] = "WORLD_41", [202] = "WORLD_42", [203] = "WORLD_43", [204] = "WORLD_44", [205] = "WORLD_45", [206] = "WORLD_46", [207] = "WORLD_47", [208] = "WORLD_48", [209] = "WORLD_49", [210] = "WORLD_50", [211] = "WORLD_51", [212] = "WORLD_52", [213] = "WORLD_53", [214] = "WORLD_54", [215] = "WORLD_55", [216] = "WORLD_56", [217] = "WORLD_57", [218] = "WORLD_58", [219] = "WORLD_59", [220] = "WORLD_60", [221] = "WORLD_61", [222] = "WORLD_62", [223] = "WORLD_63", [224] = "WORLD_64", [225] = "WORLD_65", [226] = "WORLD_66", [227] = "WORLD_67", [228] = "WORLD_68", [229] = "WORLD_69", [230] = "WORLD_70", [231] = "WORLD_71", [232] = "WORLD_72", [233] = "WORLD_73", [234] = "WORLD_74", [235] = "WORLD_75", [236] = "WORLD_76", [237] = "WORLD_77", [238] = "WORLD_78", [239] = "WORLD_79", [240] = "WORLD_80", [241] = "WORLD_81", [242] = "WORLD_82", [243] = "WORLD_83", [244] = "WORLD_84", [245] = "WORLD_85", [246] = "WORLD_86", [247] = "WORLD_87", [248] = "WORLD_88", [249] = "WORLD_89", [250] = "WORLD_90", [251] = "WORLD_91", [252] = "WORLD_92", [253] = "WORLD_93", [254] = "WORLD_94", [255] = "WORLD_95", [256] = "KP0", [257] = "KP1", [258] = "KP2", [259] = "KP3", [260] = "KP4", [261] = "KP5", [262] = "KP6", [263] = "KP7", [264] = "KP8", [265] = "KP9", [266] = "KP_PERIOD", [267] = "KP_DIVIDE", [268] = "KP_MULTIPLY", [269] = "KP_MINUS", [270] = "KP_PLUS", [271] = "KP_ENTER", [272] = "KP_EQUALS", [273] = "UP", [274] = "DOWN", [275] = "RIGHT", [276] = "LEFT", [277] = "INSERT", [278] = "HOME", [279] = "END", [280] = "PAGEUP", [281] = "PAGEDOWN", [282] = "F1", [283] = "F2", [284] = "F3", [285] = "F4", [286] = "F5", [287] = "F6", [288] = "F7", [289] = "F8", [290] = "F9", [291] = "F10", [292] = "F11", [293] = "F12", [294] = "F13", [295] = "F14", [296] = "F15", [300] = "NUMLOCK", [301] = "CAPSLOCK", [302] = "SCROLLOCK", [303] = "RSHIFT", [304] = "LSHIFT", [305] = "RCTRL", [306] = "LCTRL", [307] = "RALT", [308] = "LALT", [309] = "RMETA", [310] = "LMETA", [311] = "LSUPER", [312] = "RSUPER", [313] = "MODE", [314] = "COMPOSE", [315] = "HELP", [316] = "PRINT", [317] = "SYSREQ", [318] = "BREAK", [319] = "MENU", [320] = "POWER", [321] = "EURO", [322] = "UNDO", } events.keydown = {} events.keyup = {} events.mousedown = {} events.mouseup = {} events.mousemotion = {} function install_remote_input(raw_prefix) if not raw_prefix then prefix = "" else prefix = raw_prefix .. "/" end print("====================") print("you might now start remote.py using this commandline:") print() print("remote.py /" .. PATH .. "/" .. prefix .. " " .. WIDTH .. " " .. HEIGHT) print("====================") util.osc_mapper{ [prefix .. "keyup"] = function(code) node.dispatch("keyup", KEYMAP[code], raw_prefix) end; [prefix .. "keydown"] = function(code) node.dispatch("keydown", KEYMAP[code], raw_prefix) end; [prefix .. "mousedown"] = function(button, x, y) node.dispatch("mousedown", button, x, y, raw_prefix) end; [prefix .. "mouseup"] = function(button, x, y) node.dispatch("mouseup", button, x, y, raw_prefix) end; [prefix .. "mousemotion"] = function(x, y) node.dispatch("mousemotion", x, y, raw_prefix) end; } end return { install_remote_input = install_remote_input; } info-beamer-1.0~pre4/contrib/remote/remote.py0000644000175000017500000000371712452774240017150 0ustar nknkimport sys try: import pygame from pygame.locals import * except ImportError: print "==========================" print "You have to install pygame" print "==========================" raise try: from OSC import OSCClient, OSCMessage # provided by pyOSC except ImportError: print "=========================" print "You have to install pyOSC" print "=========================" raise PORT = 4444 if len(sys.argv) != 5: print "usage: remote " sys.exit(1) addr, path, width, height = sys.argv[1:5] width, height = int(width), int(height) client = OSCClient() client.connect((addr, PORT)) pygame.init() screen = pygame.display.set_mode((width, height)) pygame.display.set_caption('Info Beamer Remote Control') font = pygame.font.Font(None, 16) text = font.render('Sending to info-beamer @ %s:%d' % (addr, PORT), True, (255, 255, 255)) screen.fill((255, 0, 0)) screen.blit(text, ( (width - text.get_width()) / 2, (height - text.get_height()) / 2 )) pygame.display.flip() while 1: event = pygame.event.wait() if event.type == KEYUP: msg = OSCMessage(path + "keyup") msg.append(event.key) client.send(msg) elif event.type == KEYDOWN: if event.key == K_ESCAPE: break msg = OSCMessage(path + "keydown") msg.append(event.key) client.send(msg) elif event.type == MOUSEBUTTONDOWN: msg = OSCMessage(path + "mousedown") msg.append(event.button) msg.append(event.pos[0]) msg.append(event.pos[1]) client.send(msg) elif event.type == MOUSEBUTTONUP: msg = OSCMessage(path + "mouseup") msg.append(event.button) msg.append(event.pos[0]) msg.append(event.pos[1]) client.send(msg) elif event.type == MOUSEMOTION: msg = OSCMessage(path + "mousemotion") msg.append(event.pos[0]) msg.append(event.pos[1]) client.send(msg) info-beamer-1.0~pre4/contrib/netheat.pl0000644000175000017500000000420212452774240015763 0ustar nknk#!/usr/bin/perl use 5.010; use strict; use warnings; use bignum; use Carp; use SNMP::Info; use Data::Dumper; use Net::OpenSoundControl::Client; use Time::HiRes qw(sleep); use Math::BigFloat; use List::Util qw(min); my $sleep_time = 1; my $snmp = SNMP::Info->new(AutoSpecify => 0, Debug => 0, DestHost => '10.0.0.254', Community => 'public', Version => 2, BigInt => 1) or carp "cannot connect to snmp service"; my $osc_client = Net::OpenSoundControl::Client->new( Host => '192.168.23.20', Port => 4444) or carp "could not initialize osc"; my @interface_whitelist = ('alicedsl','qscdsl','eth2'); my @interfaces = grep { $_->{name} ~~ @interface_whitelist and not exists $snmp->if_ignore()->{$_->{idx}} and $snmp->i_up()->{$_->{idx}} eq 'up' and $snmp->i_up_admin()->{$_->{idx}} eq 'up'; } map { {idx=>$_, name=>$snmp->i_name()->{$_}} } keys $snmp->interfaces(); my %override_max_speed = ( 'wan' => 17_000_000, 'alicedsl' => 17_000_000 ); my %speeds = map { ( $_->{name} => ($override_max_speed{$_->{name}} // $snmp->i_speed_raw()->{$_->{idx}} or croak("no speed for interface ".$_->{name}))/8 ) } @interfaces; sub derive_val { state %cache; my ($name, $idx) = @_; my $counter = $snmp->i_octet_in64()->{$idx} + $snmp->i_octet_out64()->{$idx}; my $r = ($counter - ($cache{$idx} // $counter)) / $sleep_time; $cache{$idx} = $counter; return min(1,$r/$speeds{$name}); } sub send_val { my $val = shift; $osc_client->send($val); say join ', ', @$val; } while (1) { eval { $snmp->load_i_octet_in64(); $snmp->load_i_octet_out64(); map { send_val(['/gauge/if/' . $_->{name}, 'f', derive_val($_->{name}, $_->{idx})]); } @interfaces; 1; } or do { print STDERR "error sending counter values: " . $@; }; sleep($sleep_time); } info-beamer-1.0~pre4/contrib/oscproxy.pl0000644000175000017500000000121412452774240016221 0ustar nknk#!/usr/bin/perl use 5.010; use strict; use warnings; use Carp; use Data::Dumper; use Net::OpenSoundControl::Server; use Net::OpenSoundControl::Client; my $client = Net::OpenSoundControl::Client->new( Host => $ARGV[0], Port => 4444) or carp "error creating osc client"; my $server = Net::OpenSoundControl::Server->new( Port => 4444, Handler => \&proxy) or carp "error creating osc server"; sub proxy { eval { my ($sender, $msg) = @_; $msg = [$ARGV[1] . $msg->[0], @$msg[1..2]]; say Dumper($msg); $client->send($msg); } or do { say STDERR "error: $@"; }; } $server->readloop(); info-beamer-1.0~pre4/contrib/test.js0000644000175000017500000000302312452774240015313 0ustar nknkloadedInterfaceName = "GPN News"; interfaceOrientation = "portrait"; send = function() { oscManager.sendOSC(["/news", "ff", multi.xvalue, multi.yvalue]); }; pages = [[ { "name": "refresh", "type": "Button", "bounds": [.6, .9, .2, .1], "startingValue": 0, "isLocal": true, "mode": "contact", "ontouchstart": "interfaceManager.refreshInterface()", "stroke": "#aaa", "label": "refresh", }, { "name": "tabButton", "type": "Button", "bounds": [.8, .9, .2, .1], "mode": "toggle", "stroke": "#aaa", "isLocal": true, "ontouchstart": "if(this.value == this.max) { control.showToolbar(); } else { control.hideToolbar(); }", "label": "menu", // }, { // "name":"myButton", // "type":"Button", // "x" : 0, "y" : 0, // "width" : .25, "height" : .25, // "mode" : "momentary", // "min":10, "max":20, // "midiMin":0, "midiMax":64, // "address" : "/news", // }, { // "name" : "mySlider", // "type" : "Slider", // "x" : 0.25, "y" : 0, // "width" : .25, "height" : .75, // "min" : -1, "max" : 1, // "address" : "/news", // "isVertical" : true, // "isXFader" : false, }, { "name" : "multi", "type" : "MultiTouchXY", "bounds": [0,0,1,1], "isMomentary": false, "maxTouches": 1, "isLocal": true, "ontouchmove": "send();" } ]]; info-beamer-1.0~pre4/doc/0000755000175000017500000000000012452774240013105 5ustar nknkinfo-beamer-1.0~pre4/doc/.gitignore0000644000175000017500000000001412452774240015070 0ustar nknkmanual.html info-beamer-1.0~pre4/doc/README.txt0000644000175000017500000000010612452774240014600 0ustar nknkDocumentation is available on https://info-beamer.com/doc/info-beamer info-beamer-1.0~pre4/samples/0000755000175000017500000000000012452774240014004 5ustar nknkinfo-beamer-1.0~pre4/samples/green/0000755000175000017500000000000012452774240015104 5ustar nknkinfo-beamer-1.0~pre4/samples/green/blue/0000755000175000017500000000000012452774240016033 5ustar nknkinfo-beamer-1.0~pre4/samples/green/blue/node.lua0000644000175000017500000000012012452774240017454 0ustar nknkgl.setup(640, 480) function node.render() gl.clear(0, 0, 1, 1) -- blue end info-beamer-1.0~pre4/samples/green/red/0000755000175000017500000000000012452774240015656 5ustar nknkinfo-beamer-1.0~pre4/samples/green/red/node.lua0000644000175000017500000000011712452774240017305 0ustar nknkgl.setup(100, 800) function node.render() gl.clear(1, 0, 0, 1) -- red end info-beamer-1.0~pre4/samples/green/README.txt0000644000175000017500000000013612452774240016602 0ustar nknkSee the documentation at http://info-beamer.org/doc/ for more information about this example. info-beamer-1.0~pre4/samples/green/node.lua0000644000175000017500000000047612452774240016543 0ustar nknkgl.setup(800, 600) function node.render() gl.clear(0, 1, 0, 1) -- green -- render to image object and draw local red = resource.render_child("red") red:draw(640, 20, 780, 580) -- render an draw without creating an intermediate value resource.render_child("blue"):draw(50, 200, 300, 380) end info-beamer-1.0~pre4/samples/hello/0000755000175000017500000000000012452774240015107 5ustar nknkinfo-beamer-1.0~pre4/samples/hello/README.silkscreen.txt0000644000175000017500000000214612452774240020751 0ustar nknkThank you for downloading Silkscreen, a type family for your Web graphics by Jason Kottke (jason@kottke.org). To install the Silkscreen type family, unzip this file and drag the files into the Fonts folder in the Control Panel. If you encounter any problems in using this font, please email me and I'll see if I can try and fix it. Please note that I can't help you with any installation issues. Please consult your system's help files for assistance. This font is free for personal and corporate use and may be redistributed in this unmodified form on your Web site. I would ask that you not modify and then redistribute this font...although you may modify it for your own personal use. If you really like this font and use it often, feel free to mail me (e- or snail mail) some small token of your appreciation. A URL of your work using Silkscreen would be appreciated as well. All future bug fixes, updates, and additions to the Silkscreen type family will be available on my Web site at the following URL: http://www.kottke.org/plus/type/silkscreen/index.html Again, thanks for downloading Silkscreen. Enjoy! -jasoninfo-beamer-1.0~pre4/samples/hello/README.txt0000644000175000017500000000011312452774240016600 0ustar nknkHello world example. See http://info-beamer.org/doc/ for more information. info-beamer-1.0~pre4/samples/hello/node.lua0000644000175000017500000000022312452774240016534 0ustar nknkgl.setup(1024, 768) font = resource.load_font("silkscreen.ttf") function node.render() font:write(120, 320, "Hello World", 100, 1,1,1,1) end info-beamer-1.0~pre4/samples/hello/silkscreen.ttf0000644000175000017500000004364012452774240017777 0ustar nknk0OS/2y@NPCLT4nA 6cmap:= cvt SM@$fpgm\ܢdglyf0B6hdmxAXHheadX_=6hhea4$hmtx,Z?$loca %:maxp X name?b<xgpost G ><8preppDS|8t_<77  kbb$ @ ]P( 8Q( x  G P(      8 Qsend bread and water to jason@kottke.orgsend bread and water to jason@kottke.orgSilkscreenSilkscreenNormalNormalkott:Silkscreenkott:SilkscreenSilkscreenSilkscreen1.0 Sat Aug 21 15:44:28 19991.0 Sat Aug 21 15:44:28 1999SilkscreenSilkscreen@,vE %E#ah#h`D-,E %E#ah#h`D-, 8@68-, @868-,Fv Gh#Fah X %#8%6e8Y-@ EvEhDF+F+F+F+F+ F+ F+EhDEhDEhDEhDEhD  =@    Fv/7?@  Fv/7?@    Fv/7??</<@  Fv/7?Vt~8 !!"b"#8#$$F$%6%&','((),)d)**+,t--.b/"/0<01t2623j4445x6{b  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a$$  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a~   !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`a w}q}k}}k}}w}}}k}k}wq}q}}q}}}}}}}}}wq}q}q}}k}}}}q}q}}}w}}}q}k}k}}}}}}q}}k}k}k}k}q}}q}}q}}}}}}q}q}}}w}}}q}k}k}}}}}}q}}k}k}k}k}q}q}w}q}}q}ww}}}}}}}4Alts@ ~  }qpquSilkscreenŕ?SilR00d                                                                                                                                                                                                          info-beamer-1.0~pre4/samples/image/0000755000175000017500000000000012452774240015066 5ustar nknkinfo-beamer-1.0~pre4/samples/image/beamer.png0000644000175000017500000007605112452774240017040 0ustar nknkPNG  IHDR4c_PLTED,8BJLRRTYZ [[`bb bgii!npotq ut-z|{~*;+7D0<L$5KW.>G Q\,:MWmb1; Q ,th8^TG'~5v*FmQ:!Ȅ0OȎn<'̘4GЉ?vQ-Ղ[9ԕ։iC՜0xrקN݀=݇HXgݢaB8rLUly_gOYpxcTlbu~piWtRNS@fbKGDH pHYs  tIME 2NtEXtCommentCreated with GIMPW IDATxpxꎨU㎰: i5=uJuΝ~Hض3;L/UǗ6 K&Lۜ8N)*pQ2h``{hp-WR)\SH?<+'v8 }YL0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &L0a„ &LұӇOA3&䡇&&5&̐9QY2av{t\kqvzddM7 &4Ȝ9n!Sn4M,g&4\/Z޴,F:Up,O#&l.fޘ)ic&53*V׊Fvl,5| `! #~0„p3Hj T+g%&̟Ǥ4)3& ΀FT"*LL?ay4+& L!xʊF0;CVJ(7j&Nn@JΥ33T0RSrVH0w>CV+NٌcҒ*~B„y3Ļf(a\̼05s< iF0 H@#Lˎt0 7@ sgBݧlgɣ3G?5;{|TV&h8aĜx k'lھyc4[i'5z6/~–61_1ȶ)'nI:Yw2  ̩/=9H+ЊM%91l*M"4U R^ [{aD"Wab9FèER6feY1LөXUI'~–(2G>F-L :R+e)5G&%o "[%t8]`n&_l+̾wVu3dI+ IA`lVMR5}L=%~–(3OKjִ17*u%:mXP/ʎG+l^4[M`8=GO^WfŏV?#V0Pj+@c_vW`7&%uTC$ 2lh֤FY`_3սaKEi TyBuәR6~.DѠ.M٬p5=l1;#lP0;;d7X| KYЌᗞD4d}`MU 2Cϔ1tMЊq_{HS Y'1&KMlL9ircL2_FgQ--7shBj uO8qZnB4 LAc _>&h@1UT]D̼<.ASԉmq=Œ;)'EzIhoyyLxfFNT.gZЌJLբ/%a!Y֊X\ʪ:4;C7)}J>@W7Ւ3hҀ$F unӘa )OaNjfK~\7TiכmQFgˑ\}j 8mO:ω(4L!~*J4.Y}Rji9+mw>VÀ']M);Z}jLP/lI VװgR&ra 3k2h.7rAU*u o MEjQP{BcO?Lϳ^PO_UA*]vdBByV%GCfevqoYE>?ʊ/4pW9W3C3wBC=Mp7$v1N"3§:Ss{yhiִž#(<{[iF$$v0ͶL b؞$t5<"<v٬9&O&'݄3аMaEl&h^h `4[drs4M\  oGǥ% \W6? UР>-?c39d h]4v|}6/ uFi ʚo=}54騖54-:e xv px&А}j KOVx)4U1]мN]%@f݂&2hB2B})@C3yсJ4@='vA&8t!b=N*fSCė\\<4 ji|LMK}K@#ٱ5R-p2{FfX2FlvgފiT@i(tTo a.8{H1bKeMZ0_}LU 4hٴ9hx CQ=J/DxόoxZ,hu(Mј'ojU5yF &dS[.3kAibURb!ik50JB@#Sr8p$ r罟A>s[OJ3EnHAVKJ\@#쬲'N8*չԛ̝^iNzɮS7\`Oc_YU3ysC^GT,ӳag̳[7mڴuۓO=ȌMTX9Ah5_kj.54žDC6J2Y8`b%tY@#, Y,S-Ord[_Uk+=|k`V@ӝ` ueUe̵sL$ } K̔nYQ h-f&$P,N Bn͘d@chkqTJS_dlmLI۾Z23O$Q 9(YB@EJ̦1Ysg}E!W~Ӫ,_egpƂfOF& \b%?;(| *ӧt)mr+*Ic020eLlP@m1EE]hhJ. 4hQٷRhN>Ѻq-ykw] HT60xoG c`Xdt*: Ydʶ189Y qJmu=+?+.4 3:wvGU̩֮bGۼA$\Be}2)Rb02i "l\GO M{B鳊 =?W*014 1 c| nKJ{EY% ;dszh|QX&lx8x*/r;yT t\AsM㊔Պe,YhԪz.+rlԵDtO^h|?<ÅgL`h%|4Td Cl2{;$6341'(ü  n"FjCx*YYP(B@`zr@ӴgMv.ݩIjAǒK QTg|_HW 7&p踒+Cx=fc+hzVʪoh!78:f$4Ƴ,Idv9 &nX9<|mhz11alPw`@AoY7ۏ= `)Y{J,Wʕd Cs}\* 1d3H":48@o/<E#Qh=~Ab:zS(3p<>MMJUmjӢVf%5k93ni7 4?}4:ތA**RG4 3iז%g9&|'?}H4[2ayLl=AT^l妳4TY&92fOfL,kI~]4|Sc%5A73k:=d M,טLX].$144,.;ܒ* W^wۭ_!BLt%|ācYwG{x*A⬠ٯAu 9eXjfW^)eɯ= wiy66hNYf z5u-IIA/c02pU2斛 E+ fdΕtpXKAtuw"SӸ̳=;gϑt=Ec+_ ;BWtjc|!`Bj>uit~9]d60ц&b\ZɆA uk'1=]]x*/r;T ų=Ygɪ̱ ϶fgv:i}N@h +%y95Ee>Y&$׿:2>Y4`qFPs0ulh`Y:SK fv[hz +9ٛϪz՘|Yl[%ىC649H[HwPhL?1pp9fbQc 64ݝNL @,Ocfg;73u(yq* Fӂs*רAhFs'e%u b2$(e1βs`G(4=tvvZдr@3υW.-01=  IDATwf>f^^迪Ml7剷_*~R74dőn(Nt^tr Ok C\Lg6"ipM\4+iMw!4EY]ydꔷ8'x@ `G](J4R%H:Gˆt ):yf SŰ R4& !+|v1h.~hpgxP \!3ߏ<ճ鵲f20MdXj<4Kx ~VRĹDvt c70z% F#x,L:> 00C4(PoM=@JLemmCHI< t^b?i/2S0R ܎ Ɇ`A`a,,h2I~ґw5< Y!LOc`TGdzPh:;IӶ|y P.h@s=> fR%+ Wv<̬ u\q`!Po<9H.Or&j" YFV3"h~Z+ݘ="Ŏ;A@'c!c"a54 i倅Uy9EB<\o>I9JrF-aXf'2gs2C\;n  33WN{Dm,11ߊGr1@-6g 40W_ Z䠙ݮh5j,OY}3זhrrR_?=*&ky2N'e'fyjx?$|Εu9дSd1]?;)E`2c4AsdM&Q`b$٭UgPgK\VV+W` Y_Y.@hI~ {# . ۓ˴a|BWwq\<ӌSY\69Uv!dOzS'Yh|POˮNir|M4 1xJ&>0/x=L-;d?鴡Yfi3A4K]QVm;v'Sެ);;54e*8|+Т9 15VٙALi&,hiۇ0!w>bLAbz<$Ɍ|s9~wJ<-M>kwAU"Qu|3~y >DnC/ 4kBs+a朥7ا)r5F̾OfT3;SF[1k"#27UFGd}ae_b~ vL%m+Y.>htj=RҤ9CO|'2驿lV؊F !zX'VӔXht\].#ϼJALG\332izЏt0! 9gɟKcَ?3"kC/ b-44p)#5/g+gn/2e$Fp<N3ɛA^"9 <CVʥ&o> c L9$,hj,'Hpww2G#Ħ1=g}'1Nl>4DwT(NQtF"0Ohj~3jv'ٜf g<Ҁ9ل< p-G_IjtHn`b! qL2C<4'i0>7#\̕- ۄnCT+|7{V-ԁLe-bl,gyuF5rde@Y T_}xnm0ͲzBlǬ`|,htD7=N(UxRf7 sؗⅫl> 2UUnp*dDQ5]]9J28jeqs,!32ខdգ C2\m171˗wm AZ^M ITYAsك }.h1Luy܀ 4.;L+&!4^‰:>3zv`O?if*trceL7 ]t_ܝ궐 `R][f,'#3Čr$ŹA!ԏ u#&.@b#AlWaQє hƹZseQl3ԠH 4F"Řj* d*SNAw'aGz^AJ2.h΀~'1K"rUZhIfUj&p ר?.܇3O?n*+kPI<4IpDq, Nmy??>sAr3vhbf3wo vB430%[:gfZ |O0WKꗦioahLF[%9M"S(dA?9+'o:Rl(b$JYA3\ txYv: ({r[A̒iZ<%4~Y}nv!@U+xV֢̌giF.h.]ʉC 2U`ʢ=>a2DZoOG׽# wm>~%5ai #hOwA<_ <"槧e=YE;]JY"\gQЄVF }-h;߯dMawWԡi_^jQ@+3{ 3tC="K1 C2{gTlwWSeH[* ƝXi`u#hz-M;]_]7\qIFg\q?A̟AxyΦ3*fy)/@XΞO|Fxx49w*ځCcހ\[*`qy2&d1P,p@OA621 Abb==n#=~_;?3of2~yuy-p -3M6OI ҉Ԉ ,47`X'#_8H_e+W2l_4[+r#:,?hnn2~pLM=@C$5lh|4jKoTm1#c%Q3ʸLN~ixmc"_8H(k/ 14#!F/" csVu]՞4ix[3i)4 6 )z?l`j 4ѸɤPN>?;8ΏXtdhDr#)lJ &|zY POjWxIp4S(2JL!S9he01)C_8Pp] tt؝!Ȅ1)f `?I*^W)p[ϙpM1Z=3KO=.0ז1 4Y޽pľOfז 4G?ұ'#sn0lNŗiYEuk^h|#44liϟ/47fTxh !c_#@S_3'#J2}=t' a~tnjpsB=̞6:קyLKbabF>`AmAb4Ch@ca2P;[IFfC0ZY+{5VN㳄F<ߜMIYGi6kKP /+4fD.FuJKeP ~5 0K[y\М7}w%"O+:cmJuUDH=~LV9fy-R<7}sRu($h$-NPcwz{M 駺IZ$#T1΋:O/){2֩ 4hT@ts'v -.Rҁ71,1x_Rnhb́2{9&v5d1B~7/wcY frY0s~Q)6,B}c L>4Sgx ͞=xNYԜA̒׵UGnNdd4V6 <Ġ߂fW`K/.w2'0%+3~ZddUSӋ4y=tþYGoqNg)g}YR>\!K8TP,4Q{;f Bd-i3&vɫ>ه>%sk_SΤ%X1R]"\$0p{8|'0^9LjF>^ndu +b j7܄odmCCggaoGcލ`w_aV:?t]?O2O}L\HqA5`Qs Q0[O,OUAjj?dt50s9xp̍ $J2xldd$_m/*7BV?ՉyEL,ז1W%.ak eb>`Cc2kzXmwӾI|x6Y9r߯obٞd MJ:K؏5#hBC' @hBn Y-#8ǖXg'9v!95^-u MQ en"ҚE99i5F*2Se};FЌs#|x h0R^0ɨOg=m#$#.a7sgF*D=Bu*ۦT[4eZ3MOP)( 䏊eUZd e8DW?GL0ɭc4nltu_[\^;=4 ۍI kQRi ̑'ë~ǰGc;:>uB"U˖ 3fd>|Ρ9q򗯾c۸hs"4(= ~Wu盤qI*ԍSwNu6{0wS%]NlَUTnF&0%)9<|*<n_e "hrfdvLW{N=iJ~Lc4;'8½kPOG%B(|V3:߽h2nZ2o̞[x1SezQJ$T%u0e8Rpw3,sݘ@WʣX\n_K='EzXrV4GP,2-bAS9?~gn/:&:EieNVVÇ11β:r2xV[I,ß~eQ{%7V.MWl^,mmWSv1vgۣt]%gU~} X%_,W:jkdtE/'u5>& J?lbpb''s鑻Jĝ1\Y;˱pkh,go;0 ` L }v\"F\xojͲ\iD%糂f扻gd4seػ]ntMd 4%7᧥MShU5&gX^%3$)[y-&F3DSlr1 Ñb쩲A Mg{u1Jb/WeH/DcwfVI,ao{e4i0U'tCzO͜=4~MXSNvyBfN1.70*~2U3$Ә(^ 90p7Bfzvqr/-b+wţC+@fw. eU{1Rvs@ͿkdGBYU& gov ct'sc3_˽+#Io˟\椗`/a2E ]Xݿle߹+/{ji oRbtB-6Y]hCW%i󁳅fٲZ `h45z% 2-#sX^ktbptj ]/vuWHck[)6.[,4Pb.!2v'aNK e{ 4͹)֝N ;:@٬hoߎ!?/uzUb\,PKJOq.e/W0XwW|Y<,=bW-h=4ϣkH2Ɗ&LnY|;ak +Z ϊJN00cRY*V~kM8Hjelo.N<FeRIG.r]7[3~8FJ&l3nF4MrV7CO?5zЯ̖% gWE"nf~wO:62Rf9+ 4mx~Y_X;oAi_SKZe)>w+9Z3[߸&I֍Ndo4M)g FE\[+k$!yLv2\TP!pGyPbN'cd?Z1.[ブ\h/jr[ 2uI'"ag}8.6)B㷑i>Z@!ێJO%3swp'-v G?ot|o`i;ozt%kXZ8rv hgYIIyȕϯ (9eTLV)+Tx)N'"Cr'-9A2_Rn>̲_yUߙ혋$ 6q7s]W3gEi IDAT^;Ѷ41-Uv_ Yw4|*ǖj2x֥o毰GcVY*_N|zx0y~ą*t2wLj`R]Szg^,+zs(Jg.I{! @?}$s}M*d\846$4 ij<dKbKg=O'd,S>=<D|yyxO(L}L:ɜ'Na2(?%fd.*hԚ;7)zQ^™[Rt`2-U|'SdFAv%4ly e.TeФd: }rNed<:<> R%^︘cLv ).2dpS*)ky }xuFUݳyA(iܤ˸g fD*Lv7=w|:`0+8avvqCc\Ŵa%43g a6V?Ԋ2' sY- R?Sbh (ijPd5|zpEgcT=! re'gd?p,Hᗜ抲cCc\=c[bc(1jA'+ϝ90)4L<QYk,xue!f=GcAEoˎR+ӳiv&R_aOC#7^ &{2>3UD;"޹N@0c2XyJ׺i22aVSղ jPNÔ#IL N2/1~ՉafLCc4 ʜCp8@O:0.l}5֞\Uw?AEmiUєJhg3nMפ! 40h>7QA@j,hiTEw1mɢ}@OdNr.yl8ɪeL qrc64_+} YYPa/~ͱz;{q70]\oKPUu330}Y6? p% QP-F5(4k$s1c *8bu`gߜhktX1>Gc>*Eaw[ɀ 9VՉ38<)V1P܌IL,%bHt`bP'\Y&2Z`tꝻ>͍Egg?lHgLJ~>7_lAthKlH7%MV=IoavfڬԹhz,b zj4270am92Do{P,c Ld w]{G? IgRQM'^=|ئNwK~6&Y2œ=*z0E3-nY@x )X^.Z?Mr[=}kQؒ[N.HzhNh.{zJlv5ѮtQ3;/eL VOQY;O( moߞ5,-/+!8DeC;ڗмvxTIEQI)y= +A7\cƤgF^rvO^F'=~a$َru[GRflN.~##x!Fw&]+Э+V<ﵝ3MFSNk*=DA)#}+<5KɫdX/Ψϳl窢]h p֟3TLRN'$bdv?9 _H0;KhL&]bcږ{nԚiF%)m:?`OL2͜;e0MhUZtMe p_ȵ[4R8S\$8r,HÑ}Pڏ'㳘 e1ۖc fa=lɀYfD>l6O̘\b2y gG?[$dreuѦX奼-VNē&CJ2<<7J'4`e1z=|yxc{Uf9jMeɛz67'Fi&gҧ<}FG-UJ&qj.N&3|5\ :e'dBLw-' )~$0faxCg#4?'+U@ǔyJVͧF~`RO{r9lEd)0"#>fݎ2 HsɿN.= P x6&W{h99F}pHYVW:?)@3D2n0gX,K#uʘ-Kj.=R٪s.]عij˖sCd(;ً}kZj/异/d;^wcс[^ˬ,%}{|X<ﵥr8(iz#4hF>>U FRkKTet2/\z:@9KNTl|K{m79$W,Egۅ< hz7f9 lmZ_OX"M;hHFy?t0eNn݌rW}XK?O{o$ x2*mTu4@ם[jV &u Xٝ$5X<ͪg{gzH$2\|,adn^_Bطa ǰRSdhvJc0_ٻlg""O,D_#pɿAb.;OTf*MVAYι9 +GCY hǔTzCU~/:n<hbI:"C=x|c̒?ӏt~ѽp̤qS20;;F}} 4-Gc|B/4웖<K8#2DC֝Qi#-b{!wAIhu-HBjNffߝ O?=zW;u&/i^XƳJ# ИD2%WӤ149LN@3(狗vp;(/9hV13/{QMf$+[ቃ̞|1ߗiD9(e_^7oZq P!mD)Bf%9v}3z}6F>hBo?@I_mS0 'dE%T82"yӅgzfC-Y/뮊Qu* {VcQ MyjDb#)lK/E3C,y03}W|++>Ob. N1^(6fv;-b$%W+ajeXP4cnsf+h^U u>Z:8o} gd*{Diq9+bҝeO60 0{wu~,d.H&afC<SQev 5u\tfl\7.M϶E8 Gl?44Do Gv(ɐ4^Y >sXc44{Qs ;S w >YyRwHܝGYb___0ŃS< (ɫa= jzA$`b<<ý4i@_hvzKC߱.X9ezؒJf7BULVYv1D N?" M\*g6蛳4Fӫ 8s0Ɣ&^9{\2[O: ʨf?4CX4@ `=O[OHZAHΝ&?nYJiɇMgfYLЀic;O4MWKh*a/s dK? *!ȒAp ߊJ9T\;-z[HY,0eW@&>bJg4tzlzCӤgН]9 kk~s gupbeZzyC30eFbP!'.N'%Tv@n:ag4q@6=TV2XOS>JK[Q&,~]UJx Px'ؐ@ȧGg/4& hIYOIYtt2xhow]01$aY\h.-%Ocr)M%冞8Jӌ/poWc-߮/jӰf+O2)P&iͳKi*c>UM'70C9vXb@Jfb.;GO'ܹ}&OaOci3(JN/49g`{قaLSg,I, }Jݲu]OO%"Ѿ !䠁}*(ʺ?,IN4Mߟa]gSU3f9M]QyPU|S(j8uMۻΔd92߻795d:>% 4>o>EPJJ+eV7MFg5n4J Z _4&B&3[Hts݁`o/G c)[YEFQw>(< -Z4=!j6?H!ӌU\3˘ fÈ q\~L:BŸ 0z%Nx8һfCNr!Ҋ:zNuy I5|Įeu2Ռ{%+jAK۩1Zt~4hFKp?/PF"Ӿ|y"Y9CUE y:xhߦ51{wOA5GBfpl hLdb+bY-GM k;xjikEh4ó/;aEeyh0 :g# MjYK{P)4O9owHRQA ^ID/-?8 dگݙ̉G'g(FnK& +F37f8-gͭY)¡1.)L&cC,l/;;dXȼBoi7(ټN'6fǨjFC& >c ^s}mJ\gڅAsw|D8If MGfDCs&Iϊ ͳHף\X 3 9u ԦqCCh2Ă D<:xBIȴ}ZTmi::.hM && ASY|Iܫ΀4o-}X 1L9V ߱_ųdmu:hz5?[9 I ع'QO3٬jzAU5M{~U#A5\/04H'Dy)kS~+E/4(}.3Dٟ ߿ПڗK[-%mLnf4t\{iP54TSwݱhFd.e؂i[FYo՟4^->4o!Z3^hM^]7|gMowyN)V7Ģ |3nD4%}#np-o8 lR105>Z0yd%}aukjQ-kuUGɤ-̩nZP;%~_E`g$}@45fT(L՛Mm;"/4%H,hgk45$UV.Hs5ņ Űȫ ~y>ox\!*"Mg<Y2zR(2[U7GB:R3L1GV!6S)G70;fgcc4M%44f,(T0ZЬFi We%G'wfﶉ:(ԩ&*+j3M.4\=#a- ?IVu <=-!hkߚٳi Q364p^[1 PEF/ȩ3$MC8e P%6/hCqUï''g6piKhMn!lks$E)zQ1*eGyGh扑p3E?L'&m MwhXp; e4(:Y23&[0KTO'zr2~GAUazЯ3bE|} м4&آ|A`Hj 4ߤOz@镡V1fj#kNs;M < L|lL'vc1<,hfj8>~1Bn`S }c-PN!YhX#'<ꭱh9f4CoLؼGR wACn:HKiZ1y}޻!̦~fϲYuw&l\)19)<>*:=@8e!پpkM\IDATP0ƲAc_'}G=g[Ҭ :FB I;fn~ory>+~UFDdsm0pK~Gʾ_i3Y7 !:d` K?W4ZhCsC]z7[ / s?Z^e,VkP 1%b%cQr E$15@tJ֟m4?CɓTGJDUYv')M,{WVE qo36YciɰXcQ%lf@'5{/MŠ,_Bf)J3gZ^"[ X1$̨[t*dz~gh5FΤҼN44C Ck^Ǖ5Osl=b# bV+@dL/x;BIeRbb 1NxZ?Cs?/244gsq+ffSt(9̲ V1 +pd`.Idu`vtdzNh}05vi(wutwbsT{pG ,WR{nX/i/2Y\cİ͎Ae&`tth4lM9/ffEi/,@#50u2>LJi!y"/u2ݎ 2&蘑[::=g) 6C,b?,&5V@tBS.),ئQ y+#IOe͟2:w@~g}Qќ,-.{vT܆ޖ}bjURM+GW >3 s*~ +=et4Io$|s[$3͋w)V0M'攃zPd> /z:ӉOI"_%#srNևpbfEh&t<54l9ˀZ%Q9/{LnYpؗux,iµ_jGyCй̯2-y=:M)UqASG{f}OVs14ۭ?[?1t/v_Ex\ ucS"Q7xfh{Sgzli94)TsiaQ9+a6UCnU/l.|G|4>&/tcbp2B>d@g?=n JBH#̿hj!OVqj5 B)y`Qrh{i҇C I*L@ߺ@g˖mмՒmiמ"r^cvzپAcN㳂6Ȏz9tsq2ӡEy Pd@g҈EJfSl|d02s{k 2/XkAc;>(A2AaN|ͿF:F"3qd@g!@g'g4Y&7KTJk= Cc"XӴl[(1A.y.=z#p#Px( }Āj(\:wviW04rӿebJ!c ǵBYh9艧^t?{]7mLcrkoQ tơY -Mcv&ap'<*WFx͖dSN1;JAhXw|\(LrEt?O~k]5'^>z g+1ce!{dlU|h+{M9'#\u^=}wI$/̓Wv})]'|=3#W9n4[k4Œk׿A>ǑOY qɓ*K(EhjӘfD_'[ ATrǓ T|h|Ŕ0l:0РUU4جl̆w;tJy%\Cs.ZJlrM$W C~ h02Me v$@SE^[kEÖFEr=I<%4)l8ɠ24 4g/4sXnv9'.Et -1t2 }5k>4i4 9/ݪ:7x<Upv4Q˹L2y½)5O$Hr3ugכ,  c,g̬Ɋ|֟N%qW 4z\ |dleb\?^#cr$56Jjů_꘢^b#! 4(T[P&fZ4w+˚>4?-eGXKE'cv2׶̀Қ'תGdXNAϘ}h L.~Z"$AIE1ټ p C>2 R^)L[hAϧ14z2ɒf$Uu//H1y1f4ŖW7]٨LgS>]KdMTB~ v+v>,h\j ,{e!\ʂ&YDyH*ah'&"_Mh)=hBfΡyы|>Jwe>5R&J Mo끏 48nVse( ƺi|yqr:#btehX"'4M/Rb&8S cdF6Cc"=L*@ܛD% *fK& 24vY*F2eh޸< EaH&o)-~~2drܿ 4| 32X>44L:c?"d&hMBc<ʂ2]Csp45v~4#8.1lFD|eڂƲx?O kӎ2Md4730q;f&4nI0+9d0$C^Q5CsÈ"":gM-mb f\Jc&}j2dHW&0RA32tǠiX0|&+@c;u9硡)F6$-֜0%e`2t&BwӒ^*Io4< fE8a$4nBcI7&J0dxU:9w_?h i3035GG :L/!Cs2<&11Pc@kWW z Mb8UDY_S2˺ 1zƀִS`>2A&H4t4_9/{QTo<4:,1L<#ˤɄvR*23ɀZ]Ce| /U5HЖk%Y+qMYGF,Ck̵c b2XtƉb@42ɝ_ZOq5:vcaZz)Fb3*/?oԫ\/d3ĕURgL{0 P%` +#wTW̗L|86NK9U \̴yEdpŤ7!,.SyhuE\!^' 8@. / 9~K&yv{S Z)yY^NQ.a4iJ.]su-_(yZ'K IXnqS.I;Ӟ(V~䅠Qbھ [4)_ܑ3p/λv֋7C^XHd 5zޢL2QP˒ V'X!hy n]߱gͦIE4aA(tsc_KX@^mkg[OoetF%q-y ^Xhb7}V o!&O4eu>ײAH)ߚ0u]K<ϰ3k-ī!4@D#kO yQ XPjgݮ^t`,YWsOAxQR *3[T2пJ (^bp5;Mof6hn^R(#XUpMق~5E7=3,f,hED6XnV`;wώ`=4wbZszBlHXlZm6Ɣ^)iηEGS`!BX6t,Ŵ>Ɵc#żg3&"X_VPz<%[Tysg'Nq[GŦbY+*{5uL"^Ic5Gf0h)3X 2П3ÅNXD~pX$,Ҭ_█4?%cw T܉r5^t | :K`ED]KH{>" eT\8#t"+NSn_ T|hZ7{Du,ا[s k)Hz! bܖ'1LQ'xQX+2&1a:LXS?>[+IʶEQp5Fc\K%v &k65F`OtEFKi7AX_\d$wg=f8BQ^lPTYLB ?PqK,}%c}/nl֟ՠEee 袧-!#fυܜhb(/jkꪦhn^k׮6Xn#ۦ;b%dئ 8ZwG.>XC鳚i`RD0+@~Ñ55ց΃`1G |!!!/0C4KdRc~MuIIժne#}lo/lX]]G8ŕ~E jA#FUU19ОeS5A/XJt z5^+_v$sťO(ZB4*V[OA^ch8tǀwbGaSDx3YϨVşT]L r4z`ŊU N:Ο"vCl+;l|%76* }6I^ҲtQvv!VA5RX a/d([[\aBfgfI^}c5j v9 /4CӮ:oڈ?s+7&Oaz[:u4ë>~%Q-gZf#Nw4tܱm/ĦaT=8qga"{ ǶmR)jdx X4ܲuWa ܫ-A  /_܉*+-G+iozJ97?'u{$GoIQA_R1E9r*G //\{UMe!;K/IUABCr8vG۔ }YoN35Eh<u?G޵xַe=%&LRVvڣ={6>Sj$[aHd0lU\q,[&9\@#q,ߩ.W&CTϏU<*B0愀Q^0-a31wXq+wMě\4srs'N^^iXL "yjb;A[W&1@v[<&Z\3oy-I| x?eaQ1a swhKPt0c[]Lc g.,Kl:74{^)V$|GrZsOa(qGSY_CԫqO(miΒ2OFB=~A4q4ztI*PlN~X-u _I]Ic5>ղb{'=p\>7+;#*l%WҲ p;WsPy̏];#%]跞{(c#MUëN _x`j*κ\ߊkYR_"]dss"DƿHnAi]{aZR5q2)uim..bnS*>]ғ҉gh2 6.8vz李uLտi%(;mBPHFvD8AP$E? H*ņL,cc#3fwt4[ >shP"Y;]]l11Ȏevv;o0@0`q01(IJ4 1N PB`%UDHJIH_>TUUU< UU(!15o=s<w3_=|gsY׽{m,z!L?q?\P8h =߀Fv^ƪhrDx9QᓱMsμlēO^G ,;2Fu=v(|wU1Ƅ/`ar&J;1ɑ[<mLz"~'ѹ(8W[v,U/0[;tj=N|>iyr;6SN ڗ2]V5Ue%$ "awAIxuAxJ4F0-;l4@x:\gINKHCRhb Ǩ%kʢ.Ukńyl穨IYZYnWU}-cɪ4H zd>!F H;\mϵ@`#dz^<73ɫ^e,URt7A0l'qg26vN;|\UpOm A!`z CkpYR޿,cr&`.m.+4[T|e,1G349I?Te" tXW,H5$ cSɽxeQ[>+{  G)26Sh&;DAplR!Q&_1ӺgӁ:z -cbCOeQ4CM.$F^Oa&ɏRE#MŽw"%,+G,cD㞏n&z$u $kIuǟq\<_zؾS#ߪ*9lz?=qYs%o/k_~iXGUb}cTnRu4޶uEo%Y`'(DNu V/{/_d ^VߦX-/ qO#K5H5XqR ?'lK^A0!A(M3jnx꣺>Ŗ1a!qe~`,l,cWk%YʹX ;,b o}HHS :Hx&ֹ 8c֠tmdz~`a+ :c(4$}YU5J-k| |I;$j%Z1ԓ*kNsܙq<`EL,R#g4q e=[7~E_kZjhWR NiNnX6bu jX|C6lPʞ6@bHΖ,-cuϷt-U/*`HtDQ:5,V& YnVW9cH0u´Vw.a=fl#gzY֑c!(}fY-XLVSV3%Q`MjPuHQΡO7.V$LFB`շ 38" f:LN߹ :N1,xwW>V/Wn-Mqʈě XX0=Whlg I#yҭXI,HƙS!ӭI1n": |k:?I(Xb, z7Kxù?/>+ff9(+kRځUM^\=_ lywE_K]L-^uHD6wn``*+Ю:z?BSY]-4%n|PrtD /móM.vl2OJNk&G#5J&Kٶf%ᚬYNb5*^uW9h!P f􁋡յv=dٹ=3lLH 3t A\ S!X`; BzjA\ғÞR8{井T`'Sc6t TxѧE'Bm4RJo;;x`,#ޫo}ÞkG{-/hc%P9^i^t:e3A^m#B 'pp 6]K}]~,wtWY8dZMV2̌"LEYaW+YRorR7E+,ϱ#oA{EO` Bo[1ζI)ECPr!uJ}6g190U-]N5>gG7Nj)d% En {;kqO8V0A_t%EX5fAf/]C7>Ԙ^n-o@UJƨ .00أeq_)uʚF߁8?粸,rA]J~H~F9v3 U!^zdZBZ@JAnZ` gZ}ൔnW1[nvudb TT Ѿh; AF%bjլ愜)L-쿚 o"0v dAJ*i?𜕩ڐ}:dB/Bz 0sXqZ߳q`NC\h6핁 *1iRҜ X_FBae]=N[Y7NWAx?x:A:w>w,DRaZqU8 f,+P ~jen/ lОVned1 rGt[zuISЁDZ`^d> E.HQWUΎ|o{WcQ,x%54}aw2ӺU{ ñw8mI/^9ky,DGc>q+'3bEo**v*l(z͜wJv Z@CFUGdcZcg6ea. &H+(W"*wm4M4lGc6ffiq<~9p&{yx>{ޗN *;B^ݹZ<fڊq=?'Iѓɮoh 쏍\U<`'w#qUx(3ў+ *֕_џ"1,kD_ ϳ(Q|!@6ȜAJ;`XWL _[Uji E+,jodlF&*IL Q[6*xnr <#xt{,^t5C%&(]OAmz,+y#&T?Dm(b |ǹ=Ȇ42#ޠ*0:՗XZPL- C/VVԐK#Wdo!a9?Q8VC! =5n}ձކ=f`L.QDODpY:szӫFlFOvuv5M$>6${P\zijl&VDZIky ӘEBS`6 󀅝U[4Q| [$8WRK؅ fܠnI/f瑻uNLE+cάִ!(0:DhFRN1"?/=Gx+8V+i` HD5rR_@jkVܬ\Z|GΝ;w#BerIKɦdKMІ\H2lSu0y6# ߯yX}V `q=׌ؖX@ܽGVɸtvjdgVA 驙O򬌵\M_:c-1X؄׏R& [XXNE|Uau}#ԑ>aZm[SZ$)!f3 Q^ZAZOL7̇ \E::?v6d~W ##: 'om?6Du w%>|w>f"% td OLZZ\M*H[&"!{-ӿ d'NVBO$cJ(wo,o(Q_T")⇳ZRl2ScL<uS:Dq*R޵$Z&-UeVyD-plwX{xE/IP4tOZ_irb 9v(d$Q2nLգY+De ,<<2;9XXPC o7>cϻ&FkRmv__yͤ%Ȓ -×Z/@Թ VdƓkfylPb>v!5QŵV\)ơDVW`z. v{/20 ݥ$-.tF9f&#F# fm7VQ4|!s2,*(f{Mu[ hilX;EtW_)^`b9a̶ x_Ք) 5(IOx^d6(Enʁ[SQL^|` 3 <#΁@16StnT]e/c"F9={z*Rfp%D xE+`os˱ ۑÉ/j'DLT;Hn(LQꤛɶ,$դ[JcW)kRG]kAm:Uro*pҐJ? R S`l$!1IH50ܬz) r?H6> ,pK!ꥦ?R]fw(Cs (:(ʚ9$9O4ǟ#!jL@3:*RzThM@:t&*j)'O*]b%AR,QHgoEʌݯ tr2ew483M Jt2cy TE{b[b[ kClMgc>>F 2KÌUI<6՛&X ,VqH݃U8`ikck" ,^Idh+cnYx~ X֬imgKSH@%̑ ]1L+/Ǎ kg_.Sߜ= D2,K}[>#OOԚsyI-_ @&_罹u-_2y:hgòj,Kh!oȫd* H>Qc{GYSi!fFӡO /D\zr?i3`\96vD_F:+sU~ഈ\4ʹПBW[1⎯KE k1.I&HA/-&Gh˘k`a wě"? lv`kQ~,~%4HvZ<|79g3*x؆XgV9W"a&Μ ʟh^H:C DS/Œ`#IR1Y}H‰E 9J uN(MC)RXOY}Y\gԇ+[~ *:"EL΂肚^[mɾ[؅tޚqn?EVG$ ,I] _)ŽYʦsE.` PIgQW qehn-hX\ 0t]"g:{Mt C"EȭuQNZifޫHO05y WJe8 ü|5EpG7ᨆb  Hl%)3OEpj4[$] +Rv1 hk7b"E,$"OH'x ƕ E`ɩ 9/R@R³fs"E(`}-AU 9B|`6h);[GVe~bN@g`Sw9E4zQ ,h9y+Pߘ+8"ѹ¡W"*EV2uT"YMX1r r/kA HӛɭŪ&<8"Elφmid~O"h Ԥb vɮ38.|3b3VsZXvRN\O=+~_T]k՛sav1HC8kYL_k^g`Hn%;\\|E;0?hΜ93;غfZ.Ƕf-&fRFj%&e_"iv#Ig.E]DHDDt!Et]DHDDHq=yGٙbٗq{y+)E5}KJ"kZf6)ߝD6N~d XI9ٱ.1`~r) k3I j=JĀ5[QVޣ[B\Hi]%cu1`vF#`]2j=ynz>)` VNJ"+Bp@bQ/kJ˦L%jk,)oj 67o#Ub0V*bJ8Tޫ ]ύĨK 7cmD1U`\}{ Xټ/e`},)7]5+6ZFB'96Z`Iϻ`]0\U%`_cm쵸 e`a `n=^msѦwH"{ǿG^C D7M?:6y  g@"kL5q); SDրu0X#;$g %lԻ?Ȝ7QxΒVH<<{Hdl |/ԋ K`O";(66Fس)Ô %ȓ$Q=a&yFYsZ'U!r6M [EbϦ?!C~aZdnfng~m` yx2x)L>'޴Dvqry,ykESWJ{$,gyҰ؅[љYusE iwo[m}eڹkZ"湛c;u[ZZ&&'丏]}OS:>?G ibڰwdy)\ڸ?:GIJ)ln!Hdݱ.UVQ|<UX=V3VtטBCaX`x{ӻm.VDJ&Ǒ`ia YHT燹f񯍌4lR ~M09IO!wY) VqHIߞIy\i~y<:D_* t}{nWDU;rC`v6w5tj|> m&Bs=U`&p0^ІGE‘8A,??ү? :!SZH;0Pn HD8.dahX\oTopR p4S*XWL "xYD$Gt@~*+n:XC"эJ y~ʗ%Ѹ&P]F@$(O^4H$iݐRR0IENDB`info-beamer-1.0~pre4/samples/parrot/node.lua0000644000175000017500000000134412452774240016745 0ustar nknkgl.setup(400, 400) function readln() return coroutine.yield() end if not N.clients then N.clients = {} end node.event("connect", function(client) local handler = coroutine.wrap(echo) N.clients[client] = handler handler(function(...) sys.client_write(client, ...) end) end) node.event("input", function(line, client) N.clients[client](line) end) node.event("disconnect", function(client) N.clients[client] = nil end) function echo(print) print("I will repeat everything you send me") while true do local line = readln() print(line) end end util.auto_loader(_G) function node.render() gl.clear(1,1,1,1) util.draw_correct(blue_macaw, 0, 0, WIDTH, HEIGHT) end info-beamer-1.0~pre4/samples/shader/0000755000175000017500000000000012452774240015252 5ustar nknkinfo-beamer-1.0~pre4/samples/shader/lua.png0000644000175000017500000001221512452774240016542 0ustar nknkPNG  IHDR), pHYsHHFk> vpAg KPLTE""""3333DDDDUUUUffffwwwwÈđ˙̢ԪճܻQ^m2IDATxkc^tj 5PI 5{hp1_Y  5[)DZg?WXx:y1QRL)P$ŏ"((BʀbH)p? @B  ( E~,P $E}\ '@Kd!r$ + )H32TF$2 ~  u Mcl6KoF 4$L'(>*fYzɍ?cq!E"rξP!T!d8:q  A@qcH93ʊFOїH():RX:$"qNR@EAՍP"+.@NPDD1HVA>P@A_Q7vGSeT|7b1^@&˸'N PbTau 7G0w#S pbsQ0 C G򐈉P;! "d9Xf~*&θS$H $yP*?b݂ $feS!9i~ vٍጠx)* f uNfdADA@E5%'R-{K?qCӝ3JVK )ۖ"v0 qP)<3em!jB<P Xjew P!RRB^@0b9Qt(v@1, xGQ@DD~LT%V(deHKd&t3+H`%' ֎GW/=I@RJg/us? V֧DEta{ /j%gӾl@X|襋x}(h7m7x^IY)Sf:?K@JTէEUpn ަse{ <,۳X=[ӧ@;Te X?>v͗ *$@f}zm! QUة ]/`ϖ8G"P@LwOa}w:PBr&|zz KMDP_h z>j`SQ01{ 0j`@;'o1$mF2F$տ_?5g[y@NLVޠ,2s ! H(4|*%r-=AH@잼DV:bR%w%P,2"87x %,d3k`r)u1 _dƞyѵOzc"4}ujm𳡼K+]Y7VW(]R ߋ󦫚B4kˍDf8\>ŝMt붸\)h}b}re5fw}0(,C,1aߟ}.{{E 9TP@ 5}p uMTȄQlC(Ksdh1ğiC9\ Z6w"gD,DpAG13K 1Ocɧ%;[33NCR8c׶f ҵ{ @$ QS ^PΜ Z+5.a 6Dg9T‰EpػC%^@B:ڎI DDgEBs6Jn;ߎ$1m' QNud]`st7y+S.PKq]%yfP{d=qbǠw|t(yPh.$5p(= yT[à(3lQ|^=2 *| =vq9Q9\^DQ(bt`_x5]B *PD) %B&+L_ΓXn, '+ֈ“Jf9k6Pu(h_ ޝUf}g}U(`7f!͗uQyRs0m\":Ș3LS FP|_oW[]U`6fwn_ڴPY}k"Z ]F,͡qV''pe,N+870$Pm$UPDA dPkvղ@Fq  mS)e2 P8)xg#""9Bl60ApxJ ׯ5'eq6$ٺ"6Yr&O(& >h[ F0=l/ұA@D1H*}ןv\ 9pA_ş! AT[#U5xrf0}Za -F`L:!L~j'wsLa?O]O9JUGl6o6Mg6-]$md47`4"$>H.9Ⱥ1}CH $IDL\@wԋȀSB"P3@vU59rNu@h/bj@@9} p< " \BP)(4}Șz j BvE٧yuz^Pδb72k0'y( (1)g?X9V[ϭW9(2 Q˖*d*bhiŘp᷌r\V $w_QERT߽s All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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. Some files include external code. License information about these files in included in their header. video.c Includes code from ffmpeg example code http://bit.ly/w3iOvz misc.h Includes code based on lua-users wiki: http://lua-users.org/wiki/UserDataWithPointerExample Includes code based on http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ misc.c Includes code based on http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ userlib.lua Includes code based on lua-users wiki: http://lua-users.org/wiki/TableSerialization Included 3rd Party code: uthash.h utlist.h Hashtables/Lists for C structures http://uthash.sourceforge.net/ bin2c.c Convert file to C include struct.c Library for packing/unpacking structures. http://www.inf.puc-rio.br/~roberto/struct/ info-beamer-1.0~pre4/Makefile0000644000175000017500000000314612452774240014004 0ustar nknk# See Copyright Notice in LICENSE.txt RELEASE = 1.0pre3 VERSION = $(RELEASE).$(shell git rev-parse --short=6 HEAD) ifdef DEBUG CFLAGS ?= -ggdb -DDEBUG else CFLAGS ?= -O3 -DNDEBUG endif ifdef USE_LUAJIT LUA_CFLAGS ?= -I/usr/include/luajit-2.0 LUA_LDFLAGS ?= -lluajit-5.1 LUA_LUAC ?= luac CFLAGS += -DUSE_LUAJIT=1 else ################################################# # # If you have compile/link problems related to lua, try # setting these variables while running make. For example: # # $ LUA_LDFLAGS=-llua make # ################################################# LUA_CFLAGS ?= -I/usr/include/lua5.1 LUA_LDFLAGS ?= -L/usr/lib -llua5.1 LUA_LUAC ?= luac endif CFLAGS += -DVERSION='"$(VERSION)"' CFLAGS += $(LUA_CFLAGS) -I/usr/include/freetype2/ -I/usr/include/ffmpeg -std=c99 -Wall LDFLAGS += $(LUA_LDFLAGS) -levent -lglfw -lGL -lGLU -lGLEW -lftgl -lIL -lILU -lavformat -lavcodec -lavutil -lswscale -lz prefix ?= /usr/local exec_prefix ?= $(prefix) bindir ?= $(exec_prefix)/bin all: info-beamer info-beamer: main.o image.o font.o video.o shader.o vnc.o framebuffer.o misc.o struct.o $(CC) -o $@ $^ $(LDFLAGS) main.o: main.c kernel.h userlib.h module_json.h info-beamer.1: info-beamer.1.ronn ronn $< -r --pipe > $@ bin2c: bin2c.c $(CC) $^ -o $@ %.h: %.lua bin2c $(LUA_LUAC) -p $< ./bin2c $* < $< > $@ doc: markdown_py -x toc -x tables -x codehilite doc/manual.md > doc/manual.html install: info-beamer install -D -o root -g root -m 755 $< $(DESTDIR)$(bindir)/$< clean: rm -f *.o info-beamer kernel.h userlib.h module_*.h bin2c *.compiled doc/manual.html info-beamer.1 .PHONY: clean doc install info-beamer-1.0~pre4/README.md0000644000175000017500000000073412452774240013623 0ustar nknkAbout info-beamer ================= info-beamer allows you to develop interactive information displays using the Lua programming language. Read more about it on the [main website](http://info-beamer.org/) Documentation ------------- The complete documentation is available on [info-beamer.com](https://info-beamer.com/doc/info-beamer) Installation ------------ See the [documentation](https://info-beamer.com/doc/info-beamer#installing-info-beamer) for more information. info-beamer-1.0~pre4/bin2c.c0000644000175000017500000000127612452774240013507 0ustar nknk/* * Unloved program to convert a binary on stdin to a C include on stdout * * Jan 1999 Matt Mackall * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. */ #include int main(int argc, char *argv[]) { int ch, total=0; if (argc > 1) printf("const char %s[] %s=\n", argv[1], argc > 2 ? argv[2] : ""); do { printf("\t\""); while ((ch = getchar()) != EOF) { total++; printf("\\x%02x",ch); if (total % 16 == 0) break; } printf("\"\n"); } while (ch != EOF); if (argc > 1) printf("\t;\n\nconst int %s_size = %d;\n", argv[1], total); return 0; } info-beamer-1.0~pre4/font.c0000644000175000017500000000522712452774240013460 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #include #include #include #include #include #include #include #include #include "misc.h" #include "shader.h" typedef struct { FTGLfont *font; } font_t; LUA_TYPE_DECL(font) /* Instance methods */ static int font_write(lua_State *L) { font_t *font = checked_font(L, 1); GLfloat x = luaL_checknumber(L, 2); GLfloat y = luaL_checknumber(L, 3); const char *text = luaL_checkstring(L, 4); // Protect FTGL if (!check_utf8(text)) return luaL_error(L, "invalid utf8"); GLfloat size = luaL_checknumber(L, 5) / 1000.0; int type = lua_type(L, 6); if (type == LUA_TNUMBER) { GLfloat r = luaL_checknumber(L, 6); GLfloat g = luaL_checknumber(L, 7); GLfloat b = luaL_checknumber(L, 8); GLfloat a = luaL_optnumber(L, 9, 1.0); shader_set_gl_color(r, g, b, a); glBindTexture(GL_TEXTURE_2D, default_tex); } else if (type == LUA_TUSERDATA || type == LUA_TTABLE) { lua_pushliteral(L, "texid"); lua_gettable(L, 6); if (lua_type(L, -1) != LUA_TFUNCTION) return luaL_argerror(L, 6, "no texid() function"); lua_pushvalue(L, 6); lua_call(L, 1, 1); if (lua_type(L, -1) != LUA_TNUMBER) return luaL_argerror(L, 6, "texid() did not return number"); int tex_id = lua_tonumber(L, -1); lua_pop(L, 1); shader_set_gl_color(1.0, 1.0, 1.0, 1.0); glBindTexture(GL_TEXTURE_2D, tex_id); } else { return luaL_argerror(L, 6, "unsupported value. must be RGBA or texturelike"); } glPushMatrix(); glTranslatef(x, y, 0); glTranslatef(0, size * 800, 0); glScalef(size, -size, 1.0); ftglRenderFont(font->font, text, FTGL_RENDER_ALL); glPopMatrix(); lua_pushnumber(L, ftglGetFontAdvance(font->font, text) * size); return 1; } static const luaL_reg font_methods[] = { {"write", font_write}, {0,0} }; /* Lifecycle */ int font_new(lua_State *L, const char *path, const char *name) { FTGLfont *ftgl_font = ftglCreatePolygonFont(path); if (!ftgl_font) return luaL_error(L, "cannot load font file %s", path); ftglSetFontDisplayList(ftgl_font, 1); ftglSetFontFaceSize(ftgl_font, 1000, 1000); ftglSetFontCharMap(ftgl_font, ft_encoding_unicode); font_t *font = push_font(L); font->font = ftgl_font; return 1; } static int font_gc(lua_State *L) { font_t *font = to_font(L, 1); ftglDestroyFont(font->font); fprintf(stderr, INFO("gc'ing font\n")); return 0; } LUA_TYPE_IMPL(font) info-beamer-1.0~pre4/font.h0000644000175000017500000000026412452774240013461 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef FONT_H #define FONT_H int font_register (lua_State *L); int font_new(lua_State *L, const char *path, const char *name); #endif info-beamer-1.0~pre4/framebuffer.c0000644000175000017500000000525212452774240014774 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #include #include #include #include #include #include "utlist.h" #include "misc.h" #define MAX_CACHED 30 typedef struct framebuffer { GLuint fbo; GLuint tex; int width; int height; struct framebuffer *prev; struct framebuffer *next; } framebuffer_t; static framebuffer_t *framebuffers = NULL; static int num_framebuffers = 0; static void unlink_framebuffer(framebuffer_t *framebuffer) { DL_DELETE(framebuffers, framebuffer); free(framebuffer); num_framebuffers--; } void make_framebuffer(int width, int height, GLuint *tex, GLuint *fbo) { framebuffer_t *framebuffer, *tmp; DL_FOREACH_SAFE(framebuffers, framebuffer, tmp) { // Same size? if (framebuffer->height == height && framebuffer->width == width) { *tex = framebuffer->tex; *fbo = framebuffer->fbo; glBindFramebuffer(GL_FRAMEBUFFER, framebuffer->fbo); glBindTexture(GL_TEXTURE_2D, framebuffer->tex); unlink_framebuffer(framebuffer); return; } } glGenFramebuffers(1, fbo); glBindFramebuffer(GL_FRAMEBUFFER, *fbo); fprintf(stderr, INFO("new framebuffer (%dx%d): %u\n"), width, height, *fbo); glGenTextures(1, tex); glBindTexture(GL_TEXTURE_2D, *tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_INT, NULL); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *tex, 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) die("cannot initialize new framebuffer"); } void recycle_framebuffer(int width, int height, GLuint tex, GLuint fbo) { framebuffer_t *framebuffer = xmalloc(sizeof(framebuffer_t)); framebuffer->width = width; framebuffer->height = height; framebuffer->tex = tex; framebuffer->fbo = fbo; // fprintf(stderr, "added recyleable framebuffer %dx%d %d %d\n", framebuffer->width, framebuffer->height, // framebuffer->tex, framebuffer->fbo); DL_APPEND(framebuffers, framebuffer); num_framebuffers++; if (num_framebuffers > MAX_CACHED) { fprintf(stderr, ERROR("too many framebuffers in use\n")); glDeleteFramebuffers(1, &framebuffers->fbo); glDeleteTextures(1, &framebuffers->tex); unlink_framebuffer(framebuffers); } } info-beamer-1.0~pre4/framebuffer.h0000644000175000017500000000040512452774240014774 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef FRAMEBUFFER_H #define FRAMEBUFFER_H #include void make_framebuffer(int width, int height, GLuint *tex, GLuint *fbo); void recycle_framebuffer(int width, int height, GLuint tex, GLuint fbo); #endif info-beamer-1.0~pre4/image.c0000644000175000017500000001244512452774240013574 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #include #include #include #include #include #include #include #include #include #include "framebuffer.h" #include "misc.h" #include "shader.h" typedef struct { GLuint tex; GLuint fbo; int width; int height; } image_t; LUA_TYPE_DECL(image) /* Instance methods */ static int image_state(lua_State *L) { image_t *image = checked_image(L, 1); lua_pushliteral(L, "loaded"); lua_pushnumber(L, image->width); lua_pushnumber(L, image->height); return 3; } static int image_size(lua_State *L) { image_t *image = checked_image(L, 1); lua_pushnumber(L, image->width); lua_pushnumber(L, image->height); return 2; } static int image_draw(lua_State *L) { image_t *image = checked_image(L, 1); GLfloat x1 = luaL_checknumber(L, 2); GLfloat y1 = luaL_checknumber(L, 3); GLfloat x2 = luaL_checknumber(L, 4); GLfloat y2 = luaL_checknumber(L, 5); GLfloat alpha = luaL_optnumber(L, 6, 1.0); glBindTexture(GL_TEXTURE_2D, image->tex); shader_set_gl_color(1.0, 1.0, 1.0, alpha); glBegin(GL_QUADS); glTexCoord2f(0.0, 1.0); glVertex3f(x1, y1, 0); glTexCoord2f(1.0, 1.0); glVertex3f(x2, y1, 0); glTexCoord2f(1.0, 0.0); glVertex3f(x2, y2, 0); glTexCoord2f(0.0, 0.0); glVertex3f(x1, y2, 0); glEnd(); return 0; } static int image_texid(lua_State *L) { image_t *image = checked_image(L, 1); lua_pushnumber(L, image->tex); return 1; } static int image_dispose(lua_State *L) { return 0; } static const luaL_reg image_methods[] = { {"state", image_state}, {"draw", image_draw}, {"size", image_size}, {"texid", image_texid}, {"dispose", image_dispose}, {0,0} }; /* Lifecycle */ int image_create(lua_State *L, GLuint tex, GLuint fbo, int width, int height) { image_t *image = push_image(L); image->tex = tex; image->fbo = fbo; image->width = width; image->height = height; return 1; } int image_from_current_framebuffer(lua_State *L, int x, int y, int width, int height, int mipmap) { GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); GLint filter = mipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, x, y, width, height); if (mipmap) glGenerateMipmap(GL_TEXTURE_2D); return image_create(L, tex, 0, width, height); } int image_from_color(lua_State *L, GLfloat r, GLfloat g, GLfloat b, GLfloat a) { GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); unsigned char buf[4] = {r * 255, g * 255, b * 255, a * 255 }; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); return image_create(L, tex, 0, 1, 1); } int image_load(lua_State *L, const char *path, const char *name) { ILuint imageID; ilGenImages(1, &imageID); ilBindImage(imageID); if (!ilLoadImage(path)) { ilDeleteImages(1, &imageID); return luaL_error(L, "loading %s failed: %s", path, iluErrorString(ilGetError())); } ILinfo ImageInfo; iluGetImageInfo(&ImageInfo); if (ImageInfo.Origin == IL_ORIGIN_UPPER_LEFT) iluFlipImage(); if (!ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE)) { ilDeleteImages(1, &imageID); return luaL_error(L, "converting %s failed: %s", path, iluErrorString(ilGetError())); } int width = ilGetInteger(IL_IMAGE_WIDTH); int height = ilGetInteger(IL_IMAGE_HEIGHT); GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), width, height, 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData()); glGenerateMipmap(GL_TEXTURE_2D); ilDeleteImages(1, &imageID); return image_create(L, tex, 0, width, height); } static int image_gc(lua_State *L) { image_t *image = to_image(L, 1); if (image->fbo) { // If images has attached Framebuffer, put the // texture and framebuffer into the recycler. // Allocations for new framebuffers can then // reuse these => Better performance. recycle_framebuffer(image->width, image->height, image->tex, image->fbo); } else { // No Framebuffer? Just remove the texture. glDeleteTextures(1, &image->tex); } return 0; } LUA_TYPE_IMPL(image) info-beamer-1.0~pre4/image.h0000644000175000017500000000066412452774240013601 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef IMAGE_H #define IMAGE_H int image_register(lua_State *L); int image_create(lua_State *L, int tex, int fbo, int width, int height); int image_from_current_framebuffer(lua_State *L, int x, int y, int width, int height, int mipmap); int image_from_color(lua_State *L, GLfloat r, GLfloat g, GLfloat b, GLfloat a); int image_load(lua_State *L, const char *path, const char *name); #endif info-beamer-1.0~pre4/info-beamer.1.ronn0000644000175000017500000000332612452774240015565 0ustar nknkinfo-beamer(1) -- An interactive multimedia presenter ===================================================== ## SYNOPSIS `info-beamer` ## DESCRIPTION **info-beamer** uses the files and subdirectories in the specified directory and displays them according to the Lua script `node.lua`. **info-beamer** provides a simple yet powerful API to display fonts, images, videos and more. The full documentation is available on http://info-beamer.org/doc/ ## ENVIRONMENT * `INFOBEAMER_FULLSCREEN`: If set to 1, **info-beamer** will start in fullscreen mode. * `INFOBEAMER_ADDR`: If specified, only binds to this address. Defaults to `0.0.0.0`. * `INFOBEAMER_PORT`: Specifies a port for both the TCP and UDP interface. Defaults to `4444`. * `INFOBEAMER_PRECOMPILED`: If set to `1`, **info-beamer** will also load precompiled Lua files. Only use this option if you trust the files being loaded, as precompiled Lua files should be considered unsafe. * `INFOBEAMER_FULLSCALE`: If set to `1`, **info-beamer** will ignore the aspect ratio of the screen and scale the root content to the complete size of the screen. * `INFOBEAMER_WIDTH`: Sets the width of the initial screen. Useful when using the fullscreen option above. Defaults to 1024. * `INFOBEAMER_HEIGHT`: Sets the height of the initial screen. Useful when using the fullscreen option above. Defaults to 768. ## SECURITY CONSIDERATIONS By default, **info-beamer** will bind to `0.0.0.0`. Use `INFOBEAMER_ADDR` to bind to another address. ## AUTHOR Written by Florian Wesch ## COPYRIGHT **info-beamer** is Copyright (c) 2013, Florian Wesch . The code is licensed under the BSD 2-Clause License. ## SEE ALSO lua(1) info-beamer-1.0~pre4/kernel.lua0000644000175000017500000003255612452774240014336 0ustar nknk-- See Copyright Notice in LICENSE.txt function kprint(msg) print("kernel: " .. msg) end function safe_loadstring(code, chunkname, allow_precompiled) if not allow_precompiled and string.byte(code, 1) == 27 then return nil, string.format( "precompiled code not allowed for chunk '%s'", chunkname ) else return loadstring(code, chunkname) end end local seen_warnings = {} function deprecation_warning(tag, warn, level) if not seen_warnings[tag] then seen_warnings[tag] = true print(debug.traceback("deprecation warning: " .. warn, level)) end end local DEFAULT_VERTEX_SHADER = [[ varying vec2 TexCoord; void main() { TexCoord = gl_MultiTexCoord0.st; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } ]] --============= -- Sandboxing --============= -- list of childs/contents for this node. local CHILDS = {} local CONTENTS = {} -- "persistent" table for this node. survives reloads local N = {} function create_sandbox() local sandbox = { error = error; assert = assert; ipairs = ipairs; next = next; pairs = pairs; pcall = pcall; rawequal = rawequal; rawget = rawget; rawset = rawset; select = select; tonumber = tonumber; tostring = tostring; type = type; unpack = unpack; xpcall = xpcall; setmetatable = setmetatable; getmetatable = getmetatable; module = function(name, ...) local module = sandbox.package.loaded[name] if not module then module = sandbox._G[name] end if not module then module = { _NAME = name; _PACKAGE = name; } module._M = module end -- Make sure setfenv won't change the outer -- environment. if getfenv(2) == _G then error("cannot modify outer environment") end setfenv(2, module) for _, func in ipairs({...}) do module = func(module) end sandbox._G[name] = module sandbox.package.loaded[name] = module return module end; struct = { unpack = struct.unpack; }; _BUNDLED_MODULES = { ["json.lua"] = MODULE_JSON; }; coroutine = { create = coroutine.create; resume = coroutine.resume; running = coroutine.running; status = coroutine.status; wrap = coroutine.wrap; yield = coroutine.yield; }; debug = { traceback = function(message, level) local message = tostring(message or "") local level = tonumber(level) or 1 assert(level >= 0, "level is negative") assert(level < 256, "level too large") return debug.traceback(message, level) end; }; math = { abs = math.abs; acos = math.acos; asin = math.asin; atan = math.atan; atan2 = math.atan2; ceil = math.ceil; cos = math.cos; cosh = math.cosh; deg = math.deg; exp = math.exp; floor = math.floor; fmod = math.fmod; frexp= math.frexp; ldexp = math.ldexp; log = math.log; log10 = math.log10; max = math.max; min = math.min; modf = math.modf; pi = math.pi; pow = math.pow; rad = math.rad; sin = math.sin; sinh = math.sinh; sqrt = math.sqrt; tan = math.tan; tanh = math.tanh; random = math.random; randomseed = math.randomseed; }; string = { byte = string.byte; char = string.char; find = function(s, pattern, init, plain) if #s > 32768 then error("s too large") elseif #pattern > 4096 then error("pattern too large") end return string.find(s, pattern, init, plain) end; format = string.format; gmatch = string.gmatch; gsub = string.gsub; len = string.len; lower = string.lower; match = string.match; rep = function(s, n) if n > 8192 then error("n too large") elseif n < 0 then error("n cannot be negative") end return string.rep(s, n) end; reverse = string.reverse; sub = string.sub; upper = string.upper; }; table = { insert = table.insert; concat = table.concat; maxn = table.maxn; remove = table.remove; sort = table.sort; }; print = print; loadstring = function(code, chunkname) local func, err = safe_loadstring(code, chunkname, false) if func then return setfenv(func, sandbox) else return nil, err end end; resource = { render_child = render_child; load_image = load_image; load_image_async = load_image; load_video = load_video; load_font = load_font; load_file = load_file; create_shader = function(vertex, fragment) if fragment == nil then fragment = vertex vertex = DEFAULT_VERTEX_SHADER elseif vertex == nil then vertex = DEFAULT_VERTEX_SHADER deprecation_warning( "shader_nil_vertex", "Using nil vertex argument for create_shader is deprecated. Only specify a single fragment argument.", 3 ) else deprecation_warning( "create_shader", "Specifying both vertex and fragment shader is deprecated. Only specify a single fragment argument.", 3 ) end return create_shader(vertex, fragment) end; create_vnc = create_vnc; create_snapshot = create_snapshot; create_colored_texture = create_colored_texture; }; gl = { setup = function(width, height) setup(width, height) sandbox.WIDTH = width sandbox.HEIGHT = height end; clear = glClear; pushMatrix = glPushMatrix; popMatrix = glPopMatrix; rotate = glRotate; translate = glTranslate; scale = glScale; ortho = glOrtho; perspective = glPerspective; }; sys = { now = now; set_flag = function(...) kprint("set_flag() call ignored") end; get_env = function(key) return NODE_ENVIRON[key] end; platform = "desktop"; client_write = client_write; }; events = { child_add = {}; child_remove = {}; content_update = {}; content_remove = {}; osc = {}; data = {}; connect = {}; input = {}; disconnect = {}; raw_data = { function(data, is_osc, suffix) if is_osc then if string.byte(data, 1, 1) ~= 44 then kprint("no osc type tag string") return end local typetags, offset = struct.unpack(">!4s", data) local tags = {string.byte(typetags, 1, offset)} local fmt = ">!4" for idx, tag in ipairs(tags) do if tag == 44 then -- , fmt = fmt .. "s" elseif tag == 105 then -- i fmt = fmt .. "i4" elseif tag == 102 then -- f fmt = fmt .. "f" elseif tag == 98 then -- b kprint("no blob support") return else kprint("unknown type tag " .. string.char(tag)) return end end local unpacked = {struct.unpack(fmt, data)} table.remove(unpacked, 1) -- remove typetags table.remove(unpacked, #unpacked) -- remove trailing offset sandbox.node.dispatch("osc", suffix, unpack(unpacked)) else sandbox.node.dispatch("data", data, suffix) end end; }; render = { function() sandbox.node.render() end }; }; node = { alias = set_alias; event = function(event, handler) if not sandbox.events[event] then sandbox.events[event] = {} end table.insert(sandbox.events[event], handler) end; dispatch = function(event, ...) for _, handler in ipairs(sandbox.events[event] or {}) do handler(...) end end; render = function() end; }; NAME = NAME; PATH = PATH; CHILDS = CHILDS; CONTENTS = CONTENTS; N = N; } -- There is only one metatable for strings. Reset it -- to the sandbox controlled version. local string_mt = getmetatable("") for k, v in pairs(string_mt) do string_mt[k] = nil end string_mt.__index = sandbox.string sandbox._G = sandbox return sandbox end function load_into_sandbox(code, chunkname, allow_precompiled) setfenv( assert(safe_loadstring(code, chunkname, allow_precompiled)), sandbox )() end function reload(...) sandbox = create_sandbox() reset_error() -- load userlib load_into_sandbox( USERLIB, "=userlib.lua", true ) -- load all given files into the sandbox for _, usercode_file in ipairs({...}) do load_into_sandbox( load_file(usercode_file), "=" .. PATH .. "/" .. usercode_file, os.getenv("INFOBEAMER_PRECOMPILED") ) end -- send child / content events for name, added in pairs(CHILDS) do sandbox.node.dispatch("child_add", name) end for name, added in pairs(CONTENTS) do sandbox.node.dispatch("content_update", name) end end -- Einige Funktionen in der registry speichern, -- so dass der C Teil dran kommt. do local registry = debug.getregistry() local full_scale = os.getenv("INFOBEAMER_FULLSCALE") registry.traceback = debug.traceback registry.execute = function(cmd, ...) if cmd == "boot" then kprint("booting node") reload(NODE_CODE_FILE) elseif cmd == "event" then sandbox.node.dispatch(...) elseif cmd == "child_update" then local name, added = ... if added then CHILDS[name] = now() sandbox.node.dispatch("child_add", name) else CHILDS[name] = nil sandbox.node.dispatch("child_remove", name) end elseif cmd == "content_update" then local name, added = ... if name == NODE_CODE_FILE then if added then kprint("node code updated. reloading...") reload(NODE_CODE_FILE) else kprint("node code removed. resetting...") reload() end else if added then CONTENTS[name] = now() sandbox.node.dispatch("content_update", name) else CONTENTS[name] = nil sandbox.node.dispatch("content_remove", name) end end elseif cmd == "render_self" then local screen_width, screen_height = ... if full_scale then render_self():draw(0, 0, screen_width, screen_height) else sandbox.util.draw_correct( render_self(), 0, 0, screen_width, screen_height ) end end end registry.alarm = function() error("CPU usage too high") end end io = nil require = nil loadfile = nil load = nil package = nil module = nil os = { getenv = os.getenv; } dofile = nil debug = { traceback = debug.traceback; getinfo = debug.getinfo; } reload() info-beamer-1.0~pre4/main.c0000644000175000017500000013517512452774240013444 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #define _BSD_SOURCE #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "uthash.h" #include "utlist.h" #include "misc.h" #include "image.h" #include "video.h" #include "font.h" #include "shader.h" #include "vnc.h" #include "framebuffer.h" #include "struct.h" #include "kernel.h" #include "userlib.h" #include "module_json.h" #if USE_LUAJIT #include #define VERSION_STRING "Info Beamer " VERSION "+" LUA_VERSION "+" LUAJIT_VERSION #else #define VERSION_STRING "Info Beamer " VERSION "+" LUA_VERSION #endif #define INFO_URL "http://info-beamer.org/" #define NODE_CODE_FILE "node.lua" #define ENVIRONMENT_PREFIX "INFOBEAMER_ENV_" #define ENVIRONMENT_PREFIX_SIZE (sizeof(ENVIRONMENT_PREFIX)-1) #define MAX_MEM 2000000 // KB #define MAX_GL_PUSH 20 // glPushMatrix depth #define MAX_CHILD_RENDERS 20 // maximum childs rendered per node #define MAX_SNAPSHOTS 5 // maximum number of snapshots per render // Default host/port (both udp & tcp) #define LISTEN_ADDR "0.0.0.0" #define DEFAULT_PORT 4444 #ifdef DEBUG #define MAX_RUNAWAY_TIME 10 // sec #define MAX_PCALL_TIME 5000000 // usec #else #define MAX_RUNAWAY_TIME 1 // sec #define MAX_PCALL_TIME 500000 // usec #endif #define NO_GL_PUSHPOP -1 #define NODE_INACTIVITY 2.0 // node considered idle after x seconds #define NODE_CPU_BLACKLIST 60.0 // seconds a node is blacklisted if it exceeds cpu usage typedef enum { PROFILE_BOOT, PROFILE_UPDATE, PROFILE_EVENT } profiling_bins; typedef struct node_s { int wd; // inotify watch descriptor char *name; // local node name char *path; // full path (including node name) char *alias; // alias path lua_State *L; UT_hash_handle by_wd; // global handle for search by watch descriptor UT_hash_handle by_name; // childs by name UT_hash_handle by_path; // node by path UT_hash_handle by_alias; // node by alias struct node_s *parent; struct node_s *childs; int width; int height; int gl_matrix_depth; struct client_s *clients; int child_render_quota; int snapshot_quota; double profiling[3]; double last_profile; int num_frames; int num_resource_inits; int num_allocs; double last_activity; double blacklisted; } node_t; static node_t *nodes_by_wd = NULL; static node_t *nodes_by_path = NULL; static node_t *nodes_by_alias = NULL; static node_t root = {0}; typedef struct client_s { int fd; node_t *node; struct bufferevent *buf_ev; struct client_s *next; struct client_s *prev; } client_t; static int inotify_fd; static double now; static int running = 1; static int listen_port; GLuint default_tex; // white default texture struct event_base *event_base; struct evdns_base *dns_base; /*=== Forward declarations =====*/ static void client_write(client_t *client, const char *data, size_t data_size); static void client_close(client_t *client); static void node_printf(node_t *node, const char *fmt, ...); static void node_blacklist(node_t *node, double time); static void node_remove_alias(node_t *node); static void node_reset_quota(node_t *node); static int node_render_to_image(lua_State *L, node_t *node); static void node_init(node_t *node, node_t *parent, const char *path, const char *name); static void node_free(node_t *node); /*======= Lua Sandboxing =======*/ #ifndef USE_LUAJIT static void *lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) { node_t *node = ud; node->num_allocs++; (void)osize; /* not used */ if (nsize == 0) { free(ptr); return NULL; } else { return realloc(ptr, nsize); } } #endif /* execution time limiting for pcalls */ static node_t *global_node = NULL; static int timers_expired = 0; static void deadline_stop(lua_State *L, lua_Debug *ar) { lua_sethook(L, NULL, 0, 0); lua_pushliteral(L, "alarm"); lua_gettable(L, LUA_REGISTRYINDEX); lua_call(L, 0, 0); } static void deadline_signal(int i) { if (!global_node) die("urg. timer expired and no global_node"); fprintf(stderr, RED("[%s]") " timeout\n", global_node->path); if (timers_expired == 0) { // timer expired once? Try to solve it inside of // lua: set a hook that will execute deadline_stop. lua_sethook(global_node->L, deadline_stop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKLINE | LUA_MASKCOUNT, 1); node_blacklist(global_node, NODE_CPU_BLACKLIST); } else { // timer expired again without lua being stopped? die("unstoppable runaway code in %s", global_node->path); } timers_expired++; } static int lua_timed_pcall(node_t *node, int in, int out, int error_handler_pos) { node_t *old_global_node = global_node; struct itimerval old_timer; struct itimerval deadline; deadline.it_interval.tv_sec = MAX_RUNAWAY_TIME; deadline.it_interval.tv_usec = 0; deadline.it_value.tv_sec = MAX_PCALL_TIME / 1000000; deadline.it_value.tv_usec = MAX_PCALL_TIME % 1000000; setitimer(ITIMER_VIRTUAL, &deadline, &old_timer); global_node = node; timers_expired = 0; int ret = lua_pcall(node->L, in, out, error_handler_pos); setitimer(ITIMER_VIRTUAL, &old_timer, NULL); global_node = old_global_node; return ret; } static int lua_panic(lua_State *L) { die("node panic!"); return 0; } static const char *lua_safe_dedup_error_message(lua_State *L) { const char *message = lua_tostring(L, -1); if (!message) die(" error message"); lua_pushliteral(L, "last_error"); lua_rawget(L, LUA_REGISTRYINDEX); int same_as_last_time = lua_equal(L, -1, -2); lua_pop(L, 1); // remove value of last_error if (same_as_last_time) { message = NULL; } else { lua_pushliteral(L, "last_error"); lua_pushvalue(L, -2); lua_rawset(L, LUA_REGISTRYINDEX); } return message; } static void lua_node_enter(node_t *node, int args, profiling_bins bin) { node_reset_quota(node); lua_State *L = node->L; lua_pushliteral(L, "execute"); // [args] "execute" lua_rawget(L, LUA_REGISTRYINDEX); // [args] execute lua_insert(L, -1 - args); // execute [args] lua_pushliteral(L, "traceback"); // execute [args] "traceback" lua_rawget(L, LUA_REGISTRYINDEX); // execute [args] traceback const int error_handler_pos = lua_gettop(L) - 1 - args; lua_insert(L, error_handler_pos); // traceback execute [args] struct timeval before, after; gettimeofday(&before, NULL); int status = lua_timed_pcall(node, args, 0, error_handler_pos); if (status == 0) { // success // traceback lua_remove(L, error_handler_pos); // } else { // error // traceback "error" char *err = status == LUA_ERRRUN ? "runtime error" : status == LUA_ERRMEM ? "memory error" : status == LUA_ERRERR ? "error handling error" : NULL; assert(err); const char *message = lua_safe_dedup_error_message(L); if (message) node_printf(node, "%s: %s\n", err, message); lua_pop(L, 2); // } gettimeofday(&after, NULL); lua_gc(node->L, LUA_GCSTEP, 5); node->profiling[bin] += time_delta(&before, &after); node->last_activity = now; } /*======= Lua entry points =======*/ // reinit sandbox, load usercode and user code static void node_boot(node_t *node) { lua_pushliteral(node->L, "boot"); lua_node_enter(node, 1, PROFILE_BOOT); } // notify of child update static void node_child_update(node_t *node, const char *name, int added) { lua_pushliteral(node->L, "child_update"); lua_pushstring(node->L, name); lua_pushboolean(node->L, added); lua_node_enter(node, 3, PROFILE_UPDATE); } // notify of content update static void node_content_update(node_t *node, const char *name, int added) { fprintf(stderr, YELLOW("[%s]")" update %c%s\n", node->path, added ? '+' : '-', name); lua_pushliteral(node->L, "content_update"); lua_pushstring(node->L, name); lua_pushboolean(node->L, added); if (!strcmp(name, NODE_CODE_FILE)) { // reset blacklisted flag node->blacklisted = 0; // reset node dimensions node->width = 0; node->height = 0; // remove existing node alias node_remove_alias(node); } lua_node_enter(node, 3, PROFILE_UPDATE); } // event.(args...) static void node_event(node_t *node, const char *name, int args) { lua_pushliteral(node->L, "event"); // [args] "event_name" lua_pushstring(node->L, name); // [args] "event_name" name lua_insert(node->L, -2 - args); // name [args] "event_name" lua_insert(node->L, -2 - args); // "event_name" name [args] lua_node_enter(node, 2 + args, PROFILE_EVENT); } // render node static void node_render_self(node_t *node, int width, int height) { lua_pushliteral(node->L, "render_self"); lua_pushnumber(node->L, width); lua_pushnumber(node->L, height); lua_node_enter(node, 3, PROFILE_EVENT); } /*===== node macros =======*/ #define node_setup_completed(node) ((node)->width != 0) #define node_is_idle(node) (now > (node)->last_activity + NODE_INACTIVITY) #define node_is_blacklisted(node) (now < (node)->blacklisted) #define node_is_rendering(node) ((node)->gl_matrix_depth != NO_GL_PUSHPOP) /*===== Lua bindings ======*/ static node_t *get_rendering_node(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); if (!node_is_rendering(node)) luaL_error(L, "only callable in node.render"); return node; } static int luaResetError(lua_State *L) { lua_pushliteral(L, "last_error"); lua_pushnil(L); lua_rawset(L, LUA_REGISTRYINDEX); return 0; } static int luaRenderSelf(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); return node_render_to_image(L, node); } static int luaRenderChild(lua_State *L) { node_t *node = get_rendering_node(L); if (node->child_render_quota-- <= 0) return luaL_error(L, "too many childs rendered"); const char *name = luaL_checkstring(L, 1); node_t *child; HASH_FIND(by_name, node->childs, name, strlen(name), child); if (!child) return luaL_error(L, "child %s not found", name); return node_render_to_image(L, child); } static int luaSetup(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); if (node_is_rendering(node)) return luaL_error(L, "cannot change width or height while rendering"); int width = (int)luaL_checknumber(L, 1); int height = (int)luaL_checknumber(L, 2); if (width < 32 || width > 2048) luaL_argerror(L, 1, "invalid width. must be within [32,2048]"); if (height < 32 || height > 2048) luaL_argerror(L, 2, "invalid height. must be within [32,2048]"); node->width = width; node->height = height; return 0; } static int luaGlOrtho(lua_State *L) { node_t *node = get_rendering_node(L); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, node->width, node->height, 0, -1000, 1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); node->gl_matrix_depth = 0; return 0; } static int luaGlPerspective(lua_State *L) { node_t *node = get_rendering_node(L); double fov = luaL_checknumber(L, 1); double eye_x = luaL_checknumber(L, 2); double eye_y = luaL_checknumber(L, 3); double eye_z = luaL_checknumber(L, 4); double center_x = luaL_checknumber(L, 5); double center_y = luaL_checknumber(L, 6); double center_z = luaL_checknumber(L, 7); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fov, (float)node->width / (float)node->height, 0.1, 10000); gluLookAt(eye_x, eye_y, eye_z, center_x, center_y, center_z, 0, -1, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); node->gl_matrix_depth = 0; return 0; } static int luaSetAlias(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); const char *alias = luaL_checkstring(L, 1); // already exists? node_t *existing_node; HASH_FIND(by_alias, nodes_by_alias, alias, strlen(alias), existing_node); if (existing_node) { if (existing_node == node) { return 0; } else { return luaL_error(L, "alias already taken by %s", existing_node->path); } } // remove old alias if (node->alias) { HASH_DELETE(by_alias, nodes_by_alias, node); free(node->alias); } // set new alias node->alias = strdup(alias); HASH_ADD_KEYPTR(by_alias, nodes_by_alias, node->alias, strlen(node->alias), node); return 0; } static int luaLoadImage(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); const char *name = luaL_checkstring(L, 1); if (index(name, '/')) luaL_argerror(L, 1, "invalid resource name"); char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", node->path, name); node->num_resource_inits++; return image_load(L, path, name); } static int luaLoadVideo(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); const char *name = luaL_checkstring(L, 1); if (index(name, '/')) luaL_argerror(L, 1, "invalid resource name"); char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", node->path, name); node->num_resource_inits++; return video_load(L, path, name); } static int luaLoadFont(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); const char *name = luaL_checkstring(L, 1); if (index(name, '/')) luaL_argerror(L, 1, "invalid resource name"); char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", node->path, name); node->num_resource_inits++; return font_new(L, path, name); } static int luaLoadFile(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); const char *name = luaL_checkstring(L, 1); if (index(name, '/')) luaL_argerror(L, 1, "invalid resource name"); char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", node->path, name); int fd = open(path, O_RDONLY); if (fd == -1) return luaL_error(L, "cannot open file '%s'", path); luaL_Buffer b; luaL_buffinit(L, &b); while (1) { char *data = luaL_prepbuffer(&b); ssize_t data_size = read(fd, data, LUAL_BUFFERSIZE); if (data_size < 0) return luaL_error(L, "cannot read %s: %s", name, strerror(errno)); if (data_size == 0) break; luaL_addsize(&b, data_size); } close(fd); luaL_pushresult(&b); node->num_resource_inits++; return 1; } static int luaCreateColoredTexture(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); GLfloat r = luaL_checknumber(L, 1); GLfloat g = luaL_checknumber(L, 2); GLfloat b = luaL_checknumber(L, 3); GLfloat a = luaL_optnumber(L, 4, 1.0); node->num_resource_inits++; return image_from_color(L, CLAMP(r, 0, 1), CLAMP(g, 0, 1), CLAMP(b, 0, 1), CLAMP(a, 0, 1) ); } static int luaCreateSnapshot(lua_State *L) { node_t *node = get_rendering_node(L); if (node->snapshot_quota-- <= 0) return luaL_error(L, "too many snapshots"); node->num_resource_inits++; int mipmap = 0; int x = 0; int y = 0; int width = node->width; int height = node->height; if (lua_gettop(L) <= 1) { mipmap = lua_toboolean(L, 1); } else if (lua_gettop(L) == 4) { x = luaL_checknumber(L, 1); y = luaL_checknumber(L, 2); width = luaL_checknumber(L, 3); height = luaL_checknumber(L, 4); if (x < 0 || y < 0 || width < 0 || height < 0 || x + width > node->width || y + height > node->height) { return luaL_error(L, "snapshot out of bounds"); } } else { return luaL_error(L, "invalid number of arguments"); } return image_from_current_framebuffer( L, x, node->height - y - height, width, height, mipmap ); } static int luaCreateShader(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); const char *vertex = luaL_checkstring(L, 1); const char *fragment = luaL_checkstring(L, 2); node->num_resource_inits++; return shader_new(L, vertex, fragment); } static int luaCreateVnc(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); const char *host = luaL_checkstring(L, 1); int port = luaL_optnumber(L, 2, 5900); node->num_resource_inits++; return vnc_create(L, host, port); } static int luaPushFormattedArgs(lua_State *L) { luaL_Buffer b; luaL_buffinit(L, &b); int n = lua_gettop(L); lua_getglobal(L, "tostring"); for (int i = 1; i <= n; i++) { lua_pushvalue(L, n + 1); lua_pushvalue(L, i); lua_call(L, 1, 1); if (!lua_isstring(L, -1)) return luaL_error(L, "tostring must return a string to print"); if (i > 1) luaL_addchar(&b, '\t'); luaL_addvalue(&b); } luaL_addchar(&b, '\n'); luaL_pushresult(&b); return 1; } static int luaPrint(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); luaPushFormattedArgs(L); node_printf(node, "%s", lua_tostring(L, -1)); return 0; } static int luaClientWrite(lua_State *L) { node_t *node = lua_touserdata(L, lua_upvalueindex(1)); client_t *client = lua_touserdata(L, 1); lua_remove(L, 1); luaPushFormattedArgs(L); size_t string_len; const char *string = lua_tolstring(L, -1, &string_len); client_t *current_client; DL_FOREACH(node->clients, current_client) { if (current_client == client) { client_write(current_client, string, string_len); } } return 0; } static int luaGlClear(lua_State *L) { get_rendering_node(L); GLdouble r = luaL_checknumber(L, 1); GLdouble g = luaL_checknumber(L, 2); GLdouble b = luaL_checknumber(L, 3); GLdouble a = luaL_checknumber(L, 4); glClearColor(r, g, b, a); glClear(GL_COLOR_BUFFER_BIT); glUseProgram(0); return 0; } static int luaGlPushMatrix(lua_State *L) { node_t *node = get_rendering_node(L); if (node->gl_matrix_depth > MAX_GL_PUSH) return luaL_error(L, "Too may pushes"); glPushMatrix(); node->gl_matrix_depth++; return 0; } static int luaGlPopMatrix(lua_State *L) { node_t *node = get_rendering_node(L); if (node->gl_matrix_depth == 0) return luaL_error(L, "Nothing to pop"); glPopMatrix(); node->gl_matrix_depth--; return 0; } static int luaGlRotate(lua_State *L) { get_rendering_node(L); double angle = luaL_checknumber(L, 1); double x = luaL_checknumber(L, 2); double y = luaL_checknumber(L, 3); double z = luaL_checknumber(L, 4); glRotated(angle, x, y, z); return 0; } static int luaGlTranslate(lua_State *L) { get_rendering_node(L); double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); double z = luaL_optnumber(L, 3, 0.0); glTranslated(x, y, z); return 0; } static int luaGlScale(lua_State *L) { get_rendering_node(L); double x = luaL_checknumber(L, 1); double y = luaL_checknumber(L, 2); double z = luaL_optnumber(L, 3, 1.0); glScaled(x, y, z); return 0; } static int luaNow(lua_State *L) { lua_pushnumber(L, now); return 1; } /*==== Node functions =====*/ static int node_render_to_image(lua_State *L, node_t *node) { // save current gl state int prev_fbo, prev_prog; GLdouble prev_projection[16]; GLdouble prev_modelview[16]; glGetIntegerv(GL_FRAMEBUFFER_BINDING, &prev_fbo); glGetIntegerv(GL_CURRENT_PROGRAM, &prev_prog); glGetDoublev(GL_PROJECTION_MATRIX, prev_projection); glGetDoublev(GL_MODELVIEW_MATRIX, prev_modelview); glPushAttrib(GL_ALL_ATTRIB_BITS); int width = 1, height = 1; if (node_setup_completed(node)) width = node->width, height = node->height; // get new framebuffer and associated texture from recycler unsigned int fbo, tex; make_framebuffer(width, height, &tex, &fbo); // initialize gl state glUseProgram(0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, width, height); glOrtho(0, width, height, 0, -1000, 1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if (!node_setup_completed(node)) { node_printf(node, "node not initialized with gl.setup()\n"); glClearColor(0.5, 0.5, 0.5, 1); glClear(GL_COLOR_BUFFER_BIT); } else if (node_is_blacklisted(node)) { node_printf(node, "node is blacklisted\n"); glClearColor(0.5, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); } else { // clear with transparent color glClearColor(1, 1, 1, 0); glClear(GL_COLOR_BUFFER_BIT); // render node node->gl_matrix_depth = 0; node->num_frames++; node_event(node, "render", 0); while (node->gl_matrix_depth-- > 0) glPopMatrix(); node->gl_matrix_depth = NO_GL_PUSHPOP; } // rebind to framebuffer texture glBindTexture(GL_TEXTURE_2D, tex); glGenerateMipmap(GL_TEXTURE_2D); // restore previous state glPopAttrib(); glMatrixMode(GL_PROJECTION); glLoadMatrixd(prev_projection); glMatrixMode(GL_MODELVIEW); glLoadMatrixd(prev_modelview); glUseProgram(prev_prog); glBindFramebuffer(GL_FRAMEBUFFER, prev_fbo); return image_create(L, tex, fbo, width, height); } static void node_printf(node_t *node, const char *fmt, ...) { char buffer[16384]; va_list ap; va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); fprintf(stderr, GREEN("[%s]")" %s", node->path, buffer); } static void node_blacklist(node_t *node, double time) { node->blacklisted = now + time; node_printf(node, "blacklisted for %.0f seconds\n", time); } static void node_remove_alias(node_t *node) { if (node->alias) { HASH_DELETE(by_alias, nodes_by_alias, node); free(node->alias); node->alias = NULL; } } static void node_tree_gc(node_t *node) { if (!node_is_idle(node)) lua_gc(node->L, LUA_GCSTEP, 30); node_t *child, *tmp; HASH_ITER(by_name, node->childs, child, tmp) { node_tree_gc(child); }; } static node_t *node_add_child(node_t* node, const char *path, const char *name) { fprintf(stderr, YELLOW("[%s]")" adding new child node %s\n", node->name, name); node_t *child = xmalloc(sizeof(node_t)); node_init(child, node, path, name); HASH_ADD_KEYPTR(by_name, node->childs, child->name, strlen(child->name), child); return child; } static void node_remove_child(node_t* node, node_t* child) { fprintf(stderr, YELLOW("[%s]")" removing child node %s\n", node->name, child->name); node_child_update(node, child->name, 0); HASH_DELETE(by_name, node->childs, child); node_free(child); free(child); } static void node_remove_child_by_name(node_t* node, const char *name) { node_t *child; HASH_FIND(by_name, node->childs, name, strlen(name), child); if (!child) die("child not found: %s", name); node_remove_child(node, child); } static void node_reset_quota(node_t *node) { node->child_render_quota = MAX_CHILD_RENDERS; node->snapshot_quota = MAX_SNAPSHOTS; } static void node_reset_profiler(node_t *node) { node->last_profile = now; node->profiling[PROFILE_BOOT] = 0.0; node->profiling[PROFILE_UPDATE] = 0.0; node->profiling[PROFILE_EVENT] = 0.0; node->num_frames = 0; node->num_resource_inits = 0; node->num_allocs = 0; } #define lua_register_node_func(node,name,func) \ (lua_pushliteral((node)->L, name), \ lua_pushlightuserdata((node)->L, node), \ lua_pushcclosure((node)->L, func, 1), \ lua_settable((node)->L, LUA_GLOBALSINDEX)) static void node_init(node_t *node, node_t *parent, const char *path, const char *name) { // add directory watcher node->wd = inotify_add_watch(inotify_fd, path, IN_CLOSE_WRITE|IN_CREATE|IN_DELETE|IN_DELETE_SELF| IN_MOVE); if (node->wd == -1) die("cannot start watching directory %s: %s", path, strerror(errno)); node->parent = parent; node->path = strdup(path); node->name = strdup(name); node->alias = NULL; node->width = 0; node->height = 0; node_reset_profiler(node); node->last_activity = now; node->gl_matrix_depth = NO_GL_PUSHPOP; // link by watch descriptor & path HASH_ADD(by_wd, nodes_by_wd, wd, sizeof(int), node); HASH_ADD_KEYPTR(by_path, nodes_by_path, node->path, strlen(node->path), node); // create lua state #ifdef USE_LUAJIT node->L = luaL_newstate(); #else node->L = lua_newstate(lua_alloc, node); #endif if (!node->L) die("cannot create lua"); lua_atpanic(node->L, lua_panic); luaL_openlibs(node->L); image_register(node->L); video_register(node->L); font_register(node->L); shader_register(node->L); vnc_register(node->L); luaopen_struct(node->L); lua_register_node_func(node, "reset_error", luaResetError); lua_register_node_func(node, "setup", luaSetup); lua_register_node_func(node, "print", luaPrint); lua_register_node_func(node, "set_alias", luaSetAlias); lua_register_node_func(node, "client_write", luaClientWrite); lua_register_node_func(node, "render_self", luaRenderSelf); lua_register_node_func(node, "render_child", luaRenderChild); lua_register_node_func(node, "load_image", luaLoadImage); lua_register_node_func(node, "load_video", luaLoadVideo); lua_register_node_func(node, "load_font", luaLoadFont); lua_register_node_func(node, "load_file", luaLoadFile); lua_register_node_func(node, "create_colored_texture", luaCreateColoredTexture); lua_register_node_func(node, "create_snapshot", luaCreateSnapshot); lua_register_node_func(node, "create_shader", luaCreateShader); lua_register_node_func(node, "create_vnc", luaCreateVnc); lua_register_node_func(node, "glClear", luaGlClear); lua_register_node_func(node, "glPushMatrix", luaGlPushMatrix); lua_register_node_func(node, "glPopMatrix", luaGlPopMatrix); lua_register_node_func(node, "glRotate", luaGlRotate); lua_register_node_func(node, "glTranslate", luaGlTranslate); lua_register_node_func(node, "glScale", luaGlScale); lua_register_node_func(node, "glOrtho", luaGlOrtho); lua_register_node_func(node, "glPerspective", luaGlPerspective); lua_register(node->L, "now", luaNow); lua_pushstring(node->L, path); lua_setglobal(node->L, "PATH"); lua_pushstring(node->L, name); lua_setglobal(node->L, "NAME"); lua_pushlstring(node->L, userlib, userlib_size); lua_setglobal(node->L, "USERLIB"); lua_pushlstring(node->L, module_json, module_json_size); lua_setglobal(node->L, "MODULE_JSON"); lua_pushliteral(node->L, NODE_CODE_FILE); lua_setglobal(node->L, "NODE_CODE_FILE"); // get variables from environment lua_newtable(node->L); for (const char **cur = (const char**)environ; *cur; cur++) { if (strstr(*cur, ENVIRONMENT_PREFIX) != *cur) continue; const char *equals = strstr(*cur + ENVIRONMENT_PREFIX_SIZE, "="); if (!equals) continue; const char *name = *cur + ENVIRONMENT_PREFIX_SIZE; int name_len = equals - name; const char *value = equals+1; // printf("%d %.*s %s\n", name_len, name_len, name, value); lua_pushlstring(node->L, name, name_len); lua_pushstring(node->L, value); lua_rawset(node->L, -3); } lua_setglobal(node->L, "NODE_ENVIRON"); if (luaL_loadbuffer(node->L, kernel, kernel_size, "=kernel.lua") != 0) { const char *error = lua_tostring(node->L, -1); // If kernel.lua was procompiled with an incompatible lua // version, loading the embedded code fail here. Try to // detect this... die("cannot load kernel.lua: %s%s", error, strstr(error, "bad header") ? " (See 'kernel load error' in the docs)" : "" ); } if (lua_pcall(node->L, 0, 0, 0) != 0) die("kernel run %s", lua_tostring(node->L, -1)); } static void node_free(node_t *node) { node_t *child, *tmp; HASH_ITER(by_name, node->childs, child, tmp) { node_remove_child(node, child); } HASH_DELETE(by_wd, nodes_by_wd, node); HASH_DELETE(by_path, nodes_by_path, node); free(node->path); free(node->name); node_remove_alias(node); client_t *client, *tmp_client; DL_FOREACH_SAFE(node->clients, client, tmp_client) { client_close(client); } assert(node->clients == NULL); lua_close(node->L); } static void node_search_and_boot(node_t *node) { DIR *dp = opendir(node->path); if (!dp) die("cannot open directory %s: %s", node->path, strerror(errno)); struct dirent *ep; while ((ep = readdir(dp))) { if (ep->d_name[0] == '.') continue; const char *child_name = ep->d_name; char child_path[PATH_MAX]; snprintf(child_path, sizeof(child_path), "%s/%s", node->path, child_name); enum { CHILD_FILE, CHILD_DIR, CHILD_UNKNOWN } type = CHILD_UNKNOWN; if (ep->d_type == DT_UNKNOWN) { struct stat sb; if (stat(child_path, &sb) == -1) die("cannot stat %s", child_path); if (S_ISDIR(sb.st_mode)) { type = CHILD_DIR; } else if (S_ISREG(sb.st_mode)) { type = CHILD_FILE; } } else if (ep->d_type == DT_DIR) { type = CHILD_DIR; } else if (ep->d_type == DT_REG) { type = CHILD_FILE; } if (type == CHILD_DIR) { node_t *child = node_add_child(node, child_path, child_name); node_search_and_boot(child); node_child_update(node, child->name, 1); } else if (type == CHILD_FILE && strcmp(child_name, NODE_CODE_FILE)) { node_content_update(node, child_name, 1); } } closedir(dp); node_boot(node); } static void node_init_root(node_t *root, const char *base_path) { node_init(root, NULL, base_path, base_path); node_search_and_boot(root); } static node_t *node_find_by_path_or_alias(const char *needle) { size_t needle_size = strlen(needle); node_t *node; HASH_FIND(by_path, nodes_by_path, needle, needle_size, node); if (node) return node; HASH_FIND(by_alias, nodes_by_alias, needle, needle_size, node); return node; } static void node_print_profile(node_t *node, int depth) { node_t *child, *tmp; double delta = (now - node->last_profile) * 1000; fprintf(stderr, "%c%4dkb %3.0f %5.1f %6.1f %5d %5d %5.1lf%% %5.1lf%% %5.1lf%% %*s '- %s (%s)\n", node_is_blacklisted(node) ? 'X' : node_is_idle(node) ? ' ' : '*', lua_gc(node->L, LUA_GCCOUNT, 0), node->num_frames * 1000 / delta, (double)node->num_resource_inits * 1000 / delta, node->num_frames ? (double)node->num_allocs / node->num_frames : 0.0, node->width, node->height, 100 / delta * node->profiling[PROFILE_BOOT], 100 / delta * node->profiling[PROFILE_UPDATE], 100 / delta * node->profiling[PROFILE_EVENT], depth*3, "", node->name, node->alias ? node->alias : "-" ); node_reset_profiler(node); HASH_ITER(by_name, node->childs, child, tmp) { node_print_profile(child, depth+1); }; } static void node_profiler() { fprintf(stderr, " mem fps rps allocs width height boot update event name (alias)\n"); fprintf(stderr, "---------------------------------------------------------------------------\n"); node_print_profile(&root, 0); fprintf(stderr, "---------------------------------------------------------------------------\n"); } /*======= inotify ==========*/ static void check_inotify() { static char inotify_buffer[sizeof(struct inotify_event) + PATH_MAX + 1]; while (1) { size_t size = read(inotify_fd, &inotify_buffer, sizeof(inotify_buffer)); if (size == -1) { if (errno == EAGAIN) break; die("error reading from inotify fd"); } char *pos = inotify_buffer; char *end = pos + size; while (pos < end) { struct inotify_event *event = (struct inotify_event*)pos; pos += sizeof(struct inotify_event) + event->len; // printf("%s %08x %d\n", event->name, event->mask, event->wd); // ignore dot-files (including parent and current directory) if (event->len && event->name[0] == '.') continue; // ignore dot files // notifies, that wd was removed from kernel. // can be ignored (since it is handled in // IN_DELETE_SELF). if (event->mask & IN_IGNORED) continue; node_t *node; HASH_FIND(by_wd, nodes_by_wd, &event->wd, sizeof(int), node); if (!node) die("node not found: %s", event->name); char path[PATH_MAX]; snprintf(path, sizeof(path), "%s/%s", node->path, event->name); // fprintf(stderr, "event for %s (%s), mask: %08x\n", path, event->name, event->mask); if (event->mask & IN_CREATE) { struct stat stat_buf; if (stat(path, &stat_buf) == -1) { // file/path can be gone (race between inotify and // user actions) fprintf(stderr, "cannot stat %s\n", path); continue; } if (S_ISDIR(stat_buf.st_mode)) { node_t *child = node_add_child(node, path, event->name); node_search_and_boot(child); node_child_update(node, child->name, 1); } else if (S_ISREG(stat_buf.st_mode)) { node_content_update(node, event->name, 1); } } else if (event->mask & IN_CLOSE_WRITE) { node_content_update(node, event->name, 1); } else if (event->mask & IN_DELETE_SELF) { if (!node->parent) die("root node deleted. cannot continue"); node_remove_child(node->parent, node); } else if (event->mask & IN_DELETE && !(event->mask & IN_ISDIR)) { node_content_update(node, event->name, 0); } else if (event->mask & IN_MOVED_FROM) { if (event->mask & IN_ISDIR) { node_remove_child_by_name(node, event->name); } else { node_content_update(node, event->name, 0); } } else if (event->mask & IN_MOVED_TO) { if (event->mask & IN_ISDIR) { node_t *child = node_add_child(node, path, event->name); node_search_and_boot(child); node_child_update(node, child->name, 1); } else { node_content_update(node, event->name, 1); } } } } } /*============ GUI ===========*/ static int win_w, win_h; static void GLFWCALL reshape(int width, int height) { win_w = width; win_h = height; fprintf(stderr, INFO("resized to %dx%d\n"), width, height); } static void GLFWCALL keypressed(int key, int action) { if (action == GLFW_PRESS) { switch (key) { case GLFW_KEY_SPACE: node_profiler(); break; case GLFW_KEY_ESC: running = 0; break; } } } /*===== Util ========*/ static int create_socket(int type) { int one = 1; struct sockaddr_in sin; int fd = socket(AF_INET, type, 0); if (fd < 0) die("socket failed: %s", strerror(errno)); if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)) < 0) die("setsockopt reuse failed: %s", strerror(errno)); memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; const char *addr = getenv("INFOBEAMER_ADDR"); if (!addr) addr = LISTEN_ADDR; if (!inet_aton(addr, &sin.sin_addr)) die("invalid address %s", addr); sin.sin_port = htons(listen_port); if (bind(fd, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) die("binding to %s port %d failed: %s", type == SOCK_DGRAM ? "udp" : "tcp", listen_port, strerror(errno) ); return fd; } /*===== UDP (osc) Handling ========*/ static void udp_read(int fd, short event, void *arg) { char buf[1500]; int len; unsigned int size = sizeof(struct sockaddr); struct sockaddr_in client_addr; len = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&client_addr, &size); if (len == -1) die("recvfrom"); assert(len > 0); // own format: : int is_osc = 0; char payload_separator = ':'; int initial_offset = 0; // If data starts with /, assume it's osc // format: /0x00 if (*buf == '/') { is_osc = 1; payload_separator = '\0'; initial_offset = 1; }; char *sep = memchr(buf, payload_separator, len); if (!sep) { sendto(fd, LITERAL_AND_SIZE("fmt\n"), 0, (struct sockaddr *)&client_addr, size); return; } // Terminate by NUL *sep = '\0'; char *path = buf + initial_offset; char *data = sep + 1; if (is_osc) { // round up to next multiple of 4 data += 3 - (data - buf - 1) % 4; } int data_len = buf + len - data; if (data_len < 0) { sendto(fd, LITERAL_AND_SIZE("wtf\n"), 0, (struct sockaddr *)&client_addr, size); return; } // split a/b/c into first matching prefix: // a/b -> suffix: c if node a/b exists // fprintf(stderr, "udp event: %s: %*s\n", path, data_len, data); char *suffix = sep; node_t *node; while (1) { node = node_find_by_path_or_alias(path); if (node) break; char *next_split = memrchr(path, '/', suffix - path); if (!next_split) { sendto(fd, LITERAL_AND_SIZE("404\n"), 0, (struct sockaddr *)&client_addr, size); return; } if (suffix != sep) *suffix = '/'; suffix = next_split; *next_split = '\0'; } if (suffix != sep) suffix++; lua_pushlstring(node->L, data, data_len); lua_pushboolean(node->L, is_osc); lua_pushstring(node->L, suffix); node_event(node, "raw_data", 3); } static void open_udp(struct event *event) { int fd = create_socket(SOCK_DGRAM); event_set(event, fd, EV_READ | EV_PERSIST, &udp_read, NULL); if (event_add(event, NULL) == -1) die("event_add failed"); } /*===== TCP Handler ========*/ static void client_write(client_t *client, const char *data, size_t data_size) { bufferevent_write(client->buf_ev, data, data_size); } static void client_close(client_t *client) { if (client->node) { lua_pushlightuserdata(client->node->L, client); node_event(client->node, "disconnect", 1); // unlink client & node DL_DELETE(client->node->clients, client); client->node = NULL; } bufferevent_free(client->buf_ev); close(client->fd); free(client); } static void client_read(struct bufferevent *bev, void *arg) { client_t *client = arg; while (1) { char *line = evbuffer_readln(bev->input, NULL, EVBUFFER_EOL_CRLF); if (!line) break; if (client->node) { lua_pushstring(client->node->L, line); lua_pushlightuserdata(client->node->L, client); node_event(client->node, "input", 2); } else { node_t *node = node_find_by_path_or_alias(line); if (!node) { client_write(client, LITERAL_AND_SIZE("404\n")); } else { // link client & node DL_APPEND(node->clients, client); client->node = node; client_write(client, LITERAL_AND_SIZE("ok!\n")); lua_pushlightuserdata(node->L, client); node_event(client->node, "connect", 1); } } free(line); } } static void client_error(struct bufferevent *bev, short what, void *arg) { client_t *client = arg; client_close(client); } static void client_create(int fd) { client_t *client = xmalloc(sizeof(client_t)); client->fd = fd; client->buf_ev = bufferevent_new( fd, client_read, NULL, client_error, client); bufferevent_enable(client->buf_ev, EV_READ); client_write(client, LITERAL_AND_SIZE(VERSION_STRING)); client_write(client, LITERAL_AND_SIZE(" (")); client_write(client, LITERAL_AND_SIZE(INFO_URL)); client_write(client, LITERAL_AND_SIZE(") [")); char status[64]; snprintf(status, sizeof(status), "pid %d/uptime %d", getpid(), (int)now); client_write(client, status, strlen(status)); client_write(client, LITERAL_AND_SIZE("]. Select your channel!\n")); } static void accept_callback(int fd, short ev, void *arg) { int client_fd; struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); client_fd = accept(fd, (struct sockaddr *)&client_addr, &client_len); if (client_fd < 0) { fprintf(stderr, "accept() failed\n"); return; } evutil_make_socket_nonblocking(client_fd); client_create(client_fd); } static void open_tcp(struct event *event) { int fd = create_socket(SOCK_STREAM); if (listen(fd, 5) < 0) die("listen failed: %s", strerror(errno)); evutil_make_socket_nonblocking(fd); event_set(event, fd, EV_READ | EV_PERSIST, accept_callback, NULL); if (event_add(event, NULL) == -1) die("event_add failed"); } static void tick() { now = glfwGetTime(); check_inotify(); event_loop(EVLOOP_NONBLOCK); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFuncSeparate( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_ONE ); glBindFramebuffer(GL_FRAMEBUFFER, 0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glViewport(0, 0, win_w, win_h); glOrtho(0, win_w, win_h, 0, -1000, 1000); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClearColor(0.05, 0.05, 0.05, 1); glClear(GL_COLOR_BUFFER_BIT); node_render_self(&root, win_w, win_h); glfwSwapBuffers(); node_tree_gc(&root); if (!glfwGetWindowParam(GLFW_OPENED)) running = 0; } static void init_default_texture() { glGenTextures(1, &default_tex); glBindTexture(GL_TEXTURE_2D, default_tex); unsigned char white_pixel[] = {255, 255, 255, 255}; glTexImage2D(GL_TEXTURE_2D, 0, 4, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, white_pixel); } int main(int argc, char *argv[]) { fprintf(stdout, VERSION_STRING " (" INFO_URL ")\n"); fprintf(stdout, "Copyright (c) 2014 Florian Wesch \n\n"); if (argc != 2 || (argc == 2 && !strcmp(argv[1], "-h"))) { fprintf(stderr, "Usage: %s \n" "\n" "Optional environment variables:\n" "\n" " INFOBEAMER_FULLSCREEN=1 # Fullscreen mode\n" " INFOBEAMER_ADDR= # Bind to specified ip (default %s)\n" " INFOBEAMER_PORT= # Listen on alternative port (tcp & udp, default %d)\n" " INFOBEAMER_PRECOMPILED=1 # Allow precompiled code\n" " Warning: unsafe for untrusted code\n" " INFOBEAMER_FULLSCALE=1 # Scale root node to full screen size\n" " INFOBEAMER_WIDTH= # Width (default 1024)\n" " INFOBEAMER_HEIGHT= # Height (default 768)\n" "\n", argv[0], LISTEN_ADDR, DEFAULT_PORT); exit(1); } char *root_name = realpath(argv[1], NULL); if (!root_name) die("cannot canonicalize path: %s", strerror(errno)); char *split = rindex(root_name, '/'); if (!split) die("no slashes in target path. cannot continue"); *split = '\0'; if (*root_name == '\0') root_name = "/"; fprintf(stderr, INFO("chdir %s\n"), root_name); if (chdir(root_name) == -1) die("cannot chdir(%s): %s", root_name, strerror(errno)); root_name = split+1; fprintf(stderr, INFO("root node is %s\n"), root_name); inotify_fd = inotify_init1(IN_NONBLOCK); if (inotify_fd == -1) die("cannot open inotify: %s", strerror(errno)); av_register_all(); event_base = event_init(); dns_base = evdns_base_new(event_base, 1); const char *port = getenv("INFOBEAMER_PORT"); listen_port = port ? atoi(port) : DEFAULT_PORT; fprintf(stderr, INFO("tcp/udp port is %d\n"), listen_port); struct event udp_event; open_udp(&udp_event); struct event tcp_event; open_tcp(&tcp_event); glfwInit(); glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4); int mode = getenv("INFOBEAMER_FULLSCREEN") ? GLFW_FULLSCREEN : GLFW_WINDOW; int width = 1024; int height = 768; const char *new_width = getenv("INFOBEAMER_WIDTH"); if (new_width) width = atoi(new_width); const char *new_height = getenv("INFOBEAMER_HEIGHT"); if (new_height) height = atoi(new_height); fprintf(stderr, INFO("initial size is %dx%d\n"), width, height); if(!glfwOpenWindow(width, height, 8,8,8,8, 0,0, mode)) die("cannot open window"); GLenum err = glewInit(); if (err != GLEW_OK) die("cannot initialize glew"); if (!glewIsSupported("GL_VERSION_3_0")) die("need opengl 3.0 support\n"); glfwSetWindowTitle(VERSION_STRING); glfwSwapInterval(1); glfwSetWindowSizeCallback(reshape); glfwSetKeyCallback(keypressed); if (mode == GLFW_FULLSCREEN) glfwDisable(GLFW_MOUSE_CURSOR); ilInit(); iluInit(); signal(SIGVTALRM, deadline_signal); init_default_texture(); now = glfwGetTime(); node_init_root(&root, root_name); fprintf(stderr, INFO("initialization completed\n")); while (running) { tick(); } // no cleanup :-} return 0; } info-beamer-1.0~pre4/misc.c0000644000175000017500000000505212452774240013441 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #include #include #include #include #include #include "misc.h" void die(const char *fmt, ...) { va_list ap; va_start(ap, fmt); printf("CRITICAL ERROR: "); vprintf(fmt, ap); printf("\n"); va_end(ap); exit(1); } double time_delta(struct timeval *before, struct timeval *after) { double delta_seconds = after->tv_sec - before->tv_sec; double delta_milliseconds = (after->tv_usec - before->tv_usec) / 1000; if (delta_milliseconds < 0) { delta_milliseconds += 1000; delta_seconds--; } return delta_seconds * 1000 + delta_milliseconds; } void *xmalloc(size_t size) { void *ptr = calloc(1, size); if (!ptr) die("cannot malloc"); return ptr; } // Copyright (c) 2008-2009 Bjoern Hoehrmann // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. // // Modified for info-beamer static const uint8_t utf8d[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 00..1f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 20..3f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 40..5f 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // 60..7f 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, // 80..9f 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, // a0..bf 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, // c0..df 0xa,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x3,0x4,0x3,0x3, // e0..ef 0xb,0x6,0x6,0x6,0x5,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8,0x8, // f0..ff 0x0,0x1,0x2,0x3,0x5,0x8,0x7,0x1,0x1,0x1,0x4,0x6,0x1,0x1,0x1,0x1, // s0..s0 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,0,1,0,1,1,1,1,1,1, // s1..s2 1,2,1,1,1,1,1,2,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1, // s3..s4 1,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,3,1,3,1,1,1,1,1,1, // s5..s6 1,3,1,1,1,1,1,3,1,3,1,1,1,1,1,1,1,3,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // s7..s8 }; #define UTF8_ACCEPT 0 #define UTF8_REJECT 1 uint32_t decode_utf8(uint32_t* state, uint32_t* codep, uint32_t byte) { uint32_t type = utf8d[byte]; *codep = (*state != UTF8_ACCEPT) ? (byte & 0x3fu) | (*codep << 6) : (0xff >> type) & (byte); *state = utf8d[256 + *state*16 + type]; return *state; } int check_utf8(const char* s) { uint32_t codepoint, state = 0; while (*s) decode_utf8(&state, &codepoint, *(uint8_t*)s++); return state == UTF8_ACCEPT; } info-beamer-1.0~pre4/misc.h0000644000175000017500000001062012452774240013443 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef MISC_H #define MISC_H #include #include #include #include #define LITERAL_SIZE(x) (sizeof(x) - 1) #define LITERAL_AND_SIZE(x) x, LITERAL_SIZE(x) #define RED(string) "" string "" #define GREEN(string) "" string "" #define YELLOW(string) "" string "" #define BLUE(string) "" string "" #define CYAN(string) "" string "" #define WHITE(string) "" string "" #define INFO(str) WHITE("[" __FILE__ "]") " " str #define ERROR(str) RED("[" __FILE__ "]") " " str #define CLAMP(val, min, max) ((val) > (max) ? (max) : ((val) < (min) ? (min) : (val))) void die(const char *fmt, ...); void *xmalloc(size_t size); double time_delta(struct timeval *before, struct timeval *after); int check_utf8(const char* s); extern GLuint default_tex; extern struct event_base *event_base; extern struct evdns_base *dns_base; // Simple Lua binder // Based on http://lua-users.org/wiki/UserDataWithPointerExample #define LUA_TYPE_DECL(type) \ static type##_t *to_##type(lua_State *L, int index); \ static type##_t *checked_##type(lua_State *L, int index); \ static type##_t *push_##type(lua_State *L); #define LUA_TYPE_IMPL(type) \ static type##_t *to_##type(lua_State *L, int index) { \ type##_t *obj = (type##_t *)lua_touserdata(L, index); \ if (!obj) luaL_typerror(L, index, #type); \ return obj; \ } \ \ static type##_t *checked_##type(lua_State *L, int index) { \ luaL_checktype(L, index, LUA_TUSERDATA); \ type##_t *obj = (type##_t *)luaL_checkudata(L, index, #type); \ if (!obj) luaL_typerror(L, index, #type); \ return obj; \ } \ \ static type##_t *push_##type(lua_State *L) { \ type##_t *obj = (type##_t *)lua_newuserdata(L, sizeof(type##_t)); \ luaL_getmetatable(L, #type); \ lua_setmetatable(L, -2); \ return obj; \ } \ \ static int type##_tostring(lua_State *L) { \ lua_pushfstring(L, "<" #type " %p>", lua_touserdata(L, 1)); \ return 1; \ } \ \ static const luaL_reg type##_meta[] = { \ {"__gc", type##_gc}, \ {"__tostring", type##_tostring}, \ {0, 0} \ }; \ \ int type##_register(lua_State *L) { \ luaL_openlib(L, #type, type##_methods, 0); \ luaL_newmetatable(L, #type); \ luaL_openlib(L, 0, type##_meta, 0); \ lua_pushliteral(L, "__index"); \ lua_pushvalue(L, -3); \ lua_rawset(L, -3); \ lua_pushliteral(L, "__metatable"); \ lua_pushvalue(L, -3); \ lua_rawset(L, -3); \ lua_pop(L, 1); \ return 1; \ } #endif info-beamer-1.0~pre4/module_json.lua0000644000175000017500000003672412452774240015375 0ustar nknk----------------------------------------------------------------------------- -- JSON4Lua: JSON encoding / decoding support for the Lua language. -- json Module. -- Author: Craig Mason-Jones -- Homepage: http://json.luaforge.net/ -- Version: 0.9.40 -- This module is released under the MIT License (MIT). -- Please see LICENCE.txt for details. -- -- USAGE: -- This module exposes two functions: -- encode(o) -- Returns the table / string / boolean / number / nil / json.null value as a JSON-encoded string. -- decode(json_string) -- Returns a Lua object populated with the data encoded in the JSON string json_string. -- -- REQUIREMENTS: -- compat-5.1 if using Lua 5.0 -- -- CHANGELOG -- 0.9.20 Introduction of local Lua functions for private functions (removed _ function prefix). -- Fixed Lua 5.1 compatibility issues. -- Introduced json.null to have null values in associative arrays. -- encode() performance improvement (more than 50%) through table.concat rather than .. -- Introduced decode ability to ignore /**/ comments in the JSON string. -- 0.9.10 Fix to array encoding / decoding to correctly manage nil/null values in arrays. ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- Imports and dependencies ----------------------------------------------------------------------------- local math = require('math') local string = require("string") local table = require("table") local base = _G ----------------------------------------------------------------------------- -- Module declaration ----------------------------------------------------------------------------- module("json") -- Public functions -- Private functions local decode_scanArray local decode_scanComment local decode_scanConstant local decode_scanNumber local decode_scanObject local decode_scanString local decode_scanWhitespace local encodeString local isArray local isEncodable ----------------------------------------------------------------------------- -- PUBLIC FUNCTIONS ----------------------------------------------------------------------------- --- Encodes an arbitrary Lua object / variable. -- @param v The Lua object / variable to be JSON encoded. -- @return String containing the JSON encoding in internal Lua string format (i.e. not unicode) function encode (v) -- Handle nil values if v==nil then return "null" end local vtype = base.type(v) -- Handle strings if vtype=='string' then return '"' .. encodeString(v) .. '"' -- Need to handle encoding in string end -- Handle booleans if vtype=='number' or vtype=='boolean' then return base.tostring(v) end -- Handle tables if vtype=='table' then local rval = {} -- Consider arrays separately local bArray, maxCount = isArray(v) if bArray then for i = 1,maxCount do table.insert(rval, encode(v[i])) end else -- An object, not an array for i,j in base.pairs(v) do if isEncodable(i) and isEncodable(j) then table.insert(rval, '"' .. encodeString(i) .. '":' .. encode(j)) end end end if bArray then return '[' .. table.concat(rval,',') ..']' else return '{' .. table.concat(rval,',') .. '}' end end -- Handle null values if vtype=='function' and v==null then return 'null' end base.assert(false,'encode attempt to encode unsupported type ' .. vtype .. ':' .. base.tostring(v)) end --- Decodes a JSON string and returns the decoded value as a Lua data structure / value. -- @param s The string to scan. -- @param [startPos] Optional starting position where the JSON string is located. Defaults to 1. -- @param Lua object, number The object that was scanned, as a Lua table / string / number / boolean or nil, -- and the position of the first character after -- the scanned JSON object. function decode(s, startPos) startPos = startPos and startPos or 1 startPos = decode_scanWhitespace(s,startPos) base.assert(startPos<=string.len(s), 'Unterminated JSON encoded object found at position in [' .. s .. ']') local curChar = string.sub(s,startPos,startPos) -- Object if curChar=='{' then return decode_scanObject(s,startPos) end -- Array if curChar=='[' then return decode_scanArray(s,startPos) end -- Number if string.find("+-0123456789.e", curChar, 1, true) then return decode_scanNumber(s,startPos) end -- String if curChar==[["]] or curChar==[[']] then return decode_scanString(s,startPos) end if string.sub(s,startPos,startPos+1)=='/*' then return decode(s, decode_scanComment(s,startPos)) end -- Otherwise, it must be a constant return decode_scanConstant(s,startPos) end --- The null function allows one to specify a null value in an associative array (which is otherwise -- discarded if you set the value with 'nil' in Lua. Simply set t = { first=json.null } function null() return null -- so json.null() will also return null ;-) end ----------------------------------------------------------------------------- -- Internal, PRIVATE functions. -- Following a Python-like convention, I have prefixed all these 'PRIVATE' -- functions with an underscore. ----------------------------------------------------------------------------- --- Scans an array from JSON into a Lua object -- startPos begins at the start of the array. -- Returns the array and the next starting position -- @param s The string being scanned. -- @param startPos The starting position for the scan. -- @return table, int The scanned array as a table, and the position of the next character to scan. function decode_scanArray(s,startPos) local array = {} -- The return value local stringLen = string.len(s) base.assert(string.sub(s,startPos,startPos)=='[','decode_scanArray called but array does not start at position ' .. startPos .. ' in string:\n'..s ) startPos = startPos + 1 -- Infinite loop for array elements repeat startPos = decode_scanWhitespace(s,startPos) base.assert(startPos<=stringLen,'JSON String ended unexpectedly scanning array.') local curChar = string.sub(s,startPos,startPos) if (curChar==']') then return array, startPos+1 end if (curChar==',') then startPos = decode_scanWhitespace(s,startPos+1) end base.assert(startPos<=stringLen, 'JSON String ended unexpectedly scanning array.') object, startPos = decode(s,startPos) table.insert(array,object) until false end --- Scans a comment and discards the comment. -- Returns the position of the next character following the comment. -- @param string s The JSON string to scan. -- @param int startPos The starting position of the comment function decode_scanComment(s, startPos) base.assert( string.sub(s,startPos,startPos+1)=='/*', "decode_scanComment called but comment does not start at position " .. startPos) local endPos = string.find(s,'*/',startPos+2) base.assert(endPos~=nil, "Unterminated comment in string at " .. startPos) return endPos+2 end --- Scans for given constants: true, false or null -- Returns the appropriate Lua type, and the position of the next character to read. -- @param s The string being scanned. -- @param startPos The position in the string at which to start scanning. -- @return object, int The object (true, false or nil) and the position at which the next character should be -- scanned. function decode_scanConstant(s, startPos) local consts = { ["true"] = true, ["false"] = false, ["null"] = nil } local constNames = {"true","false","null"} for i,k in base.pairs(constNames) do --print ("[" .. string.sub(s,startPos, startPos + string.len(k) -1) .."]", k) if string.sub(s,startPos, startPos + string.len(k) -1 )==k then return consts[k], startPos + string.len(k) end end base.assert(nil, 'Failed to scan constant from string ' .. s .. ' at starting position ' .. startPos) end --- Scans a number from the JSON encoded string. -- (in fact, also is able to scan numeric +- eqns, which is not -- in the JSON spec.) -- Returns the number, and the position of the next character -- after the number. -- @param s The string being scanned. -- @param startPos The position at which to start scanning. -- @return number, int The extracted number and the position of the next character to scan. function decode_scanNumber(s,startPos) local endPos = startPos+1 local stringLen = string.len(s) local acceptableChars = "+-0123456789.e" while (string.find(acceptableChars, string.sub(s,endPos,endPos), 1, true) and endPos<=stringLen ) do endPos = endPos + 1 end local stringValue = 'return ' .. string.sub(s,startPos, endPos-1) local stringEval = base.loadstring(stringValue) base.assert(stringEval, 'Failed to scan number [ ' .. stringValue .. '] in JSON string at position ' .. startPos .. ' : ' .. endPos) return stringEval(), endPos end --- Scans a JSON object into a Lua object. -- startPos begins at the start of the object. -- Returns the object and the next starting position. -- @param s The string being scanned. -- @param startPos The starting position of the scan. -- @return table, int The scanned object as a table and the position of the next character to scan. function decode_scanObject(s,startPos) local object = {} local stringLen = string.len(s) local key, value base.assert(string.sub(s,startPos,startPos)=='{','decode_scanObject called but object does not start at position ' .. startPos .. ' in string:\n' .. s) startPos = startPos + 1 repeat startPos = decode_scanWhitespace(s,startPos) base.assert(startPos<=stringLen, 'JSON string ended unexpectedly while scanning object.') local curChar = string.sub(s,startPos,startPos) if (curChar=='}') then return object,startPos+1 end if (curChar==',') then startPos = decode_scanWhitespace(s,startPos+1) end base.assert(startPos<=stringLen, 'JSON string ended unexpectedly scanning object.') -- Scan the key key, startPos = decode(s,startPos) base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key) startPos = decode_scanWhitespace(s,startPos) base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key) base.assert(string.sub(s,startPos,startPos)==':','JSON object key-value assignment mal-formed at ' .. startPos) startPos = decode_scanWhitespace(s,startPos+1) base.assert(startPos<=stringLen, 'JSON string ended unexpectedly searching for value of key ' .. key) value, startPos = decode(s,startPos) object[key]=value until false -- infinite loop while key-value pairs are found end --- Scans a JSON string from the opening inverted comma or single quote to the -- end of the string. -- Returns the string extracted as a Lua string, -- and the position of the next non-string character -- (after the closing inverted comma or single quote). -- @param s The string being scanned. -- @param startPos The starting position of the scan. -- @return string, int The extracted string as a Lua string, and the next character to parse. function decode_scanString(s,startPos) base.assert(startPos, 'decode_scanString(..) called without start position') local startChar = string.sub(s,startPos,startPos) base.assert(startChar==[[']] or startChar==[["]],'decode_scanString called for a non-string') local escaped = false local endPos = startPos + 1 local bEnded = false local stringLen = string.len(s) repeat local curChar = string.sub(s,endPos,endPos) -- Character escaping is only used to escape the string delimiters if not escaped then if curChar==[[\]] then escaped = true else bEnded = curChar==startChar end else -- If we're escaped, we accept the current character come what may escaped = false end endPos = endPos + 1 base.assert(endPos <= stringLen+1, "String decoding failed: unterminated string at position " .. endPos) until bEnded local stringValue = 'return ' .. string.sub(s, startPos, endPos-1) local stringEval = base.loadstring(stringValue) base.assert(stringEval, 'Failed to load string [ ' .. stringValue .. '] in JSON4Lua.decode_scanString at position ' .. startPos .. ' : ' .. endPos) return stringEval(), endPos end --- Scans a JSON string skipping all whitespace from the current start position. -- Returns the position of the first non-whitespace character, or nil if the whole end of string is reached. -- @param s The string being scanned -- @param startPos The starting position where we should begin removing whitespace. -- @return int The first position where non-whitespace was encountered, or string.len(s)+1 if the end of string -- was reached. function decode_scanWhitespace(s,startPos) local whitespace=" \n\r\t" local stringLen = string.len(s) while ( string.find(whitespace, string.sub(s,startPos,startPos), 1, true) and startPos <= stringLen) do startPos = startPos + 1 end return startPos end --- Encodes a string to be JSON-compatible. -- This just involves back-quoting inverted commas, back-quotes and newlines, I think ;-) -- @param s The string to return as a JSON encoded (i.e. backquoted string) -- @return The string appropriately escaped. function encodeString(s) s = string.gsub(s,'\\','\\\\') s = string.gsub(s,'"','\\"') s = string.gsub(s,"'","\\'") s = string.gsub(s,'\n','\\n') s = string.gsub(s,'\t','\\t') return s end -- Determines whether the given Lua type is an array or a table / dictionary. -- We consider any table an array if it has indexes 1..n for its n items, and no -- other data in the table. -- I think this method is currently a little 'flaky', but can't think of a good way around it yet... -- @param t The table to evaluate as an array -- @return boolean, number True if the table can be represented as an array, false otherwise. If true, -- the second returned value is the maximum -- number of indexed elements in the array. function isArray(t) -- Next we count all the elements, ensuring that any non-indexed elements are not-encodable -- (with the possible exception of 'n') local maxIndex = 0 for k,v in base.pairs(t) do if (base.type(k)=='number' and math.floor(k)==k and 1<=k) then -- k,v is an indexed pair if (not isEncodable(v)) then return false end -- All array elements must be encodable maxIndex = math.max(maxIndex,k) else if (k=='n') then if v ~= table.getn(t) then return false end -- False if n does not hold the number of elements else -- Else of (k=='n') if isEncodable(v) then return false end end -- End of (k~='n') end -- End of k,v not an indexed pair end -- End of loop across all pairs return true, maxIndex end --- Determines whether the given Lua object / table / variable can be JSON encoded. The only -- types that are JSON encodable are: string, boolean, number, nil, table and json.null. -- In this implementation, all other types are ignored. -- @param o The object to examine. -- @return boolean True if the object should be JSON encoded, false if it should be ignored. function isEncodable(o) local t = base.type(o) return (t=='string' or t=='boolean' or t=='number' or t=='nil' or t=='table') or (t=='function' and o==null) end info-beamer-1.0~pre4/shader.c0000644000175000017500000001357212452774240013762 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #include #include #include #include #include #include #include #include #include #include "misc.h" typedef struct { GLuint fs; GLuint vs; GLuint po; } shader_t; LUA_TYPE_DECL(shader) /* Instance methods */ static int shader_use(lua_State *L) { shader_t *shader = checked_shader(L, 1); glUseProgram(shader->po); // No variables? if (lua_gettop(L) == 1) return 0; int num_textures = 1; luaL_checktype(L, 2, LUA_TTABLE); lua_pushnil(L); while (lua_next(L, -2)) { // copy the name and convert it to a string // (thereby changing the stack slot) // => [name] [value] [converted name] lua_pushvalue(L, -2); const char *name = lua_tostring(L, -1); GLint loc = glGetUniformLocation(shader->po, name); if (loc == -1) { // return luaL_error(L, "unknown uniform name %s. " // "maybe it is not used in the shader?", name); lua_pop(L, 2); continue; } int type = lua_type(L, -2); int len = lua_objlen(L, -2); if (type == LUA_TNUMBER) { GLfloat value = lua_tonumber(L, -2); glUniform1f(loc, value); } else if (type == LUA_TTABLE && 2 <= len && len <= 4) { GLfloat values[4]; for (int idx = 1; idx <= len; idx++) { lua_rawgeti(L, -2, idx); if (lua_type(L, -1) != LUA_TNUMBER) return luaL_error(L, "only numbers supported in %s at index %d", name, idx); values[idx -1] = lua_tonumber(L, -1); lua_pop(L, 1); } switch (len) { case 4: glUniform4f(loc, values[0], values[1], values[2], values[3]); break; case 3: glUniform3f(loc, values[0], values[1], values[2]); break; case 2: glUniform2f(loc, values[0], values[1]); break; } } else if (type == LUA_TUSERDATA || type == LUA_TTABLE) { lua_pushliteral(L, "texid"); lua_gettable(L, -3); // texid aus metatable holen if (lua_type(L, -1) != LUA_TFUNCTION) return luaL_error(L, "value %s has no texid() function", name); lua_pushvalue(L, -3); // value kopieren (als self) lua_call(L, 1, 1); // obj:texid() if (lua_type(L, -1) != LUA_TNUMBER) return luaL_error(L, "%s's texid() did not return number", name); int tex_id = lua_tonumber(L, -1); lua_pop(L, 1); glActiveTexture(GL_TEXTURE0 + num_textures); glBindTexture(GL_TEXTURE_2D, tex_id); glUniform1i(loc, num_textures); num_textures++; } else { return luaL_error(L, "unsupported value for %s. " "must be number, vector or texturelike", name); } // if (glGetError() == GL_INVALID_OPERATION) // return luaL_error(L, "unsupported assignment to %s " // "incompatible values?", name); lua_pop(L, 2); } lua_pop(L, 1); glActiveTexture(GL_TEXTURE0); GLint texloc = glGetUniformLocation(shader->po, "Texture"); if (texloc != -1) glUniform1i(texloc, 0); return 0; } static int shader_deactivate(lua_State *L) { glUseProgram(0); return 0; } static const luaL_reg shader_methods[] = { {"use", shader_use}, {"deactivate", shader_deactivate}, {0,0} }; /* Lifecycle */ int shader_new(lua_State *L, const char *vertex, const char *fragment) { char *fault = ""; char log[1024]; const char *define = "#define INFOBEAMER\n#define INFOBEAMER_PLAT_DESKTOP\n"; GLint status; GLsizei log_len; GLuint fs = 0, vs = 0, po = 0; // Pixel vs = glCreateShader(GL_VERTEX_SHADER); const char *vertex_sources[] = { define, vertex }; glShaderSource(vs, 2, vertex_sources, NULL); glCompileShader(vs); glGetObjectParameterivARB(vs, GL_COMPILE_STATUS, &status); if (!status) { fault = "compiling vertex shader"; glGetShaderInfoLog(vs, sizeof(log), &log_len, log); if (log_len > 0) goto error; } // Fragment fs = glCreateShader(GL_FRAGMENT_SHADER); const char *fragment_sources[] = { define, fragment }; glShaderSource(fs, 2, fragment_sources, NULL); glCompileShader(fs); glGetObjectParameterivARB(fs, GL_COMPILE_STATUS, &status); if (!status) { fault = "compiling fragment shader"; glGetShaderInfoLog(fs, sizeof(log), &log_len, log); if (log_len > 0) goto error; } // Program Object po = glCreateProgram(); glAttachShader(po, vs); glAttachShader(po, fs); glLinkProgram(po); glGetProgramiv(po, GL_LINK_STATUS, &status); if (!status) { fault = "linking program"; glGetProgramInfoLog(po, sizeof(log), &log_len, log); if (log_len > 0) goto error; } shader_t *shader = push_shader(L); shader->fs = fs; shader->vs = vs; shader->po = po; return 1; error: if (po) glDeleteProgram(po); if (vs) glDeleteShader(vs); if (fs) glDeleteShader(fs); return luaL_error(L, "While %s: %s", fault, log); } static int shader_gc(lua_State *L) { shader_t *shader = to_shader(L, 1); glDeleteProgram(shader->po); glDeleteShader(shader->vs); glDeleteShader(shader->fs); return 0; } LUA_TYPE_IMPL(shader) void shader_set_gl_color(GLfloat r, GLfloat g, GLfloat b, GLfloat a) { glColor4f(r, g, b, a); GLint prog, color; glGetIntegerv(GL_CURRENT_PROGRAM, &prog); color = glGetUniformLocation(prog, "Color"); if (color != -1) glUniform4f(color, r, g, b, a); } info-beamer-1.0~pre4/shader.h0000644000175000017500000000040712452774240013760 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef SHADER_H #define SHADER_H int shader_register(lua_State *L); int shader_new(lua_State *L, const char *vertex, const char *fragment); void shader_set_gl_color(GLfloat r, GLfloat g, GLfloat b, GLfloat a); #endif info-beamer-1.0~pre4/struct.c0000644000175000017500000002257212452774240014040 0ustar nknk #include #include #include #include #include "lua.h" #include "lauxlib.h" /* ** {====================================================== ** Library for packing/unpacking structures. ** $Id: struct.c,v 1.2 2008/04/18 20:06:01 roberto Exp $ ** See Copyright Notice at the end of this file ** ======================================================= */ /* ** Valid formats: ** > - big endian ** < - little endian ** ![num] - alignment ** x - pading ** b/B - signed/unsigned byte ** h/H - signed/unsigned short ** l/L - signed/unsigned long ** i/In - signed/unsigned integer with size `n' (default is size of int) ** cn - sequence of `n' chars (from/to a string); when packing, n==0 means the whole string; when unpacking, n==0 means use the previous read number as the string length ** s - zero-terminated string ** f - float ** d - doulbe ** ' ' - ignored */ /* is 'x' a power of 2? */ #define isp2(x) ((x) > 0 && ((x) & ((x) - 1)) == 0) /* dummy structure to get alignment requirements */ struct cD { char c; double d; }; #define PADDING (sizeof(struct cD) - sizeof(double)) #define MAXALIGN (PADDING > sizeof(int) ? PADDING : sizeof(int)) /* endian options */ #define BIG 0 #define LITTLE 1 static union { int dummy; char endian; } const native = {1}; typedef struct Header { int endian; int align; } Header; static size_t getnum (const char **fmt, size_t df) { if (!isdigit(**fmt)) /* no number? */ return df; /* return default value */ else { size_t a = 0; do { a = a*10 + *((*fmt)++) - '0'; } while (isdigit(**fmt)); return a; } } #define defaultoptions(h) ((h)->endian = native.endian, (h)->align = 1) static size_t optsize (lua_State *L, char opt, const char **fmt) { switch (opt) { case 'B': case 'b': return sizeof(char); case 'H': case 'h': return sizeof(short); case 'L': case 'l': return sizeof(long); case 'f': return sizeof(float); case 'd': return sizeof(double); case 'x': return 1; case 'c': return getnum(fmt, 1); case 's': case ' ': case '<': case '>': case '!': return 0; case 'i': case 'I': { int sz = getnum(fmt, sizeof(int)); if (!isp2(sz)) luaL_error(L, "integral size %d is not a power of 2", sz); return sz; } default: { const char *msg = lua_pushfstring(L, "invalid format option [%c]", opt); return luaL_argerror(L, 1, msg); } } } static int gettoalign (size_t len, Header *h, int opt, size_t size) { if (size == 0 || opt == 'c') return 0; if (size > (size_t)h->align) size = h->align; /* respect max. alignment */ return (size - (len & (size - 1))) & (size - 1); } static void commoncases (lua_State *L, int opt, const char **fmt, Header *h) { switch (opt) { case ' ': return; /* ignore white spaces */ case '>': h->endian = BIG; return; case '<': h->endian = LITTLE; return; case '!': { int a = getnum(fmt, MAXALIGN); if (!isp2(a)) luaL_error(L, "alignment %d is not a power of 2", a); h->align = a; return; } default: assert(0); } } static void putinteger (lua_State *L, luaL_Buffer *b, int arg, int endian, int size) { lua_Number n = luaL_checknumber(L, arg); unsigned long value; if (n < (lua_Number)LONG_MAX) value = (long)n; else value = (unsigned long)n; if (endian == LITTLE) { int i; for (i = 0; i < size; i++) luaL_addchar(b, (value >> 8*i) & 0xff); } else { int i; for (i = size - 1; i >= 0; i--) luaL_addchar(b, (value >> 8*i) & 0xff); } } static void correctbytes (char *b, int size, int endian) { if (endian != native.endian) { int i = 0; while (i < --size) { char temp = b[i]; b[i++] = b[size]; b[size] = temp; } } } static int b_pack (lua_State *L) { luaL_Buffer b; const char *fmt = luaL_checkstring(L, 1); Header h; int arg = 2; size_t totalsize = 0; defaultoptions(&h); lua_pushnil(L); /* mark to separate arguments from string buffer */ luaL_buffinit(L, &b); while (*fmt != '\0') { int opt = *fmt++; size_t size = optsize(L, opt, &fmt); int toalign = gettoalign(totalsize, &h, opt, size); totalsize += toalign; while (toalign-- > 0) luaL_putchar(&b, '\0'); switch (opt) { case 'b': case 'B': case 'h': case 'H': case 'l': case 'L': case 'i': case 'I': { /* integer types */ putinteger(L, &b, arg++, h.endian, size); break; } case 'x': { luaL_putchar(&b, '\0'); break; } case 'f': { float f = (float)luaL_checknumber(L, arg++); correctbytes((char *)&f, size, h.endian); luaL_addlstring(&b, (char *)&f, size); break; } case 'd': { double d = luaL_checknumber(L, arg++); correctbytes((char *)&d, size, h.endian); luaL_addlstring(&b, (char *)&d, size); break; } case 'c': case 's': { size_t l; const char *s = luaL_checklstring(L, arg++, &l); if (size == 0) size = l; luaL_argcheck(L, l >= (size_t)size, arg, "string too short"); luaL_addlstring(&b, s, size); if (opt == 's') { luaL_putchar(&b, '\0'); /* add zero at the end */ size++; } break; } default: commoncases(L, opt, &fmt, &h); } totalsize += size; } luaL_pushresult(&b); return 1; } static lua_Number getinteger (const char *buff, int endian, int issigned, int size) { unsigned long l = 0; if (endian == BIG) { int i; for (i = 0; i < size; i++) l |= (unsigned long)(unsigned char)buff[size - i - 1] << (i*8); } else { int i; for (i = 0; i < size; i++) l |= (unsigned long)(unsigned char)buff[i] << (i*8); } if (!issigned) return (lua_Number)l; else { /* signed format */ unsigned long mask = ~(0UL) << (size*8 - 1); if (l & mask) /* negative value? */ l |= mask; /* signal extension */ return (lua_Number)(long)l; } } static int b_unpack (lua_State *L) { Header h; const char *fmt = luaL_checkstring(L, 1); size_t ld; const char *data = luaL_checklstring(L, 2, &ld); size_t pos = luaL_optinteger(L, 3, 1) - 1; defaultoptions(&h); lua_settop(L, 2); while (*fmt) { int opt = *fmt++; size_t size = optsize(L, opt, &fmt); pos += gettoalign(pos, &h, opt, size); luaL_argcheck(L, pos+size <= ld, 2, "data string too short"); switch (opt) { case 'b': case 'B': case 'h': case 'H': case 'l': case 'L': case 'i': case 'I': { /* integer types */ int issigned = islower(opt); lua_Number res = getinteger(data+pos, h.endian, issigned, size); lua_pushnumber(L, res); break; } case 'x': { break; } case 'f': { float f; memcpy(&f, data+pos, size); correctbytes((char *)&f, sizeof(f), h.endian); lua_pushnumber(L, f); break; } case 'd': { double d; memcpy(&d, data+pos, size); correctbytes((char *)&d, sizeof(d), h.endian); lua_pushnumber(L, d); break; } case 'c': { if (size == 0) { if (!lua_isnumber(L, -1)) luaL_error(L, "format `c0' needs a previous size"); size = lua_tonumber(L, -1); lua_pop(L, 1); luaL_argcheck(L, pos+size <= ld, 2, "data string too short"); } lua_pushlstring(L, data+pos, size); break; } case 's': { const char *e = (const char *)memchr(data+pos, '\0', ld - pos); if (e == NULL) luaL_error(L, "unfinished string in data"); size = (e - (data+pos)) + 1; lua_pushlstring(L, data+pos, size - 1); break; } default: commoncases(L, opt, &fmt, &h); } pos += size; } lua_pushinteger(L, pos + 1); return lua_gettop(L) - 2; } /* }====================================================== */ static const struct luaL_reg thislib[] = { {"pack", b_pack}, {"unpack", b_unpack}, {NULL, NULL} }; LUALIB_API int luaopen_struct (lua_State *L) { luaL_register(L, "struct", thislib); return 1; } /****************************************************************************** * Copyright (C) 2010 Lua.org, PUC-Rio. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ info-beamer-1.0~pre4/struct.h0000644000175000017500000000022612452774240014035 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef STRUCT_H #define STRUCT_H #include LUALIB_API int luaopen_struct (lua_State *L); #endif info-beamer-1.0~pre4/userlib.lua0000644000175000017500000005421312452774240014515 0ustar nknk-- See Copyright Notice in LICENSE.txt util = {} function util.shader_loader(filename) return resource.create_shader(resource.load_file(filename)) end function util.videoplayer(name, opt) local stream, start, fps, frame, width, height local function open_stream() stream = resource.load_video(name) start = sys.now() fps = stream:fps() frame = 0 width, height = stream:size() end open_stream() opt = opt or {} local speed = opt.speed or 1 fps = fps * speed local loop = true if opt.loop ~= nil then loop = opt.loop end local done = false return { draw = function(self, x1, y1, x2, y2, alpha) if done then return end local now = sys.now() local target_frame = (now - start) * fps if target_frame > frame + 10 then print(string.format( "slow player for '%s'. missed %d frames since last call", name, target_frame - frame )) -- too slow to decode. rebase time start = now - frame * 1/fps else while frame < target_frame do if not stream:next() then if loop then print("player: looping") open_stream() stream:next() break else -- stream completed done = true return false end end frame = frame + 1 end end stream:draw(x1, y1, x2, y2, alpha) return true end; texid = function(self) return stream:texid() end; next = function(self) return not done end; size = function(self) return stream:size() end; } end util.loaders = { png = resource.load_image; jpg = resource.load_image; jpeg = resource.load_image; gif = resource.load_image; bmp = resource.load_image; ttf = resource.load_font; otf = resource.load_font; avi = util.videoplayer; mpg = util.videoplayer; ogg = util.videoplayer; flv = util.videoplayer; mkv = util.videoplayer; mp4 = util.videoplayer; mov = util.videoplayer; frag = util.shader_loader; } function util.auto_loader(container, filter) container = container or {} filter = filter or function() return true end local loaded_version = {} local function auto_load(name) if filter and not filter(name) then return end if loaded_version[name] == CONTENTS[name] then -- print("auto_loader: already loaded " .. name) return end local target, suffix = name:match("(.*)[.]([^.]+)$") if not target then print("loader: invalid resource name " .. name .. ". ignoring " .. name) return end local loader = util.loaders[suffix] if not loader then print("loader: no resource loader for suffix " .. suffix .. ". ignoring " .. name) return end local success, res = pcall(loader, name) if not success then print("loader: cannot load " .. name .. ": " .. res) else print("loader: updated " .. target .. " (triggered by " .. name .. ")") container[target] = res loaded_version[name] = CONTENTS[name] end end print("loader: loading known resources") for name, added in pairs(CONTENTS) do auto_load(name) end node.event("content_update", auto_load) node.event("content_remove", function(name) local target, suffix = name:match("(.*)[.]([^.]+)$") if target and util.loaders[suffix] and container[target] then print("loader: unloaded " .. target .. " (triggered by " .. name .. ")") container[target] = nil loaded_version[name] = nil end end) return container end function util.resource_loader(resources) local whitelist = {} for _, name in ipairs(resources) do whitelist[name] = true end util.auto_loader(_G, function(name) return whitelist[name] end) end function util.file_watch(filename, handler) local loaded_version = nil local function updated(name) if name ~= filename then return end if loaded_version == CONTENTS[filename] then return end loaded_version = CONTENTS[filename] handler(resource.load_file(filename)) end node.event("content_update", updated) updated(filename) end local function handle_suffix_match(suffix, pattern, callback, ...) local data = {...} return (function(s, e, ...) if s == nil then return false end local args = {...} for n = 1, #data do args[#args+1] = data[n] end callback(unpack(args)) return true end)(suffix:find(pattern)) end function util.osc_mapper(routes) node.event("osc", function(suffix, ...) for pattern, callback in pairs(routes) do if handle_suffix_match(suffix, pattern, callback, ...) then return end end end) end function util.data_mapper(routes) node.event("data", function(data, suffix) for pattern, callback in pairs(routes) do if handle_suffix_match(suffix, pattern, callback, data) then return end end end) end function util.generator(refiller) local items = {} return { next = function(self) local next_item = next(items) if not next_item then for _, value in ipairs(refiller()) do items[value] = 1 end next_item = next(items) if not next_item then error("no items available") end end items[next_item] = nil return next_item end; add = function(self, value) items[value] = 1 end; remove = function(self, value) items[value] = nil end; } end function util.set_interval(interval, callback) local next_call = sys.now() + interval node.event("render", function() local now = sys.now() if now > next_call then next_call = now + interval callback() end end) callback() end function util.post_effect(shader, shader_opt) local surface = resource.create_snapshot() gl.ortho() gl.clear(0,0,0,1) shader:use(shader_opt) surface:draw(0, 0, WIDTH, HEIGHT) shader:deactivate() end function util.running_text(opt) local current_idx = 1 local current_left = 0 local last = sys.now() local generator = opt.generator local font = opt.font local size = opt.size or 10 local speed = opt.speed or 10 local color = opt.color or {1,1,1,1} local texts = {} return { draw = function(self, y) local now = sys.now() local xoff = current_left local idx = 1 while xoff < WIDTH do if #texts < idx then table.insert(texts, generator.next()) end local width = font:write(xoff, y, texts[idx] .. " - ", size, unpack(color)) xoff = xoff + width if xoff < 0 then current_left = xoff table.remove(texts, idx) else idx = idx + 1 end end local delta = now - last last = now current_left = current_left - delta * speed end; add = function(self, text) generator:add(text) end; } end function util.scale_into(target_width, target_height, source_width, source_height) local prop_height = source_height * target_width / source_width local prop_width = source_width * target_height / source_height local x1, y1, x2, y2 if prop_height > target_height then local x_center = target_width / 2 local half_width = prop_width / 2 x1 = x_center - half_width y1 = 0 x2 = x_center + half_width y2 = target_height else local y_center = target_height / 2 local half_height = prop_height / 2 x1 = 0 y1 = y_center - half_height x2 = target_width y2 = y_center + half_height end return x1, y1, x2, y2 end function util.draw_correct(obj, x1, y1, x2, y2, ...) local ox1, oy1, ox2, oy2 = util.scale_into( x2 - x1, y2 - y1, obj:size() ) obj:draw(x1 + ox1, y1 + oy1, x1 + ox2, y1 + oy2, ...) end function table.filter(t, predicate) local j = 1 for i, v in ipairs(t) do if predicate(v) then t[j] = v j = j + 1 end end while t[j] ~= nil do t[j] = nil j = j + 1 end return t end -- Based on http://lua-users.org/wiki/TableSerialization -- Modified to *not* use debug.getinfo --[[ Author: Julio Manuel Fernandez-Diaz Date: January 12, 2007 (For Lua 5.1) Modified slightly by RiciLake to avoid the unnecessary table traversal in tablecount() Formats tables with cycles recursively to any depth. The output is returned as a string. References to other tables are shown as values. Self references are indicated. The string returned is "Lua code", which can be procesed (in the case in which indent is composed by spaces or "--"). Userdata and function keys and values are shown as strings, which logically are exactly not equivalent to the original code. This routine can serve for pretty formating tables with proper indentations, apart from printing them: print(table.show(t, "t")) -- a typical use Heavily based on "Saving tables with cycles", PIL2, p. 113. Arguments: t is the table. name is the name of the table (optional) indent is a first indentation (optional). --]] function table.show(t, name, indent) local cart -- a container local autoref -- for self references -- (RiciLake) returns true if the table is empty local function isemptytable(t) return next(t) == nil end local function basicSerialize (o) local so = tostring(o) if type(o) == "function" or type(o) == "number" or type(o) == "boolean" then return so else return string.format("%q", so) end end local function addtocart (value, name, indent, saved, field) indent = indent or "" saved = saved or {} field = field or name cart = cart .. indent .. field if type(value) ~= "table" then cart = cart .. " = " .. basicSerialize(value) .. ";\n" else if saved[value] then cart = cart .. " = {...}; -- " .. saved[value] .. " (self reference)\n" autoref = autoref .. name .. " = " .. saved[value] .. ";\n" else saved[value] = name --if tablecount(value) == 0 then if isemptytable(value) then cart = cart .. " = {};\n" else cart = cart .. " = {\n" for k, v in pairs(value) do k = basicSerialize(k) local fname = string.format("%s[%s]", name, k) field = string.format("[%s]", k) -- three spaces between levels addtocart(v, fname, indent .. " ", saved, field) end cart = cart .. indent .. "};\n" end end end end name = name or "__unnamed__" if type(t) ~= "table" then return name .. " = " .. basicSerialize(t) end cart, autoref = "", "" addtocart(t, name, indent) return cart .. autoref end function table.keys(t) local ret = {} for k, v in pairs(t) do ret[#ret+1] = k end return ret end function pp(t) print(table.show(t)) end -- Sandboxed package loader package = { loadlib = function(libname, funcname) error("no native linking") end; seeall = function(module) return setmetatable(module, { __index = _G }) end; loaded = { table = table; string = string; math = math; table = table; coroutine = coroutine; debug = debug; struct = struct; util = util; sys = sys; gl = gl; resource = resource; }; loaders = { function(modname) local filename = modname .. ".lua" local status, content = pcall(resource.load_file, filename) if not status then return "no file " .. filename .. ": " .. content else return function(loader_modname) assert(loader_modname == modname) local filename = PATH .. "/" .. modname .. ".lua" return assert(loadstring(content, "=" .. filename))(modname) end, filename end end; -- bundled moduls loader function(modname) local filename = modname .. ".lua" local content = _BUNDLED_MODULES[filename] if not content then return "no file " .. filename else return function(loader_modname) print("loading bundled module '" .. loader_modname .. "'") assert(loader_modname == modname) return assert(loadstring(content, "=" .. filename))(modname) end, filename end end }; } package.loaded['package'] = package function require(modname) local loaded = package.loaded[modname] if loaded then return loaded end -- find loader local loader local errors = {"module '" .. modname .. "' not found:"} for _, searcher in ipairs(package.loaders) do local searcher_val = searcher(modname) if type(searcher_val) == "function" then loader = searcher_val break elseif type(searcher_val) == "string" then errors[#errors + 1] = "\t" .. searcher_val end end if not loader then error(table.concat(errors, "\n")) end -- load module local value = loader(modname) if value then package.loaded[modname] = value elseif not package.loaded[modname] then package.loaded[modname] = true end return package.loaded[modname] end function hosted_init() local json = require "json" local hosted = nil local config_json = nil local node_json = nil local reload_config = function() print "[hosted] reloading config" -- pp(hosted) -- pp(node_json) -- pp(config_json) if hosted and node_json and config_json then local parsed = hosted.parse_config(node_json.options, config_json) _G['CONFIG'] = parsed node.dispatch("config_update", parsed) end end util.file_watch("hosted.lua", function(content) print "[hosted] loading hosted.lua" local filename = PATH .. "/hosted.lua" hosted = assert(loadstring(content, "=" .. filename))() reload_config() end) util.file_watch("node.json", function(content) print("[hosted] loading node.json") node_json = json.decode(content) _G['NODE'] = node_json reload_config() node.dispatch("node_update", node_json) end) util.file_watch("config.json", function(content) print("[hosted] loading config.json") config_json = json.decode(content) reload_config() end) util.file_watch("package.json", function(content) print("[hosted] loading package.json") local package_json = json.decode(content) _G['PACKAGE'] = package_json node.dispatch("package_update", package_json) end) end do local function red(str) return "" .. str .. "" end local function green(str) return "" .. str .. "" end local function yellow(str) return "" .. str .. "" end local handlers = { ["boolean"] = function(cmd, info, target) local function setup() target[cmd] = info.value end local function info() return string.format("(%s)", tostring(target[cmd])) end local function call(arg) local value = ({ ["true"] = true; ["1"] = true; ["y"] = true; ["false"] = false; ["0"] = false; ["n"] = false; })[arg] if value == nil then print(red("invalid value: true/false expected")) else target[cmd] = value print(green("value updated")) end end return { setup = setup; param = ""; info = info; call = call; } end; ["string"] = function(cmd, info, target) local function setup() target[cmd] = info.value end local function info() return string.format("(\"%s\")", target[cmd]) end local function call(arg) target[cmd] = arg print(green("value updated")) end return { setup = setup; param = "<\"new value\">"; info = info; call = call; } end; ["number"] = function(cmd, info, target) local function setup() target[cmd] = info.value end local function info() return string.format("(%f)", target[cmd]) end local function call(arg) local value = tonumber(arg) if value == nil then print(red("invalid value: number expected")) else target[cmd] = value print(green("value updated")) end end return { setup = setup; param = ""; info = info; call = call; } end; ["function"] = function(cmd, info, target) local function call(arg) return info.value(target, readln, arg) end return { setup = function() end; param = ""; info = function() return "" end; call = call; } end; } local function create_menu_interface(name, target, options, readln) if not target then target = _G end for cmd, info in pairs(options) do local type = info.type or type(info.value) info.handler = handlers[type](cmd, info, target) info.handler.setup() end local function print_help() local max_size = 0 local cmds = {} for cmd, info in pairs(options) do max_size = math.max(max_size, #cmd + 1 + #info.handler.param) cmds[#cmds+1] = cmd end table.sort(cmds) print() print(green("Available commands/values:")) for idx, cmd in ipairs(cmds) do local info = options[cmd] print(string.format("%-" .. tostring(max_size) .. "s - %s %s", cmd .. " " .. info.handler.param, info.help, info.handler.info())) end print() end return function() while true do print() print(yellow(name .. " - your command")) local line = readln() if line == "?" or line == "help" then print_help() elseif line == "" or line == "exit" then break else local cmd, arg = string.match(line, "^([^%s]+) (.*)$") if not cmd then cmd = line end local option = options[cmd] if option then option.handler.call(arg) else print(red("invalid command line \"" .. line .. "\". type '?' for help")) end end end end end local function create_submenu(name, options) return { value = function(target, readln) return create_menu_interface(name, target, options, readln)() end; help = name; } end local function create_variable(value, help) return { value = value; help = help; } end local function tcp_export(options, target) local main_menu = create_menu_interface("main menu", target, options, function() return coroutine.yield() end) if not N.clients then N.clients = {} end node.event("connect", function(client) local handler = coroutine.wrap(function() print(green("configuration interface for " .. PATH)) print(green("-----------------------------------------")) while true do main_menu() end end) N.clients[client] = handler handler() end) node.event("input", function(line, client) N.clients[client](line) end) node.event("disconnect", function(client) N.clients[client] = nil end) end util.menu = { tcp = tcp_export; sub = create_submenu; var = create_variable; } end info-beamer-1.0~pre4/uthash.h0000644000175000017500000016257112452774240014021 0ustar nknk/* Copyright (c) 2003-2011, Troy D. Hanson http://uthash.sourceforge.net All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UTHASH_H #define UTHASH_H #include /* memcmp,strlen */ #include /* ptrdiff_t */ #include /* exit() */ /* These macros use decltype or the earlier __typeof GNU extension. As decltype is only available in newer compilers (VS2010 or gcc 4.3+ when compiling c++ source) this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ #ifdef _MSC_VER /* MS compiler */ #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ #define DECLTYPE(x) (decltype(x)) #else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE #define DECLTYPE(x) #endif #else /* GNU, Sun and other compilers */ #define DECLTYPE(x) (__typeof(x)) #endif #ifdef NO_DECLTYPE #define DECLTYPE_ASSIGN(dst,src) \ do { \ char **_da_dst = (char**)(&(dst)); \ *_da_dst = (char*)(src); \ } while(0) #else #define DECLTYPE_ASSIGN(dst,src) \ do { \ (dst) = DECLTYPE(dst)(src); \ } while(0) #endif /* a number of the hash function use uint32_t which isn't defined on win32 */ #ifdef _MSC_VER typedef unsigned int uint32_t; typedef unsigned char uint8_t; #else #include /* uint32_t */ #endif #define UTHASH_VERSION 1.9.4 #define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */ #define uthash_malloc(sz) malloc(sz) /* malloc fcn */ #define uthash_free(ptr,sz) free(ptr) /* free fcn */ #define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */ #define uthash_expand_fyi(tbl) /* can be defined to log expands */ /* initial number of buckets */ #define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */ #define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */ #define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */ /* calculate the element whose hash handle address is hhe */ #define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho))) #define HASH_FIND(hh,head,keyptr,keylen,out) \ do { \ unsigned _hf_bkt,_hf_hashv; \ out=NULL; \ if (head) { \ HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \ if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \ HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \ keyptr,keylen,out); \ } \ } \ } while (0) #ifdef HASH_BLOOM #define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM) #define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0) #define HASH_BLOOM_MAKE(tbl) \ do { \ (tbl)->bloom_nbits = HASH_BLOOM; \ (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \ if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \ memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \ (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ } while (0); #define HASH_BLOOM_FREE(tbl) \ do { \ uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ } while (0); #define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8))) #define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8))) #define HASH_BLOOM_ADD(tbl,hashv) \ HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) #define HASH_BLOOM_TEST(tbl,hashv) \ HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1))) #else #define HASH_BLOOM_MAKE(tbl) #define HASH_BLOOM_FREE(tbl) #define HASH_BLOOM_ADD(tbl,hashv) #define HASH_BLOOM_TEST(tbl,hashv) (1) #endif #define HASH_MAKE_TABLE(hh,head) \ do { \ (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \ sizeof(UT_hash_table)); \ if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \ memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \ (head)->hh.tbl->tail = &((head)->hh); \ (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \ (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \ memset((head)->hh.tbl->buckets, 0, \ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \ HASH_BLOOM_MAKE((head)->hh.tbl); \ (head)->hh.tbl->signature = HASH_SIGNATURE; \ } while(0) #define HASH_ADD(hh,head,fieldname,keylen_in,add) \ HASH_ADD_KEYPTR(hh,head,&((add)->fieldname),keylen_in,add) #define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \ do { \ unsigned _ha_bkt; \ (add)->hh.next = NULL; \ (add)->hh.key = (char*)keyptr; \ (add)->hh.keylen = keylen_in; \ if (!(head)) { \ head = (add); \ (head)->hh.prev = NULL; \ HASH_MAKE_TABLE(hh,head); \ } else { \ (head)->hh.tbl->tail->next = (add); \ (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ (head)->hh.tbl->tail = &((add)->hh); \ } \ (head)->hh.tbl->num_items++; \ (add)->hh.tbl = (head)->hh.tbl; \ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \ (add)->hh.hashv, _ha_bkt); \ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \ HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \ HASH_FSCK(hh,head); \ } while(0) #define HASH_TO_BKT( hashv, num_bkts, bkt ) \ do { \ bkt = ((hashv) & ((num_bkts) - 1)); \ } while(0) /* delete "delptr" from the hash table. * "the usual" patch-up process for the app-order doubly-linked-list. * The use of _hd_hh_del below deserves special explanation. * These used to be expressed using (delptr) but that led to a bug * if someone used the same symbol for the head and deletee, like * HASH_DELETE(hh,users,users); * We want that to work, but by changing the head (users) below * we were forfeiting our ability to further refer to the deletee (users) * in the patch-up process. Solution: use scratch space to * copy the deletee pointer, then the latter references are via that * scratch pointer rather than through the repointed (users) symbol. */ #define HASH_DELETE(hh,head,delptr) \ do { \ unsigned _hd_bkt; \ struct UT_hash_handle *_hd_hh_del; \ if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \ uthash_free((head)->hh.tbl->buckets, \ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ HASH_BLOOM_FREE((head)->hh.tbl); \ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ head = NULL; \ } else { \ _hd_hh_del = &((delptr)->hh); \ if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \ (head)->hh.tbl->tail = \ (UT_hash_handle*)((char*)((delptr)->hh.prev) + \ (head)->hh.tbl->hho); \ } \ if ((delptr)->hh.prev) { \ ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \ (head)->hh.tbl->hho))->next = (delptr)->hh.next; \ } else { \ DECLTYPE_ASSIGN(head,(delptr)->hh.next); \ } \ if (_hd_hh_del->next) { \ ((UT_hash_handle*)((char*)_hd_hh_del->next + \ (head)->hh.tbl->hho))->prev = \ _hd_hh_del->prev; \ } \ HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ (head)->hh.tbl->num_items--; \ } \ HASH_FSCK(hh,head); \ } while (0) /* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ #define HASH_FIND_STR(head,findstr,out) \ HASH_FIND(hh,head,findstr,strlen(findstr),out) #define HASH_ADD_STR(head,strfield,add) \ HASH_ADD(hh,head,strfield,strlen(add->strfield),add) #define HASH_FIND_INT(head,findint,out) \ HASH_FIND(hh,head,findint,sizeof(int),out) #define HASH_ADD_INT(head,intfield,add) \ HASH_ADD(hh,head,intfield,sizeof(int),add) #define HASH_FIND_PTR(head,findptr,out) \ HASH_FIND(hh,head,findptr,sizeof(void *),out) #define HASH_ADD_PTR(head,ptrfield,add) \ HASH_ADD(hh,head,ptrfield,sizeof(void *),add) #define HASH_DEL(head,delptr) \ HASH_DELETE(hh,head,delptr) /* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined. * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined. */ #ifdef HASH_DEBUG #define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0) #define HASH_FSCK(hh,head) \ do { \ unsigned _bkt_i; \ unsigned _count, _bkt_count; \ char *_prev; \ struct UT_hash_handle *_thh; \ if (head) { \ _count = 0; \ for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \ _bkt_count = 0; \ _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ _prev = NULL; \ while (_thh) { \ if (_prev != (char*)(_thh->hh_prev)) { \ HASH_OOPS("invalid hh_prev %p, actual %p\n", \ _thh->hh_prev, _prev ); \ } \ _bkt_count++; \ _prev = (char*)(_thh); \ _thh = _thh->hh_next; \ } \ _count += _bkt_count; \ if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ HASH_OOPS("invalid bucket count %d, actual %d\n", \ (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ } \ } \ if (_count != (head)->hh.tbl->num_items) { \ HASH_OOPS("invalid hh item count %d, actual %d\n", \ (head)->hh.tbl->num_items, _count ); \ } \ /* traverse hh in app order; check next/prev integrity, count */ \ _count = 0; \ _prev = NULL; \ _thh = &(head)->hh; \ while (_thh) { \ _count++; \ if (_prev !=(char*)(_thh->prev)) { \ HASH_OOPS("invalid prev %p, actual %p\n", \ _thh->prev, _prev ); \ } \ _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \ _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \ (head)->hh.tbl->hho) : NULL ); \ } \ if (_count != (head)->hh.tbl->num_items) { \ HASH_OOPS("invalid app item count %d, actual %d\n", \ (head)->hh.tbl->num_items, _count ); \ } \ } \ } while (0) #else #define HASH_FSCK(hh,head) #endif /* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to * the descriptor to which this macro is defined for tuning the hash function. * The app can #include to get the prototype for write(2). */ #ifdef HASH_EMIT_KEYS #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \ do { \ unsigned _klen = fieldlen; \ write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ write(HASH_EMIT_KEYS, keyptr, fieldlen); \ } while (0) #else #define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) #endif /* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */ #ifdef HASH_FUNCTION #define HASH_FCN HASH_FUNCTION #else #define HASH_FCN HASH_JEN #endif /* The Bernstein hash function, used in Perl prior to v5.6 */ #define HASH_BER(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _hb_keylen=keylen; \ char *_hb_key=(char*)(key); \ (hashv) = 0; \ while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \ bkt = (hashv) & (num_bkts-1); \ } while (0) /* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */ #define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _sx_i; \ char *_hs_key=(char*)(key); \ hashv = 0; \ for(_sx_i=0; _sx_i < keylen; _sx_i++) \ hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ bkt = hashv & (num_bkts-1); \ } while (0) #define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _fn_i; \ char *_hf_key=(char*)(key); \ hashv = 2166136261UL; \ for(_fn_i=0; _fn_i < keylen; _fn_i++) \ hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \ bkt = hashv & (num_bkts-1); \ } while(0); #define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _ho_i; \ char *_ho_key=(char*)(key); \ hashv = 0; \ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \ hashv += _ho_key[_ho_i]; \ hashv += (hashv << 10); \ hashv ^= (hashv >> 6); \ } \ hashv += (hashv << 3); \ hashv ^= (hashv >> 11); \ hashv += (hashv << 15); \ bkt = hashv & (num_bkts-1); \ } while(0) #define HASH_JEN_MIX(a,b,c) \ do { \ a -= b; a -= c; a ^= ( c >> 13 ); \ b -= c; b -= a; b ^= ( a << 8 ); \ c -= a; c -= b; c ^= ( b >> 13 ); \ a -= b; a -= c; a ^= ( c >> 12 ); \ b -= c; b -= a; b ^= ( a << 16 ); \ c -= a; c -= b; c ^= ( b >> 5 ); \ a -= b; a -= c; a ^= ( c >> 3 ); \ b -= c; b -= a; b ^= ( a << 10 ); \ c -= a; c -= b; c ^= ( b >> 15 ); \ } while (0) #define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \ do { \ unsigned _hj_i,_hj_j,_hj_k; \ char *_hj_key=(char*)(key); \ hashv = 0xfeedbeef; \ _hj_i = _hj_j = 0x9e3779b9; \ _hj_k = keylen; \ while (_hj_k >= 12) { \ _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \ + ( (unsigned)_hj_key[2] << 16 ) \ + ( (unsigned)_hj_key[3] << 24 ) ); \ _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \ + ( (unsigned)_hj_key[6] << 16 ) \ + ( (unsigned)_hj_key[7] << 24 ) ); \ hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \ + ( (unsigned)_hj_key[10] << 16 ) \ + ( (unsigned)_hj_key[11] << 24 ) ); \ \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ \ _hj_key += 12; \ _hj_k -= 12; \ } \ hashv += keylen; \ switch ( _hj_k ) { \ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ case 5: _hj_j += _hj_key[4]; \ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ case 1: _hj_i += _hj_key[0]; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ bkt = hashv & (num_bkts-1); \ } while(0) /* The Paul Hsieh hash function */ #undef get16bits #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__) #define get16bits(d) (*((const uint16_t *) (d))) #endif #if !defined (get16bits) #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \ +(uint32_t)(((const uint8_t *)(d))[0]) ) #endif #define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \ do { \ char *_sfh_key=(char*)(key); \ uint32_t _sfh_tmp, _sfh_len = keylen; \ \ int _sfh_rem = _sfh_len & 3; \ _sfh_len >>= 2; \ hashv = 0xcafebabe; \ \ /* Main loop */ \ for (;_sfh_len > 0; _sfh_len--) { \ hashv += get16bits (_sfh_key); \ _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \ hashv = (hashv << 16) ^ _sfh_tmp; \ _sfh_key += 2*sizeof (uint16_t); \ hashv += hashv >> 11; \ } \ \ /* Handle end cases */ \ switch (_sfh_rem) { \ case 3: hashv += get16bits (_sfh_key); \ hashv ^= hashv << 16; \ hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \ hashv += hashv >> 11; \ break; \ case 2: hashv += get16bits (_sfh_key); \ hashv ^= hashv << 11; \ hashv += hashv >> 17; \ break; \ case 1: hashv += *_sfh_key; \ hashv ^= hashv << 10; \ hashv += hashv >> 1; \ } \ \ /* Force "avalanching" of final 127 bits */ \ hashv ^= hashv << 3; \ hashv += hashv >> 5; \ hashv ^= hashv << 4; \ hashv += hashv >> 17; \ hashv ^= hashv << 25; \ hashv += hashv >> 6; \ bkt = hashv & (num_bkts-1); \ } while(0); #ifdef HASH_USING_NO_STRICT_ALIASING /* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads. * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error. * MurmurHash uses the faster approach only on CPU's where we know it's safe. * * Note the preprocessor built-in defines can be emitted using: * * gcc -m64 -dM -E - < /dev/null (on gcc) * cc -## a.c (where a.c is a simple test file) (Sun Studio) */ #if (defined(__i386__) || defined(__x86_64__)) #define MUR_GETBLOCK(p,i) p[i] #else /* non intel */ #define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0) #define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1) #define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2) #define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3) #define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL)) #if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__)) #define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24)) #define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16)) #define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8)) #else /* assume little endian non-intel */ #define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24)) #define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16)) #define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8)) #endif #define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \ (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \ (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \ MUR_ONE_THREE(p)))) #endif #define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r)))) #define MUR_FMIX(_h) \ do { \ _h ^= _h >> 16; \ _h *= 0x85ebca6b; \ _h ^= _h >> 13; \ _h *= 0xc2b2ae35l; \ _h ^= _h >> 16; \ } while(0) #define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \ do { \ const uint8_t *_mur_data = (const uint8_t*)(key); \ const int _mur_nblocks = (keylen) / 4; \ uint32_t _mur_h1 = 0xf88D5353; \ uint32_t _mur_c1 = 0xcc9e2d51; \ uint32_t _mur_c2 = 0x1b873593; \ const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \ int _mur_i; \ for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \ uint32_t _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \ _mur_k1 *= _mur_c1; \ _mur_k1 = MUR_ROTL32(_mur_k1,15); \ _mur_k1 *= _mur_c2; \ \ _mur_h1 ^= _mur_k1; \ _mur_h1 = MUR_ROTL32(_mur_h1,13); \ _mur_h1 = _mur_h1*5+0xe6546b64; \ } \ const uint8_t *_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \ uint32_t _mur_k1=0; \ switch((keylen) & 3) { \ case 3: _mur_k1 ^= _mur_tail[2] << 16; \ case 2: _mur_k1 ^= _mur_tail[1] << 8; \ case 1: _mur_k1 ^= _mur_tail[0]; \ _mur_k1 *= _mur_c1; \ _mur_k1 = MUR_ROTL32(_mur_k1,15); \ _mur_k1 *= _mur_c2; \ _mur_h1 ^= _mur_k1; \ } \ _mur_h1 ^= (keylen); \ MUR_FMIX(_mur_h1); \ hashv = _mur_h1; \ bkt = hashv & (num_bkts-1); \ } while(0) #endif /* HASH_USING_NO_STRICT_ALIASING */ /* key comparison function; return 0 if keys equal */ #define HASH_KEYCMP(a,b,len) memcmp(a,b,len) /* iterate over items in a known bucket to find desired item */ #define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \ do { \ if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \ else out=NULL; \ while (out) { \ if (out->hh.keylen == keylen_in) { \ if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \ } \ if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \ else out = NULL; \ } \ } while(0) /* add an item to a bucket */ #define HASH_ADD_TO_BKT(head,addhh) \ do { \ head.count++; \ (addhh)->hh_next = head.hh_head; \ (addhh)->hh_prev = NULL; \ if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \ (head).hh_head=addhh; \ if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \ && (addhh)->tbl->noexpand != 1) { \ HASH_EXPAND_BUCKETS((addhh)->tbl); \ } \ } while(0) /* remove an item from a given bucket */ #define HASH_DEL_IN_BKT(hh,head,hh_del) \ (head).count--; \ if ((head).hh_head == hh_del) { \ (head).hh_head = hh_del->hh_next; \ } \ if (hh_del->hh_prev) { \ hh_del->hh_prev->hh_next = hh_del->hh_next; \ } \ if (hh_del->hh_next) { \ hh_del->hh_next->hh_prev = hh_del->hh_prev; \ } /* Bucket expansion has the effect of doubling the number of buckets * and redistributing the items into the new buckets. Ideally the * items will distribute more or less evenly into the new buckets * (the extent to which this is true is a measure of the quality of * the hash function as it applies to the key domain). * * With the items distributed into more buckets, the chain length * (item count) in each bucket is reduced. Thus by expanding buckets * the hash keeps a bound on the chain length. This bounded chain * length is the essence of how a hash provides constant time lookup. * * The calculation of tbl->ideal_chain_maxlen below deserves some * explanation. First, keep in mind that we're calculating the ideal * maximum chain length based on the *new* (doubled) bucket count. * In fractions this is just n/b (n=number of items,b=new num buckets). * Since the ideal chain length is an integer, we want to calculate * ceil(n/b). We don't depend on floating point arithmetic in this * hash, so to calculate ceil(n/b) with integers we could write * * ceil(n/b) = (n/b) + ((n%b)?1:0) * * and in fact a previous version of this hash did just that. * But now we have improved things a bit by recognizing that b is * always a power of two. We keep its base 2 log handy (call it lb), * so now we can write this with a bit shift and logical AND: * * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) * */ #define HASH_EXPAND_BUCKETS(tbl) \ do { \ unsigned _he_bkt; \ unsigned _he_bkt_i; \ struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \ 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \ memset(_he_new_buckets, 0, \ 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ tbl->ideal_chain_maxlen = \ (tbl->num_items >> (tbl->log2_num_buckets+1)) + \ ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \ tbl->nonideal_items = 0; \ for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \ { \ _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \ while (_he_thh) { \ _he_hh_nxt = _he_thh->hh_next; \ HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \ _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \ if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \ tbl->nonideal_items++; \ _he_newbkt->expand_mult = _he_newbkt->count / \ tbl->ideal_chain_maxlen; \ } \ _he_thh->hh_prev = NULL; \ _he_thh->hh_next = _he_newbkt->hh_head; \ if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \ _he_thh; \ _he_newbkt->hh_head = _he_thh; \ _he_thh = _he_hh_nxt; \ } \ } \ uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \ tbl->num_buckets *= 2; \ tbl->log2_num_buckets++; \ tbl->buckets = _he_new_buckets; \ tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \ (tbl->ineff_expands+1) : 0; \ if (tbl->ineff_expands > 1) { \ tbl->noexpand=1; \ uthash_noexpand_fyi(tbl); \ } \ uthash_expand_fyi(tbl); \ } while(0) /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ /* Note that HASH_SORT assumes the hash handle name to be hh. * HASH_SRT was added to allow the hash handle name to be passed in. */ #define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn) #define HASH_SRT(hh,head,cmpfcn) \ do { \ unsigned _hs_i; \ unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \ struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ if (head) { \ _hs_insize = 1; \ _hs_looping = 1; \ _hs_list = &((head)->hh); \ while (_hs_looping) { \ _hs_p = _hs_list; \ _hs_list = NULL; \ _hs_tail = NULL; \ _hs_nmerges = 0; \ while (_hs_p) { \ _hs_nmerges++; \ _hs_q = _hs_p; \ _hs_psize = 0; \ for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \ _hs_psize++; \ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ ((void*)((char*)(_hs_q->next) + \ (head)->hh.tbl->hho)) : NULL); \ if (! (_hs_q) ) break; \ } \ _hs_qsize = _hs_insize; \ while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \ if (_hs_psize == 0) { \ _hs_e = _hs_q; \ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ ((void*)((char*)(_hs_q->next) + \ (head)->hh.tbl->hho)) : NULL); \ _hs_qsize--; \ } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \ _hs_e = _hs_p; \ _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ ((void*)((char*)(_hs_p->next) + \ (head)->hh.tbl->hho)) : NULL); \ _hs_psize--; \ } else if (( \ cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \ ) <= 0) { \ _hs_e = _hs_p; \ _hs_p = (UT_hash_handle*)((_hs_p->next) ? \ ((void*)((char*)(_hs_p->next) + \ (head)->hh.tbl->hho)) : NULL); \ _hs_psize--; \ } else { \ _hs_e = _hs_q; \ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \ ((void*)((char*)(_hs_q->next) + \ (head)->hh.tbl->hho)) : NULL); \ _hs_qsize--; \ } \ if ( _hs_tail ) { \ _hs_tail->next = ((_hs_e) ? \ ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \ } else { \ _hs_list = _hs_e; \ } \ _hs_e->prev = ((_hs_tail) ? \ ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \ _hs_tail = _hs_e; \ } \ _hs_p = _hs_q; \ } \ _hs_tail->next = NULL; \ if ( _hs_nmerges <= 1 ) { \ _hs_looping=0; \ (head)->hh.tbl->tail = _hs_tail; \ DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ } \ _hs_insize *= 2; \ } \ HASH_FSCK(hh,head); \ } \ } while (0) /* This function selects items from one hash into another hash. * The end result is that the selected items have dual presence * in both hashes. There is no copy of the items made; rather * they are added into the new hash through a secondary hash * hash handle that must be present in the structure. */ #define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ do { \ unsigned _src_bkt, _dst_bkt; \ void *_last_elt=NULL, *_elt; \ UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \ ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \ if (src) { \ for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ _src_hh; \ _src_hh = _src_hh->hh_next) { \ _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ if (cond(_elt)) { \ _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \ _dst_hh->key = _src_hh->key; \ _dst_hh->keylen = _src_hh->keylen; \ _dst_hh->hashv = _src_hh->hashv; \ _dst_hh->prev = _last_elt; \ _dst_hh->next = NULL; \ if (_last_elt_hh) { _last_elt_hh->next = _elt; } \ if (!dst) { \ DECLTYPE_ASSIGN(dst,_elt); \ HASH_MAKE_TABLE(hh_dst,dst); \ } else { \ _dst_hh->tbl = (dst)->hh_dst.tbl; \ } \ HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \ (dst)->hh_dst.tbl->num_items++; \ _last_elt = _elt; \ _last_elt_hh = _dst_hh; \ } \ } \ } \ } \ HASH_FSCK(hh_dst,dst); \ } while (0) #define HASH_CLEAR(hh,head) \ do { \ if (head) { \ uthash_free((head)->hh.tbl->buckets, \ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \ HASH_BLOOM_FREE((head)->hh.tbl); \ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ (head)=NULL; \ } \ } while(0) #ifdef NO_DECLTYPE #define HASH_ITER(hh,head,el,tmp) \ for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \ el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL)) #else #define HASH_ITER(hh,head,el,tmp) \ for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \ el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL)) #endif /* obtain a count of items in the hash */ #define HASH_COUNT(head) HASH_CNT(hh,head) #define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0) typedef struct UT_hash_bucket { struct UT_hash_handle *hh_head; unsigned count; /* expand_mult is normally set to 0. In this situation, the max chain length * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If * the bucket's chain exceeds this length, bucket expansion is triggered). * However, setting expand_mult to a non-zero value delays bucket expansion * (that would be triggered by additions to this particular bucket) * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH. * (The multiplier is simply expand_mult+1). The whole idea of this * multiplier is to reduce bucket expansions, since they are expensive, in * situations where we know that a particular bucket tends to be overused. * It is better to let its chain length grow to a longer yet-still-bounded * value, than to do an O(n) bucket expansion too often. */ unsigned expand_mult; } UT_hash_bucket; /* random signature used only to find hash tables in external analysis */ #define HASH_SIGNATURE 0xa0111fe1 #define HASH_BLOOM_SIGNATURE 0xb12220f2 typedef struct UT_hash_table { UT_hash_bucket *buckets; unsigned num_buckets, log2_num_buckets; unsigned num_items; struct UT_hash_handle *tail; /* tail hh in app order, for fast append */ ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */ /* in an ideal situation (all buckets used equally), no bucket would have * more than ceil(#items/#buckets) items. that's the ideal chain length. */ unsigned ideal_chain_maxlen; /* nonideal_items is the number of items in the hash whose chain position * exceeds the ideal chain maxlen. these items pay the penalty for an uneven * hash distribution; reaching them in a chain traversal takes >ideal steps */ unsigned nonideal_items; /* ineffective expands occur when a bucket doubling was performed, but * afterward, more than half the items in the hash had nonideal chain * positions. If this happens on two consecutive expansions we inhibit any * further expansion, as it's not helping; this happens when the hash * function isn't a good fit for the key domain. When expansion is inhibited * the hash will still work, albeit no longer in constant time. */ unsigned ineff_expands, noexpand; uint32_t signature; /* used only to find hash tables in external analysis */ #ifdef HASH_BLOOM uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ uint8_t *bloom_bv; char bloom_nbits; #endif } UT_hash_table; typedef struct UT_hash_handle { struct UT_hash_table *tbl; void *prev; /* prev element in app order */ void *next; /* next element in app order */ struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ struct UT_hash_handle *hh_next; /* next hh in bucket order */ void *key; /* ptr to enclosing struct's key */ unsigned keylen; /* enclosing struct's key len */ unsigned hashv; /* result of hash-fcn(key) */ } UT_hash_handle; #endif /* UTHASH_H */ info-beamer-1.0~pre4/utlist.h0000644000175000017500000011502612452774240014042 0ustar nknk/* Copyright (c) 2007-2011, Troy D. Hanson http://uthash.sourceforge.net All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UTLIST_H #define UTLIST_H #define UTLIST_VERSION 1.9.4 #include /* * This file contains macros to manipulate singly and doubly-linked lists. * * 1. LL_ macros: singly-linked lists. * 2. DL_ macros: doubly-linked lists. * 3. CDL_ macros: circular doubly-linked lists. * * To use singly-linked lists, your structure must have a "next" pointer. * To use doubly-linked lists, your structure must "prev" and "next" pointers. * Either way, the pointer to the head of the list must be initialized to NULL. * * ----------------.EXAMPLE ------------------------- * struct item { * int id; * struct item *prev, *next; * } * * struct item *list = NULL: * * int main() { * struct item *item; * ... allocate and populate item ... * DL_APPEND(list, item); * } * -------------------------------------------------- * * For doubly-linked lists, the append and delete macros are O(1) * For singly-linked lists, append and delete are O(n) but prepend is O(1) * The sort macro is O(n log(n)) for all types of single/double/circular lists. */ /* These macros use decltype or the earlier __typeof GNU extension. As decltype is only available in newer compilers (VS2010 or gcc 4.3+ when compiling c++ code), this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ #ifdef _MSC_VER /* MS compiler */ #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ #define LDECLTYPE(x) decltype(x) #else /* VS2008 or older (or VS2010 in C mode) */ #define NO_DECLTYPE #define LDECLTYPE(x) char* #endif #else /* GNU, Sun and other compilers */ #define LDECLTYPE(x) __typeof(x) #endif /* for VS2008 we use some workarounds to get around the lack of decltype, * namely, we always reassign our tmp variable to the list head if we need * to dereference its prev/next pointers, and save/restore the real head.*/ #ifdef NO_DECLTYPE #define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); } #define _NEXT(elt,list) ((char*)((list)->next)) #define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); } #define _PREV(elt,list) ((char*)((list)->prev)) #define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); } #define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; } #define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); } #else #define _SV(elt,list) #define _NEXT(elt,list) ((elt)->next) #define _NEXTASGN(elt,list,to) ((elt)->next)=(to) #define _PREV(elt,list) ((elt)->prev) #define _PREVASGN(elt,list,to) ((elt)->prev)=(to) #define _RS(list) #define _CASTASGN(a,b) (a)=(b) #endif /****************************************************************************** * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort * * Unwieldy variable names used here to avoid shadowing passed-in variables. * *****************************************************************************/ #define LL_SORT(list, cmp) \ do { \ LDECLTYPE(list) _ls_p; \ LDECLTYPE(list) _ls_q; \ LDECLTYPE(list) _ls_e; \ LDECLTYPE(list) _ls_tail; \ LDECLTYPE(list) _ls_oldhead; \ LDECLTYPE(list) _tmp; \ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ if (list) { \ _ls_insize = 1; \ _ls_looping = 1; \ while (_ls_looping) { \ _CASTASGN(_ls_p,list); \ _CASTASGN(_ls_oldhead,list); \ list = NULL; \ _ls_tail = NULL; \ _ls_nmerges = 0; \ while (_ls_p) { \ _ls_nmerges++; \ _ls_q = _ls_p; \ _ls_psize = 0; \ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ _ls_psize++; \ _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \ if (!_ls_q) break; \ } \ _ls_qsize = _ls_insize; \ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ if (_ls_psize == 0) { \ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ } else if (_ls_qsize == 0 || !_ls_q) { \ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ } else if (cmp(_ls_p,_ls_q) <= 0) { \ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ } else { \ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ } \ if (_ls_tail) { \ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ } else { \ _CASTASGN(list,_ls_e); \ } \ _ls_tail = _ls_e; \ } \ _ls_p = _ls_q; \ } \ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \ if (_ls_nmerges <= 1) { \ _ls_looping=0; \ } \ _ls_insize *= 2; \ } \ } else _tmp=NULL; /* quiet gcc unused variable warning */ \ } while (0) #define DL_SORT(list, cmp) \ do { \ LDECLTYPE(list) _ls_p; \ LDECLTYPE(list) _ls_q; \ LDECLTYPE(list) _ls_e; \ LDECLTYPE(list) _ls_tail; \ LDECLTYPE(list) _ls_oldhead; \ LDECLTYPE(list) _tmp; \ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ if (list) { \ _ls_insize = 1; \ _ls_looping = 1; \ while (_ls_looping) { \ _CASTASGN(_ls_p,list); \ _CASTASGN(_ls_oldhead,list); \ list = NULL; \ _ls_tail = NULL; \ _ls_nmerges = 0; \ while (_ls_p) { \ _ls_nmerges++; \ _ls_q = _ls_p; \ _ls_psize = 0; \ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ _ls_psize++; \ _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \ if (!_ls_q) break; \ } \ _ls_qsize = _ls_insize; \ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ if (_ls_psize == 0) { \ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ } else if (_ls_qsize == 0 || !_ls_q) { \ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ } else if (cmp(_ls_p,_ls_q) <= 0) { \ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ } else { \ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ } \ if (_ls_tail) { \ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ } else { \ _CASTASGN(list,_ls_e); \ } \ _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \ _ls_tail = _ls_e; \ } \ _ls_p = _ls_q; \ } \ _CASTASGN(list->prev, _ls_tail); \ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \ if (_ls_nmerges <= 1) { \ _ls_looping=0; \ } \ _ls_insize *= 2; \ } \ } else _tmp=NULL; /* quiet gcc unused variable warning */ \ } while (0) #define CDL_SORT(list, cmp) \ do { \ LDECLTYPE(list) _ls_p; \ LDECLTYPE(list) _ls_q; \ LDECLTYPE(list) _ls_e; \ LDECLTYPE(list) _ls_tail; \ LDECLTYPE(list) _ls_oldhead; \ LDECLTYPE(list) _tmp; \ LDECLTYPE(list) _tmp2; \ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \ if (list) { \ _ls_insize = 1; \ _ls_looping = 1; \ while (_ls_looping) { \ _CASTASGN(_ls_p,list); \ _CASTASGN(_ls_oldhead,list); \ list = NULL; \ _ls_tail = NULL; \ _ls_nmerges = 0; \ while (_ls_p) { \ _ls_nmerges++; \ _ls_q = _ls_p; \ _ls_psize = 0; \ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \ _ls_psize++; \ _SV(_ls_q,list); \ if (_NEXT(_ls_q,list) == _ls_oldhead) { \ _ls_q = NULL; \ } else { \ _ls_q = _NEXT(_ls_q,list); \ } \ _RS(list); \ if (!_ls_q) break; \ } \ _ls_qsize = _ls_insize; \ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \ if (_ls_psize == 0) { \ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ } else if (_ls_qsize == 0 || !_ls_q) { \ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ } else if (cmp(_ls_p,_ls_q) <= 0) { \ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \ if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \ } else { \ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \ if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \ } \ if (_ls_tail) { \ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \ } else { \ _CASTASGN(list,_ls_e); \ } \ _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \ _ls_tail = _ls_e; \ } \ _ls_p = _ls_q; \ } \ _CASTASGN(list->prev,_ls_tail); \ _CASTASGN(_tmp2,list); \ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \ if (_ls_nmerges <= 1) { \ _ls_looping=0; \ } \ _ls_insize *= 2; \ } \ } else _tmp=NULL; /* quiet gcc unused variable warning */ \ } while (0) /****************************************************************************** * singly linked list macros (non-circular) * *****************************************************************************/ #define LL_PREPEND(head,add) \ do { \ (add)->next = head; \ head = add; \ } while (0) #define LL_CONCAT(head1,head2) \ do { \ LDECLTYPE(head1) _tmp; \ if (head1) { \ _tmp = head1; \ while (_tmp->next) { _tmp = _tmp->next; } \ _tmp->next=(head2); \ } else { \ (head1)=(head2); \ } \ } while (0) #define LL_APPEND(head,add) \ do { \ LDECLTYPE(head) _tmp; \ (add)->next=NULL; \ if (head) { \ _tmp = head; \ while (_tmp->next) { _tmp = _tmp->next; } \ _tmp->next=(add); \ } else { \ (head)=(add); \ } \ } while (0) #define LL_DELETE(head,del) \ do { \ LDECLTYPE(head) _tmp; \ if ((head) == (del)) { \ (head)=(head)->next; \ } else { \ _tmp = head; \ while (_tmp->next && (_tmp->next != (del))) { \ _tmp = _tmp->next; \ } \ if (_tmp->next) { \ _tmp->next = ((del)->next); \ } \ } \ } while (0) /* Here are VS2008 replacements for LL_APPEND and LL_DELETE */ #define LL_APPEND_VS2008(head,add) \ do { \ if (head) { \ (add)->next = head; /* use add->next as a temp variable */ \ while ((add)->next->next) { (add)->next = (add)->next->next; } \ (add)->next->next=(add); \ } else { \ (head)=(add); \ } \ (add)->next=NULL; \ } while (0) #define LL_DELETE_VS2008(head,del) \ do { \ if ((head) == (del)) { \ (head)=(head)->next; \ } else { \ char *_tmp = (char*)(head); \ while (head->next && (head->next != (del))) { \ head = head->next; \ } \ if (head->next) { \ head->next = ((del)->next); \ } \ { \ char **_head_alias = (char**)&(head); \ *_head_alias = _tmp; \ } \ } \ } while (0) #ifdef NO_DECLTYPE #undef LL_APPEND #define LL_APPEND LL_APPEND_VS2008 #undef LL_DELETE #define LL_DELETE LL_DELETE_VS2008 #undef LL_CONCAT /* no LL_CONCAT_VS2008 */ #undef DL_CONCAT /* no DL_CONCAT_VS2008 */ #endif /* end VS2008 replacements */ #define LL_FOREACH(head,el) \ for(el=head;el;el=el->next) #define LL_FOREACH_SAFE(head,el,tmp) \ for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) #define LL_SEARCH_SCALAR(head,out,field,val) \ do { \ LL_FOREACH(head,out) { \ if ((out)->field == (val)) break; \ } \ } while(0) #define LL_SEARCH(head,out,elt,cmp) \ do { \ LL_FOREACH(head,out) { \ if ((cmp(out,elt))==0) break; \ } \ } while(0) /****************************************************************************** * doubly linked list macros (non-circular) * *****************************************************************************/ #define DL_PREPEND(head,add) \ do { \ (add)->next = head; \ if (head) { \ (add)->prev = (head)->prev; \ (head)->prev = (add); \ } else { \ (add)->prev = (add); \ } \ (head) = (add); \ } while (0) #define DL_APPEND(head,add) \ do { \ if (head) { \ (add)->prev = (head)->prev; \ (head)->prev->next = (add); \ (head)->prev = (add); \ (add)->next = NULL; \ } else { \ (head)=(add); \ (head)->prev = (head); \ (head)->next = NULL; \ } \ } while (0); #define DL_CONCAT(head1,head2) \ do { \ LDECLTYPE(head1) _tmp; \ if (head2) { \ if (head1) { \ _tmp = (head2)->prev; \ (head2)->prev = (head1)->prev; \ (head1)->prev->next = (head2); \ (head1)->prev = _tmp; \ } else { \ (head1)=(head2); \ } \ } \ } while (0); #define DL_DELETE(head,del) \ do { \ assert((del)->prev != NULL); \ if ((del)->prev == (del)) { \ (head)=NULL; \ } else if ((del)==(head)) { \ (del)->next->prev = (del)->prev; \ (head) = (del)->next; \ } else { \ (del)->prev->next = (del)->next; \ if ((del)->next) { \ (del)->next->prev = (del)->prev; \ } else { \ (head)->prev = (del)->prev; \ } \ } \ } while (0); #define DL_FOREACH(head,el) \ for(el=head;el;el=el->next) /* this version is safe for deleting the elements during iteration */ #define DL_FOREACH_SAFE(head,el,tmp) \ for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp) /* these are identical to their singly-linked list counterparts */ #define DL_SEARCH_SCALAR LL_SEARCH_SCALAR #define DL_SEARCH LL_SEARCH /****************************************************************************** * circular doubly linked list macros * *****************************************************************************/ #define CDL_PREPEND(head,add) \ do { \ if (head) { \ (add)->prev = (head)->prev; \ (add)->next = (head); \ (head)->prev = (add); \ (add)->prev->next = (add); \ } else { \ (add)->prev = (add); \ (add)->next = (add); \ } \ (head)=(add); \ } while (0) #define CDL_DELETE(head,del) \ do { \ if ( ((head)==(del)) && ((head)->next == (head))) { \ (head) = 0L; \ } else { \ (del)->next->prev = (del)->prev; \ (del)->prev->next = (del)->next; \ if ((del) == (head)) (head)=(del)->next; \ } \ } while (0); #define CDL_FOREACH(head,el) \ for(el=head;el;el=(el->next==head ? 0L : el->next)) #define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \ for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \ (el) && ((tmp2)=(el)->next, 1); \ ((el) = (((el)==(tmp1)) ? 0L : (tmp2)))) #define CDL_SEARCH_SCALAR(head,out,field,val) \ do { \ CDL_FOREACH(head,out) { \ if ((out)->field == (val)) break; \ } \ } while(0) #define CDL_SEARCH(head,out,elt,cmp) \ do { \ CDL_FOREACH(head,out) { \ if ((cmp(out,elt))==0) break; \ } \ } while(0) #endif /* UTLIST_H */ info-beamer-1.0~pre4/video.c0000644000175000017500000002566012452774240013623 0ustar nknk/* See Copyright Notice in LICENSE.txt */ /* * Includes from code by Michael Meeuwisse * https://docs.google.com/leaf?id=0B_dz2NwhjXB-NDQ0NWNjOWEtMzJiNy00ZjcwLWJjMjYtZTU2YmQzMWMzYmU0 * * License: * * (C) Copyright 2010 Michael Meeuwisse * * Adapted from avcodec_sample.0.5.0.c, license unknown * * ffmpeg_test is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * ffmpeg_test is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with ffmpeg_test. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "misc.h" #include "shader.h" typedef struct { AVFormatContext *format_context; AVCodecContext *codec_context; AVCodec *codec; AVFrame *raw_frame; AVFrame *scaled_frame; uint8_t *buffer; struct SwsContext *scaler; int stream_idx, format; int width, height; int buffer_width, buffer_height; double par; GLuint tex; double fps; int finished; } video_t; LUA_TYPE_DECL(video) /* Helper functions */ static void video_free(video_t *video) { if (video->scaler) sws_freeContext(video->scaler); if (video->raw_frame) av_free(video->raw_frame); if (video->scaled_frame) av_free(video->scaled_frame); if (video->codec_context) avcodec_close(video->codec_context); if (video->format_context) avformat_close_input(&video->format_context); av_free(video->buffer); } static int video_open(video_t *video, const char *filename) { video->finished = 0; video->format = PIX_FMT_RGB24; if (avformat_open_input(&video->format_context, filename, NULL, NULL) || avformat_find_stream_info(video->format_context, NULL) < 0) { fprintf(stderr, ERROR("cannot open video stream %s\n"), filename); goto failed; } video->stream_idx = -1; for (int i = 0; i < video->format_context->nb_streams; i++) { if (video->format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { video->stream_idx = i; break; } } if (video->stream_idx == -1) { fprintf(stderr, ERROR("cannot find video stream\n")); goto failed; } AVStream *stream = video->format_context->streams[video->stream_idx]; video->codec_context = stream->codec; video->codec = avcodec_find_decoder(video->codec_context->codec_id); /* Save Width/Height */ video->width = video->codec_context->width; video->height = video->codec_context->height; if (!video->codec || avcodec_open2(video->codec_context, video->codec, NULL) < 0) { fprintf(stderr, ERROR("cannot open codec\n")); goto failed; } video->buffer_width = video->codec_context->width; video->buffer_height = video->codec_context->height; fprintf(stderr, INFO("pixel aspect ratio: %d/%d, size: %dx%d buffer size: %dx%d\n"), video->codec_context->sample_aspect_ratio.num, video->codec_context->sample_aspect_ratio.den, video->width, video->height, video->buffer_width, video->buffer_height ); video->par = (float)video->codec_context->sample_aspect_ratio.num / video->codec_context->sample_aspect_ratio.den; if (video->par == 0) video->par = 1; /* Frame rate fix for some codecs */ if (video->codec_context->time_base.num > 1000 && video->codec_context->time_base.den == 1) video->codec_context->time_base.den = 1000; /* Get FPS */ // http://libav-users.943685.n4.nabble.com/Retrieving-Frames-Per-Second-FPS-td946533.html if ((stream->time_base.den != stream->avg_frame_rate.num) || (stream->time_base.num != stream->avg_frame_rate.den)) { video->fps = 1.0 / stream->avg_frame_rate.den * stream->avg_frame_rate.num; } else { video->fps = 1.0 / stream->time_base.num * stream->time_base.den; } fprintf(stderr, INFO("fps: %lf\n"), video->fps); /* Get framebuffers */ video->raw_frame = avcodec_alloc_frame(); video->scaled_frame = avcodec_alloc_frame(); if (!video->raw_frame || !video->scaled_frame) { fprintf(stderr, ERROR("cannot preallocate frames\n")); goto failed; } /* Create data buffer */ video->buffer = av_malloc(avpicture_get_size( video->format, video->buffer_width, video->buffer_height )); /* Init buffers */ avpicture_fill( (AVPicture *) video->scaled_frame, video->buffer, video->format, video->buffer_width, video->buffer_height ); /* Init scale & convert */ video->scaler = sws_getContext( video->buffer_width, video->buffer_height, video->codec_context->pix_fmt, video->buffer_width, video->buffer_height, video->format, SWS_BICUBIC, NULL, NULL, NULL ); if (!video->scaler) { fprintf(stderr, ERROR("scale context init failed\n")); goto failed; } /* Give some info on stderr about the file & stream */ av_dump_format(video->format_context, 0, filename, 0); return 1; failed: video_free(video); return 0; } static int video_next_frame(video_t *video) { AVPacket packet; av_init_packet(&packet); again: /* Can we read a frame? */ if (av_read_frame(video->format_context, &packet)) { fprintf(stderr, "no next frame\n"); video->finished = 1; av_free_packet(&packet); return 0; } /* Is it what we're trying to parse? */ if (packet.stream_index != video->stream_idx) { // fprintf(stderr, "not video\n"); av_free_packet(&packet); goto again; } /* Decode it! */ int complete_frame = 0; avcodec_decode_video2(video->codec_context, video->raw_frame, &complete_frame, &packet); /* Success? If not, drop packet. */ if (!complete_frame) { fprintf(stderr, ERROR("incomplete video packet\n")); av_free_packet(&packet); goto again; } /* Flip vertically * XXX: This feels wrong. What's the right way to do this? */ int heights[] = { video->buffer_height - 1, video->buffer_height / 2 - 1, video->buffer_height / 2 - 1, 0, }; for (int i = 0; i < 4; i++) { video->raw_frame->data[i] += video->raw_frame->linesize[i] * heights[i]; video->raw_frame->linesize[i] = -video->raw_frame->linesize[i]; // fprintf(stderr, "%d -> %d\n", video->raw_frame->linesize[i], video->scaled_frame->linesize[i]); } sws_scale( video->scaler, (const uint8_t* const *)video->raw_frame->data, video->raw_frame->linesize, 0, video->buffer_height, video->scaled_frame->data, video->scaled_frame->linesize ); av_free_packet(&packet); return 1; } /* Instance methods */ static int video_size(lua_State *L) { video_t *video = checked_video(L, 1); lua_pushnumber(L, video->width); lua_pushnumber(L, video->height / video->par); return 2; } static int video_fps(lua_State *L) { video_t *video = checked_video(L, 1); lua_pushnumber(L, video->fps); return 1; } static int video_next(lua_State *L) { video_t *video = checked_video(L, 1); if (!video_next_frame(video)) { lua_pushboolean(L, 0); return 1; } glBindTexture(GL_TEXTURE_2D, video->tex); glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE); glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE); glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS, video->buffer_height - video->height); glPixelStorei(GL_UNPACK_ROW_LENGTH, video->buffer_width); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, video->width, video->height, GL_RGB, GL_UNSIGNED_BYTE, video->buffer ); glGenerateMipmap(GL_TEXTURE_2D); glPopClientAttrib(); lua_pushboolean(L, 1); return 1; } static int video_state(lua_State *L) { video_t *video = checked_video(L, 1); lua_pushstring(L, video->finished ? "finished" : "loaded"); lua_pushnumber(L, video->width); lua_pushnumber(L, video->height / video->par); lua_pushnumber(L, video->fps); return 4; } static int video_draw(lua_State *L) { video_t *video = checked_video(L, 1); GLfloat x1 = luaL_checknumber(L, 2); GLfloat y1 = luaL_checknumber(L, 3); GLfloat x2 = luaL_checknumber(L, 4); GLfloat y2 = luaL_checknumber(L, 5); GLfloat alpha = luaL_optnumber(L, 6, 1.0); glBindTexture(GL_TEXTURE_2D, video->tex); shader_set_gl_color(1.0, 1.0, 1.0, alpha); glBegin(GL_QUADS); glTexCoord2f(0.0, 1.0); glVertex3f(x1, y1, 0); glTexCoord2f(1.0, 1.0); glVertex3f(x2, y1, 0); glTexCoord2f(1.0, 0.0); glVertex3f(x2, y2, 0); glTexCoord2f(0.0, 0.0); glVertex3f(x1, y2, 0); glEnd(); return 0; } static int video_texid(lua_State *L) { video_t *video = checked_video(L, 1); lua_pushnumber(L, video->tex); return 1; } static int video_dispose(lua_State *L) { return 0; } static const luaL_reg video_methods[] = { {"state", video_state}, {"draw", video_draw}, {"next", video_next}, {"size", video_size}, {"fps", video_fps}, {"texid", video_texid}, {"dispose", video_dispose}, {0,0} }; /* Lifecycle */ int video_load(lua_State *L, const char *path, const char *name) { video_t video; memset(&video, 0, sizeof(video_t)); if (!video_open(&video, path)) return luaL_error(L, "cannot open video %s", path); glGenTextures(1, &video.tex); glBindTexture(GL_TEXTURE_2D, video.tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, video.width, video.height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL ); *push_video(L) = video; return 1; } static int video_gc(lua_State *L) { video_t *video = to_video(L, 1); fprintf(stderr, INFO("gc'ing video: tex id: %d\n"), video->tex); glDeleteTextures(1, &video->tex); video_free(video); return 0; } LUA_TYPE_IMPL(video) info-beamer-1.0~pre4/video.h0000644000175000017500000000027012452774240013616 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef VIDEO_H #define VIDEO_H int video_register(lua_State *L); int video_load(lua_State *L, const char *path, const char *name); #endif info-beamer-1.0~pre4/vnc.c0000644000175000017500000003316412452774240013301 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #define _BSD_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "misc.h" #include "shader.h" typedef struct vnc_s vnc_t; typedef void(*protocol_handler)(vnc_t *); typedef struct { uint8_t bpp; uint8_t depth; uint8_t bigendian; uint8_t truecolor; uint16_t red_max; uint16_t green_max; uint16_t blue_max; uint8_t red_shift; uint8_t green_shift; uint8_t blue_shift; uint8_t padding[3]; } pixelformat_t; struct vnc_s { GLuint tex; int width; int height; struct bufferevent *buf_ev; char *host; int port; int alive; protocol_handler handler; int num_bytes; pixelformat_t pixelformat; // state for rect update int num_rects; int rect_x; int rect_y; int rect_w; int rect_h; }; LUA_TYPE_DECL(vnc) /* Instance methods */ static int vnc_size(lua_State *L) { vnc_t *vnc = checked_vnc(L, 1); lua_pushnumber(L, vnc->width); lua_pushnumber(L, vnc->height); return 2; } static int vnc_draw(lua_State *L) { vnc_t *vnc = checked_vnc(L, 1); GLfloat x1 = luaL_checknumber(L, 2); GLfloat y1 = luaL_checknumber(L, 3); GLfloat x2 = luaL_checknumber(L, 4); GLfloat y2 = luaL_checknumber(L, 5); GLfloat alpha = luaL_optnumber(L, 6, 1.0); glBindTexture(GL_TEXTURE_2D, vnc->tex); shader_set_gl_color(1.0, 1.0, 1.0, alpha); glBegin(GL_QUADS); glTexCoord2f(0.0, 1.0); glVertex3f(x1, y1, 0); glTexCoord2f(1.0, 1.0); glVertex3f(x2, y1, 0); glTexCoord2f(1.0, 0.0); glVertex3f(x2, y2, 0); glTexCoord2f(0.0, 0.0); glVertex3f(x1, y2, 0); glEnd(); return 0; } static int vnc_alive(lua_State *L) { vnc_t *vnc = checked_vnc(L, 1); lua_pushboolean(L, vnc->alive); return 1; } static int vnc_texid(lua_State *L) { vnc_t *vnc = checked_vnc(L, 1); lua_pushnumber(L, vnc->tex); return 1; } static const luaL_reg vnc_methods[] = { {"draw", vnc_draw}, {"size", vnc_size}, {"alive", vnc_alive}, {"texid", vnc_texid}, {0,0} }; /* Protocol utils */ static void vnc_printf(vnc_t *vnc, const char *fmt, ...) { char buffer[16384]; va_list ap; va_start(ap, fmt); vsnprintf(buffer, sizeof(buffer), fmt, ap); va_end(ap); fprintf(stderr, CYAN("[vnc@%s:%d]")" %s", vnc->host, vnc->port, buffer); } static void vnc_set_handler(vnc_t *vnc, protocol_handler handler, int num_bytes) { vnc->handler = handler; vnc->num_bytes = num_bytes; if (evbuffer_get_length(vnc->buf_ev->input) >= vnc->num_bytes) vnc->handler(vnc); } static void vnc_close(vnc_t *vnc) { if (vnc->buf_ev) { vnc_printf(vnc, "connection closed\n"); bufferevent_free(vnc->buf_ev); vnc->buf_ev = NULL; } if (vnc->tex) { glDeleteTextures(1, &vnc->tex); vnc->tex = 0; } vnc->alive = 0; } static void vnc_read(struct bufferevent *bev, void *arg) { vnc_t *vnc = arg; if (evbuffer_get_length(bev->input) >= vnc->num_bytes) vnc->handler(vnc); } static void vnc_event(struct bufferevent *bev, short events, void *arg) { vnc_t *vnc = arg; if (events & BEV_EVENT_CONNECTED) { vnc_printf(vnc, "connected!\n"); } else if (events & BEV_EVENT_ERROR) { int err = bufferevent_socket_get_dns_error(bev); if (err) { vnc_printf(vnc, "dns error: %s\n", evutil_gai_strerror(err)); } else { vnc_printf(vnc, "connection error!\n"); } return vnc_close(vnc); } else if (events & BEV_EVENT_EOF) { vnc_printf(vnc, "eof!\n"); return vnc_close(vnc); } } static const int endian_test = 1; #define is_bigendian() ((*(char*)&endian_test) == 0) #define swap32(v) ((((v) & 0xff000000) >> 24) | \ (((v) & 0x00ff0000) >> 8) | \ (((v) & 0x0000ff00) << 8) | \ (((v) & 0x000000ff) << 24)) static int vnc_decode(vnc_t *vnc, const unsigned char *pixels) { unsigned char *converted = malloc(vnc->rect_w * vnc->rect_h * 4); assert(vnc->pixelformat.bpp == 32); int row_size = vnc->rect_w * 4; for (int row = 0; row < vnc->rect_h; row++) { uint32_t *src = (uint32_t*)(pixels + row * row_size); uint32_t *dest = (uint32_t*)(converted + (vnc->rect_h - row - 1) * row_size); for (int col = 0; col < vnc->rect_w; col++) { uint32_t raw = *src; if (is_bigendian() ^ vnc->pixelformat.bigendian) { raw = swap32(raw); } uint32_t r = (raw >> vnc->pixelformat.red_shift) & vnc->pixelformat.red_max; uint32_t g = (raw >> vnc->pixelformat.green_shift) & vnc->pixelformat.green_max; uint32_t b = (raw >> vnc->pixelformat.blue_shift) & vnc->pixelformat.blue_max; *dest = 255 << 24 | b << 16 | g << 8 | r; dest++, src++; } } glBindTexture(GL_TEXTURE_2D, vnc->tex); glTexSubImage2D( GL_TEXTURE_2D, 0, vnc->rect_x, vnc->height - vnc->rect_y - vnc->rect_h, vnc->rect_w, vnc->rect_h, GL_RGBA, GL_UNSIGNED_BYTE, converted ); glGenerateMipmap(GL_TEXTURE_2D); free(converted); return 1; } /* Packet definitions */ typedef struct { uint16_t x; uint16_t y; uint16_t w; uint16_t h; uint32_t encoding; } pkt_server_rect; typedef struct { uint8_t msg_type; #define SERVER_MSG_TYPE_FRAMEBUFFER_UPDATE 0 #define SERVER_MSG_TYPE_BELL 2 #define SERVER_MSG_TYPE_CUT_TEXT 3 } pkt_server_base_msg; typedef struct { /* extends pkt_server_base_msg */ uint8_t msg_type; uint8_t padding[1]; uint16_t num_rects; } pkt_server_frameupdate; typedef struct { /* extends pkt_server_base_msg */ uint8_t msg_type; uint8_t padding[3]; uint32_t text_len; } pkt_server_cut_text; typedef struct { uint16_t width; uint16_t height; pixelformat_t pixelformat; uint32_t name_len; } pkt_server_init; typedef struct { uint32_t security_type; #define SERVER_SECURITY_NO_AUTH 1 } pkt_server_auth; typedef struct { uint8_t R; uint8_t F; uint8_t B; uint8_t handshake[9]; } pkt_server_handshake; typedef struct { uint8_t msg_type; #define CLIENT_MSG_TYPE_UPDATE_REQUEST 3 uint8_t incremental; uint16_t x; uint16_t y; uint16_t w; uint16_t h; } pkt_client_update_request; typedef struct { uint8_t shared; } pkt_client_init; /* Protocol */ static void vnc_read_msg_header(vnc_t *vnc); static void vnc_read_rect(vnc_t *vnc); static void vnc_send_update_request(vnc_t *vnc, int x, int y, int w, int h, int incremental); static void vnc_read_cut_text(vnc_t *vnc) { evbuffer_drain(vnc->buf_ev->input, vnc->num_bytes); return vnc_set_handler(vnc, vnc_read_msg_header, sizeof(pkt_server_base_msg)); } static void vnc_read_cut(vnc_t *vnc) { pkt_server_cut_text in_pkt; evbuffer_remove(vnc->buf_ev->input, &in_pkt, sizeof(in_pkt)); uint32_t text_len = ntohl(in_pkt.text_len); if (text_len > 2048) { vnc_printf(vnc, "too large server cut text\n"); return vnc_close(vnc); } return vnc_set_handler(vnc, vnc_read_cut_text, text_len); } static void vnc_read_rect_data(vnc_t *vnc) { unsigned char *pixels = evbuffer_pullup(vnc->buf_ev->input, vnc->num_bytes); if (!vnc_decode(vnc, pixels)) { vnc_printf(vnc, "decoding failed\n"); return vnc_close(vnc); } evbuffer_drain(vnc->buf_ev->input, vnc->num_bytes); if (--vnc->num_rects == 0) { return vnc_send_update_request(vnc, 0, 0, vnc->width, vnc->height, 1); } else { return vnc_set_handler(vnc, vnc_read_rect, sizeof(pkt_server_rect)); } } static void vnc_read_rect(vnc_t *vnc) { pkt_server_rect in_pkt; evbuffer_remove(vnc->buf_ev->input, &in_pkt, sizeof(in_pkt)); vnc->rect_x = ntohs(in_pkt.x); vnc->rect_y = ntohs(in_pkt.y); vnc->rect_w = ntohs(in_pkt.w); vnc->rect_h = ntohs(in_pkt.h); if ((vnc->rect_x + vnc->rect_w > vnc->width) || (vnc->rect_y + vnc->rect_h > vnc->height)) { vnc_printf(vnc, "invalid rect (out of bound)\n"); return vnc_close(vnc); } return vnc_set_handler(vnc, vnc_read_rect_data, vnc->pixelformat.bpp / 8 * vnc->rect_w * vnc->rect_h); } static void vnc_read_rects(vnc_t *vnc) { pkt_server_frameupdate in_pkt; evbuffer_remove(vnc->buf_ev->input, &in_pkt, sizeof(in_pkt)); vnc->num_rects = ntohs(in_pkt.num_rects); if (vnc->num_rects == 0) { vnc_printf(vnc, "zero rect update\n"); return vnc_close(vnc); } return vnc_set_handler(vnc, vnc_read_rect, sizeof(pkt_server_rect)); } static void vnc_read_msg_header(vnc_t *vnc) { // peek into header without removing it pkt_server_base_msg in_pkt = *(pkt_server_base_msg *)evbuffer_pullup( vnc->buf_ev->input, sizeof(pkt_server_base_msg)); if (in_pkt.msg_type == SERVER_MSG_TYPE_FRAMEBUFFER_UPDATE) { return vnc_set_handler(vnc, vnc_read_rects, sizeof(pkt_server_frameupdate)); } else if (in_pkt.msg_type == SERVER_MSG_TYPE_BELL) { // ignore the bell evbuffer_drain(vnc->buf_ev->input, sizeof(in_pkt)); return vnc_set_handler(vnc, vnc_read_msg_header, sizeof(pkt_server_base_msg)); } else if (in_pkt.msg_type == SERVER_MSG_TYPE_CUT_TEXT) { return vnc_set_handler(vnc, vnc_read_cut, sizeof(pkt_server_cut_text)); } else { vnc_printf(vnc, "unexpected msg_type\n"); return vnc_close(vnc); } } static void vnc_send_update_request(vnc_t *vnc, int x, int y, int w, int h, int incremental) { pkt_client_update_request out_pkt = { .msg_type = CLIENT_MSG_TYPE_UPDATE_REQUEST, .incremental = incremental, .x = htons(x), .y = htons(y), .w = htons(w), .h = htons(h), }; bufferevent_write(vnc->buf_ev, &out_pkt, sizeof(out_pkt)); return vnc_set_handler(vnc, vnc_read_msg_header, sizeof(pkt_server_base_msg)); } static void vnc_read_server_name(vnc_t *vnc) { evbuffer_drain(vnc->buf_ev->input, vnc->num_bytes); return vnc_send_update_request(vnc, 0, 0, vnc->width, vnc->height, 0); } static void vnc_read_server_init(vnc_t *vnc) { pkt_server_init in_pkt; evbuffer_remove(vnc->buf_ev->input, &in_pkt, sizeof(in_pkt)); uint32_t name_len = ntohl(in_pkt.name_len); if (name_len > 512) { vnc_printf(vnc, "name too long\n"); return vnc_close(vnc); } if (in_pkt.pixelformat.bpp != 32) { vnc_printf(vnc, "invalid bpp (only 32bit supported)\n"); return vnc_close(vnc); } vnc->width = ntohs(in_pkt.width); vnc->height = ntohs(in_pkt.height); vnc->pixelformat = in_pkt.pixelformat; vnc->pixelformat.red_max = ntohs(vnc->pixelformat.red_max); vnc->pixelformat.green_max = ntohs(vnc->pixelformat.green_max); vnc->pixelformat.blue_max = ntohs(vnc->pixelformat.blue_max); if (vnc->width > 1920 || vnc->height > 1080) { vnc_printf(vnc, "screen too large\n"); return vnc_close(vnc); } glGenTextures(1, &vnc->tex); glBindTexture(GL_TEXTURE_2D, vnc->tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, vnc->width, vnc->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); vnc_printf(vnc, "got screen: %dx%d\n", vnc->width, vnc->height); return vnc_set_handler(vnc, vnc_read_server_name, name_len); } static void vnc_read_server_auth(vnc_t *vnc) { pkt_server_auth in_pkt; evbuffer_remove(vnc->buf_ev->input, &in_pkt, sizeof(in_pkt)); if (ntohl(in_pkt.security_type) != SERVER_SECURITY_NO_AUTH) { vnc_printf(vnc, "unexpected security type\n"); return vnc_close(vnc); } pkt_client_init out_pkt = { .shared = 1 }; bufferevent_write(vnc->buf_ev, &out_pkt, sizeof(out_pkt)); return vnc_set_handler(vnc, vnc_read_server_init, sizeof(pkt_server_init)); } static void vnc_read_handshake(vnc_t *vnc) { pkt_server_handshake in_pkt; evbuffer_remove(vnc->buf_ev->input, &in_pkt, sizeof(in_pkt)); if (in_pkt.R != 'R' || in_pkt.F != 'F' || in_pkt.B != 'B') { vnc_printf(vnc, "unexpected handshake packet\n"); return vnc_close(vnc); } bufferevent_write(vnc->buf_ev, LITERAL_AND_SIZE("RFB 003.003\n")); return vnc_set_handler(vnc, vnc_read_server_auth, sizeof(pkt_server_auth)); } /* Lifecycle */ int vnc_create(lua_State *L, const char *host, int port) { vnc_t *vnc = push_vnc(L); vnc->tex = 0; vnc->width = 0; vnc->height = 0; vnc->buf_ev = NULL; vnc->alive = 1; vnc->host = strdup(host); vnc->port = port; vnc_printf(vnc, "connecting...\n"); vnc->buf_ev = bufferevent_socket_new(event_base, -1, BEV_OPT_CLOSE_ON_FREE); vnc_set_handler(vnc, vnc_read_handshake, sizeof(pkt_server_handshake)); bufferevent_setcb(vnc->buf_ev, vnc_read, NULL, vnc_event, vnc); bufferevent_enable(vnc->buf_ev, EV_READ | EV_WRITE); bufferevent_socket_connect_hostname(vnc->buf_ev, dns_base, AF_UNSPEC, host, port); return 1; } static int vnc_gc(lua_State *L) { vnc_t *vnc = to_vnc(L, 1); vnc_close(vnc); free(vnc->host); return 0; } LUA_TYPE_IMPL(vnc) info-beamer-1.0~pre4/vnc.h0000644000175000017500000000025312452774240013277 0ustar nknk/* See Copyright Notice in LICENSE.txt */ #ifndef VNC_H #define VNC_H int vnc_create(lua_State *L, const char *host, int port); int vnc_register (lua_State *L); #endif