pkpgcounter-3.50/0002755000175000017500000000000010727050450013330 5ustar jeromejeromepkpgcounter-3.50/bin/0002755000175000017500000000000010727050450014100 5ustar jeromejeromepkpgcounter-3.50/bin/pkpgcounter0000755000175000017500000000716010726765264016410 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pkpgcounter 368 2007-12-09 13:16:34Z jerome $ # # import sys from pkpgpdls.version import __version__, __author__, __authoremail__, \ __years__, __gplblurb__ from pkpgpdls import analyzer __doc__ = """pkpgcounter v%(__version__)s (c) %(__years__)s %(__author__)s pkpgcounter is a generic Page Description Language parser. pkpgcounter parses any number of input files and/or its standard input and outputs the number of pages needed to print these documents. pkpgcounter can also compute the percent of ink coverage in different colorspaces for several file formats. pkpgcounter currently recognizes the following document formats : * PostScript (both DSC compliant and binary) * PDF * PCLXL (aka PCL6) * PCL3/4/5 * DVI * OpenDocument (ISO/IEC DIS 26300) * Microsoft Word (c) (tm) (r) (etc...) * Plain text * TIFF * Several other image formats * ESC/P2 * Zenographics ZjStream * Samsung QPDL (aka SPL2) * Samsung SPL1 * ESC/PageS03 * Brother HBP * Hewlett-Packard LIDIL (hpijs) * Structured Fax * Canon BJ/BJC * ASCII PNM (Netpbm) The ten latter ones, as well as some TIFF documents, are currently only supported in page counting mode. command line usage : pkpgcounter [options] [files] options : -v | --version Prints pkpgcounter's version number then exits. -h | --help Prints this message then exits. -d | --debug Activate debug mode. -cCOLORSPACE, --colorspace=COLORSPACE Activate the computation of ink usage, and defines the colorspace to use. Supported values are 'BW' (Black), 'RGB', 'CMYK', 'CMY', and 'GC' (Grayscale vs Color). 'GC' is useful if you only need to differentiate grayscale pages from coloured pages but don't care about ink usage per se. -rRESOLUTION, --resolution=RESOLUTION The resolution in DPI to use when checking ink usage. Lower resolution is faster but less accurate. Default is 72 dpi. examples : $ pkpgcounter file1.ps file2.escp2 file3.pclxl = 2) and (sys.argv[1] in ("-h", "--help")) : print __doc__ % globals() else : analyzer.main() pkpgcounter-3.50/man/0002755000175000017500000000000010727050450014103 5ustar jeromejeromepkpgcounter-3.50/man/genman.sh0000755000175000017500000000236710723373152015720 0ustar jeromejerome#! /bin/sh # # pkpgcounter : a generic Page Description Language parser. # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: genman.sh 350 2007-11-28 23:14:47Z jerome $ # for prog in pkpgcounter ; do echo "$prog" ; help2man --no-info \ --section=1 \ --name="count number of pages required to print various types of documents" \ --manual="User Commands" \ --source="C@LL - Conseil Internet & Logiciels Libres" \ --output="temp$prog.1" \ $prog ; /bin/sed -e "s/--/\\\-\\\-/g" <"temp$prog.1" >"$prog.1" ; /bin/rm -f "temp$prog.1" echo ; done pkpgcounter-3.50/man/pkpgcounter.10000644000175000017500000000601610727050262016530 0ustar jeromejerome.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36. .TH PKPGCOUNTER "1" "December 2007" "C@LL - Conseil Internet & Logiciels Libres" "User Commands" .SH NAME pkpgcounter \- count number of pages required to print various types of documents .SH DESCRIPTION pkpgcounter v3.50 (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet .PP pkpgcounter is a generic Page Description Language parser. .PP pkpgcounter parses any number of input files and/or its standard input and outputs the number of pages needed to print these documents. .PP pkpgcounter can also compute the percent of ink coverage in different colorspaces for several file formats. .PP pkpgcounter currently recognizes the following document formats : .IP * PostScript (both DSC compliant and binary) * PDF * PCLXL (aka PCL6) * PCL3/4/5 * DVI * OpenDocument (ISO/IEC DIS 26300) * Microsoft Word (c) (tm) (r) (etc...) * Plain text * TIFF * Several other image formats * ESC/P2 * Zenographics ZjStream * Samsung QPDL (aka SPL2) * Samsung SPL1 * ESC/PageS03 * Brother HBP * Hewlett\-Packard LIDIL (hpijs) * Structured Fax * Canon BJ/BJC * ASCII PNM (Netpbm) .PP The ten latter ones, as well as some TIFF documents, are currently only supported in page counting mode. .PP command line usage : .IP pkpgcounter [options] [files] .PP options : .TP \fB\-v\fR | \fB\-\-version\fR Prints pkpgcounter's version number then exits. .TP \fB\-h\fR | \fB\-\-help\fR Prints this message then exits. .TP \fB\-d\fR | \fB\-\-debug\fR Activate debug mode. .TP \fB\-cCOLORSPACE\fR, \fB\-\-colorspace\fR=\fICOLORSPACE\fR Activate the computation of ink usage, and defines the colorspace to use. Supported values are 'BW' (Black), \&'RGB', 'CMYK', 'CMY', and 'GC' (Grayscale vs Color). \&'GC' is useful if you only need to differentiate grayscale pages from coloured pages but don't care about ink usage per se. .TP \fB\-rRESOLUTION\fR, \fB\-\-resolution\fR=\fIRESOLUTION\fR The resolution in DPI to use when checking ink usage. Lower resolution is faster but less accurate. Default is 72 dpi. .PP examples : .IP \f(CW$ pkpgcounter file1.ps file2.escp2 file3.pclxl . .PP Please e\-mail bugs to: alet@librelogiciel.com pkpgcounter-3.50/pkpgpdls/0002755000175000017500000000000010727050450015154 5ustar jeromejeromepkpgcounter-3.50/pkpgpdls/__init__.py0000644000175000017500000000147410671326560017277 0ustar jeromejerome# # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: __init__.py 282 2007-09-10 20:47:40Z jerome $ # pkpgcounter-3.50/pkpgpdls/analyzer.py0000644000175000017500000002523310726764734017376 0ustar jeromejerome# # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: analyzer.py 366 2007-12-09 13:12:58Z jerome $ # """This is the main module of pkpgcounter. It defines the PDLAnalyzer class, which provides a generic way to parse input files, by automatically detecting the best parser to use.""" import sys import os import tempfile import version, pdlparser, postscript, pdf, pcl345, pclxl, hbp, \ pil, mscrap, cfax, lidil, escp2, dvi, tiff, ooo, zjstream, \ pnmascii, bj, qpdl, spl1, escpages03, plain import inkcoverage class AnalyzerOptions : """A class for use as the options parameter to PDLAnalyzer's constructor.""" def __init__(self, debug=None, colorspace=None, resolution=None) : """Sets initial attributes.""" self.debug = debug self.colorspace = colorspace self.resolution = resolution class PDLAnalyzer : """Class for PDL autodetection.""" def __init__(self, filename, options=AnalyzerOptions()) : """Initializes the PDL analyzer. filename is the name of the file or '-' for stdin. filename can also be a file-like object which supports read() and seek(). """ self.options = options self.filename = filename self.workfile = None self.mustclose = None def getJobSize(self) : """Returns the job's size.""" size = 0 self.openFile() try : try : pdlhandler = self.detectPDLHandler() size = pdlhandler.getJobSize() except pdlparser.PDLParserError, msg : raise pdlparser.PDLParserError, "Unsupported file format for %s (%s)" % (self.filename, msg) finally : self.closeFile() return size def getInkCoverage(self, colorspace=None, resolution=None) : """Extracts the percents of ink coverage from the input file.""" result = None cspace = colorspace or self.options.colorspace res = resolution or self.options.resolution if (not cspace) or (not res) : raise ValueError, "Invalid colorspace (%s) or resolution (%s)" % (cspace, res) self.openFile() try : try : pdlhandler = self.detectPDLHandler() dummyfile = tempfile.NamedTemporaryFile(mode="w+b") filename = dummyfile.name try : pdlhandler.convertToTiffMultiPage24NC(filename, self.options.resolution) result = inkcoverage.getInkCoverage(filename, cspace) finally : dummyfile.close() except pdlparser.PDLParserError, msg : raise pdlparser.PDLParserError, "Unsupported file format for %s (%s)" % (self.filename, msg) finally : self.closeFile() return result def openFile(self) : """Opens the job's data stream for reading.""" self.mustclose = False # by default we don't want to close the file when finished if hasattr(self.filename, "read") and hasattr(self.filename, "seek") : # filename is in fact a file-like object infile = self.filename elif self.filename == "-" : # we must read from stdin infile = sys.stdin else : # normal file self.workfile = open(self.filename, "rb") self.mustclose = True return # Use a temporary file, always seekable contrary to standard input. self.workfile = tempfile.NamedTemporaryFile(mode="w+b") self.filename = self.workfile.name while True : data = infile.read(pdlparser.MEGABYTE) if not data : break self.workfile.write(data) self.workfile.flush() self.workfile.seek(0) def closeFile(self) : """Closes the job's data stream if we have to.""" if self.mustclose : self.workfile.close() def readFirstAndLastBlocks(self, inputfile) : """Reads the first and last blocks of data.""" # Now read first and last block of the input file # to be able to detect the real file format and the parser to use. firstblock = inputfile.read(pdlparser.FIRSTBLOCKSIZE) try : inputfile.seek(-pdlparser.LASTBLOCKSIZE, 2) lastblock = inputfile.read(pdlparser.LASTBLOCKSIZE) except IOError : lastblock = "" return (firstblock, lastblock) def detectPDLHandler(self) : """Tries to autodetect the document format. Returns the correct PDL handler class or None if format is unknown """ if not os.stat(self.filename).st_size : raise pdlparser.PDLParserError, "input file %s is empty !" % str(self.filename) (firstblock, lastblock) = self.readFirstAndLastBlocks(self.workfile) # IMPORTANT : the order is important below. FIXME. for module in (postscript, \ pclxl, \ pdf, \ qpdl, \ spl1, \ dvi, \ tiff, \ cfax, \ zjstream, \ ooo, \ hbp, \ lidil, \ pcl345, \ escp2, \ escpages03, \ bj, \ pnmascii, \ pil, \ mscrap, \ plain) : # IMPORTANT : don't move this one up ! try : return module.Parser(self, self.filename, (firstblock, lastblock)) except pdlparser.PDLParserError : pass # try next parser raise pdlparser.PDLParserError, "Analysis of first data block failed." def main() : """Entry point for PDL Analyzer.""" import optparse from copy import copy def check_cichoice(option, opt, value) : """To add a CaseIgnore Choice option type.""" valower = value.lower() if valower in [v.lower() for v in option.cichoices] : return valower else : choices = ", ".join([repr(o) for o in option.cichoices]) raise optparse.OptionValueError( "option %s: invalid choice: %r (choose from %s)" % (opt, value, choices)) class MyOption(optparse.Option) : """New Option class, with CaseIgnore Choice type.""" TYPES = optparse.Option.TYPES + ("cichoice",) ATTRS = optparse.Option.ATTRS + ["cichoices"] TYPE_CHECKER = copy(optparse.Option.TYPE_CHECKER) TYPE_CHECKER["cichoice"] = check_cichoice parser = optparse.OptionParser(option_class=MyOption, usage="python analyzer.py [options] file1 [file2 ...]") parser.add_option("-v", "--version", action="store_true", dest="version", help="Show pkpgcounter's version number and exit.") parser.add_option("-d", "--debug", action="store_true", dest="debug", help="Activate debug mode.") parser.add_option("-c", "--colorspace", dest="colorspace", type="cichoice", cichoices=["bw", "rgb", "cmyk", "cmy", "gc"], help="Activate the computation of ink usage, and defines the colorspace to use. Supported values are 'BW', 'RGB', 'CMYK', 'CMY', and 'GC'.") parser.add_option("-r", "--resolution", type="int", default=72, dest="resolution", help="The resolution in DPI to use when checking ink usage. Lower resolution is faster but less accurate. Default is 72 dpi.") (options, arguments) = parser.parse_args() if options.version : print "%s" % version.__version__ elif not (72 <= options.resolution <= 1200) : sys.stderr.write("ERROR: the argument to the --resolution command line option must be between 72 and 1200.\n") sys.stderr.flush() else : if (not arguments) or ((not sys.stdin.isatty()) and ("-" not in arguments)) : arguments.append("-") totalsize = 0 lines = [] try : for arg in arguments : try : parser = PDLAnalyzer(arg, options) if not options.colorspace : totalsize += parser.getJobSize() else : (cspace, pages) = parser.getInkCoverage() for page in pages : lineparts = [] for k in cspace : # NB : this way we preserve the order of the planes try : lineparts.append("%s : %s%%" % (k, ("%f" % page[k]).rjust(10))) except KeyError : pass lines.append(" ".join(lineparts)) except (IOError, pdlparser.PDLParserError), msg : sys.stderr.write("ERROR: %s\n" % msg) sys.stderr.flush() except KeyboardInterrupt : sys.stderr.write("WARN: Aborted at user's request.\n") sys.stderr.flush() if not options.colorspace : print "%i" % totalsize else : print "\n".join(lines) if __name__ == "__main__" : main() pkpgcounter-3.50/pkpgpdls/bj.py0000644000175000017500000000474010726775416016143 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: bj.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for Canon BJ documents.""" import os import mmap import pdlparser class Parser(pdlparser.PDLParser) : """A parser for Canon BJ documents.""" format = "Canon BJ/BJC" def isValid(self) : """Returns True if data is BJ/BJC, else False.""" if self.firstblock.startswith("\033[K\002\000") : return True else : return False def getJobSize(self) : """Counts pages in a Canon BJ document. Algorithm by Jerome Alet. The documentation used for this was : ghostscript-8.60/src/gdevbj*.c """ infileno = self.infile.fileno() minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) pagecount = 0 pos = 0 try : try : while True : if minfile[pos] == "\033" : # Look if we've found an initialization sequence # through the Set Initial Condition command pageheader = minfile[pos:pos+7] if pageheader in ("\033[K\002\000\000\017", "\033[K\002\000\000\044", "\033[K\002\000\004\044") : pagecount += 1 pos += 6 pos += 1 except IndexError : # EOF ? pass finally : minfile.close() # reached EOF return pagecount pkpgcounter-3.50/pkpgpdls/cfax.py0000644000175000017500000000776610726775416016504 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: cfax.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for Structured Fax documents.""" import struct import pdlparser class Parser(pdlparser.PDLParser) : """A parser for Structured Fax documents.""" format = "Structured Fax" def isValid(self) : """Returns True if data is Structured Fax, else False.""" if self.firstblock.startswith("Sfff") : return True else : return False def getJobSize(self) : """Counts pages in a Structured Fax document. Algorithm by Jerome Alet. The documentation used for this was : http://delphi.pjh2.de/articles/graphic/sff_format.php """ unpack = struct.unpack pagecount = 0 docheader = self.infile.read(20) try : (sffid, version, reserved, userinfo, docpagecount, offsetfirstpage, offsetlastpage, offsetdocumentend) = unpack("<4sBBHHHII", docheader) self.infile.seek(offsetfirstpage - len(docheader), 1) while True : headerid = self.infile.read(1) if not headerid : break headerid = ord(headerid) if 1 <= headerid <= 216 : # Normal record header self.infile.seek(headerid, 1) elif headerid == 255 : # Illegal line / Additional user info additionalbyte = self.infile.read(1) if not additionalbyte : break additionalbyte = ord(additionalbyte) if 1 <= additionalbyte <= 255 : # Skip additional user information (reserved) self.infile.seek(additionalbyte, 1) elif not headerid : # Record with more than 216 MH-coded bytes recordlen = self.infile.read(2) if not recordlen : break recordlen = unpack(" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: dvi.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for DVI documents.""" import sys import os import mmap from struct import unpack import pdlparser class Parser(pdlparser.PDLParser) : """A parser for DVI documents.""" totiffcommands = [ 'dvips -q -o - "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -' ] required = [ "dvips", "gs" ] format = "DVI" def isValid(self) : """Returns True if data is DVI, else False.""" try : if (ord(self.firstblock[0]) == 0xf7) \ and (ord(self.lastblock[-1]) == 0xdf) : return True else : return False except IndexError : return False def getJobSize(self) : """Counts pages in a DVI document. Algorithm by Jerome Alet. The documentation used for this was : http://www.math.umd.edu/~asnowden/comp-cont/dvi.html """ infileno = self.infile.fileno() minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) pagecount = 0 pos = -1 eofchar = chr(0xdf) postchar = chr(0xf8) try : try : while minfile[pos] == eofchar : pos -= 1 idbyte = minfile[pos] if idbyte != minfile[1] : raise IndexError, "Invalid DVI file." pos = unpack(">I", minfile[pos - 4:pos])[0] if minfile[pos] != postchar : raise IndexError, "Invalid DVI file." pagecount = unpack(">H", minfile[pos + 27: pos + 29])[0] except IndexError : # EOF ? pass finally : minfile.close() # reached EOF return pagecount pkpgcounter-3.50/pkpgpdls/escp2.py0000644000175000017500000000520310726775416016557 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: escp2.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for ESC/P2 documents.""" import sys import pdlparser class Parser(pdlparser.PDLParser) : """A parser for ESC/P2 documents.""" format = "ESC/P2" def isValid(self) : """Returns True if data is ESC/P2, else False.""" if self.firstblock.startswith("\033@") or \ self.firstblock.startswith("\033*") or \ self.firstblock.startswith("\n\033@") or \ self.firstblock.startswith("\0\0\0\033\1@EJL") : # ESC/P Raster ??? Seen on Stylus Photo 1284 return True else : return False def getJobSize(self) : """Counts pages in an ESC/P2 document.""" # with Gimpprint, at least, for each page there # are two Reset Printer sequences (ESC + @) marker1 = "\033@" # with other software or printer driver, we # may prefer to search for "\r\n\fESCAPE" # or "\r\fESCAPE" marker2r = "\r\f\033" marker2rn = "\r\n\f\033" # and ghostscript's stcolor for example seems to # output ESC + @ + \f for each page plus one marker3 = "\033@\f" # while ghostscript's escp driver outputs instead # \f + ESC + @ marker4 = "\f\033@" data = self.infile.read() pagecount1 = data.count(marker1) pagecount2 = max(data.count(marker2r), data.count(marker2rn)) pagecount3 = data.count(marker3) pagecount4 = data.count(marker4) if pagecount2 : return pagecount2 elif pagecount3 > 1 : return pagecount3 - 1 elif pagecount4 : return pagecount4 else : return int(pagecount1 / 2) pkpgcounter-3.50/pkpgpdls/escpages03.py0000644000175000017500000000731210726775416017503 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: escpages03.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for TIFF documents.""" import sys import os import mmap from struct import unpack import pdlparser import pjl class Parser(pdlparser.PDLParser) : """A parser for ESC/PageS03 documents.""" format = "ESC/PageS03" def isValid(self) : """Returns True if data is TIFF, else False.""" if self.firstblock.startswith("\033\1@EJL") and \ (self.firstblock.find("=ESC/PAGES03\n") != -1) : return True else : return False def getJobSize(self) : """Counts pages in an ESC/PageS03 document. Algorithm by Jerome Alet. Reverse engineered the file format. """ infileno = self.infile.fileno() minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) pagecount = 0 marker = "=ESC/PAGES03\n" startpos = minfile.find(marker) startsequence = chr(0x1d) if startpos == -1 : raise pdlparser.PDLParserError, "Invalid ESC/PageS03 file." startpos += len(marker) if minfile[startpos] != startsequence : raise pdlparser.PDLParserError, "Invalid ESC/PageS03 file." endsequence = "eps{I" lgendsequence = len(endsequence) try : try : while True : if minfile[startpos] == startsequence : skiplen = 0 while True : startpos += 1 c = minfile[startpos] if not c.isdigit() : break else : skiplen = (skiplen * 10) + int(c) if minfile[startpos:startpos+lgendsequence] == endsequence : startpos += (skiplen + lgendsequence) else : if minfile[startpos:startpos+6] == "\033\1@EJL" : # Probably near the end of the file. # Test suite was too small to be sure. ejlparser = pjl.EJLParser(minfile[startpos:]) pagecount = ejlparser.environment_variables.get("PAGES", "1") if pagecount.startswith('"') and pagecount.endswith('"') : pagecount = pagecount[1:-1] pagecount = int(pagecount) if pagecount <= 0 : pagecount = 1 # TODO : 0 or 1000000 ??? ;-) break startpos += 1 except IndexError : pass finally : minfile.close() return pagecount pkpgcounter-3.50/pkpgpdls/hbp.py0000644000175000017500000000503110726775416016313 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: hbp.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for Brother HBP documents.""" import sys import os import mmap from struct import unpack import pdlparser class Parser(pdlparser.PDLParser) : """A parser for HBP documents.""" format = "Brother HBP" def isValid(self) : """Returns True if data is HBP, else False.""" if self.firstblock.find("@PJL ENTER LANGUAGE = HBP\n") != -1 : return True else : return False def getJobSize(self) : """Counts pages in a HBP document. Algorithm by Jerome Alet. The documentation used for this was : http://sf.net/projects/hbp-for-brother/ IMPORTANT : this may not work since @F should be sufficient, but the documentation really is unclear and I don't know how to skip raster data blocks for now. """ infileno = self.infile.fileno() minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) pagecount = 0 formfeed = "@G" + chr(0) + chr(0) + chr(1) + chr(0xff) + "@F" fflen = len(formfeed) pos = 0 try : try : while True : if (minfile[pos] == "@") \ and (minfile[pos:pos+fflen] == formfeed) : pagecount += 1 pos += fflen else : pos += 1 except IndexError : # EOF ? pass finally : minfile.close() # reached EOF return pagecount pkpgcounter-3.50/pkpgpdls/inkcoverage.py0000644000175000017500000001141510723322501020016 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: inkcoverage.py 346 2007-11-28 17:28:30Z jerome $ # """This modules implements the computation of ink coverage in different colorspaces.""" import sys import pdlparser try : from PIL import Image except ImportError : sys.stderr.write("ERROR: You MUST install the Python Imaging Library (python-imaging) for pkpgcounter to work.\n") raise pdlparser.PDLParserError, "The Python Imaging Library is missing." def getPercent(img, nbpix) : """Extracts the percents per color component from a picture. Faster without Psyco on my own machine. """ result = {} bands = img.split() for (i, bandname) in enumerate(img.getbands()) : result[bandname] = 100.0 * (reduce(lambda current, next: current + (next[1] * next[0]), enumerate(bands[i].histogram()), 0) / 255.0) / nbpix return result def getPercentCMYK(img, nbpix) : """Extracts the percents of Cyan, Magenta, Yellow, and Black from a picture. PIL doesn't produce useable CMYK for our algorithm, so we use the algorithm from PrintBill. Psyco speeds this function up by around 2.5 times on my computer. """ if img.mode != "RGB" : img = img.convert("RGB") cyan = magenta = yellow = black = 0 for (r, g, b) in img.getdata() : if r == g == b : black += 255 - r else : cyan += 255 - r magenta += 255 - g yellow += 255 - b return { "C" : 100.0 * (cyan / 255.0) / nbpix, "M" : 100.0 * (magenta / 255.0) / nbpix, "Y" : 100.0 * (yellow / 255.0) / nbpix, "K" : 100.0 * (black / 255.0) / nbpix, } def getPercentGC(img, nbpix) : """Determines if a page is in grayscale or colour mode.""" if img.mode != "RGB" : img = img.convert("RGB") gray = 0 for (r, g, b) in img.getdata() : if not (r == g == b) : # optimize : if a single pixel is no gray the whole page is colored. return { "G" : 0.0, "C" : 100.0 } return { "G" : 100.0, "C" : 0.0 } def getPercentBW(img, nbpix) : """Extracts the percents of Black from a picture, once converted to gray levels.""" if img.mode != "L" : img = img.convert("L") return { "B" : 100.0 - getPercent(img, nbpix)["L"] } def getPercentRGB(img, nbpix) : """Extracts the percents of Red, Green, Blue from a picture, once converted to RGB.""" if img.mode != "RGB" : img = img.convert("RGB") return getPercent(img, nbpix) def getPercentCMY(img, nbpix) : """Extracts the percents of Cyan, Magenta, and Yellow from a picture once converted to RGB.""" result = getPercentRGB(img, nbpix) return { "C" : 100.0 - result["R"], "M" : 100.0 - result["G"], "Y" : 100.0 - result["B"], } def getInkCoverage(fname, colorspace) : """Returns a list of dictionnaries containing for each page, for each color component, the percent of ink coverage on that particular page. """ result = [] colorspace = colorspace.upper() computation = globals()["getPercent%s" % colorspace] if colorspace in ("CMYK", "GC") : # faster with psyco on my machine try : import psyco except ImportError : pass else : psyco.bind(getPercentCMYK) index = 0 try : image = Image.open(fname) except (IOError, OverflowError), msg : raise pdlparser.PDLParserError, "%s (%s)" % (msg, fname) else : try : while True : nbpixels = image.size[0] * image.size[1] result.append(computation(image, nbpixels)) index += 1 image.seek(index) except EOFError : pass return (colorspace, result) if __name__ == "__main__" : # NB : length of result gives number of pages ! print getInkCoverage(sys.argv[1], "CMYK") pkpgcounter-3.50/pkpgpdls/lidil.py0000644000175000017500000001016510726775416016643 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: lidil.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for HP LIDIL format. Documentation used : hplip-2.7.10/prnt/ldl.py hplip-2.7.10/prnt/hpijs/ldlencap.h """ import struct import pdlparser HEADERSIZE = 10 # LIDIL header is 10 bytes long # Packet types taken from hplip-2.7.10/prnt/ldl.py PACKET_TYPE_COMMAND = 0 PACKET_TYPE_DISABLE_PACING = 1 PACKET_TYPE_ENABLE_PACING = 2 PACKET_TYPE_RESUME_NORMAL_OPERATION = 3 PACKET_TYPE_DISABLE_RESPONSES = 4 PACKET_TYPE_ENABLE_RESPONSES = 5 PACKET_TYPE_RESET_LIDIL = 6 PACKET_TYPE_SYNC = 7 PACKET_TYPE_SYNC_COMPLETE = 8 # Command codes we are interested in. LDL_LOAD_PAGE = 1 LDL_EJECT_PAGE = 2 class Parser(pdlparser.PDLParser) : """A parser for HP LIDIL documents.""" format = "Hewlett-Packard LIDIL" def isValid(self) : """Returns True if data is LIDIL, else False.""" # Beginning Of File marker is a Sync packet, followed with # a Sync Complete packet followed with a Reset packet. # We just look at the start of the Sync packet for simplicity's sake. BOFMarker = "$\x01\x00\x00\x07" # End Of File marker is a Sync Complete packet followed # with a Reset packet. We ignore the preceding Sync packet # for simplicity's sake. EOFMarker = "$\x00\x10\x00\x08\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff$$\x00\x10\x00\x06\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff$" if self.firstblock.startswith(BOFMarker) \ and self.lastblock.endswith(EOFMarker) : return True else : return False def getJobSize(self) : """Computes the number of pages in a HP LIDIL document.""" unpack = struct.unpack ejectpage = loadpage = 0 try : while True : header = self.infile.read(HEADERSIZE) if not header : break if (len(header) != HEADERSIZE) or (header[0] != "$") : # Invalid header or no Frame Sync byte. raise pdlparser.PDLParserError, "This file doesn't seem to be valid Hewlett-Packard LIDIL datas." (framesync, cmdlength, dummy, packettype, commandnumber, referencenumber, datalength) = unpack(">BHBBBHH", header) if packettype == PACKET_TYPE_COMMAND : if commandnumber == LDL_LOAD_PAGE : loadpage += 1 elif commandnumber == LDL_EJECT_PAGE : ejectpage += 1 self.infile.seek(cmdlength + datalength - len(header), 1) # relative seek except struct.error : raise pdlparser.PDLParserError, "This file doesn't seem to be valid Hewlett-Packard LIDIL datas." # Number of page eject commands should be sufficient, # but we never know : someone could try to cheat the printer # by loading a page but not ejecting it, and ejecting it manually # later on. Not sure if the printers would support this, but # taking the max value works around the problem in any case. self.logdebug("Load : %i Eject : %i" % (loadpage, ejectpage)) return max(loadpage, ejectpage) pkpgcounter-3.50/pkpgpdls/mscrap.py0000644000175000017500000000707410726775416017040 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: mscrap.py 374 2007-12-09 14:26:15Z jerome $ # """This module implements a page counter for Microsoft Word (r) (tm) (c) (etc...) documents""" import os import tempfile import pdlparser import version class Parser(pdlparser.PDLParser) : """A parser for that MS crap thing.""" totiffcommands = [ 'xvfb-run -a abiword --import-extension=.doc --print="| gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r\"%(dpi)i\" -sOutputFile=\"%(outfname)s\" -" "%(infname)s"' ] required = [ "xvfb-run", "xauth", "abiword", "gs" ] format = "Microsoft shitty" def isValid(self) : """Returns True if data is MS crap, else False. Identifying datas taken from the file command's magic database. IMPORTANT : some magic values are not reused here because they IMPORTANT : seem to be specific to some particular i18n release. """ if self.firstblock.startswith("PO^Q`") \ or self.firstblock.startswith("\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1") \ or self.firstblock.startswith("\xfe7\x00#") \ or self.firstblock.startswith("\xdb\xa5-\x00\x00\x00") \ or self.firstblock.startswith("\x31\xbe\x00\x00") \ or self.firstblock[2112:].startswith("MSWordDoc") : # Here we do the missing test because all commands will be needed even in page counting mode if self.isMissing(self.required) : return False else : return True else : return False def getJobSize(self) : """Counts pages in a Microsoft Word (r) (tm) (c) (etc...) document. First we convert from .doc to .ps, then we use the PostScript parser. """ doctops = 'xvfb-run -a abiword --import-extension=.doc --print="%(outfname)s" "%(infname)s"' workfile = tempfile.NamedTemporaryFile(mode="w+b") try : outfname = workfile.name infname = self.filename status = os.system(doctops % locals()) if status or not os.stat(outfname).st_size : raise pdlparser.PDLParserError, "Impossible to convert input document %(infname)s to PostScript" % locals() psinputfile = open(outfname, "rb") try : (first, last) = self.parent.readFirstAndLastBlocks(psinputfile) import postscript return postscript.Parser(self.parent, outfname, (first, last)).getJobSize() finally : psinputfile.close() finally : workfile.close() raise pdlparser.PDLParserError, "Impossible to count pages in %(infname)s" % locals() pkpgcounter-3.50/pkpgpdls/ooo.py0000644000175000017500000000500310726775416016335 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: ooo.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for OpenDocument documents.""" import sys import zipfile import pdlparser class Parser(pdlparser.PDLParser) : """A parser for OpenOffice.org documents.""" totiffcommands = [ 'xvfb-run -a abiword --import-extension=.odt --print="| gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r\"%(dpi)i\" -sOutputFile=\"%(outfname)s\" -" "%(infname)s"' ] required = [ "xvfb-run", "xauth", "abiword", "gs" ] format = "ISO/IEC DIS 26300" def isValid(self) : """Returns True if data is OpenDocument, else False.""" if self.firstblock[:2] == "PK" : try : self.archive = zipfile.ZipFile(self.filename) self.contentxml = self.archive.read("content.xml") self.metaxml = self.archive.read("meta.xml") except : return False else : return True else : return False def getJobSize(self) : """Counts pages in an OpenOffice.org document. Algorithm by Jerome Alet. """ pagecount = 0 try : # First try with Text documents index = self.metaxml.index("meta:page-count=") pagecount = int(self.metaxml[index:].split('"')[1]) except : # Now try with Impress documents pagecount = self.contentxml.count(" # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pcl345.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for PCL3/4/5 documents.""" import sys import os import mmap from struct import unpack import pdlparser import pjl NUL = chr(0x00) LINEFEED = chr(0x0a) FORMFEED = chr(0x0c) ESCAPE = chr(0x1b) ASCIILIMIT = chr(0x80) class Parser(pdlparser.PDLParser) : """A parser for PCL3, PCL4, PCL5 documents.""" totiffcommands = [ 'pcl6 -sDEVICE=pdfwrite -r"%(dpi)i" -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -sOutputFile=- "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(outfname)s" -', 'pcl6 -sDEVICE=pswrite -r"%(dpi)i" -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -sOutputFile=- "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r%(dpi)i -sOutputFile="%(outfname)s" -', ] required = [ "pcl6", "gs" ] format = "PCL3/4/5" mediasizes = { # ESC&l####A 0 : "Default", 1 : "Executive", 2 : "Letter", 3 : "Legal", 6 : "Ledger", 25 : "A5", 26 : "A4", 27 : "A3", 45 : "JB5", 46 : "JB4", 71 : "HagakiPostcard", 72 : "OufukuHagakiPostcard", 80 : "MonarchEnvelope", 81 : "COM10Envelope", 90 : "DLEnvelope", 91 : "C5Envelope", 100 : "B5Envelope", 101 : "Custom", } mediasources = { # ESC&l####H 0 : "Default", 1 : "Main", 2 : "Manual", 3 : "ManualEnvelope", 4 : "Alternate", 5 : "OptionalLarge", 6 : "EnvelopeFeeder", 7 : "Auto", 8 : "Tray1", } orientations = { # ESC&l####O 0 : "Portrait", 1 : "Landscape", 2 : "ReversePortrait", 3 : "ReverseLandscape", } mediatypes = { # ESC&l####M 0 : "Plain", 1 : "Bond", 2 : "Special", 3 : "Glossy", 4 : "Transparent", } def isValid(self) : """Returns True if data is PCL3/4/5, else False.""" try : pos = 0 while self.firstblock[pos] == chr(0) : pos += 1 except IndexError : return False else : firstblock = self.firstblock[pos:] if firstblock.startswith("\033E\033") or \ firstblock.startswith("\033%1BBPIN;") or \ ((pos == 11000) and firstblock.startswith("\033")) or \ (firstblock.startswith("\033*rbC") and (not self.lastblock[-3:] == "\f\033@")) or \ firstblock.startswith("\033*rB\033") or \ firstblock.startswith("\033%8\033") or \ (firstblock.find("\033%-12345X") != -1) or \ (firstblock.find("@PJL ENTER LANGUAGE=PCL\012\015\033") != -1) or \ (firstblock.startswith(chr(0xcd)+chr(0xca)) and (firstblock.find("\033E\033") != -1)) : return True else : return False def setPageDict(self, attribute, value) : """Initializes a page dictionnary.""" dic = self.pages.setdefault(self.pagecount, { "linescount" : 1, "copies" : 1, "mediasource" : "Main", "mediasize" : "Default", "mediatype" : "Plain", "orientation" : "Portrait", "escaped" : "", "duplex": 0 }) dic[attribute] = value def readByte(self) : """Reads a byte from the input stream.""" tag = ord(self.minfile[self.pos]) self.pos += 1 return tag def endPage(self) : """Handle the FF marker.""" #self.logdebug("FORMFEED %i at %08x" % (self.pagecount, self.pos-1)) if not self.hpgl2 : # Increments page count only if we are not inside an HPGL2 block self.pagecount += 1 def escPercent(self) : """Handles the ESC% sequence.""" if self.minfile[self.pos : self.pos+7] == r"-12345X" : #self.logdebug("Generic ESCAPE sequence at %08x" % self.pos) self.pos += 7 buffer = [] quotes = 0 char = chr(self.readByte()) while ((char < ASCIILIMIT) or (quotes % 2)) and (char not in (FORMFEED, ESCAPE, NUL)) : buffer.append(char) if char == '"' : quotes += 1 char = chr(self.readByte()) self.setPageDict("escaped", "".join(buffer)) #self.logdebug("ESCAPED : %s" % "".join(buffer)) self.pos -= 1 # Adjust position else : while 1 : (value, end) = self.getInteger() if end == 'B' : self.enterHPGL2() while self.minfile[self.pos] != ESCAPE : self.pos += 1 self.pos -= 1 return elif end == 'A' : self.exitHPGL2() return elif end is None : return def enterHPGL2(self) : """Enters HPGL2 mode.""" #self.logdebug("ENTERHPGL2 %08x" % self.pos) self.hpgl2 = True def exitHPGL2(self) : """Exits HPGL2 mode.""" #self.logdebug("EXITHPGL2 %08x" % self.pos) self.hpgl2 = False def handleTag(self, tagtable) : """Handles tags.""" tagtable[self.readByte()]() def escape(self) : """Handles the ESC character.""" #self.logdebug("ESCAPE") self.handleTag(self.esctags) def escAmp(self) : """Handles the ESC& sequence.""" #self.logdebug("AMP") self.handleTag(self.escamptags) def escStar(self) : """Handles the ESC* sequence.""" #self.logdebug("STAR") self.handleTag(self.escstartags) def escLeftPar(self) : """Handles the ESC( sequence.""" #self.logdebug("LEFTPAR") self.handleTag(self.escleftpartags) def escRightPar(self) : """Handles the ESC( sequence.""" #self.logdebug("RIGHTPAR") self.handleTag(self.escrightpartags) def escE(self) : """Handles the ESCE sequence.""" #self.logdebug("RESET") self.resets += 1 def escAmpl(self) : """Handles the ESC&l sequence.""" while 1 : (value, end) = self.getInteger() if value is None : return if end in ('h', 'H') : mediasource = self.mediasources.get(value, str(value)) self.mediasourcesvalues.append(mediasource) self.setPageDict("mediasource", mediasource) #self.logdebug("MEDIASOURCE %s" % mediasource) elif end in ('a', 'A') : mediasize = self.mediasizes.get(value, str(value)) self.mediasizesvalues.append(mediasize) self.setPageDict("mediasize", mediasize) #self.logdebug("MEDIASIZE %s" % mediasize) elif end in ('o', 'O') : orientation = self.orientations.get(value, str(value)) self.orientationsvalues.append(orientation) self.setPageDict("orientation", orientation) #self.logdebug("ORIENTATION %s" % orientation) elif end in ('m', 'M') : mediatype = self.mediatypes.get(value, str(value)) self.mediatypesvalues.append(mediatype) self.setPageDict("mediatype", mediatype) #self.logdebug("MEDIATYPE %s" % mediatype) elif end == 'X' : self.copies.append(value) self.setPageDict("copies", value) #self.logdebug("COPIES %i" % value) elif end == 'F' : self.linesperpagevalues.append(value) self.linesperpage = value #self.logdebug("LINES PER PAGE : %i" % self.linesperpage) #else : # self.logdebug("Unexpected end <%s> and value <%s>" % (end, value)) def escAmpa(self) : """Handles the ESC&a sequence.""" while 1 : (value, end) = self.getInteger() if value is None : return if end == 'G' : #self.logdebug("BACKSIDES %i" % value) self.backsides.append(value) self.setPageDict("duplex", value) def escAmpp(self) : """Handles the ESC&p sequence.""" while 1 : (value, end) = self.getInteger() if value is None : return if end == 'X' : self.pos += value #self.logdebug("SKIPTO %08x" % self.pos) def escStarb(self) : """Handles the ESC*b sequence.""" while 1 : (value, end) = self.getInteger() if (end is None) and (value is None) : return if end in ('V', 'W', 'v', 'w') : self.pos += (value or 0) #self.logdebug("SKIPTO %08x" % self.pos) def escStarr(self) : """Handles the ESC*r sequence.""" while 1 : (value, end) = self.getInteger() if value is None : if end is None : return elif end in ('B', 'C') : #self.logdebug("EndGFX") if self.startgfx : self.endgfx.append(1) else : #self.logdebug("EndGFX found before StartGFX, ignored.") pass if end == 'A' and (0 <= value <= 3) : #self.logdebug("StartGFX %i" % value) self.startgfx.append(value) def escStaroptAmpu(self) : """Handles the ESC*o ESC*p ESC*t and ESC&u sequences.""" while 1 : (value, end) = self.getInteger() if value is None : return def escSkipSomethingW(self) : """Handles the ESC???###W sequences.""" while 1 : (value, end) = self.getInteger() if value is None : return if end == 'W' : self.pos += value #self.logdebug("SKIPTO %08x" % self.pos) def newLine(self) : """Handles new lines markers.""" if not self.hpgl2 : dic = self.pages.get(self.pagecount, None) if dic is None : self.setPageDict("linescount", 1) dic = self.pages.get(self.pagecount) nblines = dic["linescount"] self.setPageDict("linescount", nblines + 1) if (self.linesperpage is not None) \ and (dic["linescount"] > self.linesperpage) : self.pagecount += 1 def getInteger(self) : """Returns an integer value and the end character.""" sign = 1 value = None while 1 : char = chr(self.readByte()) if char in (NUL, ESCAPE, FORMFEED, ASCIILIMIT) : self.pos -= 1 # Adjust position return (None, None) if char == '-' : sign = -1 elif not char.isdigit() : if value is not None : return (sign*value, char) else : return (value, char) else : value = ((value or 0) * 10) + int(char) def skipByte(self) : """Skips a byte.""" #self.logdebug("SKIPBYTE %08x ===> %02x" % (self.pos, ord(self.minfile[self.pos]))) self.pos += 1 def handleImageRunner(self) : """Handles Canon ImageRunner tags.""" tag = self.readByte() if tag == ord(self.imagerunnermarker1[-1]) : oldpos = self.pos-2 codop = self.minfile[self.pos:self.pos+2] length = unpack(">H", self.minfile[self.pos+6:self.pos+8])[0] self.pos += 18 if codop != self.imagerunnermarker2 : self.pos += length self.logdebug("IMAGERUNNERTAG SKIP %i AT %08x" % (self.pos-oldpos, self.pos)) else : self.pos -= 1 # Adjust position def getJobSize(self) : """Count pages in a PCL5 document. Should also work for PCL3 and PCL4 documents. Algorithm from pclcount (c) 2003, by Eduardo Gielamo Oliveira & Rodolfo Broco Manin published under the terms of the GNU General Public Licence v2. Backported from C to Python by Jerome Alet, then enhanced with more PCL tags detected. I think all the necessary PCL tags are recognized to correctly handle PCL5 files wrt their number of pages. The documentation used for this was : HP PCL/PJL Reference Set PCL5 Printer Language Technical Quick Reference Guide http://h20000.www2.hp.com/bc/docs/support/SupportManual/bpl13205/bpl13205.pdf """ infileno = self.infile.fileno() self.minfile = minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) self.pages = {} self.pagecount = 0 self.resets = 0 self.backsides = [] self.copies = [] self.mediasourcesvalues = [] self.mediasizesvalues = [] self.orientationsvalues = [] self.mediatypesvalues = [] self.linesperpagevalues = [] self.linesperpage = None self.startgfx = [] self.endgfx = [] self.hpgl2 = False self.imagerunnermarker1 = chr(0xcd) + chr(0xca) # Markers for Canon ImageRunner printers self.imagerunnermarker2 = chr(0x10) + chr(0x02) self.isimagerunner = (minfile[:2] == self.imagerunnermarker1) tags = [ lambda : None] * 256 tags[ord(LINEFEED)] = self.newLine tags[ord(FORMFEED)] = self.endPage tags[ord(ESCAPE)] = self.escape tags[ord(ASCIILIMIT)] = self.skipByte tags[ord(self.imagerunnermarker1[0])] = self.handleImageRunner self.esctags = [ lambda : None ] * 256 self.esctags[ord('%')] = self.escPercent self.esctags[ord('*')] = self.escStar self.esctags[ord('&')] = self.escAmp self.esctags[ord('(')] = self.escLeftPar self.esctags[ord(')')] = self.escRightPar self.esctags[ord('E')] = self.escE self.escamptags = [lambda : None ] * 256 self.escamptags[ord('a')] = self.escAmpa self.escamptags[ord('l')] = self.escAmpl self.escamptags[ord('p')] = self.escAmpp self.escamptags[ord('b')] = self.escSkipSomethingW self.escamptags[ord('n')] = self.escSkipSomethingW self.escamptags[ord('u')] = self.escStaroptAmpu self.escstartags = [ lambda : None ] * 256 self.escstartags[ord('b')] = self.escStarb self.escstartags[ord('r')] = self.escStarr self.escstartags[ord('o')] = self.escStaroptAmpu self.escstartags[ord('p')] = self.escStaroptAmpu self.escstartags[ord('t')] = self.escStaroptAmpu self.escstartags[ord('c')] = self.escSkipSomethingW self.escstartags[ord('g')] = self.escSkipSomethingW self.escstartags[ord('i')] = self.escSkipSomethingW self.escstartags[ord('l')] = self.escSkipSomethingW self.escstartags[ord('m')] = self.escSkipSomethingW self.escstartags[ord('v')] = self.escSkipSomethingW self.escleftpartags = [ lambda : None ] * 256 self.escleftpartags[ord('s')] = self.escSkipSomethingW self.escleftpartags[ord('f')] = self.escSkipSomethingW self.escrightpartags = [ lambda : None ] * 256 self.escrightpartags[ord('s')] = self.escSkipSomethingW self.pos = 0 try : try : while 1 : tags[self.readByte()]() except IndexError : # EOF ? pass finally : self.minfile.close() self.logdebug("Pagecount : \t\t\t%i" % self.pagecount) self.logdebug("Resets : \t\t\t%i" % self.resets) self.logdebug("Copies : \t\t\t%s" % self.copies) self.logdebug("NbCopiesMarks : \t\t%i" % len(self.copies)) self.logdebug("MediaTypes : \t\t\t%s" % self.mediatypesvalues) self.logdebug("NbMediaTypes : \t\t\t%i" % len(self.mediatypesvalues)) self.logdebug("MediaSizes : \t\t\t%s" % self.mediasizesvalues) self.logdebug("NbMediaSizes : \t\t\t%i" % len(self.mediasizesvalues)) self.logdebug("MediaSources : \t\t\t%s" % self.mediasourcesvalues) nbmediasourcesdefault = len([m for m in self.mediasourcesvalues if m == 'Default']) nbmediasourcesnotdefault = len(self.mediasourcesvalues) - nbmediasourcesdefault self.logdebug("MediaSourcesDefault : \t\t%i" % nbmediasourcesdefault) self.logdebug("MediaSourcesNOTDefault : \t%i" % nbmediasourcesnotdefault) self.logdebug("Orientations : \t\t\t%s" % self.orientationsvalues) nborientations = len(self.orientationsvalues) self.logdebug("NbOrientations : \t\t\t%i" % nborientations) self.logdebug("StartGfx : \t\t\t%s" % len(self.startgfx)) self.logdebug("EndGfx : \t\t\t%s" % len(self.endgfx)) self.logdebug("BackSides : \t\t\t%s" % self.backsides) self.logdebug("NbBackSides : \t\t\t%i" % len(self.backsides)) self.logdebug("IsImageRunner : \t\t\t%s" % self.isimagerunner) if self.isimagerunner : self.logdebug("Adjusting PageCount : +1") self.pagecount += 1 # ImageRunner adjustment elif self.linesperpage is not None : self.logdebug("Adjusting PageCount : +1") self.pagecount += 1 # Adjusts for incomplete last page elif len(self.startgfx) == len(self.endgfx) == 0 : if self.resets % 2 : if nborientations == self.pagecount + 1 : self.logdebug("Adjusting PageCount : +1") self.pagecount += 1 elif (self.pagecount > 1) \ and (nborientations == self.pagecount - 1) : self.logdebug("Adjusting PageCount : -1") self.pagecount -= 1 elif (self.pagecount > 1) \ and (self.resets == 2) \ and (not nbmediasourcesdefault) \ and (nbmediasourcesnotdefault == 1) : self.logdebug("Adjusting PageCount : -1") self.pagecount -= 1 self.pagecount = self.pagecount or nbmediasourcesdefault if not self.pagecount : if self.resets == len(self.startgfx) : self.pagecount = self.resets defaultpjlcopies = 1 defaultduplexmode = "Simplex" defaultpapersize = "" oldpjlcopies = -1 oldduplexmode = "" oldpapersize = "" for pnum in range(self.pagecount) : # if no number of copies defined, take the preceding one else the one set before any page else 1. page = self.pages.get(pnum, self.pages.get(pnum - 1, self.pages.get(0, { "copies" : 1, "mediasource" : "Main", "mediasize" : "Default", "mediatype" : "Plain", "orientation" : "Portrait", "escaped" : "", "duplex": 0}))) pjlstuff = page["escaped"] if pjlstuff : pjlparser = pjl.PJLParser(pjlstuff) nbdefaultcopies = int(pjlparser.default_variables.get("COPIES", -1)) nbcopies = int(pjlparser.environment_variables.get("COPIES", -1)) nbdefaultqty = int(pjlparser.default_variables.get("QTY", -1)) nbqty = int(pjlparser.environment_variables.get("QTY", -1)) if nbdefaultcopies > -1 : defaultpjlcopies = nbdefaultcopies if nbdefaultqty > -1 : defaultpjlcopies = nbdefaultqty if nbcopies > -1 : pjlcopies = nbcopies elif nbqty > -1 : pjlcopies = nbqty else : if oldpjlcopies == -1 : pjlcopies = defaultpjlcopies else : pjlcopies = oldpjlcopies if page["duplex"] : duplexmode = "Duplex" else : defaultdm = pjlparser.default_variables.get("DUPLEX", "") if defaultdm : if defaultdm.upper() == "ON" : defaultduplexmode = "Duplex" else : defaultduplexmode = "Simplex" envdm = pjlparser.environment_variables.get("DUPLEX", "") if envdm : if envdm.upper() == "ON" : duplexmode = "Duplex" else : duplexmode = "Simplex" else : duplexmode = oldduplexmode or defaultduplexmode defaultps = pjlparser.default_variables.get("PAPER", "") if defaultps : defaultpapersize = defaultps envps = pjlparser.environment_variables.get("PAPER", "") if envps : papersize = envps else : if not oldpapersize : papersize = defaultpapersize else : papersize = oldpapersize else : if oldpjlcopies == -1 : pjlcopies = defaultpjlcopies else : pjlcopies = oldpjlcopies duplexmode = (page["duplex"] and "Duplex") or oldduplexmode or defaultduplexmode if not oldpapersize : papersize = defaultpapersize else : papersize = oldpapersize papersize = oldpapersize or page["mediasize"] if page["mediasize"] != "Default" : papersize = page["mediasize"] if not duplexmode : duplexmode = oldduplexmode or defaultduplexmode oldpjlcopies = pjlcopies oldduplexmode = duplexmode oldpapersize = papersize copies = max(pjlcopies, page["copies"]) # Was : pjlcopies * page["copies"] self.pagecount += (copies - 1) self.logdebug("%s*%s*%s*%s*%s*%s*BW" % (copies, \ page["mediatype"], \ papersize, \ page["orientation"], \ page["mediasource"], \ duplexmode)) return self.pagecount pkpgcounter-3.50/pkpgpdls/pclxl.py0000644000175000017500000007513010726775416016673 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pclxl.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for PCLXL (aka PCL6) documents.""" import sys import os import mmap from struct import unpack import pdlparser import pjl class Parser(pdlparser.PDLParser) : """A parser for PCLXL (aka PCL6) documents.""" totiffcommands = [ 'pcl6 -sDEVICE=pdfwrite -r"%(dpi)i" -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -sOutputFile=- "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -', 'pcl6 -sDEVICE=pswrite -r"%(dpi)i" -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -sOutputFile=- "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -', ] required = [ "pcl6", "gs" ] format = "PCLXL (aka PCL6)" mediasizes = { 0 : "Letter", 1 : "Legal", 2 : "A4", 3 : "Executive", 4 : "Ledger", 5 : "A3", 6 : "COM10Envelope", 7 : "MonarchEnvelope", 8 : "C5Envelope", 9 : "DLEnvelope", 10 : "JB4", 11 : "JB5", 12 : "B5Envelope", 12 : "B5", 14 : "JPostcard", 15 : "JDoublePostcard", 16 : "A5", 17 : "A6", 18 : "JB6", 19 : "JIS8K", 20 : "JIS16K", 21 : "JISExec", 96 : "Default", } mediasources = { 0 : "Default", 1 : "Auto", 2 : "Manual", 3 : "MultiPurpose", 4 : "UpperCassette", 5 : "LowerCassette", 6 : "EnvelopeTray", 7 : "ThirdCassette", } orientations = { 0 : "Portrait", 1 : "Landscape", 2 : "ReversePortrait", 3 : "ReverseLandscape", 4 : "Default", } def isValid(self) : """Returns True if data is PCLXL aka PCL6, else False.""" if (((self.firstblock[:128].find("\033%-12345X") != -1) and \ (self.firstblock.find(" HP-PCL XL;") != -1) and \ ((self.firstblock.find("LANGUAGE=PCLXL") != -1) or \ (self.firstblock.find("LANGUAGE = PCLXL") != -1)))) \ or ((self.firstblock.startswith(chr(0xcd)+chr(0xca)) and (self.firstblock.find(" HP-PCL XL;") != -1))) : return True else : return False def beginPage(self, nextpos) : """Indicates the beginning of a new page, and extracts media information.""" # self.logdebug("BeginPage at %x" % nextpos) self.pagecount += 1 # Default values mediatypelabel = "Plain" mediasourcelabel = "Main" mediasizelabel = "Default" orientationlabel = "Portrait" duplexmode = None # Now go upstream to decode media type, size, source, and orientation # this saves time because we don't need a complete parser ! minfile = self.minfile pos = nextpos - 2 while pos > 0 : # safety check : don't go back to far ! val = ord(minfile[pos]) if val in (0x44, 0x48, 0x41) : # if previous endPage or openDataSource or beginSession (first page) break if val == 0x26 : mediasource = ord(minfile[pos - 2]) mediasourcelabel = self.mediasources.get(mediasource, str(mediasource)) pos -= 4 elif val == 0x25 : while (pos > 0) and (ord(minfile[pos]) != 0xc0) : # we search the preceding ubyte tag pos -= 1 if pos > 0 : if ord(minfile[pos-1]) == 0xc8 : # if we found an ubyte_array then the media # size is completely spelled arraylength = ord(minfile[pos+1]) mediasizelabel = minfile[pos+2:pos+2+arraylength].title() pos -= 1 else : # if we just found an ubyte, then the media # size is known by its index mediasize = ord(minfile[pos+1]) mediasizelabel = self.mediasizes.get(mediasize, str(mediasize)) pos -= 1 # self.logdebug("Media size : %s" % mediasizelabel) elif val == 0x28 : orientation = ord(minfile[pos - 2]) orientationlabel = self.orientations.get(orientation, str(orientation)) pos -= 4 elif val == 0x27 : savepos = pos pos -= 1 startpos = size = None while pos > 0 : # safety check : don't go back to far ! val = ord(minfile[pos]) pos -= 1 if val == 0xc8 : length = self.tags[ord(minfile[pos+2])] # will probably always be a byte or uint16 if length == 1 : startpos = pos + 4 size = unpack("B", self.minfile[pos+3:startpos])[0] elif length == 2 : startpos = pos + 5 size = unpack(self.unpackShort, self.minfile[pos+3:startpos])[0] elif length == 4 : startpos = pos + 7 size = unpack(self.unpackLong, self.minfile[pos+3:startpos])[0] else : raise pdlparser.PDLParserError, "Error on size at %s : %s" % (pos+2, length) break mediatypelabel = minfile[startpos:startpos+size] # self.logdebug("Media type : %s" % mediatypelabel) elif val == 0x34 : duplexmode = "Simplex" pos -= 2 elif val in (0x35, 0x36) : duplexmode = "Duplex" pos -= 2 # else : TODO : CUSTOM MEDIA SIZE AND UNIT ! else : pos -= 1 # ignored self.pages[self.pagecount] = { "copies" : 1, "orientation" : orientationlabel, "mediatype" : mediatypelabel, "mediasize" : mediasizelabel, "mediasource" : mediasourcelabel, "duplex" : duplexmode, } return 0 def endPage(self, nextpos) : """Indicates the end of a page.""" # self.logdebug("EndPage at %x" % nextpos) pos3 = nextpos - 3 minfile = self.minfile if minfile[pos3:nextpos-1] == self.setNumberOfCopies : # The EndPage operator may be preceded by a PageCopies attribute # So set number of copies for current page. # From what I read in PCLXL documentation, the number # of copies is an unsigned 16 bits integer try : nbcopies = unpack(self.unpackShort, minfile[pos3-2:pos3])[0] # self.logdebug("Number of copies : %i" % nbcopies) self.pages[self.pagecount]["copies"] = nbcopies except KeyError : self.logdebug("It looks like this PCLXL file is corrupted.") return 0 def setColorSpace(self, nextpos) : """Changes the color space.""" if self.minfile[nextpos-4:nextpos-1] == self.RGBColorSpace : # TODO : doesn't seem to handle all cases ! self.iscolor = True return 0 def array_Generic(self, nextpos, size) : """Handles all arrays.""" pos = nextpos datatype = ord(self.minfile[pos]) pos += 1 length = self.tags[datatype] if callable(length) : length = length(pos) try : return 1 + length + size * unpack(self.unpackType[length], self.minfile[pos:pos+length])[0] except KeyError : raise pdlparser.PDLParserError, "Error on array size at %x" % nextpos def array_8(self, nextpos) : """Handles byte arrays.""" return self.array_Generic(nextpos, 1) def array_16(self, nextpos) : """Handles 16 bits arrays.""" return self.array_Generic(nextpos, 2) def array_32(self, nextpos) : """Handles 32 bits arrays and Canon ImageRunner tags.""" minfile = self.minfile irtag = minfile[nextpos-1:nextpos+3] if irtag in (self.imagerunnermarker1, self.imagerunnermarker2) : # This is the beginning of a Canon ImageRunner tag # self.logdebug("Canon ImageRunner tag at %x" % (nextpos-1)) codop = minfile[nextpos+1:nextpos+3] length = unpack(">H", minfile[nextpos+7:nextpos+9])[0] # self.logdebug("Canon ImageRunner block length=%04x" % length) toskip = 19 if irtag != self.imagerunnermarker2 : toskip += length # self.logdebug("Canon ImageRunner skip until %x" % (nextpos+toskip)) return toskip else : # This is a normal PCLXL array return self.array_Generic(nextpos, 4) def embeddedDataSmall(self, nextpos) : """Handle small amounts of data.""" return 1 + ord(self.minfile[nextpos]) def embeddedData(self, nextpos) : """Handle normal amounts of data.""" return 4 + unpack(self.unpackLong, self.minfile[nextpos:nextpos+4])[0] def skipHPPCLXL(self, nextpos) : """Skip the 'HP-PCL XL' statement if needed.""" minfile = self.minfile if nextpos and (minfile[nextpos:nextpos+11] == " HP-PCL XL;") : pos = nextpos while minfile[pos] != '\n' : pos += 1 length = (pos - nextpos + 1) # self.logdebug("Skip HP PCLXL statement until %x" % (nextpos + length)) return length else : return 0 def littleEndian(self, nextpos) : """Toggles to little endianness.""" self.unpackType = { 1 : "B", 2 : "H", 4 : ">I" } self.unpackShort = self.unpackType[2] self.unpackLong = self.unpackType[4] # self.logdebug("BigEndian at %x" % (nextpos - 1)) return self.skipHPPCLXL(nextpos) def reservedForFutureUse(self, nextpos) : """Outputs something when a reserved byte is encountered.""" self.logdebug("Byte at %x is out of the PCLXL Protocol Class 2.0 Specification" % nextpos) return 0 def x46_class3(self, nextpos) : """Undocumented tag 0x46 in class 3.0 streams.""" pos = nextpos - 3 minfile = self.minfile val = ord(minfile[pos]) while val == 0xf8 : funcid = ord(minfile[pos+1]) try : offset = self.x46_functions[funcid] except KeyError : self.logdebug("Unexpected subfunction 0x%02x for undocumented tag 0x46 at %x" % (funcid, nextpos)) break else : pos -= offset length = self.tags[ord(self.minfile[pos])] if callable(length) : length = length(pos+1) if funcid == 0x92 : # we want to skip these blocks try : return unpack(self.unpackType[length], self.minfile[pos+1:pos+length+1])[0] except KeyError : raise pdlparser.PDLParserError, "Error on size '%s' at %x" % (length, pos+1) val = ord(minfile[pos]) return 0 def escape(self, nextpos) : """Handles the ESC code.""" pos = endpos = nextpos minfile = self.minfile if minfile[pos : pos+8] == r"%-12345X" : endpos = pos + 9 endmark = chr(0x0c) + chr(0x00) + chr(0x1b) asciilimit = chr(0x80) quotes = 0 while (minfile[endpos] not in endmark) and \ ((minfile[endpos] < asciilimit) or (quotes % 2)) : if minfile[endpos] == '"' : quotes += 1 endpos += 1 # Store this in a per page mapping. # NB : First time will be at page 0 (i.e. **before** page 1) ! stuff = self.escapedStuff.setdefault(self.pagecount, []) stuff.append(minfile[pos : endpos]) self.logdebug("Escaped datas : [%s]" % repr(minfile[pos : endpos])) return endpos - pos def skipKyoceraPrescribe(self, nextpos) : """Skips Kyocera Prescribe commands.""" pos = nextpos - 1 minfile = self.minfile if minfile[pos:pos+3] == "!R!" : while (pos - nextpos) < 1024 : # This is a realistic upper bound, to avoid infinite loops if (minfile[pos] == ";") and (minfile[pos-4:pos] == "EXIT") : pos += 1 prescribe = self.prescribeStuff.setdefault(self.pagecount, []) prescribe.append(minfile[nextpos-1:pos]) self.logdebug("Prescribe commands : [%s]" % repr(minfile[nextpos-1:pos])) break pos += 1 return (pos - nextpos) else : return 0 def getJobSize(self) : """Counts pages in a PCLXL (PCL6) document. Algorithm by Jerome Alet. The documentation used for this was : HP PCL XL Feature Reference Protocol Class 2.0 http://www.hpdevelopersolutions.com/downloads/64/358/xl_ref20r22.pdf Protocol Class 2.1 Supplement xl_ref21.pdf Protocol Class 3.0 Supplement xl_refsup30r089.pdf """ infileno = self.infile.fileno() self.minfile = minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) self.iscolor = False found = False while not found : line = self.infile.readline() if not line : break pos = line.find(" HP-PCL XL;") if pos != -1 : found = True endian = ord(line[pos - 1]) if endian == 0x29 : self.littleEndian(0) elif endian == 0x28 : self.bigEndian(0) # elif endian == 0x27 : # TODO : This is the ASCII binding code : what does it do exactly ? # else : raise pdlparser.PDLParserError, "Unknown endianness marker 0x%02x at start !" % endian if not found : raise pdlparser.PDLParserError, "This file doesn't seem to be PCLXL (aka PCL6)" # Initialize Media Sources for i in range(8, 256) : self.mediasources[i] = "ExternalTray%03i" % (i - 7) # Initialize table of tags self.tags = [ 0 ] * 256 self.tags[0x1b] = self.escape # The escape code self.tags[0x21] = self.skipKyoceraPrescribe # 0x21 is not normally used # GhostScript's sources tell us that HP printers # only accept little endianness, but we can handle both. self.tags[0x28] = self.bigEndian # BigEndian self.tags[0x29] = self.littleEndian # LittleEndian self.tags[0x43] = self.beginPage # BeginPage self.tags[0x44] = self.endPage # EndPage self.tags[0x45] = self.reservedForFutureUse # reserved self.tags[0x46] = self.x46_class3 self.tags[0x4a] = self.reservedForFutureUse # reserved self.tags[0x4b] = self.reservedForFutureUse # reserved self.tags[0x4c] = self.reservedForFutureUse # reserved self.tags[0x4d] = self.reservedForFutureUse # reserved self.tags[0x4e] = self.reservedForFutureUse # reserved self.tags[0x56] = self.reservedForFutureUse # TODO : documentation not clear about reserved status self.tags[0x57] = self.reservedForFutureUse # reserved self.tags[0x59] = self.reservedForFutureUse # reserved self.tags[0x5a] = self.reservedForFutureUse # reserved self.tags[0x6a] = self.setColorSpace # to detect color/b&w mode self.tags[0x87] = self.reservedForFutureUse # reserved self.tags[0x88] = self.reservedForFutureUse # reserved self.tags[0x89] = self.reservedForFutureUse # reserved self.tags[0x8a] = self.reservedForFutureUse # reserved self.tags[0x8b] = self.reservedForFutureUse # reserved self.tags[0x8c] = self.reservedForFutureUse # reserved self.tags[0x8d] = self.reservedForFutureUse # reserved self.tags[0x8e] = self.reservedForFutureUse # reserved self.tags[0x8f] = self.reservedForFutureUse # reserved self.tags[0x90] = self.reservedForFutureUse # reserved self.tags[0x9a] = self.reservedForFutureUse # reserved self.tags[0x9c] = self.reservedForFutureUse # reserved self.tags[0xa4] = self.reservedForFutureUse # reserved self.tags[0xa5] = self.reservedForFutureUse # reserved self.tags[0xa6] = self.reservedForFutureUse # reserved self.tags[0xa7] = self.reservedForFutureUse # reserved self.tags[0xaa] = self.reservedForFutureUse # reserved self.tags[0xab] = self.reservedForFutureUse # reserved self.tags[0xac] = self.reservedForFutureUse # reserved self.tags[0xad] = self.reservedForFutureUse # reserved self.tags[0xae] = self.reservedForFutureUse # reserved self.tags[0xaf] = self.reservedForFutureUse # reserved self.tags[0xb7] = self.reservedForFutureUse # reserved self.tags[0xba] = self.reservedForFutureUse # reserved self.tags[0xbb] = self.reservedForFutureUse # reserved self.tags[0xbc] = self.reservedForFutureUse # reserved self.tags[0xbd] = self.reservedForFutureUse # reserved self.tags[0xbe] = self.reservedForFutureUse # reserved # self.tags[0xbf] = self.passThrough # PassThrough mode should already be taken care of automatically self.tags[0xc0] = 1 # ubyte self.tags[0xc1] = 2 # uint16 self.tags[0xc2] = 4 # uint32 self.tags[0xc3] = 2 # sint16 self.tags[0xc4] = 4 # sint32 self.tags[0xc5] = 4 # real32 self.tags[0xc6] = self.reservedForFutureUse # reserved self.tags[0xc7] = self.reservedForFutureUse # reserved self.tags[0xc8] = self.array_8 # ubyte_array self.tags[0xc9] = self.array_16 # uint16_array self.tags[0xca] = self.array_32 # uint32_array self.tags[0xcb] = self.array_16 # sint16_array self.tags[0xcc] = self.array_32 # sint32_array self.tags[0xcd] = self.array_32 # real32_array and unfortunately Canon ImageRunner self.tags[0xce] = self.reservedForFutureUse # reserved self.tags[0xcf] = self.reservedForFutureUse # reserved self.tags[0xd0] = 2 # ubyte_xy self.tags[0xd1] = 4 # uint16_xy self.tags[0xd2] = 8 # uint32_xy self.tags[0xd3] = 4 # sint16_xy self.tags[0xd4] = 8 # sint32_xy self.tags[0xd5] = 8 # real32_xy self.tags[0xd6] = self.reservedForFutureUse # reserved self.tags[0xd7] = self.reservedForFutureUse # reserved self.tags[0xd8] = self.reservedForFutureUse # reserved self.tags[0xd9] = self.reservedForFutureUse # reserved self.tags[0xda] = self.reservedForFutureUse # reserved self.tags[0xdb] = self.reservedForFutureUse # reserved self.tags[0xdc] = self.reservedForFutureUse # reserved self.tags[0xdd] = self.reservedForFutureUse # reserved self.tags[0xde] = self.reservedForFutureUse # reserved self.tags[0xdf] = self.reservedForFutureUse # reserved self.tags[0xe0] = 4 # ubyte_box self.tags[0xe1] = 8 # uint16_box self.tags[0xe2] = 16 # uint32_box self.tags[0xe3] = 8 # sint16_box self.tags[0xe4] = 16 # sint32_box self.tags[0xe5] = 16 # real32_box self.tags[0xe6] = self.reservedForFutureUse # reserved self.tags[0xe7] = self.reservedForFutureUse # reserved self.tags[0xe8] = self.reservedForFutureUse # reserved self.tags[0xe9] = self.reservedForFutureUse # reserved self.tags[0xea] = self.reservedForFutureUse # reserved self.tags[0xeb] = self.reservedForFutureUse # reserved self.tags[0xec] = self.reservedForFutureUse # reserved self.tags[0xed] = self.reservedForFutureUse # reserved self.tags[0xee] = self.reservedForFutureUse # reserved self.tags[0xef] = self.reservedForFutureUse # reserved self.tags[0xf0] = self.reservedForFutureUse # reserved self.tags[0xf1] = self.reservedForFutureUse # reserved self.tags[0xf2] = self.reservedForFutureUse # reserved self.tags[0xf3] = self.reservedForFutureUse # reserved self.tags[0xf4] = self.reservedForFutureUse # reserved self.tags[0xf5] = self.reservedForFutureUse # reserved self.tags[0xf6] = self.reservedForFutureUse # reserved self.tags[0xf7] = self.reservedForFutureUse # reserved self.tags[0xf8] = 1 # attr_ubyte self.tags[0xf9] = 2 # attr_uint16 self.tags[0xfa] = self.embeddedData # dataLength self.tags[0xfb] = self.embeddedDataSmall # dataLengthByte self.tags[0xfc] = self.reservedForFutureUse # reserved self.tags[0xfd] = self.reservedForFutureUse # reserved self.tags[0xfe] = self.reservedForFutureUse # reserved self.tags[0xff] = self.reservedForFutureUse # reserved # color spaces self.BWColorSpace = "".join([chr(0x00), chr(0xf8), chr(0x03)]) self.GrayColorSpace = "".join([chr(0x01), chr(0xf8), chr(0x03)]) self.RGBColorSpace = "".join([chr(0x02), chr(0xf8), chr(0x03)]) # set number of copies self.setNumberOfCopies = "".join([chr(0xf8), chr(0x31)]) # subcodes for undocumented tag 0x46 and the negative # offset to grab the value from. self.x46_functions = { 0x91 : 5, 0x92 : 5, 0x93 : 3, 0x94 : 3, 0x95 : 5, 0x96 : 2, 0x97 : 2, 0x98 : 2, } # Markers for Canon ImageRunner printers self.imagerunnermarker1 = chr(0xcd) + chr(0xca) + chr(0x10) + chr(0x00) self.imagerunnermarker2 = chr(0xcd) + chr(0xca) + chr(0x10) + chr(0x02) self.pages = { 0 : { "copies" : 1, "orientation" : "Default", "mediatype" : "Plain", "mediasize" : "Default", "mediasource" : "Default", "duplex" : None, } } tags = self.tags self.pagecount = 0 self.escapedStuff = {} # For escaped datas, mostly PJL commands self.prescribeStuff = {} # For Kyocera Prescribe commands pos = oldpos = 0 try : try : while 1 : try : tag = ord(minfile[pos]) except OverflowError : pos = oldpos + 1 pos += 1 length = tags[tag] if length : if callable(length) : length = length(pos) oldpos = pos pos += length except IndexError : # EOF ? pass finally : self.minfile.close() # now handle number of copies for each page (may differ). if self.iscolor : colormode = "Color" else : colormode = "BW" defaultduplexmode = "Simplex" defaultpapersize = "" defaultpjlcopies = 1 oldpjlcopies = -1 oldduplexmode = "" oldpapersize = "" for pnum in range(1, self.pagecount + 1) : # if no number of copies defined, take 1, as explained # in PCLXL documentation. # NB : is number of copies is 0, the page won't be output # but the formula below is still correct : we want # to decrease the total number of pages in this case. page = self.pages.get(pnum, self.pages.get(1, { "copies" : 1, "mediasize" : "Default", "duplex" : None })) pjlstuff = self.escapedStuff.get(pnum, self.escapedStuff.get(0, [])) if pjlstuff : pjlparser = pjl.PJLParser("".join(pjlstuff)) nbdefaultcopies = int(pjlparser.default_variables.get("COPIES", -1)) nbcopies = int(pjlparser.environment_variables.get("COPIES", -1)) nbdefaultqty = int(pjlparser.default_variables.get("QTY", -1)) nbqty = int(pjlparser.environment_variables.get("QTY", -1)) if nbdefaultcopies > -1 : defaultpjlcopies = nbdefaultcopies if nbdefaultqty > -1 : defaultpjlcopies = nbdefaultqty if nbcopies > -1 : pjlcopies = nbcopies elif nbqty > -1 : pjlcopies = nbqty else : if oldpjlcopies == -1 : pjlcopies = defaultpjlcopies else : pjlcopies = oldpjlcopies if page["duplex"] : duplexmode = page["duplex"] else : defaultdm = pjlparser.default_variables.get("DUPLEX", "") if defaultdm : if defaultdm.upper() == "ON" : defaultduplexmode = "Duplex" else : defaultduplexmode = "Simplex" envdm = pjlparser.environment_variables.get("DUPLEX", "") if envdm : if envdm.upper() == "ON" : duplexmode = "Duplex" else : duplexmode = "Simplex" else : if not oldduplexmode : duplexmode = defaultduplexmode else : duplexmode = oldduplexmode defaultps = pjlparser.default_variables.get("PAPER", "") if defaultps : defaultpapersize = defaultps envps = pjlparser.environment_variables.get("PAPER", "") if envps : papersize = envps else : if not oldpapersize : papersize = defaultpapersize else : papersize = oldpapersize else : if oldpjlcopies == -1 : pjlcopies = defaultpjlcopies else : pjlcopies = oldpjlcopies if not oldduplexmode : duplexmode = defaultduplexmode else : duplexmode = oldduplexmode if not oldpapersize : papersize = defaultpapersize else : papersize = oldpapersize duplexmode = oldduplexmode papersize = oldpapersize or page["mediasize"] if page["mediasize"] != "Default" : papersize = page["mediasize"] if not duplexmode : duplexmode = oldduplexmode or defaultduplexmode oldpjlcopies = pjlcopies oldduplexmode = duplexmode oldpapersize = papersize copies = max(pjlcopies, page["copies"]) # Was : pjlcopies * page["copies"] self.pagecount += (copies - 1) self.logdebug("%s*%s*%s*%s*%s*%s*%s" % (copies, page["mediatype"], papersize, page["orientation"], page["mediasource"], duplexmode, colormode)) return self.pagecount pkpgcounter-3.50/pkpgpdls/pdf.py0000644000175000017500000001076710726775416016327 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pdf.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for PDF documents.""" import re import pdlparser class PDFObject : """A class for PDF objects.""" def __init__(self, major, minor, description) : """Initialize the PDF object.""" self.major = major self.minor = minor self.majori = int(major) self.minori = int(minor) self.description = description self.comments = [] self.content = [] self.parent = None self.kids = [] class Parser(pdlparser.PDLParser) : """A parser for PDF documents.""" totiffcommands = [ 'gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" "%(infname)s"' ] required = [ "gs" ] openmode = "rU" format = "PDF" def isValid(self) : """Returns True if data is PDF, else False.""" if self.firstblock.startswith("%PDF-") or \ self.firstblock.startswith("\033%-12345X%PDF-") or \ ((self.firstblock[:128].find("\033%-12345X") != -1) and (self.firstblock.upper().find("LANGUAGE=PDF") != -1)) or \ (self.firstblock.find("%PDF-") != -1) : return True else : return False def getJobSize(self) : """Counts pages in a PDF document.""" # First we start with a generic PDF parser. lastcomment = None objects = {} inobject = 0 objre = re.compile(r"\s?(\d+)\s+(\d+)\s+obj[<\s/]?") for line in self.infile : line = line.strip() if line.startswith("% ") : if inobject : obj.comments.append(line) else : lastcomment = line[2:] else : # New object begins here result = objre.search(line) if result is not None : (major, minor) = line[result.start():result.end()].split()[:2] obj = PDFObject(major, minor, lastcomment) obj.content.append(line[result.end():]) inobject = 1 elif line.startswith("endobj") \ or line.startswith(">> endobj") \ or line.startswith(">>endobj") : # Handle previous object, if any if inobject : # only overwrite older versions of this object # same minor seems to be possible, so the latest one # found in the file will be the one we keep. # if we want the first one, just use > instead of >= oldobject = objects.setdefault(major, obj) if int(minor) >= oldobject.minori : objects[major] = obj # self.logdebug("Object(%i, %i) overwritten with Object(%i, %i)" % (oldobject.majori, oldobject.minori, obj.majori, obj.minori)) # self.logdebug("Object(%i, %i)" % (obj.majori, obj.minori)) inobject = 0 else : if inobject : obj.content.append(line) # Now we check each PDF object we've just created. newpageregexp = re.compile(r"(/Type)\s?(/Page)[/>\s]", re.I) pagecount = 0 for obj in objects.values() : content = "".join(obj.content) count = len(newpageregexp.findall(content)) if count and (content != r"<>") : # Empty pages which are not rendered ? pagecount += count return pagecount pkpgcounter-3.50/pkpgpdls/pdlparser.py0000644000175000017500000001356110726775416017545 0ustar jeromejerome# # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pdlparser.py 374 2007-12-09 14:26:15Z jerome $ # """This module defines the base class for all Page Description Language parsers.""" import sys import os KILOBYTE = 1024 MEGABYTE = 1024 * KILOBYTE FIRSTBLOCKSIZE = 16 * KILOBYTE LASTBLOCKSIZE = int(KILOBYTE / 4) class PDLParserError(Exception): """An exception for PDLParser related stuff.""" def __init__(self, message = ""): self.message = message Exception.__init__(self, message) def __repr__(self): return self.message __str__ = __repr__ class PDLParser : """Generic PDL parser.""" totiffcommands = None # Default command to convert to TIFF required = [] # Default list of required commands openmode = "rb" # Default file opening mode format = "Unknown" # Default file format def __init__(self, parent, filename, (firstblock, lastblock)) : """Initialize the generic parser.""" self.parent = parent # We need some copies for later inclusion of parsers which # would modify the parent's values self.filename = filename[:] self.firstblock = firstblock[:] self.lastblock = lastblock[:] self.infile = None if not self.isValid() : raise PDLParserError, "Invalid file format !" else : self.logdebug("Input file is in the '%s' file format." % self.format) try : import psyco except ImportError : pass # Psyco is not installed else : # Psyco is installed, tell it to compile # the CPU intensive methods : PCL and PCLXL # parsing will greatly benefit from this. psyco.bind(self.getJobSize) self.infile = open(self.filename, self.openmode) # self.logdebug("Opened %s in '%s' mode." % (self.filename, self.openmode)) def __del__(self) : """Ensures the input file gets closed.""" if self.infile : self.infile.close() def findExecutable(self, command) : """Finds an executable in the PATH and returns True if found else False.""" for cmd in [p.strip() for p in command.split("|")] : # | can separate alternatives for similar commands (e.g. a2ps|enscript) for path in os.environ.get("PATH", "").split(":") : fullname = os.path.abspath(os.path.join(os.path.expanduser(path), cmd)) if os.path.isfile(fullname) and os.access(fullname, os.X_OK) : return True return False def isMissing(self, commands) : """Returns True if some required commands are missing, else False.""" howmanythere = 0 for command in commands : if not self.findExecutable(command) : sys.stderr.write("ERROR: %(command)s is missing or not executable. You MUST install it for pkpgcounter to be able to do what you want.\n" % locals()) sys.stderr.flush() else : howmanythere += 1 if howmanythere == len(commands) : return False else : return True def logdebug(self, message) : """Logs a debug message if needed.""" if self.parent.options.debug : sys.stderr.write("%s\n" % message) def isValid(self) : """Returns True if data is in the expected format, else False.""" raise RuntimeError, "Not implemented !" def getJobSize(self) : """Counts pages in a document.""" raise RuntimeError, "Not implemented !" def convertToTiffMultiPage24NC(self, outfname, dpi) : """Converts the input file to TIFF format, X dpi, 24 bits per pixel, uncompressed. Writes TIFF datas to the file named by outfname. """ if self.totiffcommands : if self.isMissing(self.required) : raise PDLParserError, "At least one of the following commands is missing and should be installed for the computation of ink coverage : %s" % repr(self.required) infname = self.filename for totiffcommand in self.totiffcommands : error = False commandline = totiffcommand % locals() # self.logdebug("Executing '%s'" % commandline) status = os.system(commandline) if os.WIFEXITED(status) : if os.WEXITSTATUS(status) : error = True else : error = True if not os.path.exists(outfname) : error = True elif not os.stat(outfname).st_size : error = True else : break # Conversion worked fine it seems. sys.stderr.write("Command failed : %s\n" % repr(commandline)) if error : raise PDLParserError, "Problem during conversion to TIFF." else : raise PDLParserError, "Impossible to compute ink coverage for this file format." pkpgcounter-3.50/pkpgpdls/pil.py0000644000175000017500000000414510726775416016333 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pil.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for image formats supported by the Python Imaging Library.""" import pdlparser try : from PIL import Image except ImportError : sys.stderr.write("ERROR: You MUST install the Python Imaging Library (python-imaging) for pkpgcounter to work.\n") raise pdlparser.PDLParserError, "The Python Imaging Library is missing." import version class Parser(pdlparser.PDLParser) : """A parser for plain text documents.""" totiffcommands = [ 'convert "%(infname)s" "%(outfname)s"' ] required = [ "convert" ] def isValid(self) : """Returns True if data is an image format supported by PIL, else False.""" try : image = Image.open(self.filename) except (IOError, OverflowError) : return False else : self.format = "%s (%s)" % (image.format, image.format_description) return True def getJobSize(self) : """Counts pages in an image file.""" index = 0 image = Image.open(self.filename) try : while True : index += 1 image.seek(index) except EOFError : pass return index pkpgcounter-3.50/pkpgpdls/pjl.py0000644000175000017500000001326510674212011016312 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pjl.py 291 2007-09-19 12:20:25Z jerome $ # """This modules implements a really minimalist PJL/EJL parser.""" # NOTES : QTY= is the number of collated copies for a job. # NOTES : COPIES= is the number of uncollated copies for each page of a job import sys class PJLParserError(Exception): """An exception for PJLParser related stuff.""" def __init__(self, message = ""): self.message = message Exception.__init__(self, message) def __repr__(self): return self.message __str__ = __repr__ class PJLParser : """A parser for PJL documents. Information extracted for bpl11897.pdf which was downloaded from Hewlett-Packard's website. """ JL = "PJL" def __init__(self, pjljob, debug=0) : """Initializes JL Parser.""" self.debug = debug self.jlmarker = "@%s" % self.JL self.statements = pjljob.replace("\r\n", "\n").split("\n") self.default_variables = {} self.environment_variables = {} self.parsed = 0 self.parse() def __str__(self) : """Outputs our variables as a string of text.""" if not self.parsed : return "" mybuffer = [] if self.default_variables : mybuffer.append("Default variables :") for (k, v) in self.default_variables.items() : mybuffer.append(" %s : %s" % (k, v)) if self.environment_variables : mybuffer.append("Environment variables :") for (k, v) in self.environment_variables.items() : mybuffer.append(" %s : %s" % (k, v)) return "\n".join(mybuffer) def logdebug(self, message) : """Logs a debug message if needed.""" if self.debug : sys.stderr.write("%s\n" % message) def cleanvars(self) : """Cleans the variables dictionnaries.""" for dicname in ("default", "environment") : varsdic = getattr(self, "%s_variables" % dicname) for (k, v) in varsdic.items() : if len(v) == 1 : varsdic[k] = v[0] def parse(self) : """Parses a JL job.""" for i in range(len(self.statements)) : statement = self.statements[i] if statement.startswith(self.jlmarker) : parts = statement.split() nbparts = len(parts) if parts[0] == self.jlmarker : # this is a valid JL statement, but we don't # want to examine all of them... if (nbparts > 2) \ and ((parts[1].upper() in ("SET", "DEFAULT")) \ or ((self.jlmarker == "@EJL") and (parts[1].upper() == "JI"))) : # this is what we are interested in ! try : (varname, value) = "".join(parts[2:]).split("=", 1) # TODO : parse multiple assignments on the same SET/JI statement except : self.logdebug("Invalid JL SET statement [%s]" % repr(statement)) else : # all still looks fine... if parts[1].upper() == "DEFAULT" : varsdic = self.default_variables else : varsdic = self.environment_variables variable = varsdic.setdefault(varname.upper(), []) variable.append(value) else : self.logdebug("Ignored JL statement [%s]" % repr(statement)) self.logdebug(parts) else : self.logdebug("Invalid JL statement [%s]" % repr(statement)) else : self.logdebug("Invalid JL statement [%s]" % repr(statement)) self.cleanvars() self.parsed = 1 class EJLParser(PJLParser) : """A parser for EJL (Epson Job Language) documents.""" JL = "EJL" def test() : """Test function.""" if (len(sys.argv) < 2) or ((not sys.stdin.isatty()) and ("-" not in sys.argv[1:])) : sys.argv.append("-") for arg in sys.argv[1:] : klass = PJLParser if arg == "-" : infile = sys.stdin mustclose = 0 else : if arg.endswith(".ejl") : klass = EJLParser infile = open(arg, "rb") mustclose = 1 try : parser = klass(infile.read(), debug=1) except PJLParserError, msg : sys.stderr.write("ERROR: %s\n" % msg) sys.stderr.flush() if mustclose : infile.close() print str(parser) if __name__ == "__main__" : test() pkpgcounter-3.50/pkpgpdls/plain.py0000644000175000017500000000611310726775416016647 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: plain.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for plain text documents.""" import pdlparser import version class Parser(pdlparser.PDLParser) : """A parser for plain text documents.""" totiffcommands = [ 'enscript --quiet --portrait --no-header --columns 1 --output - "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -', 'a2ps --borders 0 --quiet --portrait --no-header --columns 1 --output - "%(infname)s" | gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" -', ] required = [ "a2ps | enscript", "gs" ] openmode = "rU" format = "plain text" def isValid(self) : """Returns True if data is plain text, else False. It's hard to detect a plain text file, so we just try to extract lines from the first block (sufficiently large). If it's impossible to find one we consider it's not plain text. """ lines = self.firstblock.split("\r\n") if len(lines) == 1 : lines = lines[0].split("\r") if len(lines) == 1 : lines = lines[0].split("\n") if len(lines) > 1 : return True else : return False def getJobSize(self) : """Counts pages in a plain text document.""" pagesize = 66 # TODO : Does this vary wrt the default page size ? # TODO : /etc/papersize and /etc/paper.config pagecount = 0 linecount = 0 for line in self.infile : if line.endswith("\n") : linecount += 1 if (linecount > pagesize) : pagecount += 1 linecount = 0 else : cnt = line.count("\f") if cnt : pagecount += cnt linecount = 0 else : raise pdlparser.PDLParserError, "Unsupported file format. Please send the file to %s" % version.__authoremail__ return pagecount + 1 # NB : empty files are catched in isValid() pkpgcounter-3.50/pkpgpdls/pnmascii.py0000644000175000017500000000401210726775416017343 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: pnmascii.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for PNM (ascii) documents.""" import pdlparser class Parser(pdlparser.PDLParser) : """A parser for PNM (ascii) documents.""" openmode = "rU" format = "PNM (ascii)" def isValid(self) : """Returns True if data is ASCII PNM, else False.""" if self.firstblock.split()[0] in ("P1", "P2", "P3") : self.marker = self.firstblock[:2] return True else : return False def getJobSize(self) : """Counts pages in a PNM (ascii) document.""" pagecount = 0 linecount = 0 divby = 1 marker = self.marker for line in self.infile : linecount += 1 if (linecount == 2) and (line.find("device=pksm") != -1) : # Special case of cmyk map divby = 4 # Unfortunately any whitespace is valid, # so we do it the slow way... pagecount += line.split().count(marker) if not (pagecount % divby) : return pagecount // divby else : return pagecount pkpgcounter-3.50/pkpgpdls/postscript.py0000644000175000017500000002145210726775416017761 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: postscript.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for PostScript documents.""" import sys import os import pdlparser import inkcoverage class Parser(pdlparser.PDLParser) : """A parser for PostScript documents.""" totiffcommands = [ 'gs -sDEVICE=tiff24nc -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET -r"%(dpi)i" -sOutputFile="%(outfname)s" "%(infname)s"' ] required = [ "gs" ] openmode = "rU" format = "PostScript" def isValid(self) : """Returns True if data is PostScript, else False.""" if self.firstblock.startswith("%!") or \ self.firstblock.startswith("\004%!") or \ self.firstblock.startswith("\033%-12345X%!PS") or \ ((self.firstblock[:128].find("\033%-12345X") != -1) and \ ((self.firstblock.find("LANGUAGE=POSTSCRIPT") != -1) or \ (self.firstblock.find("LANGUAGE = POSTSCRIPT") != -1) or \ (self.firstblock.find("LANGUAGE = Postscript") != -1))) or \ (self.firstblock.find("%!PS-Adobe") != -1) : return True else : return False def throughGhostScript(self) : """Get the count through GhostScript, useful for non-DSC compliant PS files.""" self.logdebug("Internal parser sucks, using GhostScript instead...") if self.isMissing(self.required) : raise pdlparser.PDLParserError, "The gs interpreter is nowhere to be found in your PATH (%s)" % os.environ.get("PATH", "") infname = self.filename command = 'gs -sDEVICE=bbox -dPARANOIDSAFER -dNOPAUSE -dBATCH -dQUIET "%(infname)s" 2>&1 | grep -c "%%HiResBoundingBox:" 2>/dev/null' pagecount = 0 fromchild = os.popen(command % locals(), "r") try : try : pagecount = int(fromchild.readline().strip()) except (IOError, OSError, AttributeError, ValueError), msg : raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document : %s" % msg finally : if fromchild.close() is not None : raise pdlparser.PDLParserError, "Problem during analysis of Binary PostScript document" self.logdebug("GhostScript said : %s pages" % pagecount) return pagecount * self.copies def natively(self) : """Count pages in a DSC compliant PostScript document.""" pagecount = 0 self.pages = { 0 : { "copies" : 1 } } oldpagenum = None previousline = "" notrust = False prescribe = False # Kyocera's Prescribe commands acrobatmarker = False pagescomment = None for line in self.infile : line = line.strip() if (not prescribe) and line.startswith(r"%%BeginResource: procset pdf") \ and not acrobatmarker : notrust = True # Let this stuff be managed by GhostScript, but we still extract number of copies elif line.startswith(r"%ADOPrintSettings: L") : acrobatmarker = True elif line.startswith("!R!") : prescribe = True elif line.startswith(r"%%Pages: ") : try : pagescomment = max(pagescomment or 0, int(line.split()[1])) except ValueError : pass # strange, to say the least elif line.startswith(r"%%Page: ") or line.startswith(r"(%%[Page: ") : proceed = 1 try : # treats both "%%Page: x x" and "%%Page: (x-y) z" (probably N-up mode) newpagenum = int(line.split(']')[0].split()[-1]) except : notinteger = 1 # It seems that sometimes it's not an integer but an EPS file name else : notinteger = 0 if newpagenum == oldpagenum : proceed = 0 else : oldpagenum = newpagenum if proceed and not notinteger : pagecount += 1 self.pages[pagecount] = { "copies" : self.pages[pagecount-1]["copies"] } elif line.startswith(r"%%Requirements: numcopies(") : try : number = int(line.split('(')[1].split(')')[0]) except : pass else : if number > self.pages[pagecount]["copies"] : self.pages[pagecount]["copies"] = number elif line.startswith(r"%%BeginNonPPDFeature: NumCopies ") : # handle # of copies set by some Windows printer driver try : number = int(line.split()[2]) except : pass else : if number > self.pages[pagecount]["copies"] : self.pages[pagecount]["copies"] = number elif line.startswith("1 dict dup /NumCopies ") : # handle # of copies set by mozilla/kprinter try : number = int(line.split()[4]) except : pass else : if number > self.pages[pagecount]["copies"] : self.pages[pagecount]["copies"] = number elif line.startswith("{ pop 1 dict dup /NumCopies ") : # handle # of copies set by firefox/kprinter/cups (alternate syntax) try : number = int(line.split()[6]) except : pass else : if number > self.pages[pagecount]["copies"] : self.pages[pagecount]["copies"] = number elif line.startswith("/languagelevel where{pop languagelevel}{1}ifelse 2 ge{1 dict dup/NumCopies") : try : number = int(previousline[2:]) except : pass else : if number > self.pages[pagecount]["copies"] : self.pages[pagecount]["copies"] = number elif line.startswith("/#copies ") : try : number = int(line.split()[1]) except : pass else : if number > self.pages[pagecount]["copies"] : self.pages[pagecount]["copies"] = number elif line.startswith(r"%RBINumCopies: ") : try : number = int(line.split()[1]) except : pass else : if number > self.pages[pagecount]["copies"] : self.pages[pagecount]["copies"] = number previousline = line # extract max number of copies to please the ghostscript parser, just # in case we will use it later self.copies = max([ v["copies"] for (k, v) in self.pages.items() ]) # now apply the number of copies to each page if not pagecount and pagescomment : pagecount = pagescomment for pnum in range(1, pagecount + 1) : page = self.pages.get(pnum, self.pages.get(1, self.pages.get(0, { "copies" : 1 }))) copies = page["copies"] pagecount += (copies - 1) self.logdebug("%s * page #%s" % (copies, pnum)) self.logdebug("Internal parser said : %s pages" % pagecount) return (pagecount, notrust) def getJobSize(self) : """Count pages in PostScript document.""" self.copies = 1 (nbpages, notrust) = self.natively() newnbpages = nbpages if notrust or not nbpages : try : newnbpages = self.throughGhostScript() except pdlparser.PDLParserError, msg : self.logdebug(msg) return max(nbpages, newnbpages) pkpgcounter-3.50/pkpgpdls/qpdl.py0000644000175000017500000002757510726775416016523 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: qpdl.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for QPDL (aka SPL2) documents.""" import sys import os import mmap from struct import unpack import pdlparser import pjl class Parser(pdlparser.PDLParser) : """A parser for QPDL (aka SPL2) documents.""" format = "QPDL (aka SPL2)" mediasizes = { # The first values are identical to that of PCLXL 0 : "Letter", 1 : "Legal", 2 : "A4", 3 : "Executive", 4 : "Ledger", 5 : "A3", 6 : "COM10Envelope", 7 : "MonarchEnvelope", 8 : "C5Envelope", 9 : "DLEnvelope", 10 : "JB4", 11 : "JB5", 12 : "B5Envelope", 12 : "B5", 14 : "JPostcard", 15 : "JDoublePostcard", 16 : "A5", 17 : "A6", 18 : "JB6", 21 : "Custom", 23 : "C6", 24 : "Folio", } mediasources = { # Again, values are identical to that of PCLXL 0 : "Default", 1 : "Auto", 2 : "Manual", 3 : "MultiPurpose", 4 : "UpperCassette", 5 : "LowerCassette", 6 : "EnvelopeTray", 7 : "ThirdCassette", } def isValid(self) : """Returns True if data is QPDL aka SPL2, else False.""" if ((self.firstblock[:128].find("\033%-12345X") != -1) and \ ((self.firstblock.find("LANGUAGE=QPDL") != -1) or \ (self.firstblock.find("LANGUAGE = QPDL") != -1))) : return True else : return False def beginPage(self, nextpos) : """Indicates the beginning of a new page, and extracts media information.""" self.pagecount += 1 copies = unpack(self.unpackShort, self.minfile[nextpos+1:nextpos+3])[0] mediasize = ord(self.minfile[nextpos+3]) mediasource = ord(self.minfile[nextpos+8]) duplexmode = unpack(self.unpackShort, self.minfile[nextpos+10:nextpos+12])[0] self.pages[self.pagecount] = { "copies" : copies, "mediasize" : self.mediasizes.get(mediasize, str(mediasize)), "mediasource" : self.mediasources.get(mediasource, str(mediasource)), "duplex" : duplexmode, } return 16 # Length of a page header def endPage(self, nextpos) : """Indicates the end of a page.""" epcopies = unpack(self.unpackShort, self.minfile[nextpos:nextpos+2])[0] bpcopies = self.pages[self.pagecount]["copies"] if epcopies != bpcopies : self.logdebug("ERROR: discrepancy between beginPage (%i) and endPage (%i) copies" % (bpcopies, epcopies)) return 2 # Length of a page footer def beginBand(self, nextpos) : """Indicates the beginning of a new band.""" bandlength = unpack(self.unpackLong, self.minfile[nextpos+6:nextpos+10])[0] return bandlength + 10 # Length of a band header - length of checksum def littleEndian(self) : """Toggles to little endianness.""" self.unpackType = { 1 : "B", 2 : "H", 4 : ">I" } self.unpackShort = self.unpackType[2] self.unpackLong = self.unpackType[4] return 0 def escape(self, nextpos) : """Handles the ESC code.""" pos = endpos = nextpos minfile = self.minfile if minfile[pos : pos+8] == r"%-12345X" : endpos = pos + 9 endmark = chr(0x0c) + chr(0x00) + chr(0x1b) asciilimit = chr(0x80) quotes = 0 while (minfile[endpos] not in endmark) and \ ((minfile[endpos] < asciilimit) or (quotes % 2)) : if minfile[endpos] == '"' : quotes += 1 endpos += 1 # Store this in a per page mapping. # NB : First time will be at page 0 (i.e. **before** page 1) ! stuff = self.escapedStuff.setdefault(self.pagecount, []) stuff.append(minfile[pos : endpos]) self.logdebug("Escaped datas : [%s]" % repr(minfile[pos : endpos])) return endpos - pos def maybeEOF(self, nextpos) : """Tries to detect the EOF marker.""" if self.minfile[nextpos:nextpos+9] == self.eofmarker : return 9 else : return 0 def getJobSize(self) : """Counts pages in a QPDL (SPL2) document. Algorithm by Jerome Alet. The documentation used for this was : Spécification Technique (documentation non officielle) Le Language SPL2 par Aurélien Croc http://splix.ap2c.org """ # Initialize table of tags self.tags = [ lambda pos : 0 ] * 256 self.tags[0x00] = self.beginPage self.tags[0x01] = self.endPage self.tags[0x09] = self.maybeEOF self.tags[0x0c] = self.beginBand self.tags[0x1b] = self.escape # The escape code self.eofmarker = "\033%-12345X" infileno = self.infile.fileno() self.pages = { 0 : { "copies" : 1, "orientation" : "Default", "mediatype" : "Plain", "mediasize" : "Default", "mediasource" : "Default", "duplex" : None, } } self.minfile = minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) self.pagecount = 0 self.escapedStuff = {} # For escaped datas, mostly PJL commands self.bigEndian() pos = 0 tags = self.tags try : try : while 1 : tag = ord(minfile[pos]) pos += 1 pos += tags[tag](pos) except IndexError : # EOF ? pass finally : self.minfile.close() defaultduplexmode = "Simplex" defaultpapersize = "" defaultpjlcopies = 1 oldpjlcopies = -1 oldduplexmode = "" oldpapersize = "" for pnum in range(1, self.pagecount + 1) : # NB : is number of copies is 0, the page won't be output # but the formula below is still correct : we want # to decrease the total number of pages in this case. page = self.pages.get(pnum, self.pages.get(1, { "copies" : 1, "mediasize" : "Default", "duplex" : None })) pjlstuff = self.escapedStuff.get(pnum, self.escapedStuff.get(0, [])) if pjlstuff : pjlparser = pjl.PJLParser("".join(pjlstuff)) nbdefaultcopies = int(pjlparser.default_variables.get("COPIES", -1)) nbcopies = int(pjlparser.environment_variables.get("COPIES", -1)) nbdefaultqty = int(pjlparser.default_variables.get("QTY", -1)) nbqty = int(pjlparser.environment_variables.get("QTY", -1)) if nbdefaultcopies > -1 : defaultpjlcopies = nbdefaultcopies if nbdefaultqty > -1 : defaultpjlcopies = nbdefaultqty if nbcopies > -1 : pjlcopies = nbcopies elif nbqty > -1 : pjlcopies = nbqty else : if oldpjlcopies == -1 : pjlcopies = defaultpjlcopies else : pjlcopies = oldpjlcopies if page["duplex"] : duplexmode = page["duplex"] else : defaultdm = pjlparser.default_variables.get("DUPLEX", "") if defaultdm : if defaultdm.upper() == "ON" : defaultduplexmode = "Duplex" else : defaultduplexmode = "Simplex" envdm = pjlparser.environment_variables.get("DUPLEX", "") if envdm : if envdm.upper() == "ON" : duplexmode = "Duplex" else : duplexmode = "Simplex" else : if not oldduplexmode : duplexmode = defaultduplexmode else : duplexmode = oldduplexmode defaultps = pjlparser.default_variables.get("PAPER", "") if defaultps : defaultpapersize = defaultps envps = pjlparser.environment_variables.get("PAPER", "") if envps : papersize = envps else : if not oldpapersize : papersize = defaultpapersize else : papersize = oldpapersize else : if oldpjlcopies == -1 : pjlcopies = defaultpjlcopies else : pjlcopies = oldpjlcopies if not oldduplexmode : duplexmode = defaultduplexmode else : duplexmode = oldduplexmode if not oldpapersize : papersize = defaultpapersize else : papersize = oldpapersize duplexmode = oldduplexmode papersize = oldpapersize or page["mediasize"] if page["mediasize"] != "Default" : papersize = page["mediasize"] if not duplexmode : duplexmode = oldduplexmode or defaultduplexmode oldpjlcopies = pjlcopies oldduplexmode = duplexmode oldpapersize = papersize copies = max(pjlcopies, page["copies"]) # Was : pjlcopies * page["copies"] self.pagecount += (copies - 1) self.logdebug("%s*%s*%s*%s" % (copies, papersize, page["mediasource"], duplexmode)) return self.pagecount pkpgcounter-3.50/pkpgpdls/spl1.py0000644000175000017500000001164610726775416016432 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: spl1.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for SPL1 documents.""" import os import mmap import struct import pdlparser import version ESCAPECHARS = (chr(0x1b), chr(0x24)) class Parser(pdlparser.PDLParser) : """A parser for SPL1 documents.""" format = "SPL1 (aka GDI)" def isValid(self) : """Returns True if data is SPL1, else False.""" if ((self.firstblock[:128].find("\033%-12345X") != -1) and \ (self.firstblock.find("$PJL ") != -1) and \ ((self.firstblock.find("LANGUAGE=SMART") != -1) or \ (self.firstblock.find("LANGUAGE = SMART") != -1))) : return True else : return False def littleEndian(self) : """Toggles to little endianness.""" self.unpackType = { 1 : "B", 2 : "H", 4 : ">I" } self.unpackShort = self.unpackType[2] self.unpackLong = self.unpackType[4] # self.logdebug("Big Endian") return 0 def escape(self, nextpos) : """Handles the ESC code.""" self.isbitmap = False pos = endpos = nextpos minfile = self.minfile if minfile[pos : pos+8] == r"%-12345X" : endpos = pos + 9 elif minfile[pos-1] in ESCAPECHARS : endpos = pos else : return 0 endmark = (chr(0x1b), chr(0x00)) asciilimit = chr(0x80) quotes = 0 while (minfile[endpos] not in endmark) and \ ((minfile[endpos] < asciilimit) or (quotes % 2)) : if minfile[endpos] == '"' : quotes += 1 endpos += 1 # Store this in a per page mapping. # NB : First time will be at page 0 (i.e. **before** page 1) ! stuff = self.escapedStuff.setdefault(self.pagecount, []) datas = minfile[pos-1 : endpos] stuff.append(datas) if datas.endswith("$PJL BITMAP START\r\n") : self.isbitmap = True # self.logdebug("New bitmap") self.logdebug("Escaped datas : [%s]" % repr(datas)) return endpos - pos + 1 def getJobSize(self) : """Counts pages in an SPL1 document. Algorithm by Jerome Alet. """ infileno = self.infile.fileno() self.minfile = minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) self.pagecount = 0 self.escapedStuff = {} # For escaped datas, mostly PJL commands self.bigEndian() self.isbitmap = False pos = 0 unpack = struct.unpack try : try : while 1 : tag = minfile[pos] if tag in ESCAPECHARS : pos += self.escape(pos+1) else : if not self.isbitmap : raise pdlparser.PDLParserError, "Unfortunately SPL1 is incompletely recognized. Parsing aborted. Please report the problem to %s" % version.__authoremail__ (offset, seqnum) = unpack(">IH", minfile[pos:pos+6]) # self.logdebug("Offset : %i Sequence Number : %i" % (offset, seqnum)) if not seqnum : # Sequence number resets to 0 for each new page. self.pagecount += 1 pos += 4 + offset except struct.error, msg : raise pdlparser.PDLParserError, "Unfortunately SPL1 is incompletely recognized (%s). Parsing aborted. Please report the problem to %s" % (msg, version.__authoremail__) except IndexError : # EOF ? pass finally : minfile.close() return self.pagecount pkpgcounter-3.50/pkpgpdls/tiff.py0000644000175000017500000000572510726775416016504 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: tiff.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for TIFF documents.""" import sys import os import mmap from struct import unpack import pdlparser class Parser(pdlparser.PDLParser) : """A parser for TIFF documents.""" totiffcommands = [ 'cp "%(infname)s" "%(outfname)s"' ] required = [ "cp" ] format = "TIFF" def isValid(self) : """Returns True if data is TIFF, else False.""" littleendian = (chr(0x49)*2) + chr(0x2a) + chr(0) bigendian = (chr(0x4d)*2) + chr(0) + chr(0x2a) if self.firstblock[:4] in (littleendian, bigendian) : return True else : return False def getJobSize(self) : """Counts pages in a TIFF document. Algorithm by Jerome Alet. The documentation used for this was : http://www.ee.cooper.edu/courses/course_pages/past_courses/EE458/TIFF/ """ infileno = self.infile.fileno() minfile = mmap.mmap(infileno, os.fstat(infileno)[6], prot=mmap.PROT_READ, flags=mmap.MAP_SHARED) pagecount = 0 littleendian = (chr(0x49)*2) + chr(0x2a) + chr(0) bigendian = (chr(0x4d)*2) + chr(0) + chr(0x2a) if minfile[:4] == littleendian : integerbyteorder = " # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: version.py 376 2007-12-09 20:32:26Z jerome $ # """This modules defines some important constants used in this software.""" __version__ = "3.50" __doc__ = """pkpgcounter : a generic Page Description Languages parser.""" __author__ = "Jerome Alet" __authoremail__ = "alet@librelogiciel.com" __years__ = "2003, 2004, 2005, 2006, 2007" __gplblurb__ = """This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see .""" pkpgcounter-3.50/pkpgpdls/zjstream.py0000644000175000017500000000741010726775416017404 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: zjstream.py 374 2007-12-09 14:26:15Z jerome $ # """This modules implements a page counter for ZjStream documents.""" import struct import pdlparser class Parser(pdlparser.PDLParser) : """A parser for ZjStream documents.""" def isValid(self) : """Returns True if data is ZjStream, else False.""" if self.firstblock[:4] == "ZJZJ" : self.format = "Zenographics ZjStream (little endian)" return self.littleEndian() elif self.firstblock[:4] == "JZJZ" : self.format = "Zenographics ZjStream (big endian)" return self.bigEndian() else : return False def littleEndian(self) : """Toggles to little endianness.""" self.unpackHeader = " This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ==================================================================== This directory contains a gzipped PostScript file, master.ps.gz, obtained by printing to a file a part of the SlashDot.org website from the Galeon web browser on July 2nd 2004. When uncompressed, this 16 pages file can be used to test the accuracy of the generic Page Description Language analyzer included in pkpgcounter for different conversion outputs of gs. To see if it works, simply launch : $ ./runtests.sh It should report 16 pages for each document. If it doesn't then there's a bug in the generic Page Description Language analyzer. Please report this to : alet@librelogiciel.com This script will also launch the test for the computation of ink coverage. Look at the file colors.pdf to see what the results should look like. pkpgcounter-3.50/tests/colors.pdf0000644000175000017500000002200710501350737016466 0ustar jeromejerome%PDF-1.3 %“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com % 'BasicFonts': class PDFDictionary 1 0 obj % The standard fonts dictionary << /F1 2 0 R /F2 3 0 R /F3 13 0 R >> endobj % 'F1': class PDFType1Font 2 0 obj % Font Helvetica << /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >> endobj % 'F2': class PDFType1Font 3 0 obj % Font Courier << /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font >> endobj % 'Page1': class PDFPage 4 0 obj % Page dictionary << /Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page2': class PDFPage 5 0 obj % Page dictionary << /Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page3': class PDFPage 6 0 obj % Page dictionary << /Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page4': class PDFPage 7 0 obj % Page dictionary << /Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page5': class PDFPage 8 0 obj % Page dictionary << /Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page6': class PDFPage 9 0 obj % Page dictionary << /Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page7': class PDFPage 10 0 obj % Page dictionary << /Contents 24 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page8': class PDFPage 11 0 obj % Page dictionary << /Contents 25 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'Page9': class PDFPage 12 0 obj % Page dictionary << /Contents 26 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'F3': class PDFType1Font 13 0 obj % Font Helvetica-Bold << /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font >> endobj % 'Page10': class PDFPage 14 0 obj % Page dictionary << /Contents 27 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >> /Type /Page >> endobj % 'R15': class PDFCatalog 15 0 obj % Document Root << /Outlines 28 0 R /PageMode /UseNone /Pages 17 0 R /Type /Catalog >> endobj % 'R16': class PDFInfo 16 0 obj << /Author (anonymous) /CreationDate (20060911231409) /Producer (ReportLab http://www.reportlab.com) /Subject (unspecified) /Title (untitled) >> endobj % 'R17': class PDFPages 17 0 obj % page tree << /Count 10 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 14 0 R ] /Type /Pages >> endobj % 'R18': class PDFStream 18 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 923 >> stream Gat%"D,8n?&H7^.IlJSu_$$IWCK%TS!Y$sed_m=Q,egdKds-#qaDo;tmrq>* AF1kUWVYmBchX.o5?@n2I$!c]/`8+0M]2`9Kd6c[4$Fqan3&cokS@G$WETY! nR-q?*'reAYo=@4`dpM:0SX*=-V5p?8/80A]J.^Z$CKu*n.ZdLE\KM/SBDOE epW#.V:+Lt:/<&/%E[f#6,I:H6n*C/%(r*t`QK^W="5Jd8e)^+7WT'S<+[&K 3Fl;F?t(GVit$1rboZ\j)>YjBVOUmr1em#o/g];6U\)c&7_IP%L[dXn*sS)^ $l)27A-=3Ln`gNN_.9*o@YX/W+]Q8u.r,jdZ%ZSYe9B(+/hkYrE;^gjn-uEO 1m^kVKTpE*-_o':CBT,006RZ@#hfPb9<'^VWUs=tk*/q@M^^DW\Q"R%`hC#* d\DBA5MHTdoa>)5Tkj-aiJtF-,oB/ZYCL.n:& <@)5?IK`t>_;jnt>X(?[cTAX)okfq2*,j+;c>j(Yf<+GBa$?H?:endstream endobj % 'R19': class PDFStream 19 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 108 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b6:`Tj:5Z7V=S`h JQ\k9VKt_oVIg/N-AHg^(7#^C7B$Vh>.e)I]NbGJW"J\~>endstream endobj % 'R20': class PDFStream 20 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 109 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b6:`Vj:5Z7V=S`h JT[AaRd(cYS!kd.Ql,*k=BJ`T'W!9=C%63mn8\O0AY]q2~>endstream endobj % 'R21': class PDFStream 21 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 109 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b6:`Xj:5Z7V=S`h JT[AaRd(cYS!kd.Ql,*k=BJ`T'W!9=C%63mn8\O0AY9Y.~>endstream endobj % 'R22': class PDFStream 22 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 108 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b6:aOT\tf;B(L') JJk>NVKt_oVIg/N-AHg^(7#^C7B$Vh>.e)I]NbGZG7iL~>endstream endobj % 'R23': class PDFStream 23 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 106 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b6:i)NF6AiEohii VO"**7cpR[$5OtCH579^((*L0$;Od;>RJ,K!-N>pf`~>endstream endobj % 'R24': class PDFStream 24 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 107 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b6:i+NF6AiEohlF R9H'E)4?t_.9MrSl<.4k=st)].QD/4E[gKu!<@7\&_R~>endstream endobj % 'R25': class PDFStream 25 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 107 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b@LZRkD`k]o5`rD RAQ:IH:I%oAdT;#L3aUNQ50frWQAn^&_R~>endstream endobj % 'R26': class PDFStream 26 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 108 >> stream GapQh0E=F,0U\H3i"VoYmq/M+BVZ3&VI4)3B;,ssUYm'-b@R=HJ_gZE2D8,Q Qsj`DWb5j[C8PBI@]3pJ@;2E3PcEZ;`QP*nb67lg&eW^~>endstream endobj % 'R27': class PDFStream 27 0 obj % page stream << /Filter [ /ASCII85Decode /FlateDecode ] /Length 894 >> stream Gau0C9lJc?%)!J@J)I0=2@Q$BIJ9,'m@h_"0JMSO-H_dnW<:m\p[dRX7H5dK ,WVh+":h9K8+P'7_LT':epYlr0Zi7n%0M?H/V+3P+SuJsg%ed[^k&J&_%Q)d YW!Y[MGV8#BPRq+PX2a40A$4^DVhl,gq3EnBPP'T$J?NB^?thB0\Z=CngYAO (+fXEhAJmRkOk^R^ub/XR$U6EeXLsS^-hMUTR(*N[MuZiMnEq8PQ,gqZ762` XHlL\5n4F+#*r9"L6ornJQ3-iXsdY5(Y`@0!d?q@XoHpt;cZWleA0tSG]kt* Q0X7L-eAO,jfSWX.D`mdBjNnTg`jspB#bS?ga`!2qD!L(t&J>A7;PN*gXjebl(^^ "$nQeL9\t+'k9W^TkQocWE1V$MFP3.Lm>u`'uXUi?Rt&&;Q<\U?`@^d"&#=O B]/dB8J'*me[aR,Bf0U9<_?U^GMN`H-i:n+$T%Z24Ul]gi#,HD:5,$mn*kLV 3fuj5)Sn1r91%eJXiBLd_P2"N/h&=q7fB*)iA'U>gLCra5@q>_+&&*'kq!*@rHIW-Hh'&dl&]nNp."/,qCJ3HdiiR? C"fqVm'@ZkS.8DoZ62W@%-E`"c((6-\KnDP4]).lE^:A6ris&-MGaE+*^bco F%N>J2a5F^$)Pu-)/!Yr)+5'$AWY<#Vp&EPh4@#1:psHc?/"XR-:Y7:?hC=m ARoQJ6[U_u'IT8Gj/<,E_<;e-NA5;D3E`]9KAfq7D:`@ST'G9,(l(SNQ9$1) 9i"KSn0bG1h;8Y(BE%uHN0WZ~>endstream endobj % 'R28': class PDFOutlines 28 0 obj << /Count 0 /Type /Outlines >> endobj xref 0 29 0000000000 65535 f 0000000113 00000 n 0000000234 00000 n 0000000399 00000 n 0000000558 00000 n 0000000849 00000 n 0000001140 00000 n 0000001431 00000 n 0000001722 00000 n 0000002013 00000 n 0000002304 00000 n 0000002596 00000 n 0000002888 00000 n 0000003182 00000 n 0000003357 00000 n 0000003650 00000 n 0000003788 00000 n 0000003986 00000 n 0000004179 00000 n 0000005247 00000 n 0000005500 00000 n 0000005754 00000 n 0000006008 00000 n 0000006261 00000 n 0000006512 00000 n 0000006764 00000 n 0000007016 00000 n 0000007269 00000 n 0000008310 00000 n trailer << /ID % ReportLab generated PDF document -- digest (http://www.reportlab.com) [(s\242'\002\325\364\351\177k"\2261\351\326\222G) (s\242'\002\325\364\351\177k"\2261\351\326\222G)] /Info 16 0 R /Root 15 0 R /Size 29 >> startxref 8362 %%EOF pkpgcounter-3.50/tests/gstests.py0000755000175000017500000003060110726745757016565 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: gstests.py 363 2007-12-09 11:05:14Z jerome $ # # """This script generates a testsuite from a PostScript input file and ghostscript.""" import sys import os import glob import md5 import tempfile import time MEGABYTE = 1024 * 1024 class TestSuite : """A class for the testsuite.""" def __init__(self, inputfile) : """Initializes the testsuite.""" self.tmp = None self.inputfile = inputfile self.results = {} self.supportedpct = self.failedpct = self.unsupportedpct = None self.md5sum = self.computeChecksum() self.mastersize = None def __del__(self) : """Remove temporary file, if any.""" if self.tmp is not None : self.tmp.close() def computeChecksum(self) : """Computes an MD5 checksum for the input file's content.""" checksum = md5.new() istemp = False if self.inputfile == "-" : # Input is standard input, so we must use a temporary # file to be able to loop over all available devices. self.tmp = tempfile.NamedTemporaryFile(mode="w+b") self.inputfile = self.tmp.name infile = sys.stdin istemp = True else : infile = open(self.inputfile, "rb") while True : data = infile.read(MEGABYTE) if not data : break if istemp : self.tmp.write(data) checksum.update(data) if istemp : self.tmp.flush() else : infile.close() return checksum.hexdigest() def getAvailableDevices(self) : """Returns a list of available GhostScript devices. The list is returned without any x11, bbox, nor ijs related device. """ answerfd = os.popen('/bin/echo "devicenames ==" | gs -dBATCH -dQUIET -dNOPAUSE -dPARANOIDSAFER -sDEVICE=nullpage -', "r") answer = answerfd.readline().strip() if not answerfd.close() : if answer.startswith("[/") and answer.endswith("]") : devices = [ dev[1:] for dev in answer[1:-1].split() \ if dev.startswith("/") \ and (not dev.startswith("/x11")) \ and (not dev == "/ijs") \ and (not dev == "/nullpage") \ and (not dev == "/bbox") ] devices.sort() return devices return [] def getAvailableIJSPrintClasses(self) : """Returns a list of available IJS Print Classes. Currently the list is a static one and doesn't contain all the available print classes. """ return [ "DJ3600", "DJ3320", "DJ9xx", "DJGenericVIP", "LJColor", "DJ850", "DJ890", "DJ9xxVIP", "DJ8xx", "DJ540", "DJ660", "DJ6xx", "DJ350", "DJ6xxPhoto", "DJ630", "DJ8x5", "DJ4100", "AP21xx", "AP2560", "AP2xxx", "PSP100", "PSP470", "Undefined", "Postscript", "LJJetReady", "LJMono", "LJFastRaster", "LJZjsMono", ] def batchGeneration(self, infilename, devices, root, command) : """Loops over a set of devices calling a particular command.""" parts = root.split(".") if (len(parts) > 1) and (parts[-1] == "hpijs") : devprefix = parts[-1] + "/" else : devprefix = "" for device in devices : outfilename = "%(root)s.%(device)s" % locals() cmd = command % locals() if os.path.exists(outfilename) and os.stat(outfilename).st_size : sys.stdout.write("Skipping %(outfilename)s : already exists.\n" % locals()) else : sys.stdout.write("Generating %(outfilename)s " % locals()) sys.stdout.flush() os.system(cmd) sys.stdout.write("\n") if not os.path.exists(outfilename) : sys.stderr.write("ERROR : During the generation of %(outfilename)s\n" % locals()) elif not os.stat(outfilename).st_size : sys.stderr.write("ERROR : Unsupported driver, impossible to generate %(outfilename)s\n" % locals()) os.remove(outfilename) else : self.results[outfilename] = { "command" : cmd, "device" : "%s" % (devprefix + device), "result" : None, "details" : None, } def genTestSuite(self) : """Generate the testsuite.""" root = "testsuite.%s" % self.md5sum self.batchGeneration(self.inputfile, self.getAvailableDevices(), root, 'gs -dQUIET -dBATCH -dNOPAUSE -dPARANOIDSAFER -sOutputFile="%(outfilename)s" -sDEVICE="%(device)s" "%(infilename)s"') self.batchGeneration(self.inputfile, self.getAvailableIJSPrintClasses(), "%(root)s.hpijs" % locals(), 'gs -dBATCH -dQUIET -dPARANOIDSAFER -dNOPAUSE -sDEVICE=ijs -sIjsServer=hpijs -dIjsUseOutputFD -sDeviceManufacturer="HEWLETT-PACKARD" -sDeviceModel="%(device)s" -sOutputFile="%(outfilename)s" "%(infilename)s"') def runPipe(self, cmd) : """Runs a command in a pipe, returns the command's output as a string.""" answerfd = os.popen(cmd, "r") try : return answerfd.read().strip() finally : answerfd.close() def computeSize(self, filename) : """Computes the size in pages of a file in the testsuite.""" answer = self.runPipe('pkpgcounter "%(filename)s" 2>/dev/null' % locals()) try : return int(answer) except (ValueError, TypeError) : return 0 def runTests(self) : """Launches the page counting tests against the testsuite.""" masterfilename = self.inputfile self.mastersize = mastersize = self.computeSize(masterfilename) if not mastersize : raise RuntimeError, "Unable to compute the size of the testsuite's master file %(masterfilename)s" % locals() else : sys.stdout.write("Master file's contains %(mastersize)i pages.\n" % locals()) testsuite = glob.glob("testsuite.*") testsuite.sort() nbtests = len(testsuite) for testfname in testsuite : parts = testfname.split(".") if len(parts) > 3 : devname = ".".join(parts[2:]) else : devname = parts[-1] result = self.results.setdefault(testfname, { "command" : "See above", "device" : devname, "result" : None, "details" : None }) sys.stdout.write("Testing %(testfname)s ... " % locals()) sys.stdout.flush() size = self.computeSize(testfname) if size != mastersize : if not size : result["result"] = "UNSUPPORTED" result["details"] = "Unsupported file format" else : result["result"] = "FAILED" result["details"] = "Found %(size)i pages instead of %(mastersize)i\n" % locals() else : result["result"] = "SUPPORTED" result["details"] = None sys.stdout.write("%s\n" % result["result"]) self.supportedpct = 100.0 * len([True for r in self.results.values() if r["result"] == "SUPPORTED"]) / nbtests self.failedpct = 100.0 * len([True for r in self.results.values() if r["result"] == "FAILED"]) / nbtests self.unsupportedpct = 100.0 * len([True for r in self.results.values() if r["result"] == "UNSUPPORTED"]) / nbtests def genHTMLReport(self, filename) : """Generates an HTML report.""" reportdate = "%s (UTC)" % time.asctime(time.gmtime(time.time())) title = "pkpgcounter v%s report for testsuite %s generated on %s" \ % (self.runPipe("pkpgcounter --version"), \ self.md5sum, \ reportdate) out = open(filename, "w") out.write("%s\n" % title) out.write("

%s

\n" % title) out.write("
    \n") out.write("
  • Testsuite's MD5 checksum : %s
  • \n" % self.md5sum) out.write("
  • Testsuite contains : %i pages
  • \n" % self.mastersize) out.write("
  • Ghostscript used to generate testsuite : v%s
  • \n" % self.runPipe("gs --version")) out.write("
  • Supported : %.2f%%
  • \n" % self.supportedpct) out.write("
  • Failed : %.2f%%
  • \n" % self.failedpct) out.write("
  • Unsupported : %.2f%%
  • \n" % self.unsupportedpct) out.write("
\n") out.write("

Green means that pkpgcounter obtained the expected result.

\n") out.write("

Orange means that pkpgcounter obtained an incorrect result.IMPORTANT : if only 1 page is found, this is often due to image formats which don't support multiple pages anyway.

\n") out.write("

Red means that pkpgcounter doesn't recognize the input file's format.

\n") out.write('\n') linecount = 0 keys = self.results.keys() keys.sort() for key in keys : value = self.results[key] linecount += 1 if not (linecount % 2) : linecolor = "#DEDEDE" else : linecolor = "#FFFFFF" out.write('\n' % linecolor) if value["result"] == "SUPPORTED" : color = "#00FF00" elif value["result"] == "UNSUPPORTED" : color = "#FF0000" else : color = "orange" out.write('\n' % (color, value["device"])) out.write('\n' % (value["details"] or " ")) out.write('\n' % value["command"]) out.write("\n") out.write("
DeviceDetailsCommand line
%s%s%s
\n") out.close() def main() : """Main function.""" try : if len(sys.argv) == 1 : sys.argv.append("-") if len(sys.argv) != 2 : sys.stderr.write("usage : %s [inputfile.ps]\n" % sys.argv[0]) sys.exit(-1) else : testsuite = TestSuite(sys.argv[1]) testsuite.genTestSuite() testsuite.runTests() testsuite.genHTMLReport("%s.html" % testsuite.md5sum) except KeyboardInterrupt : sys.stderr.write("Interrupted at user's request !\n") if __name__ == "__main__" : sys.exit(main()) pkpgcounter-3.50/tests/master.ps.gz0000644000175000017500000041323010224222451016743 0ustar jeromejerome‹žzĺ@master.psä}k“Ü6’íçŠ_ÁÝސ>ČU|“Z#ř”{,Š5–d=;á`WąťiUŰőhŠ­ë˙~Č2ÁęÖŘ3;{ďŐŽ{Š@"ó ń$~öoŻ^?ÉVýEűÄ˙|1űěłź?nWÝö*ď?t7ë;•mÄ[ˆx oĽˆˇcŇďu¸j‚Žű•îUťŰPł|ąŚ°2Čh¤ŒĆ(یšöĎFľ˘W-¤´&§VŠiÇÔ"vČŽ“ń:AjŤČڂ†Šz¤ęeŞŢ(ُ٬şŰN'SG8BŔq@ cÂ;D80Sw&äo¤Ýž_![—ŞeŻoUŕkGUűů‹Ëó‘—ÝvuŮSMVÒuť˝"+0šPú_Çůč:MŠ^Ÿ•ůüG’ńŤóQ{č?54i×űöWç˛ß5ëľN3ŻLڧj膇ţq“q@~jxć¨0ŞUZ%MÞ Ę:ďUSDÍűň ĂyřEęéŘGśN„˙ęüŞC?ŽVrjQ8b‰˜l…˛|Ȳ^v›v˙䛞<Đ!ÚfóË‰Ôøĺ^ń ŤŽŠŽ””J׎‘÷ë¸ pOxRŔŮĄYwKˆń㝊ńK„˙ ˙TD@#‡v}ۨMFúŕÁôÁiúP¤—t„ O…DS!çëŽÚSȊ”ĘŠĽ,[Nü œřTNBÍ0 ă¨ę!uň`ęä4u:¤–¤¤ŠHďq˛…-ĂśĹ}ŘaÝű<Ö…M}Âqďń\šůĚ_ßm.úľI˙°Çş§.űvەÔ4¨–â‹/fnôż oĄŰ=âj„‡&€< ™Q?@_ƒbŔp až 5„Y°HcĂhŠĽ^@X9ż>nݚÝqłnްk#ý=!?VxD§m$2…ß ą\˛““÷Í yX>ٝ$H1Rˆĺ”„˜˝×2+ʚIˆ9|=­"XUٟŕ⋡˜‹•˝b=ĺľP *{ 1ƒoNŒÄËá4ëORHˆ¸bVß -!^#Ŕ,ží `ŽÂř[úÖbކÁˇp(,Ë%Äě˝Fş.ÖgŽ#‚5šˇ§Ţ†őšă=!Ěâ[ŮźbçhaĚÝwÓRŊÎűœYüţg2ďNpćô{{‡uŸ„ۙŠ1Ť?Lş,ý2…™ÜD‘cč 1ťë~{]RfęrÝă eŚâ›‘¨›™ ?"5 e@°rLZž‰ü1qšĆŇzÎ-ŹÇxş™Âl}VIŒMoZ‰Ą‰ÓmşÄŃÎMpŁ­×ÓÚĺaČľ? ČF_'ŐĂIsŮuaœz)Đr@Ł őcFąî0ń'Ż0cnCŸ‡•QőZŘ­ydś> Ě°ćÜKgÂró ˘`Šygœ ëĚ{ĺL. „€ e2ţ…ľĺŁd­üń'ÓźĎx]nü }?úV•ť˙²ňń>˙ÂârŇ.a‰ůxâaXhî'íVuŹ ĂŻ ; ň LGAý Ť6%ő$š¸ž…z@ 5B €F-4šXh 4ľĐhfĄ)Đ\˘ŃhaĄĆśĘBmľ@iâÉ(VąׅfŽĹ¤ Í\‹Išš“4s-&=hćZLzĐĚľ˜ôŔŻk1é}-&=đëZLzĆ ‹IĎXa1é+,&}cEiĄĆ ‹_ßXQ[(|Çłřőa›gńëĂ6ĎâׇmžĹ/FwgńëĂ6ĎâׇmžĹoŰ<‹ßśyżló,~c›Ĺo`lłř5~ćYüĆ6‹ßŔŘfńŰ,~Řć[üFČ͡ř›oń!7ßâ7BnžĹodrłřÁ¤ońƒ3ßâ7gžĹo Î|‹ßŘXań+,~cc…Ĺolʰřż‰ąÂâ7?ż l ,~ŘXü&°-°řM`[`ń›ŔśŔâ7mĹoۋߜż)l ,~Sc›ĹojlłřMmżŠąÍâ75śYüŚĆ6‹ßś…“14 -&SŘJ& X¨‘Z(l # …malĄ°-L,ś…Š…Âś0łPc[nĄ(ˇ°°Pc›äĚumVŸeĘ"’츌-‰,vL Ĺv\hŰqa[l1iڝŘbҔfjՋúŚViڐPJÎč棄0ŽQĆaî 4Ai†šgĄ  ž…z@KŽ4´ĐhdĄ!ĐŘB ‰…Ć@SKc[nĹ5haĹ5J‰ú†‡J Q`4Ťe\ôYaą°PđPŘLÂâÂfě’É#ą°”rŁJ×BĄYéY(,.-ščqÂ2°P“[hĄŕĄ”%ĄÇ ËŘBÁC™X(x(S …ĹefĄĆśÜBm……ŰJ 5śYĺŰj …m•Ĺ/úĄ°˛řE?Vżč‡ÂĘâýPXYü˘ +‹_ôCaeń‹~(Ź,~Ń…•Ĺ/úĄ°˛řMŒmżč‡ÂÚŞó.rŤ] EnľgĄœ[´eáC‡Č•ĺŔŤ#ˇśP–yŽ…Ś@enÚßČó-ÔX¨4´PčŕE-4šXh4ľPcEfĄŕÁłxpm’łŔ3ś•jlŤ,ÔŘf1‰™eä/,śůż˜ˇDžĹ/ć-‘oń‹yKä[übŢůż˜ˇDžĹ/ć-‘oń‹yKä[übŢůżžąÍâó–(°,ĆL" ,‹Ń*Ge1Zĺ(°,ĆL" ,‹“›e1ú€(°,Fo–ĹąŃ̲=zXc&–ĹĄ‘`yThlł<*4śYŰ, m–Gaő -~ąz…żX=ˆB‹_ôYQ$%řÓF‘kĄĐ,ň,šEž…Bł(°Ph… ͢ČBfą…‚őČ*!Œl˘Č*!Œ‚˘H–ŸTźýđ]ôąQ,%„ŚĺŠeY„­DIdĄ$–0™ş &S+.FşQX(˜Ěj yfÉEYXŁŠĐ´gÖH!äşéV —üwĂ&3‚XŮ÷b‰ß /Žâ/!źÔ”‹~„╌˘Ÿú^d‚vwä-DżšK:–ĎĽLŘXF{ aľˆˇ` ŤQ—ÝŐq׎°ď‚`lŽÚ ˆ­i7)TkV PvŃńN8Qđpžh:˘ĂFf‚łÖG—.š=h@GÍ)Ú[ʆwWSH1†Pś"“Ň ůTVȘ VÍŐď˘öĚQ.†łĐë_)?EçŢoŐn2uÄŞY 2°'ŕ}ÄU¨]Żťx†ˇđd™‡<ňô˘ßU(6ÍíŠŮ¨ŘŹ[>Úâ [Ɉîën‡hX=#Ô ĹĘEŐ.aŁ2n˘—ƒ'Úx5:œ`VvťţýĐ*šflĄĐă 0oÄĆVĘĹŰx ›3.„#zŃľÓPŠ]!.^<č:+EK éę,Z*)¤)…Ú˛rK× 0ʗž ýKß M(+`°ÂĂސăśS˝&Ÿ=%Ô3őěĐ5ëUwy Ł€ęÖV…ÇKĺÍÍán.ĎÛźa#!Řd´SŻDˇ&‰uť14zX `ě <.ŠĚÖpô~u\CUŰ7›fđ|Ďťˇ=Đ4 K #jœn& ŕ ă’ÓC\žŮs¤ [R0 Ĺnú?ŕTĆö˛Űv‡;€xŰ­şäŤ1ŽyŃeNjÂęáŔœéť=ĚňŁEôĚjĽŤ8ÓG™)÷ɇ¨T@Čs惺śâP ĺťď6Ž {f•4L¸Ú‡33ĹbáĂp¸Ůó0ŸR,@œyüůŘÝRł]";L’Ô&k;„3éóŃ"}ĄâŒ>^ ‰ÎШ?CP`ôą°“éëöƒ[Ršľ?ŒÚČľń4lĎaXŻ˘’ďß´jťöqŕ;hX88ĄŞŠĆmLwÍ4îľQz>œÇéá°kÁ&v:şÚĐůfEHĄcK˘Ýx]ť ő g@W€Řˇ[/čšäjwÚô˜0ŕ 3AoHž pˆ ?Č8Ä G04zBO,źŽ=ĄRhl…™ć]Ągdřô„E‘áÓĹ>™‘á3E†Ď@đ>Ágdř „EŃŔ§TÉđ gˆ ŸĄÔÓđˆ˜‰Ůöuąî—ď€aÓÖVbŘ:*ȸ@ťƒÄ˜ÝőaÝđVQ°OJ ŘÇůN`ŘšwŠÎŻ.ú@YŢWŞ;÷1_šI( ^Ý#¨âv-újóEá„XśŃŘÎÄ+F Ł­ĐlĺRb& ‡Zú_Úí,Áž+n}Ճ‚>tƋžn{+fîćEĄ29^pPO˛‘Íúîž:Ćö‡ů 5]ëí4é‘í1 Á—40GFf˝w˘áŽ€•ApĂĂúx§°Ú䙵ĂU×lĚ<ŢŹűmŽ{tF\>Ĺ1_Ż#ź>ĉ§ŸâhĎs~ÄkĂ5’ŕ}Ą<†A üĎa†˝;›p{ψÔÚÓŔ+_„Zoây–Pů&>áu{B 5qš¸3łjGÎBš­Ý„0CĽX°#°°@) ´Bž™ĺ; Áa>Ŕ-'›¸ë“„Ăvr‚0Ý˝ŰĺfGymÖ6 Źą90Tî‹ľČ SŠx!R‡źSG&ő•HmNč˛MÍhmiß!ÓLތŘӀâA?ăn‚Műfş*ƒ†› .ťf¨„2ŰťăM×\şç^ƒqْ™tĺrrAĄŽđ*UČ 0+ 䫓$Ţ2IcśĘŤ{›&‰ä•N“T¨Ëú"ŒIŞHMRÉű&&Š4I…ŕ岚˜ X™ X曠8z9AqJp‚â:ĹŢ~‚bűďEă2Aą6A™x]ö›Ć4Z8¨ŽŤź„qÖz8ű!ØńҜäAÉI–Ą8—ŠžHœi?Ż$ƤŸës Ç Pˇ˝’(ĆjËŠ¸UAń03˙Ă$zl]W&qé´ýzľ?ÜqEA“ťÇD*q——fźÓk‚K›\,mNBĆĽÍIŔ¸´9 –6'¸Xڜ„ˆĽÍIȸ´9 °ďPœ K׍ł„q|DB8?"!Üé%!!‘ΐHW|I÷|IÎ+!$‘Žý’îţ’.“n“Ž“Εo ^I7ƒI׃Is áĉ„pčDB¸2LB¸7LB¸É°ńÚ'ۧ°Üh†2 SĆăc›žHDđ€LœŢü#B+yýÄĺ@?šHĘۀ$>šH‰{$l.’˜}C ‘×I\Ţ$ń“ ƒdŕäÖ $Ż’¸ź?Hâ'—ÉŔÉMB"¨Ž’ źSHâňb!‰Ëۅ$~rŐ ”÷ I|rِ ’— I\Ţ0$qy͐ÄO“ ‡dźuHââę! 3íߟJJ*sb^Żcôœ˜pjĺýśĽĄ§Áă§<ş_†&d 7Ű=ŚĂç1ÄL—Íy ÁĽœću/^ŘřůäőŻ Îlˆ‹Iő4ÄȂŠ# ž8\ĄgdÁ|Ó­ŕŰƒ `ćlšĚęćGŁešž!Óx0¤H&CŽŠ4Ě– âň“ A`1ša‹›Ţ"82RMB +ÇÂ,żąĄGŚú˛ĂŁ9TŽGź‚1r2áÖVǘˇÚÔšgo €Z›\SÄľś×şůέí_ńb1űňK¨+t݅žĚ[_škŽóž×ýöđćîŚu|\Ä­‘ ŃřÁůëç ˛rA˙7üř›ŒĆ_,Q°ş˘‰ţB‡űž˝0r¨&6wĄh„…ÎÇĘş†|řşŔÍń o§¨CŒ4ĆrĺĆ_C™ŤO´źÚőË=>ľé#<ŢW>ˆţčü:\6näéu-řś}ŁŢ8ĂżtáЈzÓßś‡^?E40R÷zKşÇ~öOâ-×ýžľäÓŔtOU—˘˝ďVW—ŸźkMůôy~¤f_Ç7°+Şë‹ŮNę˙F íaŮ,ŻÍ§bţ ůéP˙lîŻÚĂ28ýAé@RÚĽŽĹš)lţ˛żZÓ šîRŸ\×>›o.ö×ý{RřţŸ9ŰăFKMŕ$Ćâp÷‰ű€8;ŽłěęĺS6X¨ź?&Ăôńşí˝ť]§Y­~‡XőĎĂuřTýT-ŘôŤÓ¨Ŕ!ď¨ţF9´žąţÉŤ[uˇće¨5F“SśđQ¸°ŁóWd  EJ §ůŢZę¨>ƒpŠu/mř-ÜůRěIšÓřĘ.Ş#ĘyŽ:™jp|Ś •çá÷‹‰­2Ŕ˙î7ąłďV‚OĆ|Ľí§Zö ”Ôš¸;´' ˜Đ.ôiL“J­ƒŞřTÌëň|ľkŢ˙¨öŞÚťúqŠÚĺ |-ťUÍխ쏚ÇZŒüÌFU͚„tÔ˛´:TI˜/ŐăřĽ 5Rä(şŃÖßl€/ߒáœúݖfFƒÇΗşÁt>â{şľQ+1ë˝–˘sĄţjóœ!Ý5C éEĐŐ^-¤ňoH˝éi”ăаoKŁç{$uŐתę‘ ?&13ĹôÄ;• -’6NšŕĺíghkI5 ô§’NľÓ)Ą’Şú™ű+D?ěŽ-ĘßĐwŮđW-¸Žă&ŘAŸ,áˇÍAÝńţ@AżÔĄőđmŽI9‹ŕáƒzPĄ>ťŚËpřŠBűó˝ęŒÝTČ#'5…Ś=-§N'Î'Łß烟ŒŞT×`Œ;”ƒ­¸mФLLÔ?ŘqŹ˙XęÚüŞŞ!đˇ°ö÷¨šđŁUřo I~@âÄ}—Ô&?ÔHŻ˝=wü/ńŰAÚ辏Nkňď,raąsľÎ˛ů„ŐÔaX,tԌňO‚ďÍ×{‰UčĐ3S˜YŠąÄ0„Pi;&féÚţĹAœ”#xv„ůŇ!HÍ!6Çľłä˜ĂƒŢӔʱĺΧqUGž'súÓׇÉ?Îîďî2­űÎX“Oť´iô:cŢßĐĘÚŘi<“ć´•‰Ź`Š”ě3çƒsçźwŽFžĚĆ!"Ń;SÎa¨ţ`€¨Đ qCy–óš;Ž)N‘nˆŽĽ<ń>!Fm1b‰ńĆńôý:Ÿ cžŢp&ĂĚ[?.°mŻNc3sűăbígâÍę§ă^}Úp؟; ŚjĺĚUˆ¨ëžy؋j,'ţŠüW:Ý7wÇMˇ}ň\:ŸTo‹'_xíÔ1“űSîŸđă‘ëŻďâ[şŸÍ>sŠëvůŽčŇ mˇ§ňžQŰ{Ű…΋fűvßR÷źŞËc!ÎŮ%uMˇíÚiôŁŮđčŠáůCžš˛ƒsݨ•˘vKsŚ­ZBv˝óHKzl„ĚÔćmőŐĺ-ľhjŮĺŠÇszś%sľ^ňšz/ŞőK°7‡ă~đ íśúŞ7×ţ$ÝüE˙KÁ ´Ť7ýs•ł‡ĄwnZČ˝ą>>,[YŽ^X|ĐN#šľ{ěoWŠ6ÝUˆ5Âď¨Đޜ‹ă^Ş´‡–Ł^´”tCő§ť ‰Ď}†¸b ő€îßą‚uś#¨€*‘ŸŠ˙ SŔÍNĎÚŽUY÷ÎĄĽţăpÝ:Ç=U埤°)h˝ŘĄ[_ôFtŽwúa@ŠŹ–Ú⠜QŕŁ7”—úŘ5 qtyłkŐ\źŰ:węÓžZCőźw›žÓx!|A­*ľ^fE´°ţ¨<ďçcGî7V#S$_Ç^îǧ™řŸČ¤w6ÍťÖiT‹ńaţźŰ?8ϨNQšďú÷ŠŐGíŐSç%5~ËćŚUáڏ>5Ўf>"MŐJ…:_ŕź§HÎű~÷ΚGĽOŘM&5ŰťĄ†KŠi´ĽşŠ üß_iGP_önśŤWĺN> Tyv=“p •–ľü}ZŠWˇş64űni”űGq#´bď\˛RÎĺŽßüö⠂t†•ĺúfçüőü՛łó—Ż˙öűŠ• ˙|Ô˙DŚúľę ˙óń?ĄËŐŢyňłód_VߞŐoöďwÝĄ%ŕ\sYwëöOœ'Ť—çݞˇŻ+ú•goŠŻ~GŃŤĺr+Ë'ŤűZĂ?ęfă‰óżűéšżŽ'÷VőßTđ4tZKň°§÷™Dđ_ÂâčÍĄOVĎÉێÍUŤůřŁ+"ݢű1ö@ë8Ú>Lu<Ô:ÍB-qę[Ujj.ÉÎßV[ťĂiű}őöż­‚:_ÔgĎŤ—Ů‹ęËß[W˙ߨ—eüŽz9rđ?Ł‚žňů贂~ŞZŽéţaꨊ*Í iA?iäpŕ ČË~yT‡_ŇđŽ]}c´OUož¤ä˝őlť\W­‰s_”\˝t#/šçŰvˇjśÍçß´Wę4Öç‹Ď?.7Í EÓÖíŃCQ¨ČôŘâÇaÜóő͛÷?üůůŮí1îćŰŻ_ßžüŽČ’ţEüŃY<&™ßbôÔqiÚu2dW<™a;ޑÎ\źQĆŁţ­ĄN˙únh7gŰË^˝1?yţŢ[BćGSe›9ÓůnŐę;>Ľţý5MZř¤&VăÚa-DŞWçR6F4L¸<ÁT~ďż@œď^¨EGŘ*ŁńĺXÓ&™QŤUţ§{çwv9Î}}Ž#:qßד Uc݈Ö Ň[’ţ6jM^t~yšoMŻ5ŻËüîĐîÍă3<úƒí…ڜऎɧĚôn;fz‘W-ÚdĺšvĽ‰Zź$Ě d18ڈO–Ă“WâMłďޡÎY ›ŕ§Űá^5UtZ‡AŐWťîś9´ĐvŽGę#N ÔQÇńˇgßrty\ě˜ř…ކp•‰^HłZWYŽ2Ś6ŃÍ´ Ôˇ˛94OŠ“SˇŚĺÝś!wŇĹ3{ôUűá1żýqőG§^šÝAEŸQyťŽ:oëęÓ֞>8ěůꨯŻP‹Rý•g„‹BýM˘Ďý.˘™>ašľú›ŤHąç*qäęoŚđ¤PHš¨ĐLZÎuŤÖ"wŐšäÜW"ňLĺŸW*A^+źHőßBĽ(J§,R…ęwEćB}PSAu˘r¨łlĄ.ŽŐßXýuS2Íő˛\Y™“ňn૛äƒRý gꜪ´ÄM¨ţęH:7Ş”¸8MÔ_Ç•”d‘ú[Ôę¤rRŤŕT'Č\_ý՜ćŠ<7WÇžÝBQᖮJ\&*~™ëß5‘¸p+ľ *ő7RÁ•˘Ę­ËJ”˘BýMCő7׿ŤHuu‹Z_sď)ČS'´=/ Ô_ĽŞçűęˇ_ŤĐ@S÷U"^)ĄAŞâ„ýžy‘Ęًő7öT@ŹNl{q¤ÄЧţfU/ĘĚ Ý”şč*Ý2Lü˘ŹâY–U™[űqž$AU~‘቗ŞűF u6IŠżŤü"MëÄsƒ")‹€ú`—Q¤|VÖYúUšČCŻv+7%!yA…]S€Oăź đ˜~WĄľř‰’_¸‰W’G&ł LB?Ȋ,Mƒ:MÓ¸(ˇitYqçůYžDi]†š—&yH…–^Ee]–4jʲ”qý‚,ôBύ˛" Œ(Í}ßóâ‚T̃:ö‹,(ŁHÝ˝úE^çU”çőŒěÉł2U§$Â2Ŕ+Ş9^–úIQ)9iFTrb=[TľŸÔ)BEžŇx"ĄT@ąÉŻý¸LŠčƒŽű˘çĆČőĚë XS–lŔďBĂÂđFřÇ툋˝†xá2oťSë”çm@ĘÖe™ő’)Ni˙ľœžăš’s]ůîrçąź3tJ3Ś?2Dv,3ëˇbŚ€/>V{Gk7ňäźÂ>h­×ý}´¸烊ŹëŒgZĆIë„ĺh6{‹Ű°üs§xOźőz`ś‘Ś cQqMźď‘$HóŃsۃ—D…ţ=OŹ7ÚÎFĎľCmŹČV0AiŠČˆVuE`Ńv$<Žg‘ˆ_šß˛•~ľl!N+>÷X:|űçÄW :ł#ŠCÚů~šDsSDV§ŔΧî<‚šm¨,ŰČ/N;ť[–‚‰[çœ2ĝ—ŘLşSSLa=Şźő<îšÇŠ…\öŹ#:fą&Xě2ëě1Ęčűş˘×Č ëčä”5Uä˝ĘtĚʗ™˜}#€V÷QľKeŹÇ?gďYk^ÝâđMźp\ˆ´HT´+$ďiFx8śdAĹW¤2$żÁUśĘ•ž*ř ĺ2 #XşRRŘPœe‰ą™Đ…„ ;>w– Ü .ŠmĚ3Î;ÖŰϟm\ě™ß@ôň,[ž6œ &c™ö0#Čř¤Ǚ:ĕ}Ă恲W¤c/šGPŮǙ‡áŘS^}ęgÖxK˙v"(™>V .ŻٙcÇ˙aű°ZÓx,',ŔV~SÁ5á˜ć`š6ľ¨Ý<sÄâ͂i)‘p\aÂÂÇąaa܋Y%ĐŃĚbgž3eüîŢeŠ;Ě÷I¤x^UŻ­ńڰ1¸ ëźWވçëq #^}Ă-ŕ\wdPřĹ>cI ŇK´âĂ{ÔtËŢŮX ËÂîs‘°„0°rǀ}$Ü@dąi֍Ű¢ÍśaôDƒ…ŕhÁƒň̄SŞ]hŹ•Ç8Xů)ă:ŒČÓ¸%ßůŕ™´˙˜ŃÚošÇĎ<@J`lđˆQU]1“ŕă€S˄+Ĺ_:]wÇŃoƒž‰ŐŻăqŢi?íôxŁĽCËY-T>˜ĺÁ~÷č&ÁTÁż`ĺęŔ?{ž°ëÄ^9IyKxŢ.: b˝fÄŁŸFţđűEPóžY4îŽSÄ}÷•ŸĚ˙sŚ…˜ęŔÁłÎšˆ:­0Z€ !Ž Qۆĺ'H`9¸ŻpľŸ8„ŻÝÁ&nˇ؞Ú¸!ü{—d–‹(ĹmŽźŘdwëÁ6ŕH>8uC‘OŕYY¤1ěqAĐâŔĹX­Â}Ë6%`đě0Q_AÚ#Ćq‘2śą`'řţ1ÂđÍ­&Đng%4œŔ8ˆ'<ÚFbŐks+ `ś†KKŒahś#ý8ő„zO8r]JA´Jl9Ś8-ŕ p˜Ŕ Šł-(ýظhĹź€ˆKÄú:i”¤¨‡-^ážçBH€Ń›Б†m|3#<@ińÖqفz“Ę &˝P(`ߌE‚hŹ#.˜ż…ČMs7n "ÉëđÁq_Á O„7E-Ö^ŒG𾝥;6܏n핷FĄ1Ëkˇć&ü…b?ŤFőŮy.LŕVńŔ1q0ĹDŹ p Ô¸ŔĽŽ•AˆđĆjNŠ€Ax#"|;Č XšÎÁ€eb*ŮŇ ¤Ş…`ť7q~J%íˆAKE¨ŒÍüŽóĚë(č°!`l.5Ż„˙ź<{xŇ:Fŕ'€sCTŃ˙8Ąő\I†Uĺ‰  ÉĚv#ţŹŃ;(ŒˆşŽ‡ęV ‚šž{, ˙u`!úňćÄa'ÚeIô.ÜdÚĄ­ OŠqÎ cÍö#ƒěŞaŠŕeØq=qÚÎóGœš>ą菈7Ë>2‘žó#Kĺ‰0ÍËM/Ÿ›)â UĉuČk_ř.&y ôM/@tď‚ńk’”é˙÷mĆéˆűŠÝîŕYˆĺ;bioxĚ+0|ęŃS– Ť°iŒ_Ë„ą?\沲nyŔEą+Swô¸lŘ"l ‰â’cʸ÷x.†|×ü|wAěDôtČ3÷ZŇió–/güĐą°ú¸÷•NQ0ęq— 2b…nFą,üXÓßąĎi.ŐTB^†‡7Ŕ)kCX1Í2Ě\ŘR}'&ËjšŢ‹8gčd&Ź4áᚹbĐpëţŔąN•WN,,(|Ç7éÖŠvvÇŮÓčdâ˝ĚS+j7&%ĐríS&./V p6ŁÝź…iďń˜ Ľóh@B(°ŠĂÁ]@'ó^&ÚćydOgôŒ/D­Ž˘U~KXń8ŞčŢVÜEŘ@œ逃i-ˆB´8‚űət­Œ uE¨˝M<Şx8 ZÚć˜:œ]čš/ĐÍe ĹiIDĚ3N“ˆęę\ŕ&OI0ŤN’ÄdӃľ¸[gňđ‘ŕˇL/„VaTÎŤ fÂ~D‚x–§ş ˝˜q‰ő1‹ü,ˇu„ŠÉŔ@káuî2`ŃUlŕB|É:„hcÚp"L­Éx)&‘Ă2‹WHX2ţăMjăAŰź,fóqŔýÁýJ`qńťćČYm|$ĄqŰľŐnŘߝ \ꢓ%[˜GyĺąŕŐ¸™ ˘7"‡3ZTý!/,Ř&$wŢ6 łĹŰłącŮĄŸ‡ţ›9ďQm ü G´fAŕ:îĄĂ<}Â0ö Ó¨IŽĹŞĄ4í^Ś&č3näÇĂn#qPé?ŚÎœŇcŞž+ xڈă&ţ ,iů Ĺ;Çf°4)4›=M ´quJOZˆĚ.@#üš‚4s ć?ÔÇ[–ŕŁŕB€&E@ël5~tŢ1ü(Ě7ő ˝]g‚>BćUąm(Öqů¨3rä¸ Bq”O[V0ҲOŽ.çŤĹăŽ|„ľe›4şăŠëîÇy'TÇHx–_ěëŚÄMk^űŒ‹M%Şě‰ČąÜK€çÂß =Ž1%ćŹ ¨¨"™+ĆÇŻ{I~˜“Ć9ăőŔňӎءl Ä×ń Xř~=÷€f˘n¤Œ›đř’ÖôdÔŽ% t`žˆĐ|ÂÚtëŽ\aD‡,;0 ?`űŘ\ @PtŒÔ¤Š…Ćč 6 ƒćaZĐáŢš)/źÍˆ*ϰ}Mřáč„úḚ̑™%Ŕˆ÷CFaĄ°(‡šČJFź€t=žŤŽş˛YŤPyiÇąďXiށŘÁĘę>!e‘ĂY˜4žřʊ= kÓ|8_a" ÓÄî ˆ˘Q(v˘ şî…R#fŹW-Ŕ~.˜ďˆOÄP‹Ě^žßÄbW‰5B7ÍŔAĄ WÂíe2 CŒ#ŞÜžlä­ÔqÉš°„Bšj AŰ vÝ÷y‹íŔŤŰyÜxdBÉŠ¨gCqŔЧ~ćD–QՙP6LZ đœŘ?Â/âԀĐAÂîŻ#xrž¸h$ŽÓ`Ž”[zűşŽl{<累H)„dń2ŠâŢŔĂÄଠ56Áٍ =8‡÷ǟ­Á Ď 4čv źŤÎr…ëťĆĐăěě8ÓÁDŕ\a í•wC(ąC§+HuÎx™ÁĚaÄâۋ§ĂR2M›L)†ƒşĘîŠÉ„Ůť:f–´şBNœŢ`÷ bĄaŸˆˆŽ"ě5sź°‘ŤŢŮÜćErW€šâLŃŽ '§ăĂŕ ;ďE8ó†|⌠aLƗáŢŰąŹŒÇxç9Íš0ŘŚ]™HgloôdöÄb'›‘9 ĐW}Ćn"˝šö¸8 Πi¸‘,BŐIŸ9ř× NŰ{,.j8n#ň„qś(~q2".ݟو02öźë$ţŔp'^dEiöeMQ/“x< Ŕ/‚+ŻP Jp`ť +ą8qM˜i5č\ I_Œ o#˛AD€h‘ěÖó¨]Äád"vn9šäÄźĐ÷żşâ.lú4ځĹ5ťʂ@x<ÜMXE(qÖkX–4­Á2H/–ŃYŚ]h„“í5uG7ŽŔćݤ-@)ěřÔ (†ťa¸ÝaŢnFÉ ö#Ai8lxhÖ ŒP;˘5vÍXęwŒŽNlKť°óÉČé@€kٰ–źčąĺ ďAě "éĹi7G˝<Ø6ŮčŠ9×ŇXpC˃!Äß8IÖ\¸ р;k—×E€Ĺkľ“1ŃKş(ěւXઠ ĺ‘dŠĂĚ#Ź[î;ĆŔOÖÝhU` žéX[ĹžÇ\ ŃO„ _78Ú´.@'ŽTęŔRűˆďgšLN ő˘ƒŐ3‚ůx$ó`= ‚řĚwti42Űňěą7XÂě뀯˜Ăł1Ň*:2¨˝6tľyîxźłGď…]8st‰Wöʨ•ř ůĂܨ˜Ä°qÄTĆVM@ÉNď‚5'6ƒ˛őc;Ą+ …čbéń€ź ‰0ą:V!ˇ'ËZÓŚčpŸfŮ|ĘX:aݘ@SéěI9­üë P)ĆÓÍÔΨŘÄăL,ďš@áÔM?'ŮÄůl Ŕ%˘ł{‹l€GŘýé’ůŠšB^ƒ…ŁćMą)kVÜ"]‹ ‰ô?ŁÉńŠ™_g\äDôÁ]öăYÍÁ‚DX}Vx: Čyˇ¨ĹaĄ(žęŕb6€ćŠx>˘e3Ž•ŔŃl™Ç—ŰpGVڃŠŕ`rđžf^f”i‘S´ZÓqÄ`˝ۉ5Ű<_tŠ0ŔuAĘâŕşnŃĚĐ2;qö>ó˘ßŚ˝ ¸h–`=†)aJŐ$bxâTl\jů¤Ĺ€*7ąća-ÝhR LĹB ŽľóžVCŘ-ĂF)€xV EY=;ŮáĎ8śs&5jpö1x‘Ű“sAxC0ř#<9G{<1(Çôf+‚ωWŔ[ƒ]ĂńŻŁŁ ńšjąxff°&čč #fýň¨ô]şěeŕW|˝?ĆwˇŠÂ­WŔٍó`‚qžč´LDy;~Ĺ1îĺ0ii&oôÇq‹*ňJ€‚/"œŠKá˜Ţžă*j?<.ƒ¤ŽÇ9Ćaó4#ş6{ ~AˇčĎ?=rÁŻmxƁ˙h#î˝Ý{,ˆČbA-Ą&ĘAż,ĽZ0Ä(Ťó¨{„YՙÜäRȅŸ lCđGA÷Ÿz6ˇ¨n€(–Ń~ ăĆ΄Ľ[<Ş@ŻŔʓ°Ë=y†ƒiX…‚+Ě=5Řâ6ežÇŇ!(ahŁĄÓlQ†aŘcűY\qŹÄŞ@PíD]+1>’o\ƒg"˘Ű´Ť?KĄĆ@:Ť rźeigŃ1Źx‡9Lč%c+C•t+ŚX¤ Ţ^+0pńóPc†I Ö͢giËaE2&Óăˆ}đ0ŘRäIŰśŞGޗP ˘=M\¸ż°ă\\€K˜+`~ź[ě-Ţ;ŔZë 2[eú‡řťSű‰/´cXýé xœpqÍţ âœ_W‘3Đ ÔŤ;)ƒýqĢY^u•yČĘ4&z8:ÂŹ,Ć͐Ľ×ô/ž\%ô‰ó@đÓ/}2Üżđ"–TËGń¸ťç/Fƒí<@˘Ş>Ď=@˛×h'Œ° „“W ›ÂÝ0+ŽwÝŔ¸u@Uđ‚x @‰Iqą_˛öEô9,X?"söoÓńZ[Ÿ@ČŕSd˛°v7ëźëlq %d6™‡Îqrĺ|¤ćŽŚ°™ˆÖ3ů܀|"úiLž‘LČ%ŢmháSa‚‰$b‘žˇöXŘzb€^—ô,Ţjџ€pž!˜ěNőĐ!aWjjUu`ţ˛bÁbŁŁ›ąÂŇ5b<śŁQ;j›Ě „ÍlŠ ĂŠš çŁťĎTŃąĚUłŢmlpŔŠa팲Ť@+ň*x–ýÄ-3Ťö–ąěU8_ë4ĘDÇű¸:ĘÝú3Ţ3¸ë†`QŽÇ”ř´”kMžŃCłUť ­Č͛EpTwX˜Œ¸{X3.@zŁŹ‚ ľ´hąÖŒ€4iŽÍÍ#ď˝áŹčâ‡fÖ yА›tca˛ôƒ°XDÔŽŕëBYá@ô"ȡ °Ňľƒt‚ŹcפÍ0`#‰˜ËYź‚jń>€C?œ)A:˛á…Ôą?%säĄx?Ďx°‘űÎ&Š;S°ĚđŢO‚Gź ~űň*‰žÔ›Ľ[żŠç Ó0 Ź)–vʍz0ďřnĐTŤz@šńaÝşs?œ ҆ňőlÝl=l `VsŽkÄ"Ś—z,ęQĽř€ qmkKđOëĄ1żťH,SXĆcĆä âkÄl0ťlĄr•ş— Dęb°ˆýd…ŔˆŔ¨0ƒé~ .Ȑ:OćQ‰wŹEňT;IĚ:gË qŁ#•§< GDŤÁPŸ0ťł~üŔ Z 1nůłŽyçő č2Fă2Ÿ‰3łÁ9ÂH6˛} • R§tˆŤ-! HBąöc:ŘÖD˜-R „gQÄł#9V› yöÔČT6V"Ǎ0 ;d×¸áXXpŕaӄĘ@+\!ŃůVy€Ý›k›ckď‘GÂ6ö ÎÓZ™ŃšÎaň(ŤĚ,č=Ş@÷L Žď‡uł{kíľVeśŽTF 0<Ń-@Ĺ1Řâ1boĺӀŠpĚDŹ8~PţâčÔQ­KXîAóĘSl‚ŽŞ…űö?d,1´ý)Ke/^<ąVdm°f;ͼǰśč¸-őŞXďjäž$4KÇŃą5GfdqvíBŰkčˆĆđ.źÄ5`˜LičqXâK˛.Ä DR/Şĺs/ ÎŔŁa$ v–…xLׂůĎÖéβăˆŔzÖd!ě—E¸Ž¸ÁţŁ6 qě‹LJ´pÇ_ŰoŐ*+RuvAZxŽŇ‹Äń`ŚŽŮÖÍNlgśJ' 9Šöăä 7âmۉ3˜‹€nŚ‹ňšSpŔÖCĆzoÁÂ}žÖ2âŢD/Ŕâ•Â6.Óaq5ޏĎ7"@~Äâ¸xG DPžziĽX0÷%8!źzŔŒ‹ŢŃśŻ óľ’ łkĢS śYŹwOÄQ@pŘE0Ń3ŇQ,ţVPD”pOHöAKłi‰ąˇx,{Šz\/E0ÜiĽ7 fY|@ ™1´™¨—j)bWÂÜn5LĘŇŞMg€Z°1Žz€-V¤óďŃ˝u(LĐVƒ´ę4;‹pë˜ţĐ9ú bńhoË­¤‹âŤ3Üm¨ŕD`š^jŞ™•đ-„Äpř`v‰örľÎňäüĊŤě+ܒŹŔŒŰ“éXcSĂυ7°Őy[řŒĹŇY“'X˛Ł |ƒĆY SŔŹćřôźK^ÖœÚ ƒ=ƒ-˜;ÇM돳/žjÇDžT'Sô,`ąG5h„°ęćújŔ•÷žE`X‡6n6e¤• ͖ô‘&Ům•‘ OPfnuą&†¨‹+Áш7/ć×wŤX<Ä8´¸gą•e8Z1ĘÓqؘ“…ÎÜvía-`9˜XÖĹ&‘1D<)žiŔč.D_zäul€< şŹyßÍŽś=v-̚íÚ^FC2¤í˜ëjF°ŕz&ŒěOc#y\žŐáŢp* q XN8ŔRđđu Âŕ›•ú Šp…§BÜ*Ť:ěŠ3dž•ŽFó˜~‚kŢ!DŚóˆ-Z¤-aϲzŠ6X퇱aÍîćVr€ý6vfŒać ¸iąČÇaĹžf‰ő™šI9đ˛„Ás6WO†&%ĚĎYLÓ*$zm´z•Ňa÷lĄ,Ť‹o›VŤrĎ:ĄS¸}ßAôKŹśáłu¨ÂT сň…Č Qĺękg=żŠÎźő­T&zÂ`2ÖŁ ]ŕ7öŕăž[LşśŒ Ť ÷žDš?ČXř €sľˆŠo ;2>ZhŐ^BîGŒĄĂ‰!GEonęJŔžłŰHě^ť‡]ŰËVâëeë“mř ŔŹŰlž‰XŢ\ćĐ%|Íl1ŢB˜Ö–Wž™Ź/mN˛(É`T’Ě•ôDü}돦lf^u氟"OÝišC uÂÜăEˆOJńHl5´^SÖśĽ>0föH{vaç}CĎÁ!vTŮô’ČŤ†_ąÖÜ–ĽO›Š}L'PHłvó:W–đéy†FMˀ"偰ĘnŮ0y˘~ÇÜÎ56Sm•Œhünqčd HgnůĘicŃÁ•đƒ;÷ó N5UŹŁŔŠYRd:źIĎö#*ř‘ąćVBžÍ§ŁaU°`ÍŐdˆ×—iĂlé1‹Yť\FŐ"SĐOąëKŠqÁSŽ›5IřđŹđÝE ŒŐÂ_űŚQ¤.GBbÔąš†2úÁa÷úÉdQ?+RÄz~D"Ë`"Ą“Ć ČŢóćá0סËĐRÎQ Ű菖óů9‡jQ[زĽXű}ëúњâÉV,<šÖÂĐëŠú+Ž)zôŞ8p¨šeóŞt‹Ç¤aęv+Hf W‘R`Ů7›ťóĄ&›éźŃjJW÷Ȕľ¸L M—ľČ`J:ř­ŤÎü›Ř=X:OÖ;0ؘ+! ű€QťĽűcžř:1ë°ĚŘ`|‘ýw Š-°íňŠÚD9ŰńĚĂĄŠkkŐŮKAđűČ şbN™lfŤ`üuI<nlš°'›„HS3é+ÚOóř–‚â|ÄŘč  ˛e&a´‡Ťˇđš5ƌÁB%I ,™FT0°7ëŒéCŒ™lÁš{'Œó˛ źŇgP7ŕXí ›žą‰ŘBYÔŃDç#\m§1[<eŹŕ|Œ&eA››uavˆN^óŃed/,DÁD§  –SżŽˇ1UV-Bי¨k`ő|´*—Ą6q5ę<ą (OK¨ŠL&’ńcá‰0-Esn>2áłdtiY„#˜ŹŘőÖr€c íˆIp\łoRd/ať$ŠđČ Ót´ ´ö•xl1á*&MŽ”¸$bë`?4śsŢÂşdfĐŽŚ´ą ŔřFëŢBsĚŔźÖq•-0™ˆ0‡ÖjďÉĺ,ŰČaaq °YP0N2]˜Ú=Ş]+ű^;@ĺRŹ[\°Č ˜¸Ż6O ‹$g*TBCÇdÚŰčé ĆwoŘVDyßüľ´łŔâqbśŔłŰ~¸/Ůzľ˝ˇ›dbőNľscXlWć§Ń+І—€nÖGO†5cŠŽUÇń4ďÍJŸy[‹+ĆmLć•3Ćą(Œji´ˆžGwWâ5d}mŤ¸aÄ?LŚƒć×Í3žÂěD6‰/'ƒib‚é= “íą@öj1aćßŔĺĎD"‘]鏤öyą\ťż8X’cÉk‘„ŁA‹X°,ŇđŔG1Y¸öÇÜÇf Ô:â͚ĉëHP9ŕ•éşnŠ{+÷ČVi{műĄ×#lđp6€˛ĽQˆ ĄăŢí1~“~‘a5ŕ‡-šZ´Ęo%Öc6Sx´ćr2l–6ߝmC1F>Řx–Ś•čMü á@~ÄÜŕ+Ó˘˛R÷rR€Ď€â )wGČ´ •`YŹŞmţGŘ&Žâ Ź ąńúĐ[ŠdĄż p߇hË  ‘ĹřÚ0_8A˘<\­Dńój˝Ě@Č$žŢfĎ;÷É 8`Ň:˛¨gÚ,ÄIĐ(›ÚęŽáś‹b[–UŹöáU&[ňŁÍęö„P7¤Î€Šˇ` ‡j˙ü0Ͳ8Mćđžň*mťŹ6ěG•´‰!4eˇäĎ*‹­8xA+:q ÂĘmÖÓwŕ)˜Łěxƒ†Ä2fc30:Vëź<ĂľŮűä1Ŕ0Ź8­6<ŕóPŃĂź2XŇść °!JÓđ„`ěޤŐôöŹîŠJ‹­ŞŘ ”řß>at‰Ë°Œ Y"ś!v¨¤…˝Lcěmöd‰ŢúŔ$qd—šz]d% ˇŞĹ>5\]°8 {9˛ l¸u‰ĺXp\v`|Ş…Ćłlđo’f°éXóŕ+ yľŃ"âĘúÍ {\ #&‡­ŠĘĺ m1jéŃ(űËI$Ä P$B8…Ňˆ"Îg´ţÄzä`é­ÝwrCaWˆ+vž Ëokë~ÁŁ3În‹Ć0EĎáÁMąHÓ4'ÝÓa-|Ŕi{νíDň“m×néT˘EöYŮ [“ĹjVźśë×rNŘÖÓ[O„M\&UÎТ0g ëQŞŹDS=0/„¨Ťš‹>ŽÓĚ7Üm=GƇy Ćf&éČ­ŕ΄>3a݅‰Uíŕ„ŻĹ´ŽýQóšł8`m‚h+Ŕ< ٲo7ÎířÄ}˛oçě۲LŸěۍûÝcž>˛o١§ěŰĺ‰}[éűvřČžÝdßNOěŰ2^Ÿěے›ŸěŰr‘ŸěŰ2Yĺ˙úů—ď$ü5sń ,Ĺ×â^žŚoĚźü“ĆćK˜—ĺéý1;š**ËW ^NOŻţŠ—ďśáoÄË//KŘôwů]*y|ÎťÜ[r„)ëO.d?÷ö•ckÄĂ}cö덺˜߯GËzúÔYˇÜ'ăB Š›sűĺąř{ٌżśöĘťÜH›kđ'ëáÝŚ<Ęť<5žâŮşŒ°îçčçҡO)nŹ÷łt5úšŮÔoň?ń.KôĆgŁe>ŠÔÉýĐ>Să`Ţ%Vźńdś€´DÓKˇX9›ľ ŽĹąlÉĐŐţčŐŚĘÁŚěŃ*´q&ؐKý#NndtuŽÉŁ##SëűĹżü2ÁÇlćyŞsšmô"â] d îĺuëşuŽŠDĎ|řńerÖÖ4śöLmáY°ť` 6hÚÇŇo­ťm[çŠĂ5Oc0ӝĽWn\NćteH)vóěÖĺÚ1:Ěqs^Í9›nźËňĽŽ˛(LGX<˛ľŃ|-RPK­LävXÓ#KQŻ}o¸đT˝Žowa†™p0Éű|X@üf×äz–(E˘°­Đ+ňOĐŠ[âÉa&děŹÚě’MíČuë'b!ÂđaŁLĄ, WśQcÁĂMěe˜[Z nßŽˆmľ¨)ŤśˇńHć1öpŹűŔeeŕ´ŰĹĽ1ˆšŐSGŹş4.Aiă̕ń“‰ˆPÚ6Ťr´ýełĚ}Ú­e°™ŮJέđ2qíöͲôľqşÖɚœź˜GN›ÉĚU˛ŐgnGż{&ś'¸ß§c ŰZř˝Ľ+fFˆ=ßYˇžfYHć@ě/'‚ľżĎ°qĚçK’g˜ľőa­YA]=áé(UMž‰Çˆl–}M…ý•XaܢU˛\ą˜x&Ž”fşĂl]ö`ͤŔ˛JíĄ{”|”HŹÎS;Ą)Ź^ŘÎnmT~•Ďe–uĆ%uÄÎć<ëŢĺŘâkѧ= üm´-ޢ×áëĺB˜űÍcšM.ŃTR—ŚeŰf G×a#â‹|ăđtÁô@ZËXl/hť% r°XšÂV{ˆÄ6w–*Œ’ä“3˘`Ů*[Ęق•B% <ö˛me7o3ČnŹ&ŇťC0l/@ăaŮŤ||Š`ľČ˜eÇą!2÷łé׍§•I‹€‘ć`:ĘŘőa˜­EŤeM‹œ‰ÓşĎܢ6ű”7ł aë7[Ďm5ŐţyýŞ%ŻŠ[FłƒĽÖxd+ćc$Ę7[úc–_g&ԕ ÇdßhWÂźyb°Ă>v[˛:7ŮĐk oÝÝj/鐡ÉÂR/I!Ĺą sQ>iÖŸÇ4cPr’:öŔÖ­›OlČŤkg=ž›äâO(ó*ŁţplÁęíŁ7ƒüÝdvóŒ+ěS6)%7ž“Ý–řtÜX‹jż­Ź^•ˆŸ apsO­é>ŠMé§ĆŚł¤`aĘX˘hâI&şÝbPŠU*Iî‹L§1EäŔŒ‹<ź\/đÔą‘ÎÁăŐ2%ůÖĆbuHôhĹ€ŒŽfiÁ&;/ŹőڛĄŰŘAŢ4î+&Ò.$`›Â:Ůŕfţż6 üšąĺÍVŁuşË gbĽ9ˇ‹!ŰűşĚmz@f0VśěŘ[Z]l˙4á˘Ă°ČAę헮ČlŠcá ěBľdiš6 ŢʃľÓьÁ‘IÄň=ű'äiëŚ`ąĐš¤vvL!›°c[°ĺŐŠ<&6zvr€¤÷!/óŒR&ŤZ0Äđ";ř(y_ä¨)žÖ Í*°㸢+. {Rę.t‘/6ăŃrv_˙„űA&Yŕľ_Ź¨Ě¸œÖÜź¤Řďă–~KiRĆ9vŐ2ňŠší3Ž|6Ďz¤ŮŠˆGk†+á˜%óŇŚ1LŰŕp†ŕš^—˜Ńc™°<żâ3lCÁĆ,“œ“(9Fłňš§%Ű柣łNN~Ím]Öq™ë8ŕH6éjÍDY­¸šŕKś.Lˆâ€Ýśs.v“L5[%$‡řV̇[Ta’lţ Ž †Ł`ŒL nh%/dƒÝ–ąa¸ˆcăŤŕǂ… ‡ç [¨™Ä˜Äu‘ž˝Ž§fÇdŠ3†Ăž7)‰;UnÚ[m‘ZYíŔXžgGśM2én’—śŇLIJa¤Ńłľľrƒ;šEP'ۍy#ëń- Kĺ†hŕÍcŮÄ1…eăikqĐ4Ô‡2N;úkqŃ(ĹsVÍŹT“2oˇůˇlŠöȲN8yŤól“!f?d•ĹVZřœ, ’ŮĚ<ĎÓłÓ?l ŢÂŐĐH§ZŮesâŇM˛'qŽÝ€Ď*ňbՀg’’\âxy|Œ3{PvËďWe‡9"ŇŽ{bÛéVœ‡Ä$´'âžĘfU& ˆ!X*÷ŘÔMeŃęĚ#ęb}Ú`7)Î}d‰†'}ˎŇ͋„Öc/%4>Ü5ŔsĆ2Ří:ČĒxű×6Ű\$c“œQŽdŰ|mž}@QÖŘŐp{oÇ[ˆ‚7އůs˜B;L˛eęŘ9öÖ]ł;¤Qjď °~î5€zĚčŘsDů¤ÝÉ^ËË/F˛!jRWq­n˛œh˛j@đźvŽ`ái1´ÉÉúdeAËŁ­<}O2źYYbáeüľ:~ܞzđ‰¤“›ălLˆœâí]ĺâߝŃřçű‚0ÍčŐBą—ßŰvm°‡lF¤:;uČúĽy–Ö]&ŠY@7łľŠqD⚎Đpľ,6 Lţ\ĆÓö˝‡ôB–;b zšˇšâŇ~CŽSŔîĚ+đ„Žö„§(h˛TŘFďŞ î2Î ű›t€ƒ *>Œ°d cč€ß¨h”xôn mŹD’˝­žÉ;ˇ6ˆZ×ŮŘsW eôŔĆwe8€a°ëęÁöÜHčjă\?F˛ďł%‡‹LĹatfB›iébľ¸&ÍŹ B;2ŽmŞLľ Â_%&Złm<Ąw”MF̰ʄ2–fŹ&Ż%×>˘ë3b•đ`łçšK kÚZ1•M ÚʐŇʂm 3˛÷PĎāËu`ĎŢę;|ôr›#0Œ’Ší\lÇĄ"I–¸%ኼ`’@O5űlƒ§ťMrM­›#bÚPi‚ˆfű śC^ýyuh^ÝęË(uiŞ,gwŽç(=ű<7€S”u}N  ŞĚˆ,]wö¤Šą„YŤUäI—ç~’ËĆJ'^ŮşŰF9nÉÉ"‡ÉVČLŇD91­Ýjńna/Ż{[ynD­î5Œ˛kśh­ÝÓćvœVOŔÔÖ­ÔwŘ_?fĹĺ@Ŕ‚ÇDÎtK˘­ĽÎLjüŚ˝Źƒ­č\Ëô^ 4X;blŢ3*=&žČ.=ď8WUg,“FÍţžĹ yŹčnÁC7-ƒ5[ű2öČBg@´3pŠIsžç`šDž‚%q’†ŐuqǧˇŽgkdťŔŮşĘ-ăb•M‰ľF;2˘˜ßĐv:(…𲍞Z<ĚgĄ łE^łT(ÄŕËÁ)Ž2ĂJÎRo676Ę5˝{߁GlCóŽ2b—X˛€Ć.ł‰źO°ÚǙ!­vGö,€y–źpčlÂÚs+íĆ^݇Lý˘(âŽÓ€h°ĹŽ‹ÁQpžű–Öd/{•Ô‡&q1Ń„ög—íқőOE°'O’ebȄ‘šý_rCáJ§Nňž(: Ł !ł%O„)Ma—I/ŘĆť[”ĺ&w~ކnMmԂ|ŐD"l%úc…N6pGŤ œĎsň€_Ďb2% (_w˜(ޢäxR۰€öŠ´ĚňŔYs…nOhŰZĺ[ÁdbÎ<÷—Č]äź` ńb–jšń}+1˛uśur: ˇ×CkŠć‚ôŮEĆżjý*ąvýG’X>|Ů’ÍČšńđŮS™]Š7€SbŸĂžŮÁ5p„ë8~đĎ> ⣔•ÎLqŽÝ˜œžAЄs1x@ą)ŢnîĆ`Ÿş|2›"FéOĆط΂¸Ůťcy–VC+°vŇŔ,‡ŹŔr’]˛đe8Ł=đš‰0“enOĆfœfb‹dŕJřICvťťěĐ(LşiTëi0ş<]‹śîX_S#¸33ŕ!ö¸;E6ÚH€ÓEůsôˆ˝ƒ‰wćœíőŞcFy–Ľž=‘ \ľe_°ŽÁDȨؼˆwFE}5Ŕ%ٗ´˝őQbżŃ",K’ź â„%sľÍ6ŤzŕVăFÂČlč6 /zžŐĄB¸{–co)2Ĺ;Kô‰ućFČ*ËLJ…w´ťşQw8í'9ýNFr€łC˙6).eŽgČElä Éy÷ĄýŹÓϲŻň‚MDMy0Ť2GGKˆx KŽnNÇ ÝůЂ1ŕ÷$iPy_dÄúď‹Cbz"nƒ‹´ŕr峙DŽĆ$Éą†@Ô°ľöq €{łŠŐşâ^WdݑóÖB˘šZŠ}ä.óďŘ uŠŸƒ´HSRgĺĂ0,X^ă8ü§ĚöηٗĄî’šuÎj">;vůœ{ňšëx—E.D–ßC¤6™qÁČŃ2ËŰ>YíłÖޞÄËÔřcW‰Ź9îj[€&śwHĂk˙˜ZŇň타D 1nL)90×o/0> ß$łŐ0ęáL8ňźÂÚŕ`gEě…"ń$Fp˛žeČ6;ďĆnst’Fea™vÎxÄC*Sţ–Űb :î˙,ÇŘb,âżëŸq‹  ÄÝ*dS5 >čąQĆç<[­ľĚBlď 6tp#1äAęĂđMŕD÷Ę*ľýđÜ/őëěÖ­ŠcŸ‰­1w’ĆHëÜ´I† â›ÁÚÍa´âk?ÚĚJP¸”ŽXŽÎ †z!Lât€„qc-‡ë¸ůrmEŸőŕ…,Ťč3Nb>ƒ‚CňlľÍÄŃ{n´“†`úk’˘ŁÁ/-;zśĚB>@"aPôŇI§Ń^k߸•Máńk„–đ1iŠy_ŃÍąˇďU쀕ŞČJWqK“ÄúUťâ‰€ M]oŽfpäÁłŔÄS+˄V€€EŢóěˆŇj…ˆűNÜ=ńŽŐz§L˛nĄ.i–TŢC˛0ŞšbËŹT?ĽÚĄm’čK;6ou3đeGöQçޒˋóXŠIŒ2ótŘŘĆ Ż 4Ŕ[<8ÄAL@?ť-fQ<ĺ(EÔŻxřâëܞXjňŠí!{#6ąPeŰç2 L2ٖ˜2śs!™h ˆťJÁpăĂÚÉŃ=Y €;ç'@džšX¤ÝÔľSŢ<ĂsĹeę Kf×$+ˆÎ“N1w„‚uXxŃ^ęKú‘<şáEŞ‹z T_/Mż/–ű݃RíwKŽĽß—CţKŇ˙ĺŸß˙ţďż\‘ţŮ÷ďËL˙Ýţç˙řßýť˙ţŸţĺ˙ś ˙ÓżŸţiřß˙Çż‹˙Ű÷ďţőţ§ż†‚ô×˙礞^߲=„ťztËł‡§jďđTbţąbüłzôíVç[=şĺěőŠT}úXqŢ?ŐłŸőč­2=|ŹL+ÎÓSüYn%ůYnýř­}|ŞGˇŽűŹG?ÖŁˇ*úłV|mőč˙\Şź?‰Í+ř ”ďëÖx_é—x˙¤ú~I‰7Ţé,ńđ“ďdř %Ţ!ţZ%ޟváoŢ/TxÓŐÇŢ!ŐüY…wjUÝŁuŰýÔk}ű”rŠNČëĂl‘6˜ÔĎjŠv´t O]ľŞÚ!RVx[Œ=ćöšúk„&Vx›|ëKŤďűyX^­żî@C~„ę§đóŠôúm•×ÝăŇk‰`Ŕ¨ŁC%-‰]J–Ît(|mÝăŔR/™­ďŰMĄ÷„Q jů$ě˝éOęĎJPišG”Îk_ĚTv4‚ÉBg@íÝÓPyˆqY{'ź8}g.ĺh•ŽÝËə$ ÍŃ*Čڟ´ľÔ“ôě)MŇcxŸTŢĹâ0O;P|%ÜaĺˆĆŘyFŤx řĽžu˜+áU– }°ň:YUťł’„RŹ­Ůú2çÖŃ46ľ†hÍ Ë`ŮŠśQĆ`‡*9ŰŔejyň˜‰ˆĽŰ¤:H5XU×Oźř,ˇę"y¨TąN÷ŠÓžňúƒě0ťó1ąœ…N@óhňÜ ƒ˙NCIž/. fg—X•×."ůAZëFf_ węŔűwfĎƑçYLˆG"]łV_gǐ÷V‡L*ŢGóBuˇ?u*“çŁä&ßjŽ–Ŕy>;ŚŁ… “SC‡í¤ŠlN–Ő'Ěžl<ôTüËó•‘+łc {ÇŚ„Ů ŚťU9Îź+ÄPźbo‘cŹŽť3ôŘť6˙ÝaŚ“¤‰ëčŕ˝^~čmč%ä–âé1ĄY‘Żý”i/9Ř˝ c7ôŤ„†„F˛+:ÍWšÂ*ř˝ÖKpćâ˜[ç÷Hjáź`“˜˝uűsgyüÂöŽIƖ­•ĐěÁŠ'c" &ŞjÔN9ç(•Á*CFĆŚŹ˛€ ŮŇIľÉńĽŰ1ɉ0§˝Ž‘pą_€EŇw)é’UŹÎD Ń,ߔ k‘ŒXľ°#žšoŠÔ„š;ř6 wDÇĘśN’l8ĆÖ´ŐRˆ­Ÿ ŒŞöu8O+[+Ní˜ 0%̐‹•Ýň@pčŹČÎ`< iS"Đ[y˜uŒš-UůgvĽŽKj}ď“ýŮŇb™ő'DŁ˝ľC•Ę:"x\zśNe‘pąZíph¨lOC0ŠřId*˝Ď:;ťzÎ5Hb­7ÝÎŇ:ßĆYņƒ{•ICŽĚ}SœfËeBa ´9\6Ľx°Vމ[W!Ľa’+Žťýí1âĹ#U)€śą„–DZ­ĚýXɲÄŇaFg‡ :΃hÜä˘gyÎ(–ü`œH‘ç×8Ën_YMƒĺÁž˙} ě|9NëŕŒN]:ą÷c†ŰÂ~Ô๨äÂŞŰŕаąosŇ&ľČ)W-SA­Ck\Rç)&ÓÎŤĂLŤl! QKĚcé"[˝lŚ%‹C`äĎŃmžZWÇňšXon%Grß&Č;f<Óľš+jqÜčH`'ˇŹ‰Z*Řç =sŁčŹđ m"AŞü#•žÎ2 &3Žą8Ní›Űú6ŘÍě,‰čG˙f3JoEBˇâeă4J†éŮóŒń´Ů)s“GW°Š ([§F_†8zHlúŽŐç`UwŢšWX]ű)!m1gľs ů*“l\Óh˝´‚Ίśt +ZwššĆźń@Ö°yY1P’ßPę7흎x•n0ßąxö7căœ†´Q$›<#Vhľ’"âÂGź ÖЖ"é1§"öcÇÍŹY'Oľ˘seľÂMIˉ=Ĺ~sĆśÓ¨dÜŔ€Ëĺۏo]“Z,ƒŐů¨Č\Xó€Ď\š$ézěźĘ˛šË˛7˛‰t¨ÇĺXÎ~ÝŞéÎčüóÁn6Kˇ‚VůÂŞS—­Ž‘Äv^đUZDzçĘ=—(= RšŚ6~+ôfRZ,¤lI‡}‡ăÄ6gń”4[öŘm6j–Čy'ľ.•őŽŐj>× ,AóÖ‚Ľ°*ÖÂzn×˘Ž ďŒꆳ’ő;âĚ’Ăůˇ´ôŽÁ.íئȟ†˝KVÓfůž:)čŮűÖ8_$ Ă~öbDGűڋľ8cÁÉ/XyOhő&÷#°dÂ"áUœi0zŞśőŽ6kԍŠĐNËq-Ílü,I•ă# '§ĺčPˇÉăëÍś„-‡i–ƒ21ŮföÚú¸ §çaˇqűŽ—rÖßŢa„˛ÖXM0R‚fM×cd}Ú$ÉÍmŒÔĐôk˘ńěç ŰĽ N::bőĆňN:áőůŢešŠ)#śťĚź6VÍSĚľsâ€ímÁšz˜…ś!bݜ’=€-ŕZ˛´D¨Ň,‘ oĺšőß=žśm6ŽN(żjyĘF'ěŚçÝśzć(/Ű;Ťˇ_;YĺĽď™×ĹžĚĹ֖%H\yf\ĺ-ËŇS<‚yl &:38bÍS)j˜yƒ´ą‰˜PĎћy—>Š­-…Ëk8pyßš0ǰË|*?–Ó¸¤śXOß&>Ř÷ΊNA6XgÇËýĂâ´ˇl ęošĄG;›#‘Q ŰvvĽŒ^ ´iôö8ĺ$Żšľ9Sn…l])îˇ:ku‘ÜŞ'ÁŽÎAO]v¤đ”§¸9j2‹HŰűęˆ /ƒŁp…Lđřc˝ÝÇeńT&[t)Ešƒ?%ŰśáQŽ4)‡X.üSŁ^mv@Ľ=W\ŰDřŹĂ“ÉPÁvĽ5ecę´aĖ &ťę`Ć˝wLňö t9ZPVWćn3…M‚}Łżg‘m9ŔÄ2Z§ Śvô°K9XŽ'"sü<˽㺉O e<´čŽj9ސĘaô˜1ŕ1Ů$'á†ÓĽ’ÂEQżUňĽŃYÍjZžŐŠ„‹uËȧ5 jĹ,Ë. °vŘ ŚŢIDHaTéĺˆ$4Ő"Ł~pž@rh‡DOX?ĂX`ś3*v°‘%Ô2łŰßuiTy-`ވ.ŕ­Á 씔ö;ŃĎUŰôFź€mG‹Ľ€šIat%°÷D¨űŮeq˛ăĺ7Öą0×ĂFÉžFŒŐd.Z#Üu6‚,yĽ ŠĹĘuÎßr˛=ǸYüFX­rŮ%wżŠ€s+Ç ‰řŞŚ'ą†°olŰÉćŁ1ˇ#F’cĹň_'1Ôž:~š‹­N÷ŕ ƒó+lа)Ižđ/oj:ě¨k˛Ýš°ulsrԞŠU­\¸ł 6YKŻťÉF߁úŔÓ6/͎żŠzŁäqP”˘7x"j|ö;„AţRĚĚu ŻšŐlJ!Eđ’Ź@šěWaN‚ç6ęŢjá0”`ƒ Eşc4,L]Ęl÷ěŠîhţŚ ĚÄ>Ô/r ŮŘItoč˛8Ňł'6˙ j;†“¤ş ’ř{šEä’ľ}C™YFˇL ­99ŤN*ě]’]ŠćKçɰ0VFE'3×ÉúÜ*/ĺąZĐjdMü-Š.{o…U›ö€= ž'DŘ{Ž˝ŽÎ'qŘ˝‚ťÎGŒ+o—‰%zї,phf&ĽDĎ’ߌŏDFQwŠt rŮáżiŠ*Q~cž%š’¸hm řh§SwÍX!pœ$š„’k#ÓńNGjăę{+đ o9Üť¤I÷ň™×ťG‡7Żžě]’ŕż­ƒ˝'6Źĺż˙ἃ˝żśđ˙ýýżř÷˙2ţďď?üţ_üţ_÷żţŤ_ţé˙őów˙eý×˙éŻá`ďľÇ˙˛ƒ˝—×ë[ěĺrw°'łŇđtDžNďě姃˝x;ؓ\édhʡƒ˝v$÷ŃT;â O Uˇƒ˝đ‘hjz:ؓę<ؓJę<ŘkÇyĎo{ëG˘Šýé`O꧓hJ꧓hŞQNĽ'˛¨“h*ŽODSžN†‡‡á#™Uřx@yM‰Ś<Œ<‰ŚĺÔIǕŸˆŚ$̊ÉŹN˘Š4>M…úD4ŚF4u#ÇJý UžčŻRx:´L'aż‘Ú=ϒÎ÷pwÎ{řĺ‰ä+Ő'ŞŤÔî¸Jn÷Čün>IĹxćÜî‘ýŰšVüFn÷ţ\~˘ÉĘç=xß\ţ›~Ž”ŻŘˇ_`ÚžÖąéÝ#}ăcӟ4Ž_rlZâťß…ž ç~`şžÂŠiŽ_˙ÔôóMřŰŠé §Ś&ÄĘăcÓq Ÿ›śăQ§GĽĂÜčŁ<ó6GC٤ ÇĐLý:aœŸťŸš[ŚvTę7Jl4XNŃ ĆđęŢNDہé܈ąćÔX°Nś+˘”žë—ĆĄľ´ť­í`v íbö3Żkk|]>ËŃž{ÔҘŻrçS[ű= ŁdXCŮ –$ĆĄýPđŰRm¸óëŃWd0 $ëFYÎ]>ۅœŕя‘žÂźMiżŕř8Ď%-Dľ§śˇŠWŚäľ'„­Kösó—çÍ'jQBżÍŽ.Ç_Iłĺť­z›‡Ă°ÇHl]cŁęŽÁ! ăjW#A˛3’ÖŠ –H/÷Óîř‰mM>ÚJłŘźh:8Ů&7ĺţŞŮy"Vん‡ ÄČ Aéŕ‘Q×n÷O‘ËçČţ%ztŰáϗ5Ů<íŕ•Ä݈bkđ ‹<8$şŹsč×ŇI:!÷a6A´#9›m‡éČŚńS›˙ˇEyOv×d⒦>ˇÝ!Ěkç8ß<ٸaŽąO!œéíĘp@â˛K€°Í‹K–ρ8Ô4Ęć.g ím˘NŽ3Ž3:ĐÝíŇF†y25Ŕ› ’—LSÜ>09#ÚQ€ĆϽ󇶍 ĆvĹśúĺˆm˜3 Eôěąíá‹ Ą|HLŰ=óTĽť^ÂX‹Mą["b5‹3ŻNP܈Év„ě[ącypŽb’çěŇSˆÖnÍ<Ů"8ÚŢ7›gRšL<ŻŠƒŃ„Ö*’ÁŘńťťÔě>@CŇѕíœFśn ‰ž¨:})´k< ÓĆĆ6gľ6–˜ęé¨ĂFŃ­­k]vŹwŠłc™‘†1"&ۍLJ)dÇqŁĂAáÁŮęÇ2Ý:Ľ1Űe.ŠŰ˘ćΓthžC=ą˝y[ˆ0ٖC~Ž¸Ůˇ‚pƒlĘ6¤ďł)“KّńŇqZe;v~kžg/âętÇŢa|óa/3ńűžvl0aşĂ¨ƒ'Ą‹'"+[î—ch]HCvȃ3‚Ę0Řp2´Űzž/K×&ő8ĄfÝěxJ)›!1ˇeÁČŘxА#~ůkś&öľŐ ďľ“¤ än­‘•EkMÄć}婊=ČŚŔBś ş.+J }Ę(ń4śĐĄçŁ7Î{ŢÚź*ŠŇLٝ­ľDleŕĘ[€"-ËŘ&[Źا6­P>Űo씷MΨʚŮÄRf‹™#œQŽœ{LË~D™Ô´HćÂcrčšSW¸ôÄŢű¸Éc6!"â-6ŁÄ­”­_$F„dÜ[$Ęn^5Hš6í aőě“gçî\Xçi‰Ü3ŰÜL$m–—ąTśtl3ĘT§Ů“c$~ˇ `Ű1B-’6ٞÔM řěDťşÚţ]ř:ÁAŞx‚aÜ=4ŕýÂ6`rŇRQ[ťŠœ§3ČńÍF•˘ă:$GáR˛ąČ6x źpŒaj“mB]d_ç(Y;eˆŢ:W2)l,ě´üÝ´iŇ[ƒ•œáڈˇëżë{lÍsÂÉŕŕqđôkIŤ a’cmŸťqKŽ˘@FLűŚŁźƒsÊŁ~&ÚľÇ1#âý8´p•4*×nÜ79-‚‡üűbŮ@+ť?Ś6ÉcžćŔ›­“D g<űŢĘääçžĂž;EPvl˜gÔ!ŹŇyěö đPRĐe[óY%Ç˙]§ms¨çNx‡,ëȝŠ„‡‘\ =ë‡7dgżeyË&űfí=ńˆctdř€Ľ['$܉;Áękwć1;Xwőc-XŢżžŘš…tf ĄœąŃ­š“Ľ:¨rPœ)í;˘ ‰Ę0ćp°S$:Çcľn,.Ö(­ËčcĎ|<Ś RŔďZ{ůřԖ_ŕ#í˝Ł śş`N9˛O5đŹuFĘ:)¸,W°y‹ĺDSd“}O{(ŃÚ4Ć<ÇcjąáĽc‰ÄŢӎű8,çAÇjóßݖCZ7SaÁÖ6Ó“KȎ™ŒśČƒúÚ;ƒÁŸq݃ýŹřœmł éŐ0î)¸ÄC–/yHœp’kŽ`¤awLް9ֆ>ÚÔ:wy(œ;cƒCÉłÄ+[œ,ŤíżŹňĐľś¸ l •řM҂\°(Ź ři_í(ç&ŁlüxŘČˢ$+Ü6YĚ A¸\r›ĺ9Xofóo=Ř%U;bCzý›´ƒ’­„ĹůÖG§Ź˛íheuLΟKŽv߆ě|4„8ŮŞ1ĚÎAľŐ ‡qf{K–îŔfă?Ľôň-wŤĺFśV?ű’Ŕ¤Í+Í\A:EŠţuśŠV‡šÚ[1 ś"Jq 2oZ”‘Âś–şZaNĘhyt C5M;iœćÎ2›“XBrÜ`őŐɂ_Ă۰QŇÎсëźrC'^ôÎŽuLҁ]SٟăÔ Ď—,Č띇ÖOG…m“ŠÉq‡ z9O-ňęŞě?,]“ŻMd§gYs–˘ŃNŽ] ?90+ö, ů*ŮŇŃľa8<–¤ŇٛSĽšÖŘčŽáHƒ,×ÝěýśYmb›ŕŃŚ$;|ňá=ńŻ­‰Ęt|jđcÁ&ŽĄZÇŰŻőÉ~ÚŔs2¨ڐçbO XŚČPš=ě^Ažrvě{*ß~Ëö˙č0Š…­{gŻ4.sďtŁc]-ąđ=§pšk+0şŽĂP­ý˜dáAěŐBGü8ŕ˜=Ý<#Vč–%;VóD9vł yńSśmâa <;g/­Běbň {ň(V€Úy‰ewŢƒÇF)Ř@űY“,S<šĆşń ”HÄbš^Q>FŤö$ŰéƒKX…h˛Je ŕG‰$tޖRŒ ü6tw*{žžGŕÄxw$×WľÉĆŰ;ßĐiŠÇáXó…Ű 9BՃAœ9ŞśM앑{'Ë ŽíÝĂ"! ËbŔ@3ťĘ/Ăhi“mĘ­¸/cÁ¤×fŁ…QƔ$k™łŚ[ź[ľ=.X’ ÔdXboÍ폼0těŤsž&é C+??6+Óć‘ňčHj 4@›¨ Ŕl$˛<ƒ š“Ţ“ yvţďÖďë r–…l%$ÖPÖV ň°cËĂŹ –Y2´.˘i–˛Œ€ńŇĆÍbbĽ ´ôÜŮd˜řŔďŐ˜‰ÄâT\tě¸!ąťCľœG‰[šĐkĐ6;bĽFÄXěZt‡rÎ ľŞORÝNzůn%Jsž /QeŃ+¸fçœâ#Z=81m•}[šžUÇ7ꏩĘëg{…4ż¨ ™‰]’]m!ÔČŁ´“͍ťě†ęŘŇ-–+9ŹrÚŽ/ă×ÚčvŤŤ˜ă×G^Ô!÷ Ž“îhjËŁE*ű¨ôƞĹ[AŘ&ýôJ`1{l<š‹ą,]ńđS_VF™&ƆéŒh šŔŹšĘFPŁ|œ›CŹąö€GŠfĂb\_[şéˆŮ˛ž2*YzÁł@Â3\puĆ4ď€m„VR=-` ĚŞcł…@Ööţ# v”$Š—bÓPś„_œŐKE2™S̒MX`™ýü.ĎÁżŁçˆĐ ĎKń}łx*(/ËÎâ÷5HĆ_ŐÁ‚rbŐŽ5ßGš+Vœˇ}ôCqŇň@ŹáĐ3l×2[Y䘌3\-‚ř°ˇŐ>Ęŕ`Š’ąI*=›sž†pc A+ü—]‰Q€˝ň[a†ěé%zwŒöÂuywiŘ<š‘vąˇŚu?Ác—%‰UÜ¸8yŒ’íuŤä Ënuறô,„†đ‰ˆşŢxƒşI΂ŠÚœşjÓřhůwŘFŢs˛„Łdb“˙Ó6mc˘Ů:Zŕ ą…óAgPNF¨$sgU ŕÔ“Uf¸îŁÝ‡łAŮŮmN݇ăÂZśCş•âHŠĄ33ź^¤ťĎ¸pŁ"BÄÂN÷­4Çjěf…`ć›ýdr/*č‡ŕ6A¸t tŤtç2Π€‚ś]ţdlc˝1™řŔ~Ĵތđ´Z[leś\8‡9­1ď2o‡Ă˛ŠĽ]8egXmNä*řfŤćĽŽîŹnŔi–šč;Z"¸îy1•B,D;ą9şč@ˇ8eŰŠ7'~aPœ* Řj#ą:Ńë`ľĐ$3˛ĂÍ6ůCŠ‹­6Ĺх)N.(¸§ÝŞŕ˝‘CÍŤŮ+˜­ćÝä6äă@ľE˘Xób… âU1t8€_6ńÇ*Îf`ětÖeÎс˛ňís,(iœwËm'CRšĎŇůá<1a˛Óm;'M+ŸcːĺwtVńářψ:O˛)!Č ‚tä)ž#t÷Ť5Ł‹ ˙ٙÚ;nžHÓ[­Ż~tkóőVnUűĚ3ôV̘Ż"î@?ňüYAm o°œ¤šĽł˜ĽO§Ĺ,Čž7Ę| ÖŔ1ď‚6Bńـď°{Bęçŕ"”Éjۈ1ł’ѕζĎ齓.Ĺ^g4!,FLy”‹ËjYçěVyčL!/îz”ÎĆů͛ľw„A8Ažœľvwä]Ěă]đΚ8“v’š%;o[֊ âdâ;`Ťńe‡É .šÇ!GpŜwiJ„tّ™NPÖŕ:3{)ŽlÔśIÁÖ˝ÍŒ›ź?C1X–×mOć|˛‰ľňň‚ˇd $AmŮÓÜËăś&q€4Hn[€â.}çŒ@\˙ć|?çňmيl§lóÂł€ÁM6rt˘â…ś‹`¸ŽPčp0ş•ÁyÜěV˛¨Aš6Sť@YšY€ŇŔŁĐËxçÜţI.úaќMËFˆ6異ó=uŒ§ă(1EiuŒÉˆžW/+¸÷męsqBą˛ĆňĽÂKOĆĚŕ{,É `:ń†ŁkGŠQ]•źݐ–Ů\ ě$ieG+˝GÇîb^@íŒI‘Ä7+ÖŃü+x–ĹAĄ-łŒg§XŰn7a8eč%ŽĽć*üQĚ*¨KÍNŃčsÔĺĺdcFWAˆ|on}jÓÝíáŔ Y÷>î†F´:ˇ‰Ž‡Câ-™höňšÉ(č°DÉÁxˀ…,ŚĚ&)ôqe’5ap¤`šŒá/oZóŘyŚ5€öˇFŐiœĐz“X_>:9AZ‰ Ƛ^ZZTŽŁuČ}X:nżIĺ3/ŃZÔ$íe:rPŠ“ĽF^ŒőĹÄ ‡Ź‡zœËcKšî Đ{[dU #w8–VV1ßąöfs<„DÉmęYÜźło5ŠŰäcËŘދlZiĽíĆ@Ė‚$ł˛÷ĐÍ6 !ÎŐ-Mk/ĺ^hGBC›Í*ׇœ*9 žiŕ™‹FˇŁm’ÚHq>Čx˛Ż˜âDËůœ pŮá,D…ňýč-×*7Űb‘m?ŁL`3eEŸîŃŔ~Η–ÖXM¤˛Çň4ę˔笎g%TćE:ŢgŻN(-ŐěĆh.v)ńŹ1ƒ"…°°„TlýFDÔŔZąQƒáŘ€2žÜ“mň˛KKÄjëLČ<°ÁďÔşP\ćźHœˆ €ĂÔ˝äqżÄáv/yÜ7:\ǀLÎŻ:;Dž8jŤŔśu4÷ť;vŁMXTÝcN§”JDÖ÷écˇ­DځL"ú€tNPŘíÜLďX‰ŮŠaSŕÁVœŤ3ěÂgÇ/ěĹ袤”ěártjĹżbnĄŽ$ـ‚Őn_BQ  çĐ-¸[úÇl°mŠÓs p;„ĘrăD›‹Š<ŸŰYڝÖŽ:ö>oNŐÂŕďěČ`ËsYÝŇĄžŒ$ÓN#ŤČ™˛‘kjwÖŚ… 3‘k°0?BĚeąŰFš(ź8eqܘCŢRŤ˙ű6ßÁ/ĝ”ĐÁç[Ľ]j´k˛'8rřN9lMΛfBa°ˆ4uŹŘ´:<ó\ą ޕhÝĂp“ˇR 缃rŽ#ľ ňڜm{´ƒ„čĺ1”X  SëyŸdĘ[DfľśJ€“ÜK_…ˇ5wŃc”°™}—lžJŠi°M,6”I(:,ŘŒœx8›ŢYwžř#¨°ĘKçxŒřȸDÚ aĚ&˙6ÉÄ04(ŐižlÓ@!a˜ďM~äĄd Ň@ĘYúüI@3ŘÜŰ{ÖP۲g9SŒ‘m^â:LŔŢ bډy:|Ť(Źś6DÂwŒk8¸bvŘ|HH-VBy…’%Ełc$îŃěÖÉ×iIç¸.F98>jÉďůi ˝;6ÙŢ[*DEҋ#Ľ¸XÂ˙ źrň{­› ĺ`ţŕt‰š ‹‰ľŁk÷"†§8[8d.7‡Ź“UÓCœŹ7ąŰÖL8ń[V“Źr™ÖlE´‚ÇÁ<ä•%Ń~°äľŰ~’0M[?–ÉĘţ=×E&ý‘fÀVŘűŽý[ƒÇD¨›\ ąÂÖKpjRA–ÖÁA< ><$ž œd0óŒqqĘۚÁşmĽŮŠ^nöŢӁ6 — (ĺ!GýżH(vXü( šěŰ(2ž:5Č‚§u)rËjĆŽA\ŐElŹŕc Ýě$‹dĆB::€H*­4ە!˛ŤÎ9m&UYwÂh‚gD/*Š_˜öÖÁTĆ$›cď´é"M°ÜŔsr Î]ü%ŇYe_Ěؔč<ńŁď$h­bŽé¸×1ńű6ŘîcĐÔ(—““üžŹE ĹÚŰŢ/• LŽbĘV™FŔy÷!Ć˜Z#śƒ â-ČB40Ě2×ÍÎx°Ť ‡DMl&ťŰfĹJl6úŐvždďÜh.Ŕ#œŃÖÂů°˘eĘîqŸŮĆĂ~„Uv°~ôŒ[6ÚŔę łf˛{6čx˝}l5D@]ĐŽx0R•Řëş/R–ŰD0–=ś‘c†%˝Éy›Ć‰4ăÔźż(°á-ń¸„¨ă˘ărz‰'ěŁs×Đ{ĽsÖ`<’Ľ=Ů=Ď䅈ʜĽ3ăE°ĽĹŚăYňĐŮ&¸T<&"0Ń$t7łš›ĚąÇb˘¤zroçˇ­Ž˛ě/QN˘Ôbl-ŰŹ&X°neëV źľ -óŽ„Ö1 –ßÍí°)"f­Ő*é>X07˘zËÖf%Y:§)âXÚjm ö‡¨yŔ“5Ď ŞĂy‰ëœ…ćލó*˙HHqĘň.8Žč €/ţ%š=šłgmvܔ?\vǸ˜ƒďŰĄ­U/ť?NŽbçŞčEöœ ĺD‚ zOöÇŐVî$Yą•1 ÚI=>ČZ˝ĎĹj5{ŽaoŻĺ*–Jl„a<'ÂgGŤňݘ;‡™rÝkŠĽ‚Łj×ĂY ›5Žł,5›Ž›ˇäy>؅Ő‘;ĆY26FfŤ$ťEň<‚•ݸ6Ě:¨śĹŁ6Ňóç˜QŚ”ˆH';ÁÁäŘęěÝúşmąüŕmŞV0Č+,&ůxrŘ(N3ȘŔ˛?ö(ł3á+o pň1*˛3˛|ȸ[ȂÓŮţE0ĹÚńĘ`ÜŮ´Ĺ"i9YvD’cÖՌß.jC˜Ă>‰Âvš?Źü%ŹwC$ô’§Í’Éź;4s“LFdx`؈*Ŕw˘4kH× =XŹ4öˆJĚ<‘ĄpĐOpĽ°lUZX@ôĆŰúîéˆač ć‘׊QY9:K­‚09ŤđŘk(2qónJĐZ˛óŻŰyĺL|Ü f°‡‚Oç֛?$Jvű—ëčč„Ĺ)X­F" B˛hvčPąŁń+ ŕς­Bą[˛wlÎjă&“DÜ ţBřňœ\&|x˘/>2”߸ö'ŽťëOŽ{ďo\ń‰kŔ~÷×Ŕń‘k`|␓ŕäČă×Ŕ8䨚â \Ă׀Œ á#ŔÉ5`wýk =q ¤ő‰kŔŽţ˙ôŢ?чšţ ”üëҕ˙VşîŇH|I×ý$+/ă;g ˘=Š|…śű˜~-˛ňż5ÝżŇt_ŔI{îAq鳞űŃśůžî­Űž‘”Ÿo|âN˛ç>ľĎFRŢ擹>ôýĎÚţa;}ŸůövĺĽőâű žŘŇé%ŚF^šnTĺĎ|ľľäˇżŻCŁhŸoęWď V9žű­Ý ôč+쭟6s9éú‹ŘÎť<":ℯÁ‰NË`uľœ{âKŰĚSĹhywŤs×íXF@ćěŠl0Ŕ­ -A›‰6ËĄJ:Ě|Í2VłĄ ]Ďźłźu&׀ŞVŚ…Ăîp))H4ű,tÍ@DŻ“e+™˝e­Ô*ł5kě`(R˝­[ľ=łŰ˜>—NĐś×IÄÁ2ŘI^ňP$phu~Ćq‹*ç90×JÍĚĎ{8ożâ:ĎóˆYJ.lŹnÍŔS#řΉ•ËŇ"‚;âţdC`đ¨›őŤcÁš˘-e ëpV‚ IstîƒÝ'& ƒ6ŃěF?3o‚ńێ;3;#+mĐnœyôUď`Ӂĺ=–Ô/–a #ďkíĄéwŁÓÓčş• |ÝĚ0[šżçŹŰěúš×eďVÍ-ś.ö˛îÖaÚ6ÔŢŘuł)‘śçöÚ p,Ą¤“ş™KçˆNkŇ1Ď6łÉQłüfl‰ěTGUś6Ť)!ć őśeLm”âĂ ŕx`jŔĐ-äfáŒE•ZgŮř×Ăbœ€hośź/‡' A{q𗳎y}‚ú‡2óŇĺ8ud1ĽWb›kśĎa‘]wmCłCçpW™šƒ'˝Ăae“łéL'y;˙˝îöwY"dBĐ"Śžž(Ż,dęĆd%n؆6řÍēŮśŚmKD^šđ{ŘšĹ1?JîđPtĄ:MĎéĺEwŞEŔŸm‡mö*&˝Ć”,°Aţ-Çs.BŢWYŚ4wşĄŃÀaśrązCěëqŒŰ˛–m˜X™Ő™lFUaŮéÁr×%¤­sj*ďmjŹKËŽ8NmäíŚô$Őţ7ÄdŹYö展…M9î3A ó=űˇWŹ5$oKł)Lűjž;ƈľňP1Ô{~°ŞŠF§/ XöIrg ok•Šxá*śóZýšmę”Ĺ‹ŹýGÍF LÍuZ|âÁ-uĄ´YřłÄÁVń1—cśŁßš%Qó’mĎŢńLŚŐŔ,¸1ćZSíî,Ü!łLž–Ö´T3TÇłž;uÝçXů;ńů°‘Öáđ{„˜7´3}4ËŢď K9ěŰęk`‹ŐÖl"<Čý2§•4ű„AŮŰ\gʉcJfӑ vinéí¤ĚŁŚ+Ľ‘]:í$Ęm!őł ž/śimň˜ćš˜˘%C–zÉk<0 ÇĐÍŘ+“f ‹'m­W’jŒhBS=˘™ş |rŞŁgYeąE["žn°ĘőÇolÎ <<§ĂŤěć w[c0jvMőGО&c° Áśa‹žť˝lBN™šRőˇd'ŔcBú`A`>œ‘‚…”Ś:ü}RKťŮ §j˙¸ 1M .jwź,x*öčJl×,x.;lŘa6‰Ÿď™’ŽÁŰBîČ3,‹˛˛lăź§ŮŮ€ŽĄ:€˙ĺZ}.C×dZ TÖ4-öĄZ+6ŽDGâ÷(ÝděŽ~HF VŒ6Ömňë„Ně(cŇą7Ň÷,UÍh?ˎEM …}^<ŮMvIĎś­ZŚc}̒ˇâX€˛›­ËCEÎ×ŐÉ y““čWL¨'fv#Ő@>pŘÎ=x ˜:ǎČ0€ ™Ź%ą`śýËć⸹7};ă߲Syԁ_ăĘr~ źŽXřœA­ŮSARW.ŽCUCz‡J茮á!ƒ‡ťŒcBĘżœâ›°ŒCö,ÓĂôŐł4°śŢB˘-´bą‚†lž9wźXăň­ÖymŁśY%’äH4c™€–…٤ű'GŠ5ՙ™6á°&2žlŞŢ‘ĺ@ZŤó %°‡W€ÍV~‹“WÄ7çPĆěh•(w'۝-”iĺrćčŘV4-ŻÉĐ<[L§AJž†ed?łŽçTk0/‚Ż ůŠŰdŐ[ąMtžúÖŞg ś%rŁ-ůĂ1§ÎúI|Ŕ`ĎŰ>h;dÍ oSPłŘ،Ť…2ŞĄśűaąp]Ź{'×ţ¸÷ÍťZE#,°Ś3žĚƒ-{xVăL‹W¤Aˇ¤-†}˛>Ł>¸$ÜbݝÁ0Řźě°hěŃ#‘Ę( JÖmmHŃf˙˙X:ŮşÁ({°š¸üBߑüá€kďˇŽŁ€6gžS#›FhúuŹ—]l\hƒWË]Ŕ  ~ŮHZ6ňä@eôŠfŞ×ó{·”y-ČľŃ(ľ8b<œlŢ˝“ąq˝çßÁM\ńa}vČQv*Xw€ÜCcS><*cm,QŸl!ؗŠ}›ť/ř͇ÔfÄvPAâ÷ęf ČAGꚗĂꚍĐQÖ`…jHfĺz˛×)řÊ;Ż?“=(,nrt6CŕežˇJÁ^ Ŕ¤N˛FMŞĄ08Ľvâ÷Íó*LIŇŕTŰ+ć,&üR0L ,Pˆ2ű%‰÷(!úr”NŰĐo+oJpŠ=!ś[~ƒAś~Că䝸"Á+¨Ă˛îŮN„ĹBN0§ľul[NÚé üˇ Ā@Œ‹i”Ć'e;bÄnr´F'ó8o 󐾯ÓŘĽě‰D[^fą#˝ąĽôÇźŮiÁ%Œ 6Ӟ[ě–á%kCXŕJ[đr3Kł|‘ŁżŽw EďÍÖçటRRĹÖ˝f&˜ö[}ěÔ2›;[— -Ś*Ÿ.C>ĽľMů”Iٙ°–ó˄‡p´Ă()|ŔĘăЁĐ|•¤ NŒĚň”D<‹5qҞ˘GĂĄőĂ~„$Á*ć‘e Žą?vĎĺ˛Ěüß\PY.¸XsZÖ蝝­3Ęśƒ˙ÂÄŠ˝Y–Á+ľ<\ąŮś2Šmô(Ş=ĘąŇ;1p—éb}Ëd˜OUZ/0˝{šçՙ0żŃúʧňąĎßÜĎLř|Î] Çżýű˙ăę뿋˙íßýç?ţ›?ţ‹ă?Nü×˙nţ÷˙ĂűżŠŠ0Ż=ţϛ óůŠ}Óš0éŽV+„[­–“DÂSU|ŞĚJ‡‚V›ľZm’LţXçőąěŹŐ*Ÿć¤§Z-ŤŔ>Ÿ c‰Úm.Lyš ÓŞśŇÓšs.Œ]>Ÿ ăl—s.Œĺqç\çǤ3[Κ0ÎÁ9ç”ůi.ŒÓ[Κ0V¤saÚ4˜ńiFÍ9ŚÔ§š0NÉ9ç´Ů.çě™ú4&ĚOsaœ3s΅‰ç\˜żţęł{Ĺ{Վýöľ§ż\ęW˘ý¤ü’J´!€Q÷ą˙j`ňŻ7ć2îoŐh/Œ€‰ÄŮŻŒ€!čřŹmŽ­Ękk“UĚ^€đ->‹­-ú•`é|‹Î­–Ż€éŰ$˜ÉB°q°fllż4ˇ­ —)űÜR"Ĺ´ŕĎLĽUĽl9šäĎüăđۋăUä‘jƒ`j+;óΎk&”mejŕőö ţ–˝šN‚ŮbӆżÔ6kwm_ń!űWřL­Ünt4Kěýnltő*ţBœÚ?Vť¤ěD9č{§\úé ـkhSj†ŇŚž@8Ć"Ž^ň‡ż„éő/÷ó^ş×žÄD¨Gnßô"Š#lĂěQjq#X=tÉ>Ú¸ż-ćdmšMŰçuöĐ­• dOn֘¤MŽËÉl–=î!6é€ĺĽnŃ*­>îă4Řz3Ź_ hě° 0Ž{fľĘ89Ż6›RM{gŸa˛ÉCŚ&cbél§"1¸Š)ĆÉ|Oœœ+ź‚ómmޞváR‹°‡^ç2ssáť Š‡'pŔűŇwĎg"–ŠĘĹ}ßSŞ˝t]°Jh)ĞDʎ?ג“7"ĄéÖŇD]yđdGB 3YŸtK[´ÍśzLIžŠTÂÁňŮ=ؓt:çŽJ/YĂ!iÄaď˜Y÷ÔFß,ƒ‰>âé~v.‘™gŠa[ˇ$-÷F—ůÉŮÄI”Ó=Ą[R‰XQgeJÁý’l†$tÂhŘ°Ű†göŠóŹerDžä°›­.ŰVÂ΍ČqŒYŽŽ!YU $ŤĂŠ­˙9 –)\gnŸBŽŹœ|'žç×čƒ;čÝT¸›üŇbçMŽ*¸ôíą™‘š0YŠ?›GÇą˘ôAґł ­šĺľDą´Ń kMuęŚa—ž ĎŁDBy´2đ˜ŰčK*YĄčÁ âśĺéا$aOĎoŽŘIˆââ ů°‡VP:Éě—zť‹úZŮcŢĐĆŇ´:2g!Xw űË&§nݏŔşĎÓ.S/ËÂŚMŸs_ŠDZˆÉbWQ”7̞YvňŘůÎęźc*V3or‚8`ܗ)× 5ăUÚn9qěŹÄhxfłň“Ň_çuělŐ ÁlĹćÁÄ8ÉůśÖyZąfҜnąJn'ż4{ڙ’\Őśż˛ľ“Âq{ť' ÂîÉtą¸g• “A$_CfAűü›;Ő8ČĚ6ćŇ[16”EA,›ĺ¤Črż˜çXv ߪŐc’%:HĂßŐŐjšâŕöşbł2Ś  %<×,GĹ8ÄAI 6/eC'ĺxoV fôĂNG rćYn˙ş/–!E z5-ƒô0۲LŠŃÇŘĆ8újޤ˙ÜŢ-VœšźŹ¨uĐý‚‰=eŐĎöńĄr#ŁąŇŽWY u8<ËpŒ;-Űé,ë)ä”÷ łId;‹ œĆÎ űÁĽ†Ÿn€ž•ÁꡔĂ0Ç~w öě¨ĺÝĚ˝{x8ýŠĽc‘ŹÚ•€oZƒÇĄŰ$KřźôNżAÁf„>8[Í3§9%Ř͈’8ÖĘvbž=LN›l'vfKăeJƒiBŹe7'€Œ#ÜyĘÍÂnYŢ=)˜8ÂŠŔHŰkŸRθZ• Í)€dHŤÇt蜎m´až.s–:˝Œóŕ-w‹wđ Ű!›ĺ‘R^áöşŢădSřň[gLţ4H0 ěT0|zžÁîXŁ|QÖZ9wÓź•­ŻŕšŠšĹÂźaĘńĂňă<"nÍŚ¸q˜ŃwůŸËM˜˝Ď}ěÝ֞g 0u@ ¤^änYźú &úą Sâßć…,E] <›¨kcĘŇ(} śźÚeÓ;S_?ŘnuĎ&AdÁkäv@î]JG+~úV”WÚoŒüj5tAŞEşë,9˙ÎśĘÖTˆšě@^ˆ™źĂâŐÁ)ÄŮzᲠťĆ‚#ň˝(scőĐĘGYż`ŽRpőýƒ\Šłăw†Ö‡9bz­<މ HXĚH­€šé03°Í<@vPM˘Œ¤e—Ž–[ĺIi ň˛$Ě0¨€đ¤Ń´ŒĐ*$ƒ6gqÍ=z<éƒy:ëö4RŽÓʎ˝šGpOFă1ç=ałřąŻ…óš"Ÿś˜ľĚŽ qQ‹Ľ1ˆDÔ°‰}D1Š 4ÁáLö&b& ¨"7Iű:Ú>Qkň&cžĽŮržł˙śxv‘ ŁĘ3PŰ@&漞ř­‡„ý{›:l[[‡Uę>°×ź˘,ÉńŘ ˇ…¨!:”*Ëě:cÉ&~cÓkˇqźvŽ"8KĘěÝą•Ń&Tś§ťv3ĽuzŽtQ(3VĂěddMë6ŹD8ř•Ĺ1çśT؝âÜL@Q›fw§Ç˛ýŸÇ-–+˘ŮěŁsă"χŤ›°g{TŸş O݄ZąˆšÇĽiˆšjä -'¤WĂNN0aişŁDĂFŚíˆĹÎz3dډƒĹuSžĽă”gĐF~ŕj­ďĂC{`ƒo×űu>&Ž•Ű‚`=Ô K/›}‘”Úý4ňë};R9•“jżU+šs'ëádôÝô ;ĽŔ]Š›­‘ŃK\zž°€ĺrr‘-.Ů´E\lsĺe_+–2víXUŞJbŽťĂ5Œ’źŁL‰0AšÝĄbŽÍň‹ßŇš[a‡°č`;ŘŚ0ř›ŁGet •"ô'ÓŽk “ÝI#şbɆwˆqđĽĺűm éƒ^RRu„]ŕ=y.{Rh#€)|ÓÜ;Ŕ kKČŕ(h’Łte)‘7nšš:OĐhłyŕĎş;Ţ­—}ňŹg˛&Xʍ 1˜ üA•ĹĽ‚ď 1H'Ńć2Ű4-¸´´v[Ik‡`Oü=­á;ܔpĐŚG† ëd/Ťťöź$ű0Ťcźţ˘9ř$!o6 Ć“Én°™&g`'0lçĚŔ!řoŠśQ&UôMfśđ6Ái˛fôęÂŢmp¸q1üÁšfX ˙‹' G’ča皤%â} ꞂU‚!CÎľ˝sěF˛<~$’ł‚svČ+ż<Ę<° 64ÖÁ´’ěQONc1÷°Ú–ŐI’ˇXˉƒ'žU‘łPÖŃČÁ´śqڂŁ#c<ˆ‚:.ťěÁ<Áý°ĎzQ¤%ZDÜĎN÷säʰĽĹ)ÜtC.ř€Ĺëxş6Jˁ‹›STsDÄZÄÎKlÓlŚ’PČÖw$ËŔÂiÁš°\ŁťžökŞiÄUÁâőÔSL5˜Č9Œ˜ˇí'gƒL…ČŘ>{ľÁ5Ţ_ł]×XJlĽˇłoľ‡d4ÓNđÉě"­eAś8,çĐ%C Íkkťó`kśhŘw0\mQsx"1ć°f_Ÿ9>‚Žť^^p–ŘB´&Ĺ5ŕl)Ŕbľ™Ű)oˊ‘sź/yôřϞpS°Hś*ťžÚĄďXlę‘D†żˆéœˆ: ŚÖ֛ó’'Ä)8äŽő[=] –Mó|Ĺf€SŽ6á̤3ŽfApœşœ¤1ÄäTqÁ@ú†Ĺîa‚wG!˛Aaˇ$!Ů*ƒĹęLńŢńŒ‡DäIâďďj"ÇĂ:üMuÔߒěa>ēő~1—áŹA3 ­ƜÚľ D§šˆŽXe‰!`d€G¤’,0‡ç=“yĚCa×1ŚßWŰđpĚ1 Ôš˝b{x˘˛ćŒşnX ›ţA˘z,AŔľLAöw §ËŞaúÖ~“Ý>w“`48M˜!ĄÉ&¨röë` Á¨9ŽÉőe3A0’ˇF`űΊł;yÜzÂ5Č!â +A§%ÍU*FěŚńT-aém0ŃF@ƒMtźk‘‘ݹםYyŘQr|ążÓżqXŽ&F 5Ó ’\bďŘĽ0u şm ĐĹ#3Kö0Ξo´ęăę–`$íŠ\—e=™ü&ä ěöâ°Z8? ö$~Ü@qtRíb‚_JŤŽń;´m§—lÄNšľĂ;šżi­ę՟ T‡C,ÎtEšĆ0;ŘÓ&Dűś€ÚěQnmËfgšCspŽű`Œ_=kg?ËŕŠçꂵąă(ĄÎÖ5‚Ś8˜ZCŮ9A;€zďř℠YˇîÉ!ţ)âÂ&"v›qmKuܘ“eevcphŽŹ wYœ­d‰1웣ä@–qx>]:ÇK%›Á1nrhíęp2`›Óf§Ÿžĺς5ŸUßtK Ömű#2hˆUJhsQ眢m ÉrŹbî•×.rěîë<ÚŇЁ=G HělQ'2ʎG¤a;ĽplÝ Ž~D mę1#´ĎĄ+˜K[˜ŞÎsV…‚ 1ö˝éŘŹŠ}KoáÎ×AŁ„„[.yî$\)Q>‹ŃĄâ ĐYĹÎ( WfŰ1¤˜çz”ď<ĂşÚlŢÎ6Ń)™]<ă”ÄԳ햐0ą?ŽŃ8ďF<“ík“Af›ˆ˘Ô %')BŃdrK!8üŹ?TÇb8ŘőčÁj˘ĚŽÇpq˘GÁ‡dî+1>ϡ՗u˜ÚŔ"Œľ36­‹qČĂŞ…0ĺ€ŔÜtv;˘üĹ5Äč/ç!Hí_í´sřl.Ü`Úź*ńśdąŸÚƒ*vŕˆŁ”őyŜ™3qŢŔ:˜‡ą[ѓwŽĂŽđƒ€˝…Ůö#ŕÚŠŢn({eÁĘXEřH°fKJŠľľíé`‘š„ÚĚŘ/XeDz6éë<˝eśn EÜ4šŘúŞ,ô‡†j˛s´%(6Cƒ˙[ęâ4#˘ŕ%oA´(YĘŕńNoŤ[i俎z>Zâ=gŘŁÚlÎ ë9uóąx O(ę(,–ĂJťŐ.Ĺů+ęľ Ş’!8Ú=‡cl4„–•MŚőťě0˛IF ­Ľ^vjöhŹY˛6ĚBŠ)9ť Ó˝öĘL]mýWÄĎښ„íÁŘÉ7;r7e§´ËŠżoŇíđ<‘<$2HZťEđŽl ć/ŽÎbDH,>Hej#f1ÜŐßŢ^Ű´(!Ąsŕ„Áb™3kă~‚ľ3ٞ›ĺ׳­ĹŚk(3ˆČ+[ęßaÚtd–‡'qnZ ÎĐi-ž;@)r=čŠCŮkKŃ›E _XĚ-nŹ;á.Q‹Ó'úŘ~9Hf9LŘ~KčäšFDš.šÖv,/ż ŮC)ÜíÎ'„›&ă§ľÁ{bö<˜üŤłD쏐#˙€ć˛ÔWâˆh4ťz•a‡ú(Ť!E2ŁÜˆÁQ6–É“'éŕš‹ěBlťœ{ů-Ź?ďá2Ö(2$ëK€ĺNNĎŸ—*ÚđžKSoWТ°ŠĹ󅉸Ůq4k›šŠ”‹Ÿ(Î%\bÚ6K"$ÜC=;ý€4hĘŕgÁŃČâˇĚÍ!–c›Ůd!Ň+9GŘyQKW7{…]Yéz0ŚÁŐ<š\“]ȆH\ď*hİö6KbP‰.+Ńű0ax%1p VŘáéÉtšŃ fÎ&Éž8g|‹“/Ç"ĹÁŐ6Ť›ęźß{gŽąjâ‚“BfľËąZ;rÎ[M†LÚW'Ěş&žćꤖ0:bUfżâLX]v€íŃ; a ¨Î0™ÔŃlY$\trŽžnfžíJí} ,˛U2Đh`v Ú4‹żŸŢćO´Îćńޒ"âŚęůM00ďŽĂtœîfę¤*Űx{´XKxm~L79xpqX%äŒäĂůîŃŮ]OčŘĽą'ŞwTAÖŘ;C8ržńâ›ă6ÓJ`ĄŐ•ă‰^;kŹu*n”fÂeIÉť]Ôě Áô"ńüH(‚Y¨řľ˘A>ôŔkěŠHŕYcj< Îu–KĽ °ö ouňnëčé˝IŇÚRu6 mš+ŢšwÄCŰ; pĐ\ …†ŤĹƒ”™ť‡]X3+ ŃVË,[°'ppďW1fťL=߃;O€)„*˜&ÁţK/łÓAťĹ dDşâý˛ÝđMzŔIŇ‚3`ŒŐ@GĘr3(<ŻĹ*V Ž%98‘'pĐő(Çú[<Âv‚C0f˝ńÚë#<‘ĘĹŠDN…á$Ę* Ô­„PV¨#Œúłx(ŽA ćć%Ż<´Ł({ŐGJĘŮĘĝŃ4ËÔŮYßňK!Ŕ;řÚhK˙–jM!Jł šŇŚKOţŹ5̎Ž]ěŇZ9‡ŢŠz{;Ëq˛Ç>bBőJHއJŽ?ăIÁ!ŹjKättćŒcmVĆYžHb'—ŢZ/*˜ŚčíçQËę€ó8xqĎ\=łÚŻMë›yçqĹBŽ~^­I”Ęd=ĆQbF‡iđŰm;xcTmť¸ ŃÄTœ˝H&] C@0Ďý1Z‰˘Ö5(!ŮĎh˙ďqí˛ľŘęÖY–‰°Îš|†m˝÷Ŕ…Ig˘%łTnž lś°Ť˛qj’ą벋v`kه€9€N„yŔ&‡oňČgĽľÄ ˛ŽĽ›¤˘Ă•9Ädć€o™˛úě\§RÉ޸K| Í‘öľXş“tÁč˛ÇÝË;u´ĚĽĹuřç”Pý g‚̰ɹ.Nv˜Sß üŒAĘs]ů:pg‹ěHŐŢîĂ";çü¸ł˝ÜĹ$6đnvĐ4ŰY$lĘ{ŸŘbä$ËÝ7 öýJ ¨ Ö˙Zx6™…ˇŠľMŻ”RVîĽÂcĹ#bs†!U;{ńťíཅ ë6Ó;V°ZÄ=Ú$ŇH@xůĽó“ŔŘąôu—˘f™heKȐ?ž1k&KëÚ7ľ&a*îôˆXÂ䆸â` řK¨pţ˛9€ŔŁôÓ1L $°ŽLR[”tbďRß*b!?#˝ČbśbŮ"źˆD×äÓĽmĽ’!ĎĚBžűWüđýŸß}˙{îŢ˙ů?đˇż˙‡w˙ĺĂőÝťż˙/˙çö•îékďş§ß<ŻňťëeŢ}ţłďţŽ=˙Ç˙˙—ž_üřÁłţńďžűţż˙Ă_űÖ§ëďkł‘=pŐťăb?ŢýÇż˙ýď˝ ˙ç?üńmˇý˛Ÿśíݧç:űľůĽË‰ź˙Çß˙ů˙óű?ź÷Ÿöüđw˙řű÷|.ŕ—/žbüŻţôŁw#ʰcóŸ>üůgsë;Đë÷~ ďÔW˙VýH~üč×üOĹßžú[ňk%?}wüřkíťš˙x˝đńňÓÓ×ĆüđwÇĎ.ŸĂÓ7ĘřńoáăSĺ§ż?ŸžoŸŽRĘóűć§>}ü7ďţôţđ__ÚůßöŢŮßvˇ}mÍĎwožl|ď{ţřôQŢşĂ>ţł-^yşŔ§=÷zú¸áß\äO7o_‹Ÿî;=Ý(şëą=_zşňůĎňüŸáă?˝oŒOű簇ýťtÝ˝ó˝úg‚Üţyžúř×úš`œĎßôÓÖ~xžńžžq~퓀|Z‡ň$Ôçw§—–ĺĺż>w?/ŽĚë>ĺ‘G{“ťŞ*lÔ*M@!ŽÜß;Ť§'üřĐożň@°řńĘŠ†G—ţ‚'=?/Ü ÍȽ~Zć8Őەă0…wż żĐq~eb¤Ű•m@ţš—Ć~yieă+?4*ţéĘ_uĽAÔńWYhB‹řśu~A jć…łŽďlQzWŰýSřJ/Ö.lüíÂĺkÉĎyaŠ_ĺ‰CÁ3Ÿ_KxÎ çžÜ.<˝*†Ž˛58˙Ćš łšĄŚŸ–ء˝Šěgżižžżéí…n7MˇŻ{ç)ÜßšĽ]>e>ĆçI”O—ń’Nůégý´řˇ{j0 ďV˙/°ÔiřVKýüÎ-űÔň_ă§Uü¸ÔÓÓ7dÜűŇŽBţ-0ŕ7ZŕçwNď?fŁ>Iđ‡Oćă˗5°‚ÎoąŞ}ţVŤúüÎéűšŚň|}ӗ/¨‰™ńŤZá_âoPż;“?şS7?Ľ/|§𛸎ţu{öëÜšíŢgwN?|T­ś>~úA>‡^ł•~3Nٙ%ßFĺ>ťs>ŚĆ‡žˇţ<× güť2ţlö ôkšŚ;őú%âú‰úóŻ|şďŕm>ťń%eţĂóóŠü y*ß~văOÂöé0ćËĺlzˆŻ}1]~1{~ă“bË7łç7NŸż{÷ĆĆ/Âhf'|c7äo$…Ďoüé ěˇ$…uúFhöł§đÉýřIżTÎîůn|).ř&k[žŐږűľmđ9}ąćVĽ)ýVV4Ť}~ăV1óYqËř1;ÝőĽŕĺ‹=›^Ző_Ý\J6úMĚĺg7ţm:í:|Ł”Ęg7N‹Ł>`ý 9LŁüüäÔ/ł2Ýg”˙"böٍϢ”ߤk.ĺE˝ŸÝ8Mó+éša?ŚÚ×ĘĎÂ2śéKŘđ›ŹzţVŤžď“Ňc|śÂׄ˙/sb™ëˇŃőđŇ ŸÝ8ćߤš÷ß(ÝđٍłbÖŞvӏ_,\*ú&áÝXżQ’áł˙Šx嗬Îç‰ôoů,Ÿ'<ľú >—_ü|ż@ÇĎ)EüěĆIˇÚ˛2yřRE”Űě—(â/Xž<}Ł|Ög7nŃîyšűóI63‘_ň”ßBkňç!ďS,_Ňs3ó ‡}ËS°üyřř“‚ç7N?~ É?ľ¤źmŮŢ.(qřeaú/YçoeŹ>ťń‹ëÜLă}˙ѲůęjĘŚorßž•)űěĆů“Źöe5ţŹŐt`óËüżţj~Ťó´Ďn|bá™XžÔŻÓüď5ˇňĹk]ZUŐ7ą iüFáëg7ţŹŚę\ÉéÉţ>4ÇeúâĹślÎAxż w†W…ýךń”înÜđăřńPĽ|yućyQ­Ćo%5ż•Yţěßdűr:˙I„?K’}ąŠŽšjG(~óż•­ţěĆéSCpúY68ś˛‡o‚âˇ2ÁŸÝř<Ř˙Ź‹:ý<‘ÔȖŻz ř llüÜĆžťV~žšžŻţś+|+Ű^ŠŽ?śU,|ügË2ńIqhfëĹ<ţŻżşßĘl}văôąőB“đáIOtůU Bƒ˜ń›@Ěđ­ěŰg7žtHÉsřřqڇ/^ěb~gŇ7ʧ|văËbôĘĺy1ö)ŢĽýg:ůôC›žĹb‡o”TůěĆů#„üŒ‹ĺS#Ĺřó°e°1Ł_|ƒŐíż• |~ăvž_"ŞůÔađ 0đĹëÜçG)€×ŰŤŰşńÇ?ü×Ţ˙ůýťřîOţăß˙—żk´Q!ăťq Ӆ(Š'áKď~7¤çÝÖˇŻüRĂťá]}÷?ó鏟Ÿ˙K÷î˙xwyσ}x÷tË?~x˙ĂřđżŢîűř‡w˙żw?ž˙ýŸ>đ0íU˙ţ?ż˙ťݏíϧ'ýŻ˙áďńźűř…ü/<3żű÷?vOŻůó[?[ôĺş0y Nńł•<–ű]IŸ-Χ/Ÿëƒ!C\!M˙S:žÚýň?ťĐß.ôĎâBń‡ďx˙ă0Nc8?żůýíB?ýçÜľďß]ťüăÇ~ ßß~č/ôDťĐ[˙œŰŇ>ťŰN]?Ď}<˙\Ôň×|˘ż]č§˙<Űľ{-ť~ĺúyŐÁëÎ~…'úۅŢúç…];÷âü<żrţš~ĺVţŚ^í˙\şßóĎŠežŇ>ŸLíŒé—<Ńß.ôň…Žĺşđ÷˜äţ뗯tĎžôşyýK˝ÚĺĎ÷ᅬߕďž˙Ă4œôyőOŻv÷ĽŸ÷ů+m˙Ł%„U.őń=2Ż´ň/&Ům!ß7…ńĂëŸÝšŮ×-ż~ĺőĎg:˙SÓXÓtţý™¤|ńŤ]5îş/Żă“gňzžţçá…~Väńřվ…Ú]÷ëşׯÜďďőłűŇm~´Ď_íŢZŢű¸ëŸËOžB\uęüŃ×7䌴Żë÷,ö/ůӞô\Çî~žČŰřl׎úŇ}ź=Ń ÷|w_?Ż[ńlŽęúşŠ>pŸ/=Ńë—xđç×wWƒw5{÷zw[ě{ő{ťŠ}vĄë‡Š˙Ž/çßÂ6žŻ]7őů{~nv_ÝÍ<ús‰‡rô–?÷ěőżřB—ËÝoNwŻ;Żoó#Wú‚Š˝>üuˆýçgŽńťđ´§?ąŘ]{„ĚžéÚĺ+MíŐČŢyšógÎ'}ćű߲.ן9_đ|Ůół{>źaűďÍácÉ~°ĺ÷Ď~ťĐ#Ľ˝šĂ‹L__ä\S7ĎĎîşÁ÷›}ýľëö_?Ďďv÷߸— ë磟śŘ÷ß~ z|aűŻ9ž{ňh'n‹}çG†őőˆ¤ť×ć{…ź=ďEšŻżíÚŁí|}ąďžťnóýf?úîýĽ_ĐľˇčÝ ^äŃZÜŻČë0đMąČýňßËÚ ąČĂđóň¤÷ĎţL׎ťv~ž |ČW#ńîzgĎď^mÖýĘ>sŮçýďŸč^ďŻ_yaî_áőďžĎţ DÜ[Č{Ľ}ÁŻ\ţtW ~dđŻVáŮ>^žŽť>đ˝ř_×ëvŃçäAqůŻ{zýsˇRoBąëv6ű‘ĆßűÁ'żvYČë=zŽGÖý™Šý “ú Ž{†jŻĐŕ™ř]ŒÉőóŢ<ű߂öŻĎuŃĘî "ĹW˙ź°ýçË^ü3ču'ş/˙Gžö-OúlŢL_ĐľűžWËű_žßǟʍźžčźěu÷P]żđĎ(íĂÓĺWń{ Yžý‹ƒšŤ~Á‹\5둢ťĺíBoOŚÜ§Şďˇ˙/ż`›żřœöŒ~ľ]{=óţŚ\íÝžÜü—Täúç~á‰č ^äŃöż+žÉŃŁ§xÝZ><§}‹‘}őĎĎők?!GoPÎGxŞ{“rÜßŕnŢöDŻŰƒlöýÖž.Ž/<ŃőŻĹKżâ9íƒü)|ôćĚűKšÚˇ`î$ű-Ťđü‚ŠÜ÷ůśűœMwýŃ{ďúzČóŤAżýź˙>8}xšőčBŻú’—ʆŢňçŢŻ]Ęš¨×šHîŐč†jbŸťÝź‡Ä/Ŕ㡧Ă^xş{Tű(]ńL/ńŇłŰýZźžŤ˝ ęłpýčÝGŻ'̟ĽX__ěGŻsŐÇî~!é/ČCžýó> ˝˝ÚŁHő>“ühş‚óËŤÝďć#ţ‰\íýçőĆ×Ýź™‘óýĎ4½Ô^?žAŢoä#›ůş}ńŽ=Ę6?”ěףÜg‘đ5Ś}$~÷şţ¨bâ™=zýB ÎKáúE ŻIĚGů÷göč- ůűEťö<twŸűÇž†<ĚÎ ňyd‰žŮŁ{u5oyÍÎEíăUďßŕ|ݗ=ŇťîŃ7Ţţy3ţ÷vďíŽéM‡™o9"{vŕűč°ëţÔćőzwTňȟޝÉÎűé×ýąŘŁLŰW°7ß/A/`’űŁ•‡‰¨/MŹź~Ą{§üşľ|áâžŕţóu óś”Ć٘ö .ôć?ݛ"ëG…/<ŃŁâŃ ŢÝ űŇ řńŤ˝ýĎ] É5ŘúňŞơż¨ÚçÁŸçmg×Wx{žävĄG‰‚7dú^:Šš—”ű;ż˙ŤężÚ…^Ďçż~ü‚ať7őBđźň^]Ż—xUď~‹‹ýö?ŻVátĎüÔ}Vâ~OżÔ+úĽFî'żÚý6.tW ÷¨TĽťGcŻ'3ž9ë‡9śiݎěćŰJ†ďĎ)żxŢüç/|ĄK5Ŕý~=ÜľGŸŻCűÎţ‰ƒŒ{wôCŢCŇËKý…ۡşĐŁę҇đřőĐę#ݢěG?tSÔמÁšóĎëgŁ÷G /œ}Ľ?_Dœë]řkÜ˙čĎ ä ąŘýiŇŤFî…ŇŞűLă u›*^G‰÷ĎňëëÚĹźž{|ŇAy#_Š ŰSÜç^ĎCޗ=î;z]iîÎQşkzé-˙Ł ŽîŢžüźĎ‡˝÷ŻWźužń–ôW™ž–č=ĘŤ˝ kהÎĂ-p6ů…λݛګmžWćg’ýöŁ‚G›đ°büő´ÓC]űŇăŒG‡ /\čS{§/<Ńő°çY‚îN-Ż{t5Đ7É~¤ß×&Ťë>Ţďě3ĽýĺŸ_|ĄGÝUďĽć‹ľ˙u;ýČe>Kh>ÚÎ{…¸î׳˝>MíŁCŠűĚűŁýzvâ÷°ę üÚý/żš兊ńŻ GooPźîŕůË/œA^Őň‘rŢďăł]ťĎż~˛őąČýŁ~éŸ_Œ>(ř|Ýqţ„öżŢ;ňlűßŇE÷ş~!„¸ú¸ˇ|^÷ą{Ş|í2Ćż† ݅/l˙Höe7_0#˘Ćˇě`wÝČGšĄ/iařĹţ:.ôŠá/›ú–Ý|xžvoeî“?díŻcą˙z.tŃűĐČŁÓňG.ŕ‘ýë^Łżş =(~]ďłżĹWű?ɅîžőýíBťĐß.ôˇ ýíBťĐWżĐŽVřlBÂ0=›0}pîGţ|BBĺç~çÇł żzÎGó;ţĎůă9áöŸżöůߡ˙Ő'ţ×ţŢ}h~ˆ?¤â÷ ˙ďówß}÷áťŢÇ÷ő}œĆé=˙ß>żëżžß=?żŻßOßO?üđÇ>Ü.ôcşűßĺnˇ˙ý*ŻöWqĄs-.ŤóCţPżĎĹ.ĽüXĆü]ţˆ…˜*Ç4üؗ4ě~č?ô!Ž1 šťýăÇ4 ?ž?zţĐا+?ôÝđĄŽő}-玝{ôaüP>”ëퟞčşGßz~• ]˙\…s`?ä÷?|—žgůëűĆńÇż/Y‘˙0ÖđžO1t)ůyˆCĎżßöĽ°ߝż~^ćܨž}éű.~ˆ…_ˆq~87űŮî\ţź :żţýę:_ä"÷ç’÷ýĆďĎĎîüĎůóóާ|ç+ćţîóܐół;˙sýĆM§ÚgˆěÎíóܝSłÎۜćíɰ5yyËž|5ú/Ԟ÷ö6ÇÝ?üŘOÓĺCŽĂőóş#× 9•ăşăH{î^ߋG_?5áü<íWwîČŠ;羜_É}Ów7uiÎęőmůć‹ýđB—]8­ĎćąóőóőméŽĘqîEŽáťđăŁe~ôyS‘s察ˇ}i^äüűU]n[Ô|ĎyűîԔœĚ*Ę_`×î”ŕ\lžuœ>\?ĎŻ?T‘뎜[qúŒŤ…zaąOđŽÜmÂł­¸|vן`Ć~LcœŽ왢ü6Tä܄y6Gp.y÷ăűx˙ýíón/^ߊóó܊îôçZÜ;‚ˇoEwۅÓs\÷bßăł­ř~Ľ}^˝ţŠFÝişŽˆů™éú*rQ…ë.<ۄ׷âŚ"ŻîĹÍ}7űýşęޢĎśâ܄ťĎîş×ĎŤŠœđřô%6ä/fÚŸ›;¸_ţËgwo¨nŸ§çxƒşŮě{(ő>ぅęn;rˇ 6á^EÎŻ|Cy° Ýë{ńúV\7䙊œß¸úŒŤZü”Ë~° ϔăşWĚ{YţTäܑ3Ě)?”šĘ–ž°!żŽůBUx´!/ŠČݎÜŰŠ4ÔÂűëVźdŢ ÷[Ń˝ž÷ŸçýOl]>Œăp”î>ďrż#o[ě×˙´ËÝ6á‘SřE*rˇ-ÝůŸÓP݂đfĄžt^P‘ë’_7ᅭčCâMEŽëýź}ý ŕO u‰Hž!ß7-öŁ?m7ŸTó´_Ź_ŕE‹rܐԚŚ]ö[ânÉĎŻtĎžŃváüĘšŘS(߇zżççiłNkŐ=ܑŸŽ_ŹŇ™'ş _°Řo6]?áE^؋ťšĄÚWˇâ%—}ż;mniĹ›Đ=ڑˇű/Q‘Ó*Ięś÷Ťö—R‘›j¨öY?}íł{a§Ž?z.K>]ˇâŮ&œşöUxA9š/š&ƒťsG™ŤˇXĽsoy ŸEÓŻ/3—úîöŮÝţqýĆë*rˇ§Ä˝°Ř×˝x;nęžaŘś çBž‹úöMč^đĺxťľzIEÚŽ]ł×÷1ÚýVź¤"—˝xřůPEî<ÇT­)ş.íOŘŁë?n^áH\œňš SÉyřđ%öčŐĎS9ŽÖŞ{Á\˝A!Žúđ<ôľxuůťˇěČíóN-ŽgÝőˇs¤Ë1Ó=bşGF7x|݅/ľJ/ěÚŠ'ĐýRĺxR‘‹‡¸ß‹śâúů‚Šź´ž˙ᕝúôÝ՞Żv&KĎ`7ŐĂtýźăvęns΅ďíÂ/˛G>Żvę^9nç"÷ârĚs=ŕy´ S?ĽŸmEwű˙üđáüűwiúçÚ^çLĝُ›|xŽĺžŽŸÝůáŸ{t ‘oJÓTäş ?są_˙<•ěŚkçݎăŻĘńČN]|~v×_8wäz ř‹űíjq݊zÁNśŠýü™j¸ÚЇůě{ sű|°-Ÿ{ţœöč4 çŞýx)ę=—ůŕœ?ߝox5WçŢ>Ď}t+ÇŤŠÜRy_×˝íB÷v抧ށßůĽŰÁňe/ޟ׃čGŇ˝iwšBœ:őą„†`úŞ Ý™öş.ůýçM!˘jýl+.ҝß>/wz‘/UŽŻąk—­č^÷§éşnĹŁ éíËĂM¸˙<]öieN3~ ţů,ç3žË´ľ…żě\xwŽůuýŻ>ăTŽóëçZܧX}9Íî™Ď¸lĹŠ.çňw÷;ňÂî|÷ĂŇuC> ĺ)\?ťë?€ÉÜöş#W…¸ÚÉsoËßśčŚ"7zV œç{íď×ýzś!—ĎÓ)Ý€Ö ~žrüĚ];ˇâŢ}w÷{qžóyo'~ŻďĹ-˛h?s݊űϧâÓkŽáîó–žn;u­ ¸ĽfÎ0ëVŰžqsŮ̀\ýíĂ^5áŠŃť— Ę/jń`+ÎřąŕîÎĎîüĎš/×Ď\œHîŃç›víţá_؊†joŚöV#w]ňłšîş/çWޟwŇ=څ›U8Ł öšˇľ;˙\śâ…”Ć3x~‘Ź[Ôtöœ—ťCU7í?Wá|Šńyš<úźnČΜĎ{ƒ~_úů‚= öÎoß`Mƒ/,ůĺł{říËŽÝoĹŐ*œîűÉÓś\Č=}Vt~y‘+:żĄ‘G!߉gĎ­¸Éq{Š?|7–÷?ž˙.Œáś íďÝëťsîËuw}v÷{qJÓëq÷)e×BëNjýúçÝVt/(Äĺó|Šs+ŽvęšîËőóüúøűĎěíÓb˙řýőiGޟçîźúy“Łó?ŻތÜEą"W{>ęíŒý˝Âë{tqâ× éîwäZćuĹśˇ ššýg‹ý`§ž%/âÜň[Źyيîś#oؗgr^¨}>ő‹<؋[NňÍęvâwâƏ˝V?ĂB˝ "÷Ý× šľ ľ˝;ŸôÉÓ^ŒüS&˙ó8ú™%:—˙Lu4ƒws7U8—đ܅[:ě˛ oؐîöË.ÜďȳϜ§ť:îîő˝8żrÍó_Őâm.ű ţătˇ€ĺŇxr>ß‚Îr“ű?‰żĽτî-8ż´R>Y?Wäc6ň“mşűü)y° /¨Číőv<{nĹMŽNŸńK”ă'źČí+—Ň‹geÂM΍z&G÷6čÜň}g@ŘĚŢM.éáîĄ*źĺó˛!ÝŁ˝¸ĺGŰߟu´ýD"ęć{qúşrü\9/wWĂÝ=ŤĚhxúzw>њ̧_š&Ľže"nJp݅[NřËţńŽ˝E9.n˘ť& Ţrźzëšhß=_đvL˙ąœëg+ÇÓŽľ]xT |ťÍÜ⏸4ŃuW :]ÍSă÷7zM_×č űőĎëĺŠČí˜ţUŰtžžÎ Ď>˘śçޝkńv;őšŠ„—˙Ź{Ď!t÷̌]S*gUÍyšśG' óÇk¤öŻ˝ş/8…/V‘{Eiw~d›ş‡)¨ËiŢm+.vęźĐ-ظUÖýbKtłGˇŇ˛k•ß}ňë˛ĎzŰwoJ{݋3—tż#/˜‘‡řčŐyËVtW…řRŰt=/讆ęŚWńćMčíÂłúŐG›pي8­]č–âm[ńĚN݅eĎăľ×Cˆ/V‘Ű)ţk ń%QWށś§2ݔăi+.fä UáYýęyĄ[Ň÷‘Bœ—;cŽ÷@§ńŃV`ş~äB/(ÇŁĎW7äËUä,flúp=Ůęo*<ˇâb§néĂs;ožôŹz‹=zVU‰ë&œ}ŁÍYËnĹłVáۡ/{qUŽkü~sžgýž‚Š´zťBÜŰŚ—H9ÚN]•ăźÄy›ś|lŻWűŘ]ű{ŽMş×źZ×˝¸ŐôÝŠĹůÝóŇ÷[Ń˝eGޢ(Ý aŢݎ<;{żwg˙7ÁÜ)Ç­úfŽN {Ľxľ‹íŢMtĎváşwmîWŰtۊKkEwƒťíÚoQ‹G[ń%^ä’Ý"ËÓý<…¸˙óŹďč^9έ8ď|ŽÔ­Lř˛!ť _°J÷ęƁË^œXé^-îˇâę2žÔ=T‹×ˇâŠŽˆőVj"zÍú˝€˜Vhžţçr<ĺŘNpui3]E~*ŁuąJˇĎö•Ťmşa¨kÇŃľƒĺ~/î•ă<ţy¸ 7 őzÚéÁ&Ü[Ľźż¸űčŚ"”ăr–|K^SV- ~žá躡Mw[Ń=ڋóţçr~ž[qdÝ˝ž#’ťMčU@ź˝)ďš=zƒr<ڐ›Šœ÷?O;n)֓5ëtÖŻfąŽ[ńŒĺ´D×|úš×Sô›…jŸ×­č^ߋŸ°P÷áúőőž,îŢ5Ü[ĽÇ!ÄŰ˙Ür#ĚŐ­č˘}^7䙵:Î-đ{Ő7\]ůU!ű˜­úŘéřvľx Ő><ŽsůŻ őŃ&t?ŃeôfŤôS*r%Ÿ{°!7 y>Ń-.ź¤xŸšďűM¸ŰŠîő˝¸nĹ˝Z\ˇ˘ťß‹‡>㎠ŕşüÝ=V}]~YŤđ6¤{fŽěČůŒW:ĄÜ:ĽmÎSbü†˝?żmĹ5*?wíő˝x“…:UäüöëJđ–Mč^÷ o˙ó6yÆtךâëyŃuwnɌ;7Ń˝ž÷&íüźVű<[ěű:§Ű)ČEîďKsŸáŁ/U…ŸťŘoيvłŸP‘óyĎ š~^%î沯sˇ¤ł2äş '¸łPçç­ ţ$hšß‹*ţîDäŞÝ˝ÜÄýĽěŃO\č˛#7ä ´îM×őóF0یٵgëܖëV<ĽďŤE/ĐëܐóBçÂ_ÓÖςăGâ]ţŤ<ŠĎđŃ7ćŤýţÓ˙žTäüs—Ĺş*Ęýś\Oźşű/=“ÚS›.Ľď÷ŸOžöA3Ŕ,˙•'â!EÚ_Č}Á…^U”kDŇ˝ž//lŃu|A˛ď—ůţóž# ť_˙gő oćÖüM1Ÿ^c‘ĺ΀ÝoËusşG&í-ŸWŐ]˙q˝ĎýňßŰ ŤtżÜ}˝Ĺţ‚ Ý+ĘÝśtĎĚŘewíŃŁĎî~ŻŸ×‹ž°đé˙çĂÄüđBoؗŤ1ť–í?śK ě-Ÿ×K\—źťŽü#ńËň˙vűíîśĺétý˛;öč'>oşvýľëb_?Ż żü)ÂŇß҅.oţlÁe>ÜýyfFýyśĚ÷K~‹ŽŽ÷˙ĘŻöK.ô ŠÔţů •2ź›ú:~>G%Œď~7őÓgsTžžz›ŁŇżÇsŽJÎQ˙YĚQšüÁ žŸRwţç‡áűž˙ůyL_ý߯÷D˙,/tŽ,z›ĆÝ4ÔJؙŢO6G}ŸżŤ×…ż˙|´üżWű-]č\Żs™o‹}JöšŘߗďĘűďŽK~[řŸőţöů`áżőŤýŚ.ÔVüőýwߍ9O9"}[ěë2ƒ)ĆďËőó- ß˝ĹÖü:Żö[şP{ý{™ž-ö˝Lß/öł…żššËÂwmÍŻřjżĽ ]^ů\Ó4Ä1Ţdúć ŻÖúőe~aÉ/ ß=[˙_°đՋ}žţ)ͧš.ywĘôO,đšv×uź[ňî4Qo7ňż‘5ú ş˜ŽStĎĹ>—ůüźIöź°Ŕ×ĎW7¤ťŽ˙/YřżÖĹ~ ÓWŸŘ_:čŮ2żŮ¤<[ě뒟wř҅˙kZěvúşŚç"ÜĚČšœo~ýöšjWEyÓbß[™ˇ/ü_Źš“éŤdŸ+ř \żqŽČů•ó‡Î•şbńGŇ˙pąŸ÷ëWڒŸË˙×kŘéŤQ>Wíüúů•g‹}~ž_9×ëşüןšĄ—Ë’˙„d_?ďż{>ËšđÝ/ńŽáĹž“éŤXŢË×3œ}.ęM‚Ű ž_9?ďĽüü­Ű…~Ţ2_ëŮ݋üoÖ\dú\‹Ť(Ţ/ösíżS…ŤÍ>/t^âf×ŰŻ]żű,}ËbßoËł'zfäďţÍKţŤ.v{–ŤÁ˝.óőŠŻ/ŘÝŰŕŤ_˝_Áóď÷výYtô‚‘ ÷/xÚëbß/ů}ěôÐdú*r×gź˙|njĎW¸čôyŃ{É>żű °_w*|ČqŞçç-‡űÉžíÚ˝­{(ĺŻ.ůW\ěËľĎeť ŰuÉŻîđY(x“Łk’é>¨š,í˝U:űćiĎÍߕáýx]ěó+ççłäůƒ…aąďýú Šąë’˙*‹}•éóÍŻFö|Žë=Ë7]Ö‡Ýۚ{#s˝č33r]ćűĹž~>ł ÷‹}•é+b}Řďlů×XěۅîdúހܫîŐÜ|˙˝Œ<‹¸_5ŻĎLíUŚ-đőóú“ĎźČ#™žúˇXńݎŘçUďAÁ˝Sź>ăůDĎŰő‡žĄçëÂżš†˝ ä˝y}áŻ?suĽűúő{wôľűš@8ďsŸŸžš‹{w}ŠgÉşŤq¸Ď^eýş×ĺďŽw{Ýrż ŮcňląŻŚă :oŻs1{÷.ó+,öÍÔŢ/ó˙Ÿ˝é‘ĺFÚÁ˝˙ŠŘhŠŻü~)4čjń.(tł y‰Ô{ŞÎ' ŇQ} 濏“F§]HzНôȣȔüd2=x1šIł‡fî9Ăô”˛Ă˘f]ŁĄű6Ďy‘ŢnŤŐ*„8žîU<[?ާŠôœÔ¨"dF–džf§lJrÚrp?K4„Q#lłBö!^§CjšŠBţ5úę:O3qyÚ`ś ;Ę$‰ŘôÔRЖ)u\ţ2ÔĄ„§[?vćqZáMzź7+­Ťe˜>ŇďPJy”?ŰՓ햇Řî2™¤ł§Ž@ ĚF ďî‰čŞç1iPbť;ú„w¨ő–PÖŐ;%źÇ6B—CĘÓ!Îmw›=܃‰.í|Ŕ~ăîI — ×OÜtʹي•2Qňë§IÚĚÓIťÂÓŽQˆY"ŠâéťŰńląľ?HćŐ'Űg{ä;ŔxŽę ü]¸ć÷ŐP¨š!B $ŰâÓ'ŮN3Âú #´UvOÂ3ň8Fo×ě$6-˘OZę/ÝáŽ]1~˛Ý6BˆíząCŞÖ”^żAl—ä´jj| =‹ő?EěH= ™uÍőÝх tŮnősxÚ]uŘşćq-9+šŤ§=ÇőąáŽVpŮ8HěuB÷MfIŃӔ˜›ĄMGAJ)×9HŠćîČ=ÄŚ šsäAb‡EśI%‹Bą“ĚˆŘ{¸ úb%źŔviÎŢĂ%śç¸îŽœZŹi_6¨ىŞĂ=™ÝHŠžŢ@l¨(Ôk†­q9•n÷<ŔubŻŤwŐóěł]f[¨"ŚgsĎbO‡‰íđôú™Đš3-i?äju‰íY Šň_WÁÁšŽKwůvmI”™‹tžžAlępw•´_f7ÂNÓäđC`Śł]bS5˛Ž:<ÄŚ›8W™Ń5ݰŠB›>׎ˇ…ŘOťxš Jƒí¤gD—ĚîRęٰ‡cd ×î,!=eřŒ‚”.ôIç+N€ÉÔŮâš×~ĂŃĐdą qśK~Fl×4ç.ĘôüáY C[<—ƒ]{WX8{k×6cöŮAb;<˝žŃó!ë"씨ĄżžuŐ1"˛r¨ěIý ´TE)âŃŮ!2S΢Ęߨ”ącŽ-“} s —/†(ŠnpŅSš7Ď&‚ţЕx ŐœŘD<P#A˝zw=ÚTœiăy:¤šŮ†Ýý3Ľšť@ÓžłÍhˆ§Ą§.™ÝSyáÎóţ9*%ĚٚŘî(¸Ťtt)łÖÄoń\mÍü"”xth.-Ü7=^şU§G B€k"sÔyŹ{ÄýD˝9bťn×´ž/ś’™˛%ă#÷ çHťźć™~şŠÚiŞ­ó´ç¸žDl:ZwhQŢZ]­Ö L— Ɗl7˛P™˘¤Ű sĽ-¸›ł|dhÓQPß°iHÂlTu6šk¸óŹýĹđ´Ë_Ô|ľ¸|Č:Á\‡.“lý\ç~áęwcînşÜƒ"ĂhŃšŁĆzĚ ›îC<^>""Ž2aŞv}áş9LżˆYŃTäş hďB×(ąŮéÂ^ÝóĎúFş =—äl8Ť_lŁE!OhhŤÄŐRn˘´ ›.:ă ČäBo\ł=u$0`Ľ 5ĽóňPş^.úţLgm/ąř‚ôatśĂÓŽ‹ći/¨ňe˜ö$fh÷8ăšă:S‡,Ąw W8茏w ƒÄŚűěÉi3ĄĂ´‡Ř”ĺ¨oŘĺiĘƅŤ"Üó%6Sć§uwŒń^JÎŮîNCÇU,ˆ"š{‚cœíŞ*şF8<Í̇.ăy°ę ĚÎ֏Ę#ۍĐ9É)NoŃ]e˜Ř!ţœ;EÜ}ݤŇö=ÎJjv˘O:´ě¸~ƒŘ;Ĺ#ž<†¨\N%&´.ËťO×t@ËC˛˝5é‹{Ö ™§Óü´÷$ö.’3é ˝˜°‹dŰcĆňŽ)“Ů!IĽĚX—ÎÓw%6!šŤËƒęVWżxHî¸\ܧç,:lşKŤčţNńˆíœžśďYÄź}ůÜ|ôT|5kL?ě˜>’*Ú)"›‰łé|TQ0ţ:á;ő(a!şľE#€i J‹˜egçrä>ƒËô(Ľ/ČÇ`Č?yE°4ěäŁÍÓły<폤ě0Ą˝QQĘBô{sE1jÔ!ľkŘŁä…ȡmÁĺ•~ϸ$kśÇšôQôUÝOÁٟł"Ɗ÷gČńe*ç-ćĆ;ÚgÓhgEë ŃŃÄîT0ř1ĺúű§&ö†Š\–= MÉĺÎăz¤×Ąq— Đ‘#×rd˘@ŻiďîŮ#łE1?gćŠBRyŸé7 ŃFĄ9›F;+ŠYˆ#öLŃŽ6룳i”ľ"f†Ž!ŞYˆ@O9K|Z 5Gf|C@ߑ!=áAĐ5>4S÷ďŃž…čń8ű;¨h}{xôô§,DŸŽŘń Ńƅh‰{üih”Š"× Eěő…(mh„š ˆQTÖ˘ŁĽäŢđ¨§;4_÷×G) ŃcpöwSQŒâh†Lßś bo]ˆ’ˆM˘ODŁťW´îőžA옅hďВBÍmĚϘ…čé‡f–ă:]‚v-DGëŁô…č;‘Ǩ(Ţ`~ŔôĂ:ôgąí[ˆvŰ]ˆ>îRţUżmZR¨štĹS'IúÍÎSvCŐĐÜúˆP¤/DAbť—ŠbžEü퍳eí°Šâ˘ڟˆ<:›>ÝkrôťQwÂŹmŕŁzm vh!:ŒœMŰߪ^o{ëB´ehűBÍ틊ŕéŃ>Jm–~°†sn€{ÄŁˇ8Ż-¸‘]áŢö-¨ş˘—6›Ţu ]ΤŘĚĐŕ÷šUxz´u!Jš~ š3CŰzsîĆŹQş°š×Éă9+/v}!ÚŔî]‘Šş-#4›E„r?í×}ˆ ‘ŤFţ͡掵gźdŻ?ŽÂ;l˝F´sú]Ë\ÔŁ î/ý[žgh!iÚ94÷Ş0]DÝ>˛í[ˆr{gE)W<^ 3Ń(f! 2$=„v›ž>š!Ą‰ZŽÎXű÷ÝŎZü5˘}ö=J‘űÓża7˛ď>ëć隈‚ÄŢŞň‚áC Ÿ šRÔŰNbw#Y2oEëěوvhî3~!b šuń9`hnЂ¨ĺčlbo˝‹}khŃ Ń}îÓf ]@Ÿî”i”ŇťÍ dČEä!öÝ{t@E!ů˘Q“ÎPlŽť;}!:ƒŘ*Zg:;ŸnhôżQ(óÎŃÓwREŽvŞÚł‰}ô̓˜…č~?H1Đm&vL<"}!ÚĐŁĐ#śk|ś wŁBOÎddq—#wŽďŠč1vs,ŕp5ţţ;ö(4ýĐť$ŽĐL>k?řrłp;ƒÂq§ŕçÖ5zt}ŔÍčú†nűrłm>fm\ˆ jě. zŽo óž×âŃۆŘŔěô遤Ż>M”LË5 %U´ĄGފđ< Ń}zä>)††Şą;.GFÖ\]&ŘPފÖ˘ŕ°0wl[Cž Ś“†vc9:™ŘË̓ä…hÚúBobM_ŽňZkbÎE™CÍEَ—TNë ŽV˛đfčYPyš#ąĄ™L`xSQHEŹß;%Ԝӻ;Ća7ę€ îŤŚ‡Ph3×ô‡˘ŰcTÜMÁvŘš?hʃ@űűÄx'ŘËłŤ= ľ\0Ô\ţp3tîr-GëЏď&Ô\֜kí§ 7ڇíŘâ)őĄćîH#ĆkzŻr´a|ý(ş™FűžÁPs;Ż0¸El!rš9řLëę)&ý)űÉ = -DnfŽ/D°ô$ĹĎ>`9r7fš–ŁčS„š ĺ á C˜č\;˙Lą4>˜>J^ˆîCŁ”…hgÜ…č衅Žy0ĚÍ4J™xvUř`<侅(iÖ¨1ƒŠÚô­DTÎ5w„Ő/ů\tCFUňß>^¨šPŇŔ‡5ŐÓꦬĄ/Šsę…šť#<ŸňÚ]ś~ü(JÔŐŮĄćŇýĄŹG) ŃÎĄ…2[ä{ĺ 5w—ëBńOěa UQčžßc„šŁ‹Ď'ĹŐş›Ź7Ą¨aăS„š;Ě~ä>ע†FçşH_ˆvöˆ.ŕł==J_ˆ6î[čI!Ř+o¨9ŇŔËŃşžĘ੉^ˆëQ0ÔÜžxQ¸š QÖíń†<ǏjîŽ*éBt—łĚ*}!ÚÜ#ş@Ü€bÖľô…hC¨÷Í]ˆZ°˘\Ąćâ/TŢ}9 ‹îIl÷\tv¨šď%ÜLę™2ěxPsnŞ‚;˘ę)łĹř¸7Í]ˆĚĐҢ =˘ Ä]Ŕđô@ä9ÓޅłC3sš3ö-DqĘ?b!:c9ŠąßÜ8°q!Ję‘'ÔÜ/0ќLńh›ăŹ5T‚śbi#vˆ!łŽý!ŃŃî ĎřŁ˘ÍC -DĆQ—>¨¨Ĺ,D;g žŽeîţ14]Äx+ž4´`E) Ń-ĺO˘ƒ­~é­Ÿ‹îClz.:-ÔÜ}î÷łv6j˘$bßHÂqÂÁ/Ů+k¨šuŹÂýšw™ţő…(iÖ6ô(~!ÚŮŁ‹čž8ś­ ŃŃÄN_ˆÂĘßAƒśŠPQü†ůh$}…žŽ˙ř>F_÷@Ś‹pĄh Ěy5{ž’7Ô\ h‘ťLĚBtŸĄŃ纏(iÖ>ÓďÝÇśo!:ŒŘ&DXúBäSţť˘źËQ&űŤ(}!ÚĐŁő…čp>"R“Iů߈3 ˙d"śKxşĺ 5ŢžBó.8śř…ččĄŃ_\ÔÜałĎĐÜ=Á§[˘ˆM7˛EúBĕ?˝pv?E™<5.ÉsšWc˘ăřˆÚł3]„‹‰X¤Ÿ‹vŇČ]ˆ vTś^#:Ą sqđĐś.D÷!6]!öy"7Öą ÷4il]ˆ’zäZćTţŤˇc9ş Ő<—{5~!:‚¨=;ÓE¸ř@˝EĚuŠzä靳%;ŞGűîłˆĐÔÚä`bď[ˆŽ&śťBŒ‡Üzč@ˆžŁł3OC.˘#”˙}ŽYÇV”ÉSă’<—{uëB”ĆGgŰůG€óŚ1ä_u'܇Fjî`„fĘBtą=°ęƒšYCÍšGĄ"ýÄć­c5wDĚşť,G)źł“ŘôÎX.÷j5w—Ą…vRvţŃ Q^O %˙Ÿ0Ԝ‘ľĂâ°Óô.T˙°Y[aŐ)'î0pŕ~Ąć\¤+ Źđ˝…šťűĄfýIąŇ.ŁäŇG.ąsšW݅č°Xőî“fóÎůtëB”7;ň?U¨9Ď-ŸĂŽ˘nęĆLw!ŕ„UoÝč{t÷PsÁ ćßq¨š;jb^ʋώ"sÚć>@ڭܜ—F;+ŠYˆîˆŇVäÂa˙TĄć\eb–ŁLYŞîXQV힎’z䚻á™44OŚŁUWţ÷jî°um_EçĽ'fYÔd>;Ô\VHĚ=+JyztBŰÍ?U¨š21fŸŹ9|Žh=?+#6Mí˝łGĄĚ*›+ZĎ qśáţĄć[×öU”G­ĹúÁ÷ěPsT-‹žˇd§<=Ąćî¨j×'ž8*\‰˙S…šťĄL @Wż :ˆ&ÉDŁ­/DŒŘ戎_Ý*e hĘďŠF/A!ËÉ}ˆ}˙Ps‡­kű*rÓë`ŹsÔ4m1 „Ś|Ťcó SŘşw _T+ŹSí1–#O¨š•vŁGîÄÓLŐŽ¨Ôű›)Ú;‰gş–ďÎE”21ËtRŒ2!TĘÁx0m˜ţ˜…Č#kŔŽ”ć›ŒVJQľ†§sű.Ąć[׍†šńYŹ˙9-¨ë=zäyî#śÚ]ztlEžPs™zϐńä<ŽFŤwm .Ő[iwĎéß7Ŕ°Źš-ŻŽşáľcˇ/Gw'v ďř†–°eXŽž=+zVôŹča+ŠYu‹ôU˙SÓ(Ž˘ä…čq‡öŹčYŃł˘gEϊ>AEšlľĎŠž=+zVôŹčYQřůĄżŠƒžž=+zVôŹčYŃł˘gEϊž=+zVôŹčYŃł˘gEϊž=+zVô(ŃűÄć’rŕ‹žiîöŢĽG'TDĂ^ťĚŐŁřŠ`ĄÁ×_MęQÔ\đNďËq=2Á&˜Nóţ˛Kđô*u™6I˜€Ĺ’p+rťęéŠ.aÝoT´ëkŠČ˝ţżł˘ĂzóľÚß"e8{{ôçŤîüp‹›ă|7Û,Âą=Ę\‘ć/8|…ĺźË‘‰'Děę)ÓiMř"ćŐ¤Ĺ|A_ H'˝/‡őˆqśy:—ƒh+:Ů´ @9Šcz]QfŁľŠ”1Vtž˜ň‡yX˙Şcz=%.Ů>Ăr¤ţ2˛–>¨ =úVô5j„Ćđt_Ľ"ÂÂâŰŁĚ‘…ˆę)m?SčBDő¤Ű ŚüY‡íQĚ틹‘Ţ—˝=˘ł =21YH8@č]\ M§‚ţő€Ň ˘‹ UotODűŞ´p?ĆV.˛Ńफ़Š’żŘţZ;ű¸S‘K;ÚkĘ <űýzô'ʈ -]ŽÜSĚBDÍ…gcźj( ćg'(!=.Ç\8ˆS­:ěů†Řš6>n2Ô#w!žŮon(ÚaCT÷Ë1_1‹ ­Ôí‹ 5ęE°/ŻÍ&V˜Ač îâĆÇ4쯪4P WЧşä¤Ts+-h~Gř€ť@÷߄ű —ƒéKtvŕŻqĆ:Ň/wĘ]Âł]mˆwC ¸6IłŽšRÎć1ŔŽVđœiáĎ.ÉŠ¸2 Üh9” é ŚF<ąhÉW á}ł–đu^EĚ(EƒŢť›ńĐBĤŸHťRĺžęĘ7m€íLŔ¤AťJ[sŰ\71“†ŤčVŐeEÚ°/°ţZďWPúĄ"ڋĐŇVţΠ\J1şŢ/ÜYp žËo¤/F¸RNۉ7rÄqv`8”‚ž¸Çn„j7˝ĘŹ~îůƒ2*ĽEˆ×LčKĘţ+qÄ` ĎÇÓĽHh*6ó‘K5nfÝÄěöĹs3“4ć*nE†łŠ­“œ.StPfAš†u´´ž˜žŔ/.§Ź|‹ˆD|Q‘ëĄűÉ"´NŔBDˇ~t-ƒż2M×S‘ěôť-<‘16C+‡Fîš*SvFq’=˜ší¸œ:÷łš eżĐBĔ? śĺŠľ=ş›>3ýtštĽ” ŽSfy‘5č‹3((9x9˘j?´Ą„ěîZBƒ<űvţäŸkčĽËă&r^3vw—F™m}°Lh™EĎ9š̎_¤RĆGîdťš!™‹|ŞąźGúg11‚›™t-uĹÂŐDĄ^łÓcH'÷QhPfÖBœZŽ\Ń]D„đ 9Qx”Rw4ąžQ‘ťQľĂ6Ą…ˆ9XHoW° :…t?éŞ:Şš]ţ*¨EŞ7šaŮ߃4ZULÉű+wEhJľÂşIÁpśëĹŚsD—fw!â2 @ÝcVČ/aôQHC’ĺΚ™~ęđĽAěˇÚÜ7,G´WíšÍ¨›éČÝnАKŁkÜäŞ]÷4Ĺ›‹˜ńÓß$;ř…ćÎÝhQ]Ňë?@ˇÝ-Kô§˜A34Gîz#đ˜/őÓčrÝ;š…ÁŚé‘[KwP?-ՊŒdëç҈­kŽŇ¤rOŰ-×áA_g8ę¨'ÎEpt:݅ˆR2­{Ř(\c8SřÄ@H3˘š&łEC:[O֟Еţő…†ěj+ćwŢëűYúE•ł°‡ šĄ…ˆŠZw.ÖW:WůyH×˙:š›‹Â3Gťžn˜OĘ´ĚI—š­ ŃŇŁä…ČXýŇ"ĂŮîBDŘş’e4brźk!ň̚ťšç8—ŒFŽSÇľŠ°^; Ďşśu!ňpvhɎ˘ź2ŇÇC÷>ŃrZˆ\ Úŕ‰ˆPYEBŤłą‘m…kv•œŃ4'Vź§Č|QÎN_ˆl(e!şauÍaîŠÂRËš3BˇU1 ‘gŒYˆčä°Ăń†9ZýňŔ=âł÷˛3-,e!şą­‰_ˆ˜!e!2=Úş1Ů$VՂZŽö-DlÖR"ĆŮî^ž6\C>]ˆ‚ëZüBäɰŽýÖiÄŹ~ŽěŹ{ŠnˆHĘ×=+ .DúËăƒĄĽ ĺZzĚtm|T-ç~ę–$ŹrěşU>˘kľĆGŒ™ôťz*qlÖúˆ×Ó"vu ŁüݓfĐtˇžĄ…ČłősńĆ!ÓuÁşgmĎÎ?ęâěĐU7wQržŘŘ""fŤ$ ˛g[łu!â6śĐWÄBÄVژ…(dŤĺwł"3ké cHˇ_T‹Ż/Džum}!r O7@…Ťý(+ŽÓˆůE\A őeQ|9Z_ˆŕ˅38ŹťZAĽ.$…. ”˛ÝÄxćËŮP„šäî rŔŠ_ˆ<vˇ—!Bśí˘K^ˆŘŹšŚçő ; Ž ŤĹ ż„Ł|=śÚőE1hłƒ&Ł­ÖÎŮdžč9žëę&zâ-܈{¤+ ˝IIQ¤/DŚGÁAtłťbÇ,DĄšc›QJŕĐáx}!ň`"ö-D„f¨Űë ‘ÚŕBäČÚ:—{–ě˜…Čƒbőp-ńYŻ_Éĺ"rĐ×ŃQíˇ~x Ä\‡nE.üŽ‚a<śW,=,Jž 86Ô"ŘŚűE5ˇł˘pĺďŘŠŁÜäVˇÁťCp+őĚŇPę¸fw* :ŮŽÎC/gÉ^llÄtă*z\v‘?T˜<Űă}&;ł1÷€Ă#´}ąaú]}ÉEc0C›~Âňf#mŽOō Ž!($FÓŁB`˛YîlXiCöüŐBNŠvWgł`œúrŤňQĚYăŘđ7WDŞs'§peg}šCKŠGŐŇÎżUSžĂłkš×z™ÓÄ&˛ڙ1Y#%aUK•ŹłŇŔ;ĐSśöÇЅž„ÁÂłđl"ŚßU‡aÎLšŰwSQHhÍrHxš¨˛ ςN°;ŮôctúéţZ¸p9ˆ>Cď3bťŽŮ=zڟÚřÜ}Hh& ąÝ–CŠuýDR¸Ňě ¤é/áfúł™ľĐtŽŰ%|A§ŮěĐ_ÝŞ=˛#wžU$D —"ëŰŔ¨łˆK~—×í‘ĘbĂIqőË3ý0XŞäŮÖËa]ň­´1=e4Šß˜zdÍ%°+–î‡ÝyźeY7t’š.‚âşńkƒĐ˝Ëeż€d…úžůPCő´gĄ’”ŕ ;:…QŽ„€TrYK¸0Ö­ô‹HŃ ö Kwž ]mY¸*ĘsčI:›…ťź°\ˇą‘>ú8űŽŚą0hŤĽ“˝^ĺ¸ŕ™6âȚ4ĹS\Sľ;ýôźěŃ͛ý´îfô°Y[ˇźGŮjyqžODč—Kř‹zV‘ĐôŻo+…ząŽ-ƒ~Ú%ťúľw]ťÁGÂÚOQÂá6ŕ!ŽGëúŔŁłÝŠ]gWOč)xéŽ~ÚŔ ŢÚE[Ţ}śÚ˜=ˇ‡łc¨ą{DÄ=T¸ö6×fSĐWÝŐuýČsWtźżß=œ˝YĄŠV×l(ćË]×čˆJgÄ=‘¸bdvľÁ˝3›î–Řł=Ž7‡yzçîjCć ƄäźÄll.-Ömľ”QŮqÝÝčš'Čuƒ93ąŽ;4*…KŕĐNzƒ2ލéHÍĐB'Uגš„Âs8'Csg3ÄŔ7lľî“6LgÓ¨?˜\ŽĽĎ ҝȐÎ\ Íł˛69{ý”ËNÂôLb?WÖCˆ ŚÖ+ )ßq!5b†ěďLĹ2Fâ’fŰœvÜnÓ#OHíx4dhŇDLšk<]jb†éń‹„ć‘J˘;CŽŻe!š+Bˆĺďę˝řĽ)ʙă"cߐłËőÚŹ›Đ ×URŻî2éń÷‡äËu‹…,mhHłöťäٓ¸Ž• !jŤae˝"wQ^ז/„ pŸë8“FčLťĄ˘čŻ"ęd6zz:B„č4Pl=‡‡˙ĺ`Hčak;ąéů6 ířâ×Îčâí$Ś˘Ą ÂŇçóÔ¸œâśźzDTýa­Űó×]ŔĹ檈ĐA=ŔéŠ+­bUî‘Řń_Ť(œ‚­SŽUӀ ŘwWtŤ’ťáßťéú2×Z}3ĺœ­öˇÓ*Սţ4zŐĐČĽE4ĽčłŞŤuŐÍ{Wš§.)Ţć__Z °–‡R‡ŃˆČhKŞ9ÁšľÎGôÚIŁŠkÚv Ď”zŸŢçŽîŁÔ-­SÇCŁ­”ÚL#Gi˙¤S*L#*YÍźńĄ_°ŠźO//ŞIý44‚]K#Jť˘„ŃČüAż4˝ž˝nĽ”FWł(­\ż5Ż ]ŕŠéu‹FÎóZ˝]_Űôˇ.ôZFé¤<›€RLŁŻŽ}a酓Q$ häPĘĐhA)â–ŸšRžMD č3H#łMxŸIôĆ(ť„7ęčWƒŒ†ę˝ D˙\˜ƒĂ5”F1”ň,ŽÎŽhë4˘Ü”ňČÝ{ €ƒ(żP)seMďŰ|4"účĽY|› T„śŽ˘°Ÿ‡›@înâ4˘;C …ލ1ę@ Ľ‘˛0(ĽôIe§8 RXQ›V5QĚŤoę;†› ĆApä= ă§4˘ÔŃźs‹šŰĽ}ż`ԉŚQpí_—8 Ôşn*<´Xç  yćŤüâŇĹĽf.¸Îk§ÎĂM°Ň]ŠŒ<ŔA”: ‰\ů˘42ë¨qX݀F„R>rţzƒF´G@#ĹČÝ179Wx¤,ÄAôIéeÖ5H„†^§Ô˛Ń‚'Ľ‘Śă#=LŁ‚ÎşE#xŐĽ‘#q…QNšlŒFëOşĐĎ8ŃáÇé&ésĄŐxdŸO-!Ô~dD'^Ö(\‰ŁkÜbˆŇd32—wBÜÄhD„ĂŒŮŮ˜żB91ŔRz.uiZ˜siߕž ˛śŽ•ř(DWÉžŠ`*ŠRŠ<™ś"%ćiiÁě^ÉnßP‡žŠ‰†˘Z)ŠFĂŰđ:źŽk%C#(Š’5J#˛ç.˜Š˘ˇœR xŠŃˆœŮ~žŇˆ”PéŰ ŕAV24m­ilś—Ft8ŽĄ€N<쁿(Ľ˜b˛QNq4ŐŮîžŰC#×4‚g˜FDÖ6ĐČ9ë2>bǢç5vs)EŠCiDĘĂ4Ž \űáRÇŐAAňŘjW%Î,ŠŽE‰pSEô„áá)×G4ě6ođ]][P>[ŹËW mţîÄ6”reÍЈhčŕÉ>ÄA”FpxíKid0!Ž5’áFB4 Q‡Y‹şá_[Ź%’›ŒÜydn7ŠÜš6ŮO;$ْSmh°FŇ3-Ľ Ôš!_ŤmVőˇGî‚4˘'{>J#Ç;°ĐČá#řŮc™u8(H#ş~ąÓĆŞ‡ÖGŁ€ţžÁMT1›ľĆşĘý+ŐŮ@ĘA.E\;?UÓĹ íáéżEŁnbvȀŃŰC#GC1QŰ+5ő„hÚHQ;  ŕ-lM`Ľƒ&Ąy9"ś€=ˇă#Y5Ží5‚ƒÜ­b˘jÚGŁÂčQJÁ$8rW°íĽ”C#x‡.ît;]Đ=QĚnČŐD†FéRśF.Ľˆ/`ž˜uŃQhĄ&Fúd4˘” yéÉĂ=ŽžÓĆFdv-^@_Ř6œZ#ЉŐ1rPÓkAĚĐH3¤k! IŁQŠ”íĽĽŃM3ŚP{>ľgŻ[&AQMd,Žm]Ę ™,ei4‚/˘› 1…jnĘSÄsmzb *(ƒmMŘ̕Ż4J‘˛#hD¸Šp7N†›\Mpa°Yݨß8´ŐşńžHY‘q8'sTqéBąHԊÄpţvźéľXG祑qLsĚ9FđG̢Âů7Q/ăşű‡.÷;ٟvǏPŞmĂa‚—{Rť°I2g&đŃş|…ŒĹÖłë=id* 83™‰ dŸ$rˇĐˆ`"Bźłn\,Bś×Ói´z¨ƒA™UĚYÝĚşfźŻęÄ‹t:œFđa" L@ˇAĚÄzĆ‹tâC;Ź˘ˇĽ”K„ ËgÝľ†U6´Ă*Z58…(Eéĺqgl ŽÇ˝zŘĐŽČŐM“8ĹţłĽĽ Ő;Œ:tů"ćéS„l¨Č589”˘†ńň]Đ_(]¨ŢaÔ ďO䣝‡R0XJ/ł=Śż„&ĺ÷ş~Ŕľńč˛Fż\JÁAŁz™­ýĹCWd5˜Ág˘|ŃáŔ)˝@hŔČb(E.](×ět‹mZbˆ§Ş˘!žĆr(/USƒńÔUĺĺÇŞěK㠋!ČS3\揪 OóOęsĂđ ƒ<}_)YŸO×j{>Ŕóě폈5ŤýaZšáëgą•÷Zh8P˘nŚ˝›žÂĎîÓ -8ňƒ=phŤƒŠĄ1ÓŞ)Ľî?´}Ăa ʟýe}‚Ý9=xhŚGn;[ņ澺^Űü}†?(ˇœ mz›—˙é­}kŢŞőťĂ,BÓšő‹Éچ™"şńĺăe| üžę*w°Eh:ˇ >˜ťP/Ü÷ÍĐÜWé×‡i*˘ż0áÜŞjÝYˆ™5ĎĐ܁Ź?]vńč#—Sb”ŹüC;|chŽ’‹š[)“DRiąŽŽčևÉw#š[Ÿ5łdŻë Đ= dh:×%ţĆ*˛uî<łśŽüAąÜXEÖ׆dŚšŕzĽÁĄÁó†ÜĹŹý1óHNáN¤ŕFćź14w€ny°GŽnŽ Gh7nC/AuŽôy”żB€›âX„^ÚŞ^ *~t ĄşóĺŮքč ghë/­Đ'"Ń dh€ÁÍhŒV mĘ ň•60Ŕu•bvl!át‡ś>@ĎÚżo€ĄuĹb}!€x6ŁnI ‹ˇ51dö­;łť0f8<ŔJ(׺ÌҐűČ~Ą5ÖaT—ű쬕oĺ<§ŚœĘa)‘ Ă÷;ÔNˆŘĄeÂcd‰ß%ąYŁüjՔ×îăĽmß[S2˝tŻĺč2*یFíöW‰Í‡FľßęÇ\2{ś5f€f dő`—Ů”ŰSfc[g˙¨Ąš,żuŮöžĐm:3(=XxÂl2yÜ04Gî<ŤČşnvg'¸­q{ÁŒb/ŻeŮż•}Ó_ahPBŸFhㇶŽ!n ÍeÔĐ0ƒŰăĐ@ŕI5*< :‘ëú;t˜çۚˆŻőaHŁ4€-őŹyX”°na´3ŔCsOGńC[ŸMf†Ś}ĄŠĹ - XŕY0•şjc[ˇ}ńŰĆ/F#W˝şmŇů˘+ lA—C:ĚĐj’ͤĄŃŻ Źšƒes rAš–N'<×(6´őMú†Ą…Ś3´ Ľš“>‹ĆĄOCŁ€*źĎNÚú0=[2˛Ňt OwQ4?4ęq ó’ťő¤\ěَ(Ň] Ęü•đą;ŔźCs‡Ič{aft#ýs`€TíPzY‹˙ZX§¨`3B'•0!]ٓĽp׌ŹCƒ/ĂMlɆyq™ÓYăݙ5QQL`ŇĐ薌Í[×ap†ŕyÓł@& đץ=Ó:L[LrFňĚ Ţ4CŁk&Šn+Łçu÷d”đî)ëŇ|áŠ"[j˘çń87=Ő,ěpÎÎąRŐPv5Ť=ńÓ-Š;Íë<C5ËşępW}ŁF7ÓYÓ?›Ł0y†ő>hś@;Ë4S)ŽlĄm(}‰Î,=÷łŰÁCƒ/śeYUőîœě˜K˜ĐłŃYeÔÍż¨ĄÁײ‰rä‹ôݝقu›lnťę˜Ňëîk?;ěA_膙Zu Ždї܏y„*şűÚďî§gQŃYˆ-×~W[2›ˇłÄłU$$Š )Â/li ý-;,G_eOç64łźÜcígűiŁ´Ń“Hœ9řy–@w¤ŁáŞ–LđÖyŒRľtŐóčOşĎöźDuՊĐ_g€…G™:‚3Ŕ gZv§ç5şdł=$aѐ2Ą|džFw:!>Ś|äq°Ä ž˜‰Ó=Ž3ľO-tľ %î|Á_ :fv &0bAś{Ž$nšQ,tKFÄŤ8t^ IˇŒR•B*b¤oFÝźöť&NśŃ˘ÉčěL\Ž[8{• ŮrHĽŇ![ű73'áťeçď \7Ś+}ěáÎKp°tČôřEĽßŇČÔ?~J É8ČÝŤQk;´˜'Ľ,;÷ď 5“ żˆcKrV Wáz6Łë¸CגLŤ.č¤rą0œućdö#ŚťjŸ‡Í¨ëšvpŽł…Í5SľîšaHťš)(ŮօƒŞzWŐT9ąm¸ë 3ë.…ËŻ.97Źý.ƒÂáY–ͨłoőPÇ9ŮúllŽ%ß#œ„FĄz,ëÂáş:Ů>Ű”`Šm‚.Ž ŠÎ”{tšƒ˜Qć÷\Ĺp†t”ů ňmíŁlfĄńű7Źýë.*ćĽé044wŻRŹOśGrńfĺÎ`đE„†F‡_ŹÇ#I´çľTĂłąžłr0áčLD/ąę¨Č•ćĂÎý!!ÓÎŢŽˆ”ŰŒÄ@Ud‹łu€Q°!…ŰQ5žĄísozpľtń9̤ kÉ=nhnű!>>̝aśXÎaƒ í0éľZݒ†F ă\Cs{qđĐhŐĚV›uhw݈¨ şĆ ÄÁ=:¸˘e[“`Ÿ=¸GGW´žI?`9ÚÜŁƒ+ ˘Ů˘‚‡ý <ÎëűsZ\’ądqI†ŽWqIšNÄ%ëţňă4Œ<,‰-…¨$}y*•¤/!*IőE%)Ő÷ËëK?/Ł* Y÷Q˝Ďß×ňżë^}Ă_§nŞŚúmTďÓŁďą" pŁx°*ő]Ŕ?ĺúź3ŠďĄî_űkŠž?&ýýC{¤Š€F.‹dÖ_UWľó7p?”čŸăA JůŹC{¤ŠĆj˜Ĺoť+űyw¤EćŤůhŢ[Sź$/Ž“ú6J(ĎĐŠ"uŁ„w[aÖÚŤşÄd¸\ŤĐî¨tŁ_HţI‰R;9ۨz ¤ćiV´fHžŔ埔ŘŔ„iĆĽ”ƍŠ4ea ~ďćď֐|Ł.˙¤Ä6ʘDěč/Sě__UôŐ}*ĺ“”Š!ŮáÁćhĽFŕ zšîI<Äiţf*%šż?ąőĐ(ąŔŔwŔń@ľÂŐž0/@5XażÁŽ?Žb1Ć6áűřűs[ӅžE€°Ĺđj€¨Ŕ–Fů’™JObĂ\ŔQýý=[ čĂÚ^ÓßPÂ8ŘßPGĎĐ >•†śí‹>"SëQ& -ú+/gďŇM2PHa~搢ýâ•*b šťy÷›šTÜóýé4:Ź"M  Pt°1”ť.ÄîËšDČi>@(ՙyt6:bbÎ5li-JCY˝*‡ů›Júú^^_şĄ+_ŕ čćšW—ťk/'śn Ů2ů]›p6 ˆmtŠŚéGőúQ•üO <-Şyu|ÂÓe2¸Ą[™}{’ĎGlÍAT´mSWKMFlx^Żďu7„ʁüá’(yPű@ěř=ɧ&vŐŠ pó b9CĆĂ*ýLÄ&“´ŠÜ/BěO‰"0}‚ÚŞX?÷íśďClPiĐ;şˇÝ\‘çËQ# ýQj„.™.™ĄÜP–ln cĐ_đłKě˜Ýö=9(ýb–ÉUÂGۘXő7ü쒼p "3ěRĚśŽBdŸWďĐ=aĐN˛F _ź"MhßݒŽŰo˘ˆ Ă.Íů:ďŸÇ H4-BŠ‚nŠÚ…>RĄ1Fŕś=ŚŮ¸Űž?ąĄĐ_j‘|ÓЈMů †?vmÓtĺfxŽ×njŻđdŤŰ„ßP=ęĚAďlă—É\Ć1’\7zĎ0úłP<Š3ąčߛˇŽ‚çP5m=QĹ撙~SWPĐV “Íř;IhŁż|ibąahîYŔí]°GP=ŕŃS6| ą§×ţ:tđnî>ęž2ó"3|Ccˇ ăŕY#&‚uţž+ąţ†ž¸*…ö.8kÔů ‚Íô$Ą0pjžŔßĐ2[ŚWżMEAb“/ć§ čď g‡äô|ÍřŰ 4œ/×˝bN,P–qv 7ťßƢƒöĄvšĐf0ŻIÚ7Š•œhď Ęćfľ"Kđwˆ9a°ŒŘ`ýX×ĐÁo˜~×6ú‚A…l&yOŮ@ Pľđ¤ž& Ha˜]ťĂ4šŔĄ‹Ůgjúbƒ­É>Άď‚múbHŽ…>d 69şÓÝđ7Ć<$tŇă?'{[śmM5S#FiŃĺ˜ČUrtu142;  ÔVß>ĄuÔřqÄ&~ 3%0ľ˙ĂJАw ^˘Ţ,Ę5PˆMH؍Ÿ#ôPcÎHúiükđĹŞPhˆŘô`„6Á$ś9ĺBRŇşOs^Łśjş4ÁL…”/%ł!6ÝaSýrC“ Ť!6 č t8h]ŁĂh–YKF°‰mô“Ŕź\nŚ”^bŔ;Ý9˘hk`]C_0iĐC ;ŕ€Ł2~¤Ú×l@ÉOUě‹(ż"NuƒŘĐUŠĚ0ü }ÔÔĄvfx@sJěuęĐí<ň§EpœYžŞ/lČë $evăÎqx7¸ˆgZąŐž™Řô mšÁűÇđ6R2×!8ȃOwž]m jş Şƒ’¨ł…ŘłS(TG÷łŠëň"NľŘРۡbSĺWĐÎ{6Î7݇ŔűüPŁ% Ѝ†Š?Gn‘YÄu  @˜§ß]8ľ]Ť žý}Ă6bŘOœr6č I7=˘űCz Ŕ8=šSšÖPlëçę콜M¤‰.ßL™¸¸7ýUPÉފđšElÝ/şš˘üMŚĎÂ-bÚ'BbĂ?TDčŒÄŸ)=ÄŚ;Ę)ë;ƒdŮ:šEl‡żéN–:DlJr—FÔŕbˆ ölŞF\;‰ťçŢ@lčuţF˜áĽlć-b;$§ÄŽâlŞR(ŔŒr,ŠlŸM§–’œéځĄ§fÇFybý7GŤŒ‘%›GlGĽĐ3Ľ‡Ř”´.S[ŠKć÷YľLSA˙ŕٲHĽKfz:(ÜóôÂhhęÁšÁŮœ¸Ő[ź…Ř„äĚÔ'[8ÁĄ&4 ôŹO˝Č.MŮ֏ -Œ‚ćBeŕËv2ţ†= ń)´ó)Ëä‹–:/ƒü×ý-%ż€ÜÁ Ěޖ UŹ;4ő›îƒ¨2q‰ Ë*cČą) ÝZbvľT,ďĎŮbÓž/°jř^ՄĐkŘ\¸Ú‚-ô`-šjÄ5ńÝp‹™C,nßuýĆQwąBiącŁąH…‡GȝgwoKiÇ8›é6žPBő4đ4ŔŹâˆ ƒŤ% F€üŽTšă:]š3݄2îpÂ%UÁŇX(g”%6ýƒ2藨kžšUé†9HlXd€łiu9Xlˆ‚îłĎŚ_°I €ó ߘ[)OÄ]Č*bv#đevútgާŸbvHsÖ׌FƒóqŞv+2ÓočŻ˙rm8ŠŘŚëĆ@łĐS¨:jhb›} Á*tUőQ)oľôÉ'hŸĐ“žS¸EôIuÓúł€\,ÖÁwü(™Łˆ O aŒ{×xwąő?ěé>TNž7fNÂ-bƒ…”I4/Ą„ŕŘB刨Žu2Á§!'ŻëwźEě]$/‚Ż’ŸC"$vpOÁßEŒŠˆyzˆ *ĹľjC Ů›Đ4Lěőgg;݆TMXčçÎË9đá2‰ OX­\ţŚf#ˆí<‹7Ç,AbĂ \ýŁL p܅łéÎ0¤RĚöá0bGŠ‘ˆU÷ą Éuçă=8÷T#î%/×ů{4ąƒE“üĆn$t* {œ‰ŘTĽP%—ŘÇŞ‘ÉŮţÄáňźÄ6Í|6Ά?ÄŹn-NHž—ŘtuaĎÚúś@Ć;f~gÖĐěž6svˆv7Č2‡Ë ąÍÚO|ŚtKčjqĎuĄťž`­ˆŰú­žK’Nëœí!6ĺŠK˘^“6x7‹~ç 2ô„žÂţ$ŹF˘‰şĺPłJŕ gfB`Šƒˆâlă^¸o3!7ˆíŢą3ÄÖ ÓÁnfȝœ˝nŃň¨c7wČLń7t6 bĂ. étŻÉ…&¤‰Bč)›:a’¤ß-šaő d‚j„›* ĘÍëŞÂăŔ‡)ĘO }šť˘î\¸sD?Fu6ăŁtégłcjŠ2ąRŠ„”ĆzŹFԓ’ÜĹ'P\+„ÂĽ˙:™#!^ÄË=cČ­¤ ›î:Üđ1!1 ˘$§„§ä§“`uT¨_„ؐ™BźéɈmä(Vîƒż¨§ă}ŁOcbuĄB{ŁÄ’ÓŰ)@xŠQr'!ŇĄBŕŽ+&ľg/"B‘xąSN݈ćâ‰Ű2ćőż˛ŠL;ÎrxD°)ř˝(DČš„"FܧűNAç"DwîܟYE)ςv˜î:ś68|ůI`7X\ĺď>CzŞpUThŚÖŸAôáÖgánîöÝEŘ{ǏßÜ`‰‚ő§šćą>G1sÇ*ŠŇ gôY¸7Ńîâđ˙bĘ?$ě;p‰‘ĄXCϘš+č/túˇ>— LNçďŇŮ[ÇSăNNᙗ­ßŚ˘i훊ĺúwÁ~ĽÝŢJŁÄě0ÍHłĂLc;^ŞzŞ‘ŚošËĂPńě0ś˛Ă´ýĽëuv˜ů'őŠŽĎ–ćíőíĺíí­ëfI¨UMÍŮýU}ľú.>^ÉwÂ×'Š]§/ĺ8ŽĂŹkŤ—×úľ{m^ű׼d€^ďŁZрRęٟżC)Ŗ‡x;š" ĹPÎßÝKű2R^•Kúč2˙<ÍßPr˙ý0”ҁ:†ăô(ŐÝ4oˆŕ…Ľë’†v`U‚'ÝÖ׀’ ^čŇÓŐPG3 °KąNžŇ45şüľo^ް'(>^ćŐŞ5kVĘĐR> űŚÂltő&”&ІfŚŮĐE=k¨Ú…79´(Â^2ĄO]5c-Rç-ٰŔ ömŲfiiz™Ţ,uôԆ¨CU-˘Q„*ŕi¨CV}Ë;sŐ°Ÿ4ÂDTÍ4‚$Pś~ó~íu^WaĽ…áďôőÔ˝]2%ÔĄ’4¤˛čgA‹€xŒ:đaŕ˝”Ÿ˝őƒ-ź95iaš7bő{ ËŒc™~2ĺ\ă ď„čBY§0Ö fľŒzj™ĺďrÍ4‚S6H“ş˜7˙ŻˆfÉvVŕÂ,2š”:ćđ@(@ClSĄ‹á˝é‹_¸ďI#ĐÁ M°IŽĄš“*Y#"°ŕĐľJ<qŠšK SAW(Ć5¨ŁiŇ0&ŔŃĆh ‹Ö fç$j§ {öRˆw\…Ł™†okvĹŁ¨ŕ¨3k™ţŽ1ćÄíŮçC P žđW ;<…¨CdJ(Ë4EĘvď0Qsg< eyvFrOJŔY„‚…9*iÖZ§ŽŮę€i€uA˜ÎŰր 6L3(ßß@K„™Nržvw#Œ^ä Ä)BÔĄťzŔ2Ű8AU“—F@ łĄŃ[b  œ„5Bl ćéîŐčnŸP8ˆ­ý”.fŸ źŁ 9ôSőŞn1wď!›M.Á’mîĹö6‹œ„ů k œ¸]JŃ] ĽŹkšEĚö˜ÍAKĄbNP÷¤=<™…[/ ° vĎ×FDŕŁ@ŠP™2Z Ö~Í"fëGĎôđgĂ5zvâîűЈ.Üó†ćăjx§‰˘Ž5“9kĂĄď`W1F3ZřYOź9M’]"ہňĄŰcŞÍśfךű81 6I=_Ŕ50L <.ěŠĺĄŐ řJŕŻP)őK¸"ľlkôęěÚžĎ­>A.–˝rCŽ3 ć˙ľsěŮfřq­ŽĘÎýv­ŕŠ=) łÍQÔxaôNL`JôK†FÚ í›eJË)ÔP(XăőšŐZĚŒŽŞj ăYÁěŮÚ7i¨Ö[xBÉu^S–g}uEaYżs5ä äU T2Ç{P5Ŕ4™Ź5°‡ćh†ů{ƒžąÓhS9đœ/ ă Ń'7Ě*TŤý߆žúç>ÁF4óÄ8X^)M%oę›.ß÷Ą8ǀGŕ źcÜ)ŕB ^°MŔł0N[pQ抌ŻMť–ĚAÝĽ#<őž (UxČŮéoE1ă~RaYćß´ƒ#äl9€FĆ-[ŕ”×QŞô’ ƒő| †Ł­8đ|Ş0ötR؍%Y˙LŤżŽ1j'”yR˘[‚ 8Żš™Ffžt“@`”Z†!l­tC`hĐ CA`B͖PbhdČF<@BŁkŽę|AŐ @ Łč9…m¨č°=FE°XE`Cj7$:ŸhhIQN1-­^ĎëŃcT’.A Ůçőč*F) §œëń{ŒŠ@Őˆôń -Ş"8ΘEYoąŕd€pRT˘ŢąYđĘźfűôŞ7—Ń˜Œ=JůJŞh>­ĚEX‡ ł5 HLúÔ0ú4H_ŘOäIWgš1xž;mgE°K3C\îf'T UŔ`Â6Tƒ($„|Š}Ąî“†śł"ŘOŔ%ü űrz´ŃŮBlĆqŽ9Ş`ç%ŔŠÓĂ´>Š<†ˆx*2G;°Ěęu~f,=ßéĂą‘5Ď)žp䣠TJ8ŮŠ3ÝË}†śůK{â`– ř”˘}Œ ĐűS,Ž”’‚œl‘ŸjÄL6Іů!ża?ç–Ăwa~ęŹJÓiD0‡šÍtĄX`MEDôŽ–Ň"ř ÷ű(}ôgůö8ák;Î_“Âe—"H#JjÔ§ՈČĄNŕfĄĄ•/ŕ5˘”ó.GĆEľ*FËŽv˛ôZŒťÁzKÔ+U)EHv˜bĄßP\Ü:´$1ş€Â ˆŃbŞ~ýčâ¤0üJÄč•0GPNq?@řeóВhËN ×Pë1ßŐu܍ L6™rś/Ťqƒ'H˛Ý36lXăVérOš–6—RÁm9AŇS#h"÷ź^YxR‹<<áţšŠ‚Řʓ†–ţe*ą0÷B€_ř”ž Ýł#¤pLžŁÝúŔëîCŰđmĂ/ËO—ůGuI˙wƛ‰^Ż›ĄžTŐ4 âĘx5L—ëşäWĆm)\ݚKWĆçŸô§ş2ŽTŰ[üSŤźˇńĺĽiť—Ąî?ÚžŤ;ëԎŽ>|kúV+^Ć~ÜtG/PQ¨/áŠŐí­ČŠnűĐŐąÓ*"ŐĹÍZÄW¨_;ŐŔŹ˘^^ł$Đa ˜¸ˆ$=+J¨hŁś/˙G9ŤYűřýúíˇŸ^ľţœŤ/|ýöý˝¨űňň—˙ăˇ//_˙Çß~ůúţ?ćwü‘˙ţżýϗ_/˙çďóBĐuŐź óBđ?ůĎőŰ/Ĺ˙V–m{)çm‰z¨ŸúF=Ćů1Ż*g—úľR­ŐOoę1-eýťz¨Ďö׼řX˝üačíOŞlh쯍}Y—}¨GżÔ2 źÝNżüż_~˙ď_ţ×]Hkd×PҐÁˇĄöKßÍ+Ś‹d­Žěí\Ý_ţ_×ßŢ_~~!ý•%NëÁíńÇB^ŇmŰă^OĂäĄgkGő°ˇ‡­l˜âÚţŞşÔ^m‡5˝Ýîáĺçë˙úőĺŰ_l{óVó6űňckw6óĺë˝g˘dźü|]¨Ţ¨q6Ľ}čé¸Ú_ţkm?ڍĐ(k^°–MbPť†SŽ|8˝ŏEđuĹF”QŚC`ő¤VsŘ_ëw;ůVA@Ů;šÝ.ý{‡ÝwlŘV€;ŘúşM QvúżŽ?ýńőĺ7ŢRčt§ĺ Šá4Źşœě| v˘ě_ŠžÝß÷˙úöňőËď:–ąŸˇçľęQËe˘}ˇęŐv~dŒUżeꚥyĹÖGŞ/—ţJΟظz;ŽţĹ28Ÿ¨ď-(D™Ć:MŒŰێ‰"tźägš]Ađ55ěŘpaĎ7ŹĄbĂÚdş8Ë#îMRĹh i;§“ƒÜH ŢópXo%?VoZ+uúY[TýüúuúR;úŽtG§´ls‚rHŔˇpá6ËnœƒŤaźTĺtÚĺĆnń”ű×Ţ>ŹžUgßâ|؏˝ÚĎÚ6 Ɖ)ů!úb'/t, tń0Č <>”|ú˝˛ 5}˝h%Ÿ@Čů rö=tjWMîPá1-˜ž š4ľÎşŞmĂZňおëřQ2f„5 ĹËţDŘjsćŢ2nh])ÇŞ[ř}ś•3đ•ŇeՂ‘KÄ|§đÍF˝)$3Ëw' v|ˇź˛iČ5r~ę•* xÄł"î‰-'ÇnŘÄ:äŁFŢłĂŔMk°‚ŕ ›ÖČúŇ0jÜÚç]\đ*]űŤÝÜĘő ˇëx2łŸířůfhrąăGp;űžâŮC(Grń,Ňr{†kŽ­‘—í °x“vKáŚ'{~&3[*ËHČ>B•Zƒ!yoégšx­ü@&ËĎř r4y'Kď~ú•ƒłŔŢŘŮáÁÖÚ*…ÍŹdgü!hi/2—ç| ÝpďFŚžÉ$dÝ÷‰‹W?{´Ţ SÉ+kœh.ĄwßXkNőšˆŘMkzíʈƒâ2ˆÓŽ$vť ÷|Iˆ˜­°%ĹŔ6é]5N:ŰôMç?ż“Ýá;ŐeŤŃkąŰBżű ÜŤ Śá+ÎYŚŔžŞÜ­ ßmú"Î#ŁK„ëů~—‘Ë9éŸŁ•ýU&ŞuăŕR ˇěÜdŕ;š üeŸĹ/f‡ÇŐԇÖuťlK^ o˜EťšČŮ7Ž÷ĺ㲢 ôˆŘcąa RĹ˝ םŢJqŸóÎţŕ•TŒHç;Ą° ĘEżfr}ýÚPľ5¨#GŠŰ-6Y]"Y™Źoeďł’%s,V`ÂYŮąâ'‘ÁÎ>_HĄžc}Řöi 6'o.Ÿn´tŘZШl}ĚuÍcŮöˇëçhy>ľ—ąn˝-/ɸhˇq,hdh›éRUcŐS.yaĚÚséŠŐl5jŢŔŤ_ه~erá#˘˙7lĚí˝‚0’ŽénŽd‹qŠśęVí§[\ůĆ4î˜6š˘ÓČŮtŒœžhQnľśŤ™ Eľ@Đbë˙ś9îľú÷sÔĚdŞ•üež$h˝:é DqâžPěŰC'bÚř*„†#ažm–_aË9mR^I(§‰ńŠ5ˇŔCőX#€ęĺ@ű8œ“tkˇÉ ŮŠœfúÖc~™‡ÖNJł}]XGlŒ˘Úb€gßv–{W7KŘ=EÝmŠşŇ“@Ý7Ő<?Î+CÝŰRƒşżT€šČýIÚ6_:¸óňYś=]>[kŠ%ŘŤÚN Üžş^–ŐHůŹłý69ۖĘćą6cţU˛rG"͓Â(1EâŒ$|ÉäŕQĹÎ3ä,ÇŮŕ…ĂŘš}hň ÜŚ‰ęĂʔçŕ‚+đ0ÚO ‘Á{ŇË6§ÓX3rú@śď˛Ĺ_ő§eŃ#†c\0ůB( ëâQăěŰÎoćôynÄŠŸh%űĘËňŤpĐ `Q˜>ŃácÍ;K‹uŰwŽs&ÚpŸ‰%E—$îÝŚÜűŹLSY9Ýܨ°ˇŹ]Śš™=ŤrĺđpÇUxŞŮŇ>Yk]" ܣߨٟNOucŹwbżśsĆśIz°ŕ­°ŽŸ‰ ´ţ6x{Ęԍ#ÎŤľ}u>Ĺąď€ýŕVIqńÖ/Ťc¤ ‹&ąe@ĽŻŰśKŰôĹĄőŐcý¨Ž|Łëj˙̢7Ž8â|ž!î„÷“QůâÎ ˛jĺvÓúőŽtál oŞŤđpΘϪĚgÍ&a°ˆ,Ą!Šw`âĹ P°‡PúŻS^™&žÔřđ˝>mŒ ,+¤Äí™y*‡ąôLeŤh×9͡!łž`÷Wô‚ŘŚ%\wa>‹]ŞśĎ˝„ë˝’?,wÚ §oH˝YśÚ1ĎPlC_ťggGă‘1|/ĐnËˆÓ ÇôĘÔťťŻ^Ń No;ěrC;}nł\Ä;îăsđކǡž˜\€-żś~ľÇˆ°ňޞŮOcu˘BÍăO߁‹ěPqČ3S-nđ>zÇëü~šg´nÎńoőcyę ńć3ß4„. 3“TMö%Čß×§’Ÿ7ᅯ´,xYn÷˜nÍ\Q'MI۞:%źů6tN["öiŽFэŰ'§yŚŽĘs&§îOŢ|kax{Tż˜ÇŔ"Ś[sOęŇ'/[vž}ŐtŸz_Ç;‘\UŮÍëLĘľs{•„hă,{BMšŐşĄCĺôĄm‘-[żňmz성SŕڃűÜPŔ”$Ä*śÖn罄ńąEŘ`Ŕ ČÚöűˇkIü'Č˝ĆYśůő8ď‚[Ž‘úLaťnޤđJ ”VĽŠ×‰şîŇNů7ůCďĚě vŔ•w;ůG§Ř8 Ô˛¸Ăś*QD7mÎDŻę•­Ę•;ŕžËjé~~S`íJtFf™ÚŇeÜž–[˜ŔÔ՝^š!x1 ŠqšĎéi†™öňo™^ÓŇpŠÓťUŠU 3¸”…şŢí Áôgá…^WóI—Ö/¨d\Ş—y;tăîďiÚm^ďM Yc™|ô)ąÜvÝfœťŇôóÉUęgŒM…öSë‚mžzƒ´˘hЕ•Ráă|Č­Çůäٔ­”ôyƖGťZK‡ˇ"‡f֑şŕ뗟uA=s^ӗÝRĐŠŁ;-˜Ŕżü~…úlŰÝĚđh§`ŰKEŚm(g޲M-cd¤wűŰ^jfă&MÁ¸YgDďźmGĐ)ş´-›r;#gĹÓv$×,ƒ¨ëj暺Ľč˜ƒůČ4ÎiŚK]ÍÚÓ @Żú\gÖyö,w =ôƒ =‚%đŽ]_.[T˝/4ń8Ÿ ţǨŘk ł×ź=ÖS\ľž ž…b¸,~ľ‡E‰Đ›‚y>Ň܏ţ‚2˛ł˙›ęŠÔď?)đö?ŠvKSŢţť =Ôă-˙8/k?Şfűä"(Ú˛žďHU|o"žujTđ[b‹63CxŤĽÂTË)/*Řȏˇę4ëv­@9—•*oźˇq̸&VĂţý.¤fF§rœŘĘ:Š-ÓtMS˛ßÁŠěžŁ)Ó×ýČś—šŮ¸IS0nÖŃť˝ű¤¨m[4ĺ錘•˝űD5D*ąa~”OŐ§(ąꚍ2„~pe¨˝€łsĎ2•󚚸g:6#‚k Âwú#é{–›ýßTGXLtAÝńţ°gÁŚ"÷,“:ʧďYVÄsמĺsˆű#ŠéVňöë{„I]řˆŮwŔ‹zßqŤNł~ŢÜwÜxoă˜}ϡëć`WîŢw@-u×.łŇ÷C Ftűž őX/M55Ź`ďڏ™śĄ ›Šd›ZĆČ Hďöˇ˝ÔĚĆMš‚qłÎˆŢíÝw Emۢ)OgÄŹěÝwŕ 圎QDz§éŞţŇ̊uż":Ąžť*4čGÓą¨Ü|Jx7ŸÍ_wîOú^ͤšÎýű¨ĂaG"ŕPĐT„?ŐGHÁŢýÉÍţoŞ#,Nş Źy˙IÁŢý 6š?é{PŘuÚţdEŒwíO>‡ZřĚâźyŞŐ=GßWTp›xQ˛źU'´Ž^]ßÇÜxokĆş˝îJ˝$ňů"x"o¤yŮćĆëEÜ2ŰŞÇ‹ŽŞ„Ä•şś‡‚ŐŃUŠăFbљŤ¤ű­*KEÖ˘Ł şrÄŚ–!˛Ňťým/5łqÓŚô¸YgDďv{°,Em۲)ˇ3bV´š7Šůř…R‚sćh@ť}ź/JąŹœţCż|wŕW#?{“Ťlńů°÷"ŞźđÉŻQ‘˜ú˜śŔ“ßÄpGÔ,Ł}ë+$2ÖZ– Rçözd—Šź„ň…’2x*2(á= Ď\{łî QJ6ő"މœLĘp;úĺáx×igÝM euŇâ1dÁť*ý-ű„°ŢçňAŻ9Š÷ĄŮt-ÚÔ0(‡FnXuߡçSpt9IâĽoPjQđ˜Ë‚QëWŤí)ó­&‡Ůd–ŹčČ˙9‚ëwľ;: óŇaPW~ŔLëÉ^›lí1ź6F’ÚČÔuj†Ť ÷ëôިsd}fŮş×=ĎÁéƒއ´˘ábΗ’c@CČôŻęU?•šú֕LݡJĂçr_Él§Ć!Lž)éJ—-ę—-„35¨ËeQÝĐűŞ ÓM^Sďé=őŽVŻëVÜSWŽ×ՃelŠš§^_TţVuS˝†ŤęőwŐé×kĽž_ő=ę{zU߯ú~yUßî§XESŤż;ýÝă÷˨ž_ĄžR}OęŰSŃKĽžÍáú‹UńĄžßô÷먞_ŽęŰTôÚŞoÓy=¨÷őýQŠď÷Z}Ă Ţô÷ľQßď­úžő˝T¤ë†*ŢJő UŔŸŻƒú~˝Şď÷N} ęűZŞďŽQßú•kÝ~ëő÷¨žáĽ^}żżŞoŽ)×äyŐ_CŻž¤˝˝Ťo| ŞxŐˇîĐëÇťúžNęhÍŤüü]źźéďZ}›ëZŻ@I¨bTßPňňĄžaÖĆN}Ă`ĚŹMƒţÖ~Ô7ôZÚMřý2¨o ?Ťč­Rßşż/ŔG/đŐëďN}ż6ę:Ú7ę[Óşó0$Tł0(ČQCÖüđ\ގęťÖßđž§"ˇŇţŞž›őÝŐú[3•GD)"D×Ě;GŠu,"„ÇÍϜźqYĆţDzlb˛Gođ0,ć•?J~8äQp×ĺŠ÷zŰŤ˝1›Ě¨çuŤÍżŕO*# y#’Ln‹Qœ˛-ŹTon„˜żÚ_ţŤÝđĂFŹ_öĹX‹Ů°ĺ`ĺśw‡S7voŘٟ*űŤŢ9Ft9tćĽěœÓŠ}ŞáŽcÄŢ0š_zŢź"aË%Ÿ€l¸}’<'ťó†ŰżĎ‘ź;§˙’ßmÄZřuş¸ěü^Z~‡ ś0tŚ›•5e7tĂäΤÇF~Wn†X4ő8zwđ!Kýšý>DŃóiĽU/ÍÍŠ˝}ÝLaÓʗŸż|“> REŐŠ UW­ĄŒx(ľ^ŢhÍíp¤éűm/­č.ăú •ŽáíˇUşÔ[ů'ŠízĄkTýpÓäúއ”ƒű ׯ/?]ż^˙sýzYŽˆjÉRĽĹ?ücţ篗úRĎ?˙íúӗŸUÁ?Żßţřľř ~PwPŁć%QÁ ĘĹžÔŔErbšúöŰ×yÁź~űýŰożüűúňţŻ?~˙6Wţ÷Ÿßąjm‰ŇrGĹ]ůz`fX~ş,ŸŘ+É.‰°Ü˝™ś’fRžƒ‰!{t'Ú\ äЀi›u6ąŕaé=đę1ť˘oîKVŽqőƉa)qę0ç6‚qD"AdË8R˛ę:—bĽj›q&•/LÎ$ Fčç,KäÔs˘ƒ Ă|H-­nó4Ţ$Ą(fÇŔ\kHÉ”h× ÇäžL2¨Ÿ´‡‹D™ĺ‰/_ćőűx?'EON J˝/䢴*l[Ó^§žkÁŃďʀÍ@GŰ˝rž˜‚žĎ#˘S=ăk oĽžł˘O9= HŁmÜŃĆ~ĺÓ*–˜aóÜ.튧ęrŢšíűÎ-hŃWK|’|ˆOHpâŹ.nŃĹSrFhtaşŞŤŒÚśjAô Ţóľ_lF€Ń6d5&0"$*97âl7-¨4 ŹO'ĺ4#&—řő’Š0ˇěiß{ąÍ§“.ějÖ´Yţ—ć›qfťýňż?8¸;xĎő¨Ăą>7Tő ,6ÁpTˇcš˜jZźiŘéôrşd‰w­ŻjÔíhŻRśłöä%{㚐šLűŚdhěeY2T^Bú¸ť}Ź›Ÿ´fĆO{äôqo<BŰĽ}§5Oœ9ÚžŠŒ¤Š DÓVłŠ›?S))J‰DsJE‘+Ę>;˛éńVř)0sö›™q˝Syí–YۆĘTâ˛kSŇUȌđ)R˛Ÿőo b[%aů1%e+AJöęŇZd@ŞNś“"R­Iî.œČ§Q.Áۉ˝%Şë&'+qśáÍNąÖ­ZMÔťëÁ§n˝˜)ř‡Yň<›§î=ź™Î|—´ŞËɟ›\{żŁťĽ˝g´hŻZż\jޜ{÷<ćUcG;{Ę5Qىśbó&{^„ë ÚÓŹńü&¨÷â~ÄuĐšęŞßý^cŰyŚ!îbcŰé]z9Ť´çÍĆçÍĆçÍĆçÍĆo6śƒ:=8ŠĚÚX­%đČ;g5Ž 9–ŤAÝŢtĆźtÖŰQô[¤ĽĽĄóß:;ß<ćžv6ŻSŹýmÓťťéÉm:š9° (ŃäDśâî—*l Ń?‡ŃńLe/ʢÓXx?j|EŰŽˇĺ)7cŸEŞ-÷;řö†ĎńQŢwE-#ĽjzŞj>ťGМ×$H:ô]ścˆşŔă™@&ԑcÔJZ`đÎ9giżďžŽÇŇC•Ż vęU,ű“<°bčě]ÉŻ=Ž’üvšp›Ř ŠśŚę™śýţÍôîŒď.WíömOjšĆşMsmëZÔí‘%MI;VP°d%ig%:u­ÜÍ=eťÝBś"›ŃZ “uŘâYéÝn—ś­™›4ă&qzˇ;˝ŒĽ¨m[4ĺ錘•ý­—ADťŻ:ĚvĆ:Ń{uB=wu‚A?¸0ďĹîŰfZ&lw.%]‡ĂpD„MÁ@8Pd8€ŮoôSaŃýČűO vçR˛MĹćRjűZNĚOԝůŠ?ƒŕ?śŔn&ôlImEEc%[’~ąS,uÓkęüę­lÓŤďĺʖ¤—5Ď~hÍ]}OßôTwĺŸĆ5-ë™ţLa§˛*Ďög‹>¨Ł=Ś×nńnë›Ňڏ } čçÖćĺíŢíqš§ĽV2›;Řqç#2hŻőTͲňtm?]ŰO×öÓľ}fĐŢjš\5śŹx÷ńl÷¸"dńlŤĚěrˆëŽmXš69śU#z-:ĂŻ=y&ńTă8Ťş÷ä7a›ľ~mŃîľDĆ$rŻÖ˘Î:đTš°ńzĄ˝—÷™ 6ŻŃ▯\:„ˇÚŃÓŕíł=“‘a|# •–Ź]˝/uŽ?fŰjŽmC§OÜ^=Żů ĐőƒnĘ/'?.RőÝ…‡őęqó‰¨~´ÁϒđOMŇ*?† mžóĂXş“ŠçŸîTżŘ¨˘uœç“Íçő‹ĽşÎw’_L ýż˜$˙~1MۓübˇIďS;ŃtżŘź™HP“ó8“šů‡hA’_LWDýb#É҉c¤´wI~ą‘äŐăŚMÁ¸IgœŢ%ůĹ踝Ś<ł’äÓMm3u[aĎ[ĎýÍěB˜ďä3–äsŽˆ°)hZćW˘I~ąľţoŞ#,0ş ć~=Zä ÷?ŕÓ-§űĹü‚şß/öđ‚˙Řť™Đ~1d­~ąQeŽó‹éW#übá÷rúĹ|űĄłübĂPúƒ‘|~11ŘďŃ/6´ýxś_LôáĄŇí\ďYé@a2Ś•-oOŞ wR:ĐÝn§ú™ƒžžĹ§gńéY|zĎNę¨1ľŽĺKşmYţ^ҁęuëŹt ‚äçĽԉçđt  űkĆt b8aö€˝Ţœt¨Ćń´t r„™ďe%oţłĽý?7čPÎÇγҁʙ< ń_ß^ž~yă}Á2ÁTýŔ˘X?q‡ŕ ś+†„l=ąŞŸPˆ#Vh}K˜i1Fý+ăŒ<cmVŇmsIŔ'B‘ÔA$v ĽřևSJvqvđŻ66Iai@¨aűLBSwƘ$ŮćPŻÜÄřZ0IŹs ŠÍˇŔđŢŔ*@U"%Í2† >ĄŰ ăn’ʁçčmb ’ço=4{šĚŮŹwü>Ř=F2 Ęúäů,ĄKžîX´v˘ šn!Z0ž˙;_F .s˝gžˆjĺ!dń0KFúlÖőΟ>ĂţڌЃܓ[O+‰OźkO^2đ°*Ţ<( Ť4ź`ŮA=‡óEňŻ (ƒösŹ=„'î‘M™dˆ+ŠÚ.4P\ü@úLŇĺ›Í’%$ň/ﶇ|q‚qj?ƒ=9uKfÓ*ąhméQq$!ę‡ŰÚ` Ov"9Î+n˛0„”V*"ľMžđ3íX™ĺ˘í†?W’‹śf1­răHeóyq¤m]—áB F˜G*ÉďYŒöâH5mO‘Ţ&m<Ž´Uធq¤mŐˆŮXA…hľUĎń”´ GŞ+˘8Ňś­8lT‘Ţ%áHuÍlܤ)7éŒÓť$)ˇÓ”§3bV’p¤şŠmp˛ś™RłœPO䒜KÂ|'Š™°$ŠËpD„MÁT3&-H‘ŽőSaQÍČq°´ GîGŞ[NǑúu?Žôá˙ąv3Ą#p¤ČZ7p¤m5Fd1kęx+!ȍ÷râH}űĄłp¤ÍŘ÷Ţ˙÷ˆ#ƒE+ˍĚúL‰§q´ßqëĘÚLjM'3˘´ék:ŘSĽ˘ľG{8G—Ž59áÄ\ţTÚ9َ#mşy R'œ1wŁ9'‡‘xČJu{˜Ş'ň‰‡|â!ŸxČsńł vԘľ]‘VfNt†i%˘s$ҊnD­E'ŐŚĘ3‰™jM˛ϗ?D´‘>dÔMpĄţl›łVq’]?ޖúČ6hÓ}ÓýrŢŔ űCĹíĽŐƒ;k§†çiŞĘÉJw+oŰČ#”!čö…KbčQˇ.Tm{&ŽÁâ#!ČOú˝áBYňâIĎ źťää†ĚLĘvHŠÇÁCá`łôƆ#0D˘ń°P‹ŽÓźCœŢhÓ?anÎM˝t {čŰ!ŰčĂâ ÁVń#"z0‰˛cżžëžŹťŞ?Ń=)›Ď랜Őoš{R ý÷¤$˙îIMۓܓˇITĐŠîI-kÔM§ ¨ĺżn[IîI]uOÖýÄ˝‘zŒŹ€ô.É=Škfă&MÁ¸IgœŢ%š'鸝Ś<ł’äžÔMmóRÔ*6á^ŠźőÜßŰ!„ůNîI3aIîI—ማ‚Ądî=Zäž\ë˙Ś:ÂŁ zî^ĽIîÉp˙îIÝrş{Ň/¨űݓ/ř-°› ážDֺឬ[ĹRQîIýj„{2ü^N÷¤o?t–{˛ŽÚöOăžƒuOzĂÜôˁˆ\ačŘŠ–œ)3{&ŤŠlžI~„ˇVďÜŕiŰ"}[¤ ^0ŃăäFĂÍÓ­}9Łyzp)6OŁu[†kÝČء§Wç]9ÂsS w‹ďz?뎰řáľŸíopŰ@á×ÝВŃâÍĐu/ź3Äoqxˇ ­+â Úƒ†;ź°ú+Ÿži–sfË]+­tš÷Ĺ˙řëËOׯ×˙\ż^'ŞM•?üđůŸż^šK3˙üˇëO_~V˙ź~űă×â/řAÍę 0OíÍËĹĂßĚňŠţGpŔˇßţ¸Îƒż~űýŰożüűúňţŻ?~˙6Wţ÷Ÿßąj¨TţÂŞŤŹxăž\o>(._~ţňÍŮšOB-?Ňj<ŰQł5˙ŽlܢötƒjˇmŐKĽ Ę÷cŐôcÜ3E4ťí힍ĐJÉäLßz+ňM=SjŤAbđâ5]B[&Ť …‰Đ:äŽäĘŞ'†]Ÿö䍇álD?šŔ;p$ÎÍŽĺćŽS'§/šˆĚ°8‚ KHPy˙ÓŢJˇ¨ľĆ7ŘŽMoÝhŠŰŽ Űv᯾ýUoelDÁďaËKKgŻń^š´Cď?ë0§ůX+FŠSëŰoűöĺH‡aajţ%~Ućˏ—2ëkJhE‹ZŽF-°Í|ŹžĆR×ܸ'|ŃĹmŤzŞ…)iŚrźŒĘÔőc×ß^wmčR]Ϛăč.mhżTiÎkRAŠÎk~čçCÁC1DŻ2==TęN%rŃ=ڍ=ŠU@Ç)ž…ń,úTEçóĐý$U[2ŔOn‰Ó~^ÉÜ|WŸ†!‘ƒ?DâĚŔ( ďI0’ęĆăHŞVÁ-“$óFpྡ„ziç’id˜ V’&š(šdXŰ3ô ••Đ>&J n6~ÚŒŸöČíc¨„ßmÍ×#9GIŔhm›ƒyţLSáaÎ]Ńý}ŐRÄď„.Yf- ^âa=*ֆK‘ˆˆ•$ALVą­’ůŠË‚OUÉú‹´śhm§#M’ťjňTÁƒKđvbGŕM‹ÝœĚ}WŹ…8w# '+/ćĜx7OgNŞf(Yę­ĘşĐ!KŽĺpd6}çv,ú;÷çj˙0 áj=Ŕف M˝Ÿ RłżćD‚޸ŠÝiÚúœ¤đúÜ*Çxb,ôŞŠŘ¸–łS‹! &Î+Ö?—PŚŘËÎćíz¸ÎŐ@¸^¸â źü{ĺhŹ2¨}Śű"!ćë™ˇŠŞşkÎĚŮVwŐyyĂĺŕw›k´áŠšÄôÖPM‹IşžŹLÉbœčć•n.éЀRŐ5/Ům.ÁšLűŚd(Ń8ƒCĺ%¤ťŰÇşůřIkfü´GN÷žY m—öÖ<=rćhŻš†Œ$úŒ6ć ֓Îh§Tt×ÞéńăÍ5]×MvÖöškL%.ëą^J0źßňŠ˙˘X˙Ö śU–(QOř HÉns3śiŽéşq0m'™kÖ$w—šćÓ¨‚—ŕíÄžaXé&'+–xł"ň`/ ďp+ö­3™k̒çŮ<­™kr[pę˛_ť7ôśěÜ~î5č`jFÄZň„0=Ú|ôÇr[zŞąţ>îüčZl7rZz oXz ŢvKO5Œ'Ţú‘c<÷ÚOŐNě|Œ ńTŒ–Œţäłk Ěáö=Dˆę3ŮÖBŸ ŰĎb*F—@ă"ń‰Ż˝)4tŹ"†çÇŠŠŞŠĺ{ĘnY‘ígśŹĚ_íy–1řs`FrŽ„iňž3şMÝ 0ŁŞ™W‹t˜QU6$–…ňçé榯ʞ‡na%i0#]ƒUMɃÔŔPy écĚH×ÍÇ߈„"ŹGnÓ`FtünkžÉ9JƒéÖ6b *•ľílAćŠîzę5á"~/˜‘™ľ4˜‘‡őˆX/%Ł@čВ4˜ŃÚ śU˛"?ş¤K1R’3 "3Ňm3ňKnĚ訂—ŕíρ!‹Ý‚Up f¤ß…_Ě 3ňmžNƒ•Cᅨđ`F*ŃĎh#•>~ś´Ő<uŔR•-o†ě 6Âom‹ü–3CŰô]Y Ksűٜ3Ł*ŰYŁVSv›P;4.-â˛fčÄĽóNdži3ži3ži3ži3ÎL›ŃŞtŽ"ł+úwá¤č+Ď#œő&'´˘¤œƒoĎuR”*˛9jđ`bFݲ)łĽéŸ§˜÷úpÇ&™ˇý ÄS‡stSžŞ$-î1á7&  żŃ!üŰŕšl×ÚcüČ6ŰtšZ:Ľ›Śęđ€L'rˆdl9ܧ˘owđ|#­YT9˙Ńý“Ü‘o6‡’ÍćdűďNoÓQ‡^ف@#8KřnLôĺl÷ÝÔtg ÍçuŢMMs^ˆ1ôS\w’üzî4mOrÜÝ&mźßnŇ^ŢTˇÝTw<8€. Fϊ$šětEÔc7u5wĎé1˛Ňť$wŽ™›4ă&qz—䪣ăvšňtFĚJ’›N7ľÍ4?uŐ!€óÖsżć;yč̄%9č\†#" MɃЂ$çÜZ˙7ŐUĐNÜťH ’üráţÜrşĺtݜ_P÷;ĺ^đ[`7:‡ŹuĂ7ŐSěĽýj„3.ü^N_œo?t–+nœF˙EČÇňĉnF;âtÔÜĚ~´qhCWűłšŃd^ěÄaě}̇Áł‡€+ ˝hÚT„FKpMnvĽ*€C]ľŮ=i“;%‘Ž´iRŒWvO?ÚӏöôŁ=ýh§ŚŸŻşÉUcVŤßō†š2Ýő™Ü!Ž{Ń ›ŰŽúčFĘsbşLžI<Շ6Şœę➏ź’ă3’{ŒîA_M‹Iäm>r‘ ÜkÄǃŠ˝KÔs/VĎS\lżPÔ{Ş–a(yk]@-–ĂĐp÷-HrŤčЍ[e˜FîEŃc¤´wIn]37m ĆM:ăô.É­BÇí4ĺ錘•$ˇŠnj›uuPž°Žć­çţVZ!ĚwrŤ˜ KrŤ¸ 7ˆ ĂСĚ-A ’Ü*kýßTGX`tAÇÝB´ É­îŔ­˘[NwŤřuż[ĺá˙ąv3Ą#Ü*ČZ7Ü*ĂĐEç1kjw+6ύ÷rşU|űĄłÜ*CŰ8ĐTƐ_őń}9˛hóS+ÂŢhŹîČÚł3ěM§Žů×ýţŁÍ^[39„‰Ăęv­ęöP?cŢ<ąşOŹîŤ{.VˇŸˇZŽ[Ďű8\r,ac=¸C\w ´—­ŽÓH}JŔ›ŠőL⊎ŽŽán.ˇ˛6ĎFGě†Ëţ•á(/~6 "H‰ěĘv€4tŒm͈T‘QŔv­¸˝ńˇ™ü(ĺ›ÉQo–ř´äŮƎ*ÉĽh\łčÚ´Nf0‡w7Ű滝XÔ&çN!çÂŐKëđmâq‘’,eH™€+—źRP†ô`Őm#ŁÔřÄÂN†•aAń•ÜS5đhL\HŃg'(# ý8-$~OľłČäá Ąłdg‘čYž{DľY˙źTE—ł<ŽT’âِFÎ˙Šß2ßv,š1đᎠ协NÜŇXż‚łiUÍŔIć儆wĂž}Äg ÜŕşĹcŤ_ą/Á"Äy $[ëŮË&ÍMžŮävŽ0eô˜^PyAˇŹÝ yÉ˙А…šI`Ň8 żuZ6cš˛ŸęšÚ&FŘÚÁňÔ@™ĐŇEv3xs‡ƒ‡P•Œ›Đ fĎš'úŕňŕYƒPĚĂ2Â5˛węĹí †żL”vžîzűľ>sBQ‚4÷á_ WńO`k§Ţ‡Ş‡áĚ0s˛ůźŔzčÎ 3'†žܨužTŕFÝ ƒ. >ѺǨBÚçC ’€ş" ܨ§śg8 =FV@z—ÜĐ5łq“Ś`Ü´3˛wIŔ :n§)ˇ3rV’€şŠmţŰzjRC"PĎýýŔB˜ďÜ0–ÜpŽˆ0 5ONM ’€kýßTGP`  y˙IAp#Ü˙pCˇœÜđ ę~ŕĆĂ ţc ěfBG7ľn7ꡊˆ…­ŤW#€á÷r7|űĄnÔ !ÂŁ=ŽŁUyŔDŻŁqgDKŤKŃâ ,†čC‹Çm€üúÁfY"0l x쌖V—óâ[—ůóCŽŘhiZ—Ě<ôD`<OƁq&C-!Žsm–!0ÚEÝgD` Cĺ1ˆŔ@HŕÖŤ™ŹEç\ÍtG¸cw’b(­FŢź˘ckŻk‹hb-ú[Đ!zĹ3ĹÂ/y,­‚ˆţßŕ÷ŢţjÓ'~8ż÷[ÉtFvŚý!`÷4†ÉÉsSWuýJŘ=‰1qńŹ'˘çž!°%ŁăňĂžňfO(ďö=ôÇaî'7üFź8Ě/%’o]§ąŠę ł,í+"YòríĹőśĚB§˘ý”XEźÄ>éĂžp?0Šeƒž9ä@xϧcăüu>Â}˝ţçúő˛lUmŞ´řá‡Ě˙üőŇ^Úůçż]úňł*řçőŰżÁj…ŽŽ§óŒ++sšœ8›y;ŁţÇĂęˇßţ¸Îüpý6*ů÷|žü׿›+˙űĎďXľ>›V]­.LWvCë˛>ݚUݏ|ůůË7ÇČi> ľüHŤńVŁüťb‚Œ˛NŞÝśU/•ęźéÇ2hý‹hvŰŰ+bąö&“3݈ŹČ§’A“ĽťąBlľ,&Šś˘ďHaˆÔÖŐ;rꏡ:ÇĽÖâ8ÄĘŰĄœŰx=2˘ F›!Éřví›`î:5qrúO˝ŰŐ{ôĺ1Äΰp& K‚H wv_)-řĄÁv­ćmtĚ%ÜľŘ_ţkmŐťöfůé{˜ĂňÂbg7r/¸üjčŸu˜SWʑâÔúĚžcďŕŚËź'˙|ůńRf}M ­hQËŐ¨śŠúË4–şćŚ­~˰{hゆvřfŢVMU•—QůqTqŰo-•Gˇ?)öŃÍ'ő¨ŤfUvAšśŰ=ąě~›ďcĎďťčüYČpšÔ3™ůŘZÉQú-üdo€Ś‡äiÍ ŽkĆmFťěáŞUË?ŕT~ĄC7pAÇňÎƃóŃŔ^çň"heőM=c×J[ύœŢ{E’:49䜁 ÇřćŢš†ŕiÍ~ÂËâ*†ÇęG2‡ĄĄ)ˆIG3OȊ(%UeœÝžbłŰŮĄ ?+†S‹ŕő•M7×b {§ÂÄŤŚX,ĘĚ8q§ýź@ńšyxž‚—ƒ§„lŠ3œ– b…Řœ;Č{RňŒęĆgϨšv^F“Óġç‘€›^q#˘óçŢň’¤PÍĄ1ŹEč?•—>&ĽŃ€şůřIkfü¤Gn“Ri°ńť­ůz$ç()´ś-Źţü™Ś="Ž~îŠ"—ůś>čń;ĺÔXf-)ІőˆX/%5O÷ÍJ’kŹb[%+ň%u)AJ’˛kŹ "^ÚNĎŻÜý 6>ƒ*xp ŢNěˆ,„Ĺn¤ŮP˛YFćـw#mŹź˜3ӆwótVލޞJ˙m҇ĆčËnƒŸí; śXŐýůѝN ŹpÖŻ:pømF ”؍Ő?ĄˇĽ[ţ°ű?÷U]Ďił.ťşq)ąŃ3=>0>á˙Oř˙ţ2üż×W‘YÓěŃř˙nyĹŹ Y"0V•gŒëôcӂ´´rR ĆÚ7šŻĚ+1kŰôînzr›ŽA+ 잣{°h ‚ćE? ţŐbLĄf„ƒÚ-“€Śn3/CœOßMoíž}ÜyćöÜ[uŐ"RĄĎHx~=áŃł<ö8Ń2ٙÂ#ŞE7 †ŕ´ŽŮ0]´NFtŁu[ď ôˆióu’žĘwÜŠ&pĎsg¸ˇ>wÄşŻĹ{‘ß‘ŽIB,XËŞ‹Í20§đ)ŁëXOvš<¤˙_‚ĂyCž účŽóJÂ#7 ęyř0Ŕ#Bݘ?˛ńPE ,DĐK¤#š´|—lʇS€ye Q ÉyöŚ/"Q5ö"O8F§w&3NXËâfłs@Ćóf;[/0ŹÂÇóˇA!>:5ŸšG‘ńĘËÔ;ËÍ:ßzcwśvž9mŒˇFřj!ƒpŠPŁ\uzłOzzĺSf­úŠăşmđ€.ŕ"͕?rN ÖŞˇoő{ĆöEf#ŽĎj‘N|żBQáăLÔĘ4Ug7”ÍçĹŹLăt^pC1ôS+’ü¸ş%V4mOÂŤÜ&í¸JYU‰#U5ɡŽÝBş€:{§ąáX ZUŃ1¤JŠ.p2\Š%-ĄýKŞčŞP…6ÎhÚ!ˇ‹I@:zˇ1_‡Äě¤ÁTtc}ÓZţŽđMgŽčţNn!Ů÷BИIKBŠ8|GĺŮô=CwЂ4„ĘÚśU˛"9PŇ ˜ -IC¨„B¨čś@¨ř…6Ąň ´Ŕc ďvZÇTĂnTŚą‹)iVŰîVHÉďĺD§řśJgSŚŽ]ălƒ&ßąÖc(ĐÇŐć# JE'x˙ż[ĘԔĺŮه÷…,')ŕ’ŠîőĺšÜŽźĆ3Â8h‰žŠ5ľ3s=‘%OdÉYňD–œˆ,iKľs’jlY–œ‘ÚłŸĽĹbDjĎaËZčľ(?Źd=“˜U2Uźů| Ńr Śä…YN <ŕeyřƒßlFƒLęR5ŽŮMŹÍŕN 1ą^>MÔĎYĺ;#9Hé˛MQ?Ą3zNóGýF—ŮĎĹ÷ĚËĽf1žřűÜ΢*Ě ˘n*{óáy<]#PüHŚňÉŕřb)˝ĘĚ učŒ2Űiq>‘°`‘"'$N žv­. ř đĘh.áXžX”ž¨ ›`V™@˘´âI>BEP}ł“˝Ţśč çęö{A÷fjœÁ€ýé• Ď狪Y㯖í;îe?Ÿ˙ס—Ż_Ţř@°LLĘĐłxˇ$ˆœ^öjȃي|ăđŠ˝UŒ;Ě&J4¤Đ,DôôOHˆPą2vJŽĎö”(OTň‰pŻrÍoĂřTDŽ°Ď¨é=ń ćKC,ě0bBĺʆ€ŒŁ ˛‰$ýT;áŇ˝,ż RĽÖĂ >"[`źíؐÁŰů^Ź>hĄţĂŤ­Ŕ.2˝Č„źÚI'6yŽŮę9ă˘Ęó D™Ř6ńř‘^ő€ ëÚŇJTŠíÚ$ˇ4,hśmI_3îÍ ›fštϢtŸsŃ^űłŻ‡ŽęľnC`™FTşŒz˙yg÷íÍŇ!Ů{$DąíŢ#ůř‡ëׯ_~ýýʝsŻHîE—ů˙Ë˙|ůöۗ˙gąÁóß~ýĺËĎ߈š˙˘žšKuů헙ŒÚ˛o[(•Q˙Áź_~{Sý1•]|žúS‰]۰˜Ń™‰˛ůźˆÄŽ­ĘÓ‰bčťas ţ×ő*‰ejşĺŽAŒşÎ€¨ h&ÓŽéxÚaZ”nYWDÓ-ĎŕٕőYAs#ÂLlşe]37i ĆM;#{—”n™ŽŰiĘ팜•¤tËşŠmYWťn*ČşšˇžČĹmŘúÁ…ůNé–Í„%Ľ[vŽˆ°)I˛qý‘ńfżŃ˙MuFtOM ’Ň-‡űHˇŹ[NOˇěÔýé–^đ[`7:"Ý2˛ÖtË]ŁX**ݲ~5"Ýrř˝œé–}űĄJˇÜN˝?Ţ+„rúLč9ĺúÉFϝ‘‡šjů œčC[_œł($ÎAo˝ČNđqˆIhŘO;ŕrm?*‘ÍîHh§É!Gd$&Ĺďí8NO¸Ü.÷„Ë=ár§bŞç͔ŁĆ˜ň>.‡šŽ`1Ȓ‡Ye)–C\‡Ëé_#:GňžčFÔZtFŚŇ3‰™ármǛó´<9-ß=aÜí Ě\ŰŠC͔˙ZrŰšór*žŞ­+fçöľ áa|‰rבVŇˆŢQ] úĆEô Ń!ô˘nIőčí.Ćŕ@@íçn1L\Œť6Űᣙ:sSp;7%Ą ĎPKÂśžšEEd›Éíý‘Íçőţ4Ýt^ 1t÷çŽä×~IţŇeă˝ń(4mOŠGq›´ńń(šą: {JÓUěja‰°+€/>ƒď}˜ŃřękŢá1œ @ů&¨cyĎDUóxĆ$ôWSŢÄ0ö6źTXbP"ĂZ˜pŘZ<Šy‰őĎ#d^îđĽşBOnvƒ5c&7ßź65źČ -Ұˇ]ó ő1FQPŁ~őd%ŰŽĽ10ŐYk'rź¸ł$Ô7Oý#˛x špd cbžŃ‘Wo/S çżľŕ0bÉ幏Hř Oű@âÇ,D‹(†ŕŢG@܁%ńZŕłŘ{›´h‘RŽvš}Zšěš|űËř}ůéúőúŸë×ËbžPľŠŇâ‡ţ1˙ó×KwéćŸ˙výéËĎŞŕŸ×oüZü?¨7łĘP:ł‚ň*—‹íS…9P˙ŁŮôŰo\gFš~űýŰożüűúňţŻ?~˙6Wţ÷Ÿßąjm%ŐG˛ŞŤě˝ÉÚÎjvüĹĺËĎ_ž9NMóI¨ĺGZÇ‘şÜƒW\ŽQŢČAľŰśĽŽ\­‚CVM?–Ao_DłŰŢ^‘ďˆsG29ӝƊ| !,=; eq~^Ő˛Ü f%D.°¸.Ł*čś`Ci&ˇ]gĆ˜ťnęÝéť; T`lţ_°Ůí\ƒíÚjŽY‡‹űëŔľ‰†ÁbVŇď`Ë KŁĐˆC‡0ÖôŸu˜SWʑâÔú ĺ>“ŇaX˜ţęľúřäˏ—2ëkJhE‹ZŽF-°MŐ_ŚąÔ57mŔ)…ďYo\ĐĐŤÂúUľŠş3*Ü֏SÄRytű“J- Í+w~îćÇ~–)h~hó7ß łę;šřI=jfß;ąŇvœ”퓎gуN_†ăąžá=فb"bŚMO^M›L”ľç•őűd9ME ƒă˝.ç .żúڇląx‡ę-˘n~íkՌĺu–XCöER¤Ń¤ ŒHv<ˇÁ¨i˜DĂ ÷DÉéHîZ)ńĄˇ9Źr2yŐ1\nî„ÚőÄŻ lˆŃ:ć>&˙+N’ž†wŽMôĂ:ËČ9pÝÓĘäÁÂTź6(˘˙űx˙>8—Q]J–D¤fŰâý65Şë„jĚ j=çu=óNlUwٗböóފ­ŕyŇľX9xjăËv/֙a;Lš ä=éflu7¤jŻ‡á€ťąUÝür,”°źÇľ˛Ţ°„ĺ´$é~,ÔÄňľ×CËoČÂPy écZÂv]7?i͌ŸôČícŇ=Y6~ˇ5_äĽĽl×­mLÖ\Í!—ćrWš"ď´ĆCG¸ˆß+gť™ľ¤ł>Ö#b˝”Ô"ĺ9-IËŰž6ˆm•ŹČ”ÔĽ)IËŰD(oťnű€źí~ÉMČŰţ TÁƒKđvbÇ$nGťq‡VÉfě%Zx7âíʋ9ŻŃz7OgÝŁ­ć}OiĺxŔEžp“6*Cł[ežN[USú}ZىŮĹŢż w.ĚýÝ/Ä7v57ߪűPĎ>äżVŤ°ű’ą÷CľüÍJńyAôyAôyAôyAôÜ ˘óşá*2Ľ“ßr,%şœéŹgöĆŢSC°<ŮÁjKš]Ń[ëĂk-Z moíűR˜ůџ€˝+Öˇé™Äź5 Śš˝–ô~rIŘČË$7'C˝árߌŤĹvϙçj1,Őb<7îëGľÉŽ ­ôă)—‹;ŘG‰1fž]Ź0|']/–MÇŔOö¨íy˜÷Ń߂î+qC."Frčäš˙óɧîłű[şĘ7q§Ţ_­ŞşéŠÖw‡ɔůŽsŕ ››]`Fv^Ä[%‚i—8Dža‘ćYäúičma&ý[OMMˆ˜ńRBYúň™†Nübézjbycɏ €h戋^⑸)( R×Ô|y}Ťĺł‚#}(:Ç4 5Śě”˛›ŕÝUÜ8śî4™óCń\y"e5îPœ›„Ű"gAíxIˆU‘dĂAd,°(ŧÔOö*†Đr'c<ĘŞaćÓÜŮ~fŒGY);ÔY1řs0rŽÄxhňž…ń¸MÝ R…LÇxčÓ!Ă8čć#ç@`hIĆC×Ä0sóŃĄ‡ĘKHÓ0şn>~Қ?é‘ŰÇ4ŒżŰšŻGrŽŇ0şľŽÝů,RâŘÍ\Qąń{a<ĚŹĽa<<ŹGÄz){ %iľAlŤdE~tI=  -IĂx„ÂxčśŔxř%7ăń TÁƒKđvbÇ`<Ĺna<ćNŽąýn Ć#übVŒ‡oótĆcxX„OńÉFxœ‘qxR§î“ń˘"‰ňĽÓ"Ţכ%)ZĐ0ô„ĆrhGz@ řâňë,ÇÔ΂7ë×ě~rˆ™XwťŸˇBO ÇČńr<gć#žůŰUcĚ^[űçŒô=vƒ;ĈHߛLçЈZ‹ÎČG*•)‹ě†|؊LŰPĐśˆ.ącd¤wťŰś5łq“Ś`Ü´3˛w{=đHŃĽmٔŰ9+{á&8ˆhŻs[ÍŤxÓÖ}˘×ů„z"׈}Ţkčćăá&]×M˄텛@ÆEI[ >B ö3űţoŞ#(0PPŐź˙¤`7&Î6 7éşq€–“ŕ&+‚ş nň9˙ąv3Ąo@Cş†ŠĆ 6DżX+–şU'´Ž^]‡›Üx/Ü–5Ď~hmoœReéÎ&ťŮoíN5ËqľŠ§KÉ@™-ß”Č2MęŽE㞘–˝bÎd%ŻpX“šŰáÉÁFýVËŻGú‘Hŕ,ן—‚7üHuÓ5oh¤>%čꨎTr„§şęşfGŰ ™]üŠÁYŃFývĄV2`{´8UڊĹÝR´°â]Ek”’ęÍÓ¸0wă`2&0z˙Ľ˝ďú>XŤ!xşe`1ýçr#VBĚsĂÍÉytKFʐ”5˝râŕw×|†l­>k˙Víß>Ž"Œ˝ĘŚ"Šąsç ™9ě$^˝ľM' .mţő™Ü‰ÍU pĽŔ2y0cŢLĆöÄŋN‹ő‰äŽč¨Ąpňşvpšô— îÂE\ižŃ†yźÓiŠéůř}ůéúőúŸë×ËvRľŠŇâ‡ţ1˙ó×KéçŸ˙výéËĎŞŕŸ×oüZü?¨Ťœ§IaË)ŮĚ+’úA–ß~űă:OâőŰďß~űĺßח÷ýńűˇšňż˙üŽU— SYéľ´ŤěBŠgW}`2+oqůňó—oÎĘ|jů‘Vă9ś-[jřwĺ€uöTťóŚÔ9źTëM?–ÁłEDłŰŢ^‘˝ˆő?™œéGTEž‰'ţ‘0Ž`ëĘ̀›{ďĺřĺŻňć&şe++yĆ÷^G4ßgw¨‚l`šăśŞö× L†šëÔÄÉé‹AöÄΰťĂ*0DčĄ]ŚžL\7Ô¨Y'œ ;ŕ௾ýÁôŐw2‡ĺĽĽł×ŕ ĹćźôY‡9uĽ)N­ďdë;#†…ŠáŻŢӗ˙Gžüx)łžŚ„V´¨ĺjÔŤĐŤ“˛¨Ě57ĽłZ‰.FŮŁ6ŽqčœlFí—ë˨ Ç?ííŐóčö'ĽÁ ů)bń>şůA%…ćŐŠ>wó{^óžă°ćcđ8Á;L`žE:Ł9Źʨç5Ą ­çŹë‹wÖuˆ”¤@BTZˇÔBöOÜL6eąhÝÖő}[§ƒ@AUÓľgfMrÚĎ š›ŻĎ˛$Ÿ ŞšĄMLďŐ´ ‡Č@ uťĎ%}Ď@2Ź$ 5QxPĽćCĺ%¤I!¨›Ÿ´fĆO{äô1 %ÄĆďśćé‘3GIH!hmb`ţL™š÷㔊î>"~'¸Đ2kIx!ëą^JŚ–AnXIfhuŰ* Ë”ôc/AJ’€C+ƒ ‡ ítčP@r÷c‡>ƒ*xp ŢNěaą˘Y6Lj<@ËÂ;ŢJtëŜ "ďćéPDUSň#Ht2ŞHE‘]Œ†A’ĎIážGÄzlÚ,([üŮ }¸ŹçżE›ţ‹ý‰äy°ŚSĚ4ZcŤ65oGSŐĂźţÖU™ýĆĚč!HdDuŮŚŞ§iz†¤y†¤y†¤y†¤95ůOUMEćÚ‚…ZĺŸÚyĆąbä´mé ľ  |ó˜9ÂHU÷źý|!FdÓ{cŒđ=MÜÓxn¸îˆ,2÷Z%Úü‘ŔaŇťbO@5¤Ŕ˜côó€ţRg1Ľ÷z7/†rC[٤N çV`Ż4›Žq/˝QŇ0ľš§ulĎ´‹˙Żo/_żźńÎ`™Ł”{áĎíŰşŻŢ/;—ĘYOŚĘľęľ ´š'Œ ĚĘ`˙ |"ď`ˇłn‰ÉŒ†şc–žÚÓŤKűʇýXe•F€|ą“VJóžÚŚŞFfqęC‹A•ó`6Q˘cCKŘŤL„Ź(d}Ç8Ŕˆą•6śćÚRš´}w8*Ÿ¤äÁH¤“őŽôîK&ҙƒ´TĺT;í•›ą-G{˛‰¸^UÇ÷׈ëH$ßf ´(RÔNđ1L߆,™@Ÿk§R‡HĘ`n'™ć>ÓÓ7“ۉuő+ňżű^ŇžŽNʼn”Ë–'"Űό)ç‰>'"ďÁ‰Üu!g€Ż$Iš €ź'%ƒŠ n|6¨j>vőéé Ş˛ŹIŞ•ą2%4×JĽç€fFb%I)Ą &šŞšĎP”‡ĘKH“ŇBAÝ|üHˆĹzäö1)5żŰšŻGrŽ’ŇCAkŰŇÄ̟Ű#ňÄäŽ(r•ŢçĂ7á"~§QËŹ%%‰ňąëĽd ĚŸ`ý[ƒŘVɊü@ÉPŠA’¤lQ+ƒ¤‹‚śÓóE$w¨Ϡ \‚ˇ;"kaąiŁ*˝IËďF$ŽZy1gć(ďćéŹÔQÓĐŐŢ3ÂĂ nDŁ7<đô'I5u {`GôጄQS;ĎÍY ŁÄř7$Œšúax˘sžčœ':ç‰Î9=a”ŁĆ.YFɕě3&ŒŇËĐY ŁĎK5Őëȁˆ. m’/a”Î @—.‹Ř{c42üŹ„Qr„™á\Sɛχć-ś„Q“:~•0JÎÚŠŃ!ÇĄcéŽ×1ŘuĂŽ 6r;’žĘF†;đ ŽÖĂEIě‘'ŘÁźłWúőÓŠHţă Ę'r pˇňd˜žŽ˘Ó'ą´ˆXe=%P(¤§Dtů>‹ďŮNĘpQ(őČ@ƒŤ1źĂňą—@`ďw¨ŕŸÍ7‘ő@'’Ěܰôŕv_¤J"Ľn%ůˇă, ,ŽW|á/ľęĎâ,! łq<™/çŐ äk5l,ß|3W6lć֕˘Ě@ħ4¤}˝„Ő‚ůöŻóaˆ’"7$jčřZfšZęl¤áƒć­#IĎ[5¨u⤟Ub0 •ż—źUCÍ2 ćFÉćó†ZůzN‰ĄŸ;’äŰŻԑŚíI ŁŰ¤Ç mÝŚCކŞ&°ƒą‚ę°Ş–ămhAÜHWDŃFC3qh‘#+ ˝K‚éšŮ¸IS0nҧwI0#:n§)OgÄŹ$AŒtSŰ`ƒÂ€*Č[Oäň›NÂ|'t‘™°$p‘ËpD„MÁĐ3P-H­őSaŃ=GFт$LQ¸˙H‘n9QäÔý€˘‡üÇŘ̈́ŽŔ!k݀ •bŠ($‘~5H~/'ŽČˇ: Fԏ?$ĺĂŔˆDŁaDé’Ô÷U(›W6čƒvľâv`śĆéĐ҆×#­e̗`ŒöŃ?iw ö˝Ľöéťš;Mš˙ő^ˇŰčÎZn¨çSU?ĚÔy↞¸Ą'nč‰:7ÔŤŤ˛Žcú˝ś¨Žƒ ™s=jhâ:d{ŽGhD­E'@@ŚŃ3‰§zóűz`ŠŘl~#pžóÍyüNŕ^ÁJčZEďĺ+űŹ÷ś÷•?°RŃ Ä{ÇŰţĘýÓŇš˙ÁŰ@6÷H8ÔȡCUrL<üë>wîA%~Bt”Ł‹ |Öëm †pÁ­źđף›ćÖGՏ‹Ë‹ž/Ä9‡Îł?ŠÁ´{…Äź`ŠĄî?‘Ý0ő':GťŽsRpÂńÇX ôň '^äŞËoÄÍŃş ţ*˘ ٓŒd{+—ŕMڜÔľ¨Ż– Eqé}Ä f›:5cF§ Oçš#eóyݑęúYîH1ôSܑ’üş#5mOrGŢ&mź;˛kËÄ<$ş–’^ +( –ţŽŞš[Ž$š#uEÔ9Ÿoš÷Q‘”7"Äş#uÍlܤ)7éŒÓť$w$ˇÓ”§3bV’Ü‘şŠm^‰NeŰ=Ŕ+‘ˇžű{7„0ßÉi&,Éé2\%‚|tU×2w-HrGŽőSaŃ-w§Ň‚$wd¸˙w¤n9ÝéÔýîȇüÇŘ̈́ŽpG"kÝpGvU‘^ÄŹŠí­ě"7ŢËéŽôí‡ÎrG*“ícť#EŁÝ‘ú˝ĚîČśǀ;ňb˘;"ğŕă1l)?ˇ8:‘ęÜôHƒłKŃŕ< .ĂgüŠßr2ĚkÁ1äŐASŽđTƒs[w,잽Ź"n Ö ŠŔrZrˆá7dé  š€ŃPTłżBŽyŒęł–Ë{$ŢŹˆ2KÁ¸řR“V>RV,ęţf3nĐŕ L¤~ČL'Ž™zŘ(ţbŇjL;4,Ręł!€Á ĺ$ľĽˆl=˛ZbâăÍé>Č6‘ÍŔ˛a…ýžŽ‘A^7¸ľu‚ďámB´™ĘŢ]úxÄ`źůAd3dym{ÎmNjd˘Rwžä›×ާĹwůUŽz`wŢsű¸dóy}\uŻâ:žäăC?ĹÇ%É/¸5ĹÇĽi{’ë6iă}\ľĘ ‘ěăŞűŠšÖÔ|\÷-÷őЂ$—Žˆú¸ęqâ.-=FV@z—äăŞI^ 7i ĆM:ăô.ÉÇEÇí4ĺ錘•$—nj›Šť‡ńSwŢzîo2Â|'—™°$—ËpD„MÁP3-Hňq­őSaŃ=÷Ńт$W¸˙—n9ÝÇĺÔý>އüÇŘ̈́Žđq!kÝđqŐ˝bŠ(—~5ÂÇ~/§Ëˇ:ËÇU+ßôCű¸DÚÇUWe˙‰}\#Ţ)>.AAŻK qÓAQڃł|\r„§ú¸ŞĹkl1Œ˝ćKaGóa¨ƒ?Ÿ -ę̨aěĹkŇş‡a¸. ‡f4ZŠœ˜hsćŃň|‰ëşúĆÉű2râ#ŕąâüíňe0ě:šÂ„&MźŤBb7ÁMq`čkŸ8ߏVUěîPöz˘ůĚ)ôŞŽ?/ƒú)f5IţÍjšśgĽĎťIÚ ŮóuXIOž7đˆNş€ĽžŞJn^˘i‰ó*„oCAÓq+š#Ϛwž4Ż8dž6ăndĆŔćFÂŔč„yUÉ­´fOgÄŹ¤%ËSMmLŐ4ý!ůą˛Ös˙Sşć{ĺɃ KK“ç0\%îITU#Ňˑ‚´y+ýßTGX`tAÍ͂´ -;^°˙ĄäxŞĺrăy5!5ŢŁ ţc ěfBÇdĹłŹu+)^ĽX*.'žz5&%^đ˝Źń<ű!żY-ţÇ__~ş~˝ţçúő˛„ÎPľŠŇâ‡ţ1˙ó×ËpćŸ˙výéËĎŞŕŸ×oüZü?¨šXé™{Ź´SšÄÝQw Ô˙˛çŰo\çń\żýţíˇ_ţ}}y˙׿›+˙űĎďXuŠ"ôTvƒVVP+iQ0óS\žüüĺ›#ć“Pˏ´@)4˙ްnWŞÝśU/•ĺ¨Zoúą rMDłŰŢ^aÈăh29ӕ"ßÔłŤ°5?`j‘Ńß9HjŔ\†Ú˜kŸ"…<$Ef[ G[k!ŻšułCRżÔ"휜uăl3%<ŔÜujâäôĹ䗉aoFP™‡­oWfh°]‹:mÔŹÓđDž™•ń×ÚţŠ)ŤďdËKKgŻÁ\ÜĘď_|şaNóÂ.FŠSëó'řüAς×ćí˙‘/?^ĘŹŻ)Ą-jšľŔ6U™ĆR׏˛bů÷ť[꭛Q‡‚7OŁÚŮ˙8´ˇÁÝEşTŽóóč.ŷߏukšďúüÍw]}ü„Ä7_+vŰ9úXA:N€ÜăŘď¨čü‰š'~ ŇfprĆMâj“/GVe÷zSPĺpÝ^t;U €{h =úšU32œ˙)Á~e'ôÉÁĆĂB¸> CşĂ>ĄľÉţ@ŽÍQ|çŢ(ÂLůӍK‹Čüß#ˆT5=ů>ů>ů>ůžš|ž&"łgÝŁ+ԋŢĎ :ë+Ďƒ‘z{˜čŮǙV4%?ělđÍcć|ÎóΕˇ?ćizr›žťĹíöČČ^Ĺô°IŰŤě’´gj„Ą˜“ÜQąƒG@Élɚęӗ;”šŠăżÚ l<1ÚËŚÝçŇőÔFŁŹ3:Œ2 2ýŻo/_żźńÎ`™#ř ł#úNƒmǙŃĄo‹ˆŮ>äĄwe°äȜ˛äřęä”ŔÍH2ށ÷–ŃQă?Rď?inœĚŞdÓśLÜŸ’HԎhUNcy}_„ÝśÚt ďmq@‘üăČ WˇqßtIV S-ŸĹ î[׋ˆÁ9XáŠAśí`écl›ő\‚dlK[ÉSiĚ4E$Pe<‘\p€-tŮ&gœŘ–‰¨ÖX %ÝB)C†|}Ş”%óźńUՎ.łŁúÔ<(.6 ‚GäyŔ™E†ĺÓ}Ÿ_ îF5h#8!Żeú0XúŞeVžě`zŃ~n4}Ľ’ţž§çƒß úđşşZ—„ú†jĘĄ×}Y™’îÜ #: [ĂĹhÉnô5ÖdÚ7%M…Po*/!}ÜÝ>ÖÍÇOZ3ă§=rú¸Khť´ď´ćé‘3G{Qŕd$ŃhĐśná §TšVí]˜Žp? ŢuÝdgm/ÜTâ˛ëĽ#Ő/Ÿşł?Šőo b[%aů’z*Ĺ HÉî›+ŘZ$*źëĆÁ´ _“Ü]¸đOŁ \‚ˇűťk˜œŹ@šáÍRąÖ­Z—…w*oŕĂo˝˜ n–<Ďći-đBćX Ő|Ľ˙œ\.ö¤’ňíqƒś.‹uĄU~9”h|…>YçO”m MžĘÓąČČ{6( ×äT˛ H**î_ ˜m"lj1":ŘĄ7Ż|œ˜@‰‘Xxv2@L|śçWă˝ 4iB§alVŇä;c9ríťş¸3"’ƒŠá7݁Öäü‚?Ű:}łáŠŹW2šdłôZĆwÄYâ1ZI}(›(2¸kČ´uŔXØ]dĄ"@5œĽ÷eŞ|˛Ngb'Ĺrq#'KžůęJŚ÷1ü-Š 7köVŃńŽ˝ČĎĆctzÁHM†RŔ 1`Ёs2ślÝŤ—Ÿ† ~DäS܏ eÄŞ+öTéÉ'5^h'&´–€\ČÓę=‹ ő•˙ŞőŤ7(ëŕ˙3¤eKg—„DëHôęĚYŸ~ ó/4#Ž‘žk}]zcŐĂ~–•(ĺ ů¨rš šç™íąnܖőŒazC_ËÉr€Ě,7ڧĆÓ×,Tš<2ť˝Lůä˛ëŮč3ăW‡Śv.VË@ז3Děj\g%(ouÔýÎݢDolDbÎ \ÚsucŔÝ6"VSä‡ôŠâűŘjGu+JĐ\,/ېŁPa=ŞœľůƒÎťƒúžZ…žď˘[zΊ;o?gŚĘ“ÍçE!÷S^Ş<1tjŮÍÓ[’ßsŰÓ[Óö¤˜ŢˇIÓ{¨ŚRĺő* m­ h¸Ü~ŞxŞĎ złB2€78X…8Zp!˝áhń4Ž÷ l ňs/Ŕwýxf29Ů|^ĂS×÷ç%“C?Ĺđ$É áIÓö$ĂÓmŇĆžşq< ™\׍-3ŔčzŚëúŠ`hA’áIWD OŠĚMíLzŒŹ€ô.Éđ¤kfă&MÁ¸IgœŢ%žč¸Ś<ł’dxęLŹý çĎšéCrJĺ­çţçX!Ěw2<™ K2<š GDŘ´<™-H2<­őSaŃ 7œŃ‚$ĂS¸˙Ón9ÝđäÔý†§‡üÇŘ̈́Ž0dĐ鸜'ECĎ @śź=>îœđ!şÝŽĐŐÍ3 Ĺ38Ŕ38Ŕ38ŔůÁ5淏ô˜@qÝ/! 6‡€Ľč¤Čr„™´#o>_\Ńňša >×IQä3óĺs#97&ĚéI!䜞 íxně§ť5ŕnÍvńżUÎB˘ü6¸wďŞoFO*őľ™hó]:júúĚ ůMĂcć?/Ýu¨ď š§_:ŇÉwNşt$ó=\:jJ~/3öC6Ÿűєĺy™ÄĐOÁ~Hň[…–ŽýĐ´= űq›´ńŘŚŽSJ¨ZęŠ&n᱂ęV­§Žc hAöCWDąM5q¨‡#- ˝KÂ~čšé¸iSzÜ´3NtÜNSžÎˆYIÂ~茜š€›jLB=‘‹n‚+Yó°f’°ĂQ6ĂȰ´ űąÖ˙Mu„F ťB ’°áţ°şĺtě‡_P÷c?^đ[`7:űŹuű1 cDŚłŚˇEÜx/'öá: űQ÷]íÝńk{ak/ŽÔ6˜Ÿ×ę„Go<4g‰Ó*“łÄC_0š´Ż§ŕ<|}ŔˆJ. MSÚzlƒ÷Řä)ˇ?YěÇ^HÝĚí×Mvc‚ö šÄ:ߊîfb= O ĂČđ2œdčľi’jlYű2´VÓg2Ělă 1d@lbż Č QkŃ @†ŠňLâŠLërŞĂ.,ŻťűBz *Žţ–iŮOHą'°7ř­œœ:]řjÂŃ'Jřž/ďŘČśĹyĚ/ÚN5<ň&’BF‰ŽĄ›}9v܇ŃӉ7nS@Ňń|sŘ3Up(#ށ ŕBm-ł\ŮCӖČ]ΈlZ˘ܝ‰QkƒK6ťˆü e‘R€¸ŠsH˘Ä×K70ž5L$˘8^XŸI7öąđXÍY„čW‘Ő>3™…qg YüżÎǛŻ×˙\ż^– •ŞM•?üđůŸżÎÇŠqţůoןžüŹ ţyýöÇŻĹ_đƒzŐTGˇyž• ś\NcÍźÔŤ˙ń ÷íˇ?Ž3\żÍŽ_ţ=Ÿ˝ţőÇďßćĘ˙ţó;V­ĎmíVu•Ý) éUŸüĚÖ˘¸|ůůË7Çh> ľüHŤńX—ÄĄđďŠ}.Ęt7¨v[垯ĘrT­7ýXMcÍn{{Ex#68ÉäLˇ°*ňMˆOö€xA•2m­4ę÷x^é Ć-óçZ[€Mžs vŞŘwmN`w§/;›‚.đ-’Nr,`v‰ëŇ8€OE:}öRłNNpv‚Ă_kűŤ> á­ď`öˆ˘d1“_ˆř1đÓ sęJ9RœZßŃÝwÄG: SĂ_˝ÇK˙|ůńRf}M ­hQ˕šČ]ő—i,uÍÍ(C˛‹QYˇŁZŻ›Q]ćîć稜œ?NKĺáíëăĐ~EüŠŮ:Đ÷emÚÚôćc9î8NŰÇ!Ÿ˘č|bf8i8›°jÄ|ÖMLŤYĐ|ŠË$*YœůžŒ€™-=yů=*Ÿi3t剘S§ýź Óšůy< u* ěԙŃu/îČ{đ4‚şńČÓŞ™fÖL†žÎjľĺńˇ „âşć’Ąg(LV’?…š(ţtXÝ2ź) •—>&APĄn>~Қ?é‘ŰÇ$*żŰšŻGrŽ’ ¨ĐÚ6HÚü™Ş<“–ť˘űŁŰ¤ˆß şĚZ ŐÇzDŹMÉPň@ňŹ$ ”ş:ˆm•ŹČ.§^ ‚”$!SW€ŚBŰéŘԀäî§~Uđ༝ŘUÂb7 Şłü*֊¨» Օs˘T˝›§ł`ŞUÓ ţtXŸ §*G T=# YŐĚĘál¤Şěń‰ŽË|Djm4ZŰçv0jՔ §žÇb/§Ô“;îȸZîxS6O<ęúÄŁ>ń¨§ÖęôĆ_*2Ľ“ßr, :°—łŠ!˛ćjíŒZB¤,ÂôEüÁÂŔÝËťÔ›"h™Ťu§Vś÷źëÎ07ÁlÝwŒ†–oOSăĆ,¨ĺşó5˝ ĐŐŰŹŮĐJ7ž[núÁ3ĆĚŘŞşO™Ţ”l˛éÉŔľąV'úcÂ|CƒmÝ6b>ŸÔS™ŰZ?ŻžŮ;ö^ŐÍȂq×!âĄDÔ {˅…­Âôčł'Ç˝Ë8CžskoŁňAĽ5ë†đ‚źx‚6Âěečőö&€]1h \#\gŮ] Ň!w× SČ"HëĘ"0Vœ0í"FcÉúÎۡ‹ş†Z0f•0/X/2B~ICšŹ/˃Ŕěœ$>ÂlCAÎËnA^jßY˙$ƒrŒŕ R8#ţz*™Ç_\ý Žřý}úŻo/_żźń.aYçŞĆíQ=ŞsĽQ‘ˇd'îƒűGqŽ9/ öâűco`AŤsú×ěCa„ ވƒŁPÔ'4ps9Š]6łpß3†A+eľľç&ô´o.—$œ…A™ ôěŁňŔ \‘e…ë0˘-đ*Zą°!~u°¨N…žĚ‡-fUÎ }‘íg†žĚűőń<č‹ü9Đ9¨ÓĄ/šźgA_nSwôĽę”Ż0úRŐ%?%Ěu<ďťôƒ–¤A_tM úRľŁşčĄňŇÇ4苮›Ÿ´fĆOzäö1 úBÇďść둜Ł4č‹nmŁżťjűCrŔçŽ(rS‘â8"~/苙ľ4苇őˆX/%=OeÇJŇ /kƒŘVɊü@I'đ;´$ úDú˘Ű>úâ—ÜčË'P.Áۉ}Ať}ŠT†ľHč‹~7ú~1+ôšy: úRN KŢč10bœ rRö˜$Ľ‰Ż%đkňt ×ĺÄč;OŠ}ş8'UßÉΉ`-ČqVőÎYĐ;¤Cě˘ů ĽÂŠć°t‡i¸ÚdnôPŮv´c砇D'ˆeČŢϓы-ÓÓŤířYڈáš0¤YCűI1H^ľ”í$Ͳß_š>{ŚżŢ7Łq¤^ű•ć鯞¤'$é IzB’΄$ő3+yŰşoɗЧ*ëŞßH‚ˇČŚ×á-ş,˘wŢRVCźEŽ17źĽ,SŚ7 Ţ"šŽI1čŰSٰ&r"#¤ ÔáŐVĹĎ8°mčţť^h×`S50˜yÁˇYí~Ţ^Œ6ËI> Ót*Îąxń|Qˆ'X(Žu­/>$úCqÄścV@Ź*řľ_zJ>ćEÖdńîkÂ×­Ÿđ„Č' OvŐ!¨0Şł”ćDQŠa!š•ő‰¨ˇźq“nfK´8víJ Řą3| ĽNČz]"ş"yüľ Tş ă8Ý/TŁ&–ÉóÍRSşů‚¸4(ÁH¸Öüfm;ŒœË|zk5V™Ď-ąňÂ<ĂĂä >Ç´ ^“lhĄ’şq•aƒx aƒĽ]Ë7_=ç7‘űÖ-“JÁ\%‡s Î .ëÇŁßň‘ąéYČďĚšX‡ŞvtűĐy¨nlšrŐ|DÔ#*>öj˙`ĂÇĘMÜŠ1‘”ŠčD\˜l>/,l>ęö§ĄÂÄĐO…Iň‹%Śi{$ě6iăaý¤<詀°ž bľăUP8EßO E ’Ŕ`ş"ŠëUz{ üŇcd¤wI@0]37i ĆM:ăô. FÇí4ĺ錘•$˜njčcîmć#o=‘ vtDó°_f’ _.Æ{’BŚhAěk­˙›ę Œ.¨8n$!žÂýžtËéx/ż î‡{=źŕ?śŔn&tŇ YëĐŤKEáźôŤ0Żđ{9Q^žýĐY ŻžaAmexŁ? ä+ĆK;â‰-=§‘;Í{•cňd •ěĂŰ2Őäň˜°u|Ş­¸GמĽ:Fé¸ űiRŞŻ”v˛ÇĐčôů™+2“hß(śœőí&ő„I=aRO˜Ô™™DU "GąŐ>%%’4¸"äXÖF}NC\Ç,éG˝e-2Ŕđě™D;Ď$fF,͢ɚW‹}Ë3'Ą3@ŘÜŁ@Öo żäą7cçô/żO–Ő5‡m2ɛ~¨¨:çM^DRďá4@RŤv‘][Ó ´ß )K$ZMFĹ2€I ęBi~ )Zbř󸁲 .ĺ'H6 ÔJ&˜Ţő<öIăĂÚşu“<ţI°Oůˆ\2ڍľbý,Ř'…Ýjş6@€'ö)€}Ę77MykăńÄ>í;%Ô=ŰÓGKžC\2˘Ý MQ(ŤŤmˆü‡fL¤9OĆ*(H88ůbŘÖOX+0€<×8ćň–yíÄÚ㉼ÜŤőë:= –ą‰Ş!$›˜9>aoäĘ@h"Í8 ŢËâ9Pą őólGÇŚqZÖçÉ.ă…î‰ in€bŐó ËĹ ¸¨ĘđFnź= ľ÷Egúö5r$OŽKhDӆĺômî‰&_9ě.ŠźgłÉ6Č úG\t¨đȎ*ߔś­ł˘Öťë€ôçć<5Ş`Éç*(šĎSPąŰi!ůĐa„š# ň‹y xTÓöŹx‚7Iť!œ`­Y§‚G§‘§‘œd$ޞâJZG°Ä0~PPw)ŞGH Ś!ü˘CŞŠYAŇ ›ôĹé\ZřŔ˛â@8Zł§3|NŇ"Ş–6F ŤŰö`aYë‰\uphBď4&,-f ĂoĽ –Š"ë°X{¤ -^ŕJ˙7Ő–]Đpŕ+-H ě(R jů€@^AMˆřč‚˙Řť™Đ1!-k݊¨ü ‘ŐŤ1ńƒďe čŮ ůŁń?ţúňÓőëő?ׯ—áĄjSĽĹ?ücţ篗é2Í?˙íúӗŸUÁ?Żßţřľř ~PsąÂ’Í=VÚŠ\ŕaÍźeT˙#˛ěŰo\çń\żýţíˇ_ţ}}y˙׿›+˙űĎďXuŠ€d:bŐUVP+iQ0óS\žüüĺ›#ć“Pˏ´@)4˙ްnWŤ+ę„Yވ X5ʄ⚈fˇ˝˝Â†GŃdrŚ+EžŠw˝^ž‡E{Š$fkŹ[wYěpŤęáąÖ6Ńă.üÝŰ8ľ7ď2#<ŔÜujâäôŤ¤Ša_ŕžFPbťĺÖtŒá Ô°_5ëbóqaüľśżj˜Vłüô=ĚayaćącWr“Ÿ‰9öY‡9Í ť)N­[ĺĂ`!ŞĐ‹Uň˙ȗ/eÖהЊľ\Z`ŠFĂźŞŚęŔ~wK˝uŁl-­ 2ޝýC{{Ü]´ĄK*śűá]ŠoĘöÄć;oáĄ&¤Q*egbeë8™r˙=ŽfßwŃůsľĂł,]ĘeďĘ=ďĘ=ďĘ=ďʝ{WŽUHqG‘1-^ŰmzHńzQůfUČąf íäcđśœîŹ^Ž"VT˛ť4­œs]ně}ó˜;ÂwӋ sů"|‹ŚŁ­…ˆÂE!ň|4rŘޞdőş2_+Xvn<Œ‡\Ňćý9.9öÍŕ冢ŞřŻV5–Cŕ§MŃý—ŽœsÍqŹ8Ѓ÷lĺí¨|Ą ‡ŇCÂÔĹ´G~Źťţl‡źčCËÍF­@šűźđ:âvÄ żĂĆCŘá…몿ÔęJNćĐŁKŽČČ*ßŘÖŐÓ˙tÁ?]đOüŠ.řJíؤł‡ťxŕsÇ=:wˆëxX•69ࡑŞ?%ęÁä™ÄĚî÷ąäÍç󾋖÷:߅,¸•9ĆÇ>*ЍŰü†]˝ů(]y˙|QX@Œä†–ęíŻŐň Zj´ZJŤ„n˜šÎĚ-TSvŘÄŘŠš˜7ć5=Š+ňxÖÄL^Ťľ˝ŕ…P&Ż`RGźę ˘‹áŠĹux^X„ÜřiÂď]>!sĘŽfóĆfČ|#fł+élJÂŁ×} cZˆÁŠ(œ–2ď.Ś‹!źŕŒyŢ\ŔÓ$ŠQ7Ť'äBžYŞűľYň™q>,'{˛źĐÄjţśÁăš'l/.ł° ą}ŰÍmŕ ˝—Ä  >îŔú8҉˜x4…=e"˚N$ľôÚ} ôö×wF úÁ ‚¨0BÜDjÄrĄá1ŽÝ†Ç„—10|°‘ąţhחH7w¸‘~éTĺĆÚôUé4ßVyšľëůRď[ŠWáƒÁ¨Gň׊}‚Xˇ-Đ×âYы8ÚOž }§|ö‚0°XŔjžcrúfrú°žđövą“zřă&ĺëSCt$ŸŢ č+Ů|^ôUWĎűŽłĐWbč§ Ż$ů=۰˝č+MۓĐWˇIžęÚqLG_uŐH€cŘĐŐG!т$ô•Žˆ˘Ż:e;Ą`+=FV@z—„žŇ5łq“Ś`ܤ3Nď’ĐWtÜNSžÎˆYIB_錜0şśíaä­'r!NsažúĘLXúĘe8"ÂŚ ĺů.iAúj­˙›ę Œ.h8zŒ$ĄŻÂý ŻtËéč+ż îG_=źŕ?śŔn&tú YëúŞŤKEĄŻôŤčŤđ{9ŃWžýĐYčŤvŞŘ%—ť`ő|–ŞŹ“JŘźŔžă3ďäAU•.y˘QUú„ŸU5ŤáÓÉČ>ŕĚŁŃ ąÓŠ6k’#Đ*ý“M&?A$ŢÍĐŞV‡fŻóCŤ&—&yfŁSçqŮňË™Ű&{\˜)Lˇő°0ľ˘řŘg §ž}ˇ/cR Î2Ť‚›ŕƒ :.úő‹ŒĎ „ŹŽdz9ÓIß4ő™é9dóyôrťžĺ¤CßíIVńŚŤHÍŃÔ5ĎĚĄ h`űŚîx^Z”–CWDłr4íērč1˛‚úFxŘ”şf6nŇŒ›vFö.)ˇÓ”Ű9+IŠ8tSŰÂď7ó‘÷ˆčűy뚍c úÁ…ůNY8̄%%ápŽˆ°)xZ”€c­˙›ę  <ů-HĘ˝î ő†n9=ó†_P÷'ŢxxÁlÝL舜ČZ7RnĚ›qCż‘p#ü^Î|žýмۨÇn%ŰĆÓ×LšťÔŠő5kŹ<8œíŔş ş9łOşîŤÓSoČ>ŕ5ĄŢ†,#€)ސd¤tGkúëWśťŁënŢÔĺ˜?ŇGç#6҇r ă3ŮĆÓ­útŤ>ÝŞçşUËir՘]ěîé#ł[uwˆë‘>t×7­EЈZ‹Îˆô1z&1ł[u~đ<—O3˘ŃK9ď˙ ~ŻůŻÖ=$›xúѨƒŘ¸^ˇű äá`Wë}{ůúĺ÷Ë$?U,büÓŃzœŁuťbŘ?ŐČĽ<}­QŒ™Í׺m.{f!yzZ×Ě!kžÖťnŚĆŞœBEf$ŸşÚŹË#˘‰ÜPÔVćźŃ?Dź!l5ćpň-ń?ţ:źż^˙sýzYśúŞ6UZüđĂ?ćţzŠć~9˙öˇëO_~VE˙ź~űă×â/řQ˝+łÂ<Ę{Q.–‚fކŞ˙ŃČđíˇ?ŽóD]żýţíˇ_ţ}}y˙׿›+˙űĎďXľś)T ęUu•݁ ×B[%̖Ľ¸|ůůË7Çxn> ľüHŤńěc*üťbڎ˛zŞÝśU/•Ú&TixHČŞŃ육Wä+bă”LÎtç„"ßÄ nFś˛K6H jK”)ŒˇşÇ‘×ń1†MҜçJ#ř ?ˇ<(ƛlâž8ÓŰ6˝0wÝÔťÓƒ2aá¤ÂhQˇ˘éĎ"¨ŚÁvm Fßń´őařŻľýUŸŘ›ĺ§ďaËKKgFÚ ëĘgëԕr¸žĂ5ږ|gr¤Ă°p67ßDŹČ| ňRf}a -kQkÖתŤţ2écŐÔ­tŹĘ.n[ÂĐcҌęőTŽ—Q!~ěúۋăî˘ ]š•Imş4´Gu)žýĄ›7Zç5Ż Î'6_ˇuż—beë8™Š…gуÎŐýÍĐUŤ6"犝öó"ŠçćçςËÁ{0ĹwŚuf@5R"yO ýAÝřŘ_UŤ.w'˙š÷"!”ĐČ:s AHνĺ%IŔ &lX‹8m*+Ą}L ułńÓÖ`ü´Gn“ąńť­ůz$ç()´ś-(Đü9&=*PîŠ"§;ďĐ.âwŠśĚZRH0ëQą6ĚXքuÓ¤$),Řę śU˛"?PRb¤$)6ŘĘ ÁÁ íôč`ÉÝě3¨‚—ŕíψFXěF°šďŠľ˘˘„ÁťaÂV^Ě'Ěťy:+PXŐ %ťEŽnM„/ß0ˇüŕ­5ícŤőŸťxď_;NîČb× ÷ʎÖgJlʤ]hĂÜ`ěŞiš™ý 4śěÄP2b‘_˜â‹ÖŘłő{ŰáŘs—”Ľ !ÝÍ^ö<ł Č4çöu÷Dd?ŮODö‘}&"[I§G‘Ů=Ŕ÷éjč&Ď#B]m2Ů-­h‡f~Pöŕ›ÇSƒUMUłřĹŰTĘ\Wžl)ÄŐđ?XČŁČ=$*…=ŤeĆÁhĐçĹLÚ4/ˆřęˁřȞŐŇó}$ ŠÁˆÝő Ű?“źPúc5ŻŻb 9Đ|[Ňzdą%富*dPˆ˜ä[l1÷‚ś>Lž :`'ßb’bžźi@֎5ž<l)’@…¸Ş÷LąH7d8#ăLöíÚLréźŃ<úƒg Ť¤öJgžvž1éváj"zGœéЊZÎHUúć1sˆłjní¤ÔQ˛é˝šŁř{Œ¤@ňDé}ăöQsŐŮiÚˆuďݨvđLÍŠ8‹i¨üŚw;đşL"b) Ď=ůƒ}ĹţUÄĎęmŘ­ŢĆܐáŇB^ŇßhąĚ’DŔ,źn˙Ţ>&ýČv0™Úl1şZˇĐ¸˘š#EÄň K؞ŕ@•a2tÖř$ś 1zqŞD ¤ĆN3:Ůpú‚˜Ë5FÊáXÍ#ÝJ™˝ĐSݸ@éÍág¸Ä‡0G콨!”á†˙uv@üy‰%cĚů\°AۇrŃšŰxĆ٧ɽ>Ái)đ^r2D@2dg;b9öPĐ>œ.„5n/áŕDj‘-­UA¸ß3ĎćĐą›hXĽőđ!ă đMĎoĆžđ9Ş[ÁJ NƜOçâˆ%RťÝ ,lgލyĄT8Ę(č|“ÖUŽB%,Ž őݘ ŐéE™yřRPU×Pˆę#+­F‹<‚0,ä"Üş¸Ś2Pşf۝˘˘~Ď×|ɝŠÂ•Dą@1Ą8ĺ`Śś3ĄgśĺyEDˇđŒá¤jQ[)&¨—–U/'Ą/¤Ő™ ˘§J΍!’Íç… *"őY˘Á“ihARŹ’ľţoŞ#,0ş .y˙IAR˜’p˙QJtËéAJü‚ş?FÉĂ ţc ěfBG„'AÖşdƈēfM­o%žźń^ÎĐ$žýĐY‘I†ŚtŁ×D^ś ŰX|qçEXÇŔКiĽwű|ŘŃ@+ŔőxNw<ĘĘq2LJôA_rCÓš>ewG ¤đ6ˇ*÷´.ŰrdP'˙şŢNÜ ’šJÄb¤TˇëzxB¤žŠ'Dę ‘:"ĽN RY;îъΞ +B„Ôŕ1˛áݚˆ•¤t#úĆÁ ř(Ď$f†GÍj„5˙Ů2@ŠţK~o,ƒW˃dĽ° ­-żĂgsČ~œĎ)aÔöŢQąĐäLž Śęť–ć¤l…żU„ëˆjÁĎ$yr#ÖźŔŽ7E:V=N`Œîđxč jË~R•v%ëš×A‰tń`?|÷čó\g‰lJ:‘aˆŠď¸ˆăÄ9ôxŢqˆAZJôf´€a†AœkááŢßĆÎ59†Ú“6ö…$|Í7‡ŞˇBÇc˜‹Ąlbn,ôDŠ f™K×A’ˆĆAů‘#đüšŽËY[ +Ć(ť"(‘šÁ‰4`5ŠVŸş% t˝ű+˘ě<čÍń­;DÎO,ŘU`ŹřT…îýyĽO}BßőŇşšÎŒ…ęş‘ÍœGýh]€WŇt Љ‡´l*Ł^Ů_"Ńňă jŐčΊ?$çĺTÄLĂóu<’AíCš żz¸”~ žABžut×JŒMŃŕs›#˘Ç{Ľ? á6śƒd °áŢë(”í,Ňđ\@;đEčwE$bŽĐš%D“ˆ<%Sâłv-r"]čŘ P˛B}x/îšé05ú¨ń éĽ_žƒfÓŢĚĄ˛şDD9ܙë“RŒ#Sň…bäĂ˝h\@ĂąTě ń$´Jž°MŐәË–ŁžX&żgXŽœ‚ş›ÎLí#›Ď‹ ¨ťáźÄ>bč§ $ůCëЁŚíI‚ۤGÔԘ1I×Ҏ#ó¤ëꜫťŠ{ŇiA‚@WDőĐsŔ€#+ ˝KBčšŮ¸IS0nҧwI:n§)OgÄŹ$!tSۉľŠw€#1o=÷wH až‚ŔLX‚Ŕe8"ÂŚ m™ž$!ÖúżŠŽ°Ŕ肆# hA‚ Ü˙‚@ˇœŽ đ ę~ÁĂ ţc ěfBG ľn ꮉH„dÖÔćV¤ďĺDřöCg!ęşrîŔ K9y’˛‹ř˛­MvŻüNxG{'g‰ŢčóGŁô)ԓúˆXyÖ`°“X›XöŹGÓ0ž4}č<ńŽ—d"kdŕ˝Ţ .í°čƒ=)ž°nłşĘ%L$đ V‡Šy5{žŔƒ'đŕ <8x śhŽ[4ř}Ň•¸"äXÂFĺŕ”C 0řÔŚěGŚ‘ů“gjĎ$žęaž,wǀ!›łĆël•hű‡ ŁËúr@şŁ0ş>ŻY_ĘűŽÂ^Âŕ•tkS÷ş­Ń 3-]sB/°î’|¤UžígËśŮ뎺őýŇť~eCô]ďőWŕPrŸĎ7Â-eÁ‹Ţč˜Äő6tńvs_( !Žł‹sÖ"fů&˛âç<¸Yšń0Ÿc¨ăł„ĂłäIzBbTŹç1Aá ĺÂÉő2ĆÄ'Hőđ9°ƒ$×ăĂJʧrăüuވ˝ţçúő˛,ýŞ6UZüđĂ?ćţ:ĎâüßüŰߎ?}ůYýóúí_‹żŕGľ†Wnj™”q˛\N §ţÇCǡßţ¸Î rý6~ů÷|Nř׿›+˙űĎďXľ>cTÝ<誫쪆FI}J1Ë`qůňó—oŽmĚ|jů‘VăąÇ-ŁáßËU”QkPíjH^U– ůU5ýXFÍn{{EŽ#ădrŚŰůŚžš3żƒËî¸Č”¸a2ź1é"x+ű1P.ÂG™o‹xśyŽ9\”Qdť-ĐO&—mŠ˜ťNMœœž\fě ô°T“˘đş4ĄÜ°]ťƒkÔŹ“ÓĆDž6đ×ÚţŞwđÍňÓ÷0‡ĺ…]Š"Ąĺ<Űs‚ůŹcşRç×wÖôI‘îî=ůäk—2ë KhY‹ZłF-ľMŐ_ŚąÔ5×]Čçe˙őô>Ś(ŞCuŁ.‹6ĺÜŁQšÚŰKčá헣J6ĽŰďúüíÍĚnĐüąƒ8şůF-‘;ŠËďÇńůaüů? 9Ź ¤&ă[ůPşÁ0Vx> {q€ eüb81ÜvTźq•‘d-ćńăČaťüĘô ĂQ>´qĽƒÂž7ž˛ZK‡Pał[qiQAťG'Ě~ľ[&™űÉľyť×:öY‹z==ÖÍÇOZ3ă§=rú¸Hhť´ď´ćé‘3G{qŻd$Ńřˇśšĺü™äźT§TtW(éńăÁŻ]§źfÖö˘_M%.ëą^J0 ÝňŠôÄtˇą­’°ü˜’şƒ %ťąúŘZ$śëĆÁ´„]“Ü]HŘOŁ \‚ˇűtľk˜œŹ€WáM‰ęV­ËÂ[ßJTwëĹLXłäy6Ok˜ŘĚ0ŮŞYŠi뻆Íę [’ɸYqɘc÷…(Ë ž­ťţ|ôŹčD‡Ţe‡ž8ž4ö ŘڛŃ.3aźv dënޏ˛C“ÚŽq)‡“m{=ƒCóĘ>˛O ě({*PśćuĂUdËâw¤,š;‘%D—Ë1Ą˛ƒ]šęM1şL+ő)XŮąóÍcć(]U݈4IŮÂtÉŚ#đ $cç^ů“Ţ*oĚ5wI†ěšěÚşńĚĹšŔéşd~<’H”ějŽ66‡ŮzŞŠ1žÂŠLřtĐűnąˆ(V5#Âvä.°}˜6ô§Ŕ'D.%‹Š5Ů//Kü6cg}ę čĆLĂó,úv81a^”‹>ÓŢ>8pÝ;,‚mŇL]Ćię†S=ĽUÓ°ö=ˇOÉÜŽ_ÜϨňĺTf).Œćv`Ęö3;0Káţ,féšÍ•;’3ýŢH@ޓ‚ EP7> RU鐤ŠaŞrHˆ”ą2%4ĆČÜď’Gb%IĄ & ŠR€Qű†ĘJh“Â!AÝlü´5?í‘ŰǤHlünkžÉ9J ‹­m 2FÝUL’ť˘ť:— #BÄďi™ľ¤ŕHÖŁb˝”4„áSÍŹkŰ*Y‘(Šy'V’%ie0IĐvzœ¤€äî”ôTÁƒKđvbGDK",v#\ŇÜwĹZQń’ŕ݈€I+/㌘äÝ<2Š*{ZůOč ˆöCŽ ωâžÇć˛ań”ĎqĺŠN!–,e^ˇĄhҗcÄÚÍI—ÉţAř™0†Žuw‰ř@áOčÂܑő%Űnt"ŘŐÓzÇD č\ĐŐ%‰\ˆÓ#ćŠ.Ääb *Y†Ĺń”°ĄxĹłĹنĹÁŠţ”9ś>7^N†ůę::_ýžů’4<.8aođBF+ŇNHŸ˙š -šËŁÔb‡¤Nx |BxÁś{tař‚1N‹o55,Ÿ3;xŽ“[ƘéCĆŕU–Ş<~؎KǏ¨Yk]ßS9Ô'zžÇ‘/Ď+ÂűIŮNý‰vŮ|^˙ú¨/՞ä^C?Ĺť.É s]Óö$ßúmŇĆťÖÇ~Ó=ëc3ľĚąŹ ¨_jlkîVŚI^u]uޏýŔ=čzŒŹ€ô.ÉŁŽkfă&MÁ¸IgœŢ%yÓ鸝Ś<ł’äI×Mmóž}×á<Ë[Ďý}pB˜ďäD7–äCwŽˆ°)čJć{ŚIţóľţoŞ#,0ş ĺZä:÷?ŕ9×-§;Îý‚şßoţđ‚˙Řť™Đ.sd­óąŐěă0ׯFřËĂďĺt—űöCgyËGxů3;ˢ}ĺŸňŢô0ŽíŮžvчŁŒŰ”Î•ÜšÖތ~!˝ń]\vyԇYœviZŒÝéQąŮӝţt§?ÝéOwúŮWŚ5Śôń[ŽU¤S~lš’Y×Z˙ńî Ůäę-†]ĘŰrůDk•ŁŐ­ľÎ’ÎB8LŽXߖeȌa^†šŁÜ^¨@?9lĐ T̡'é[֑c ŘFä`L˝H‹áÜ@`Ŕ6YsĄ‘˛=€Ńéݓać;öC˛ĎwĹ^´“qa`ÚČÝ+˜”Ař˝ů6_ÇÚů¤S÷ŮÝ+]噵SA;CŐ°œËÖW"ř1ŒWż ¨pH—o^Ű*J"ÍÉČÓĚÉr!Tc6éR_<Ň$˝QŁÚ'@<ĂŠë“şśŸŔšísŽ4/ç›×j`óꃖňĽˆŒĐŒ<Ľ×Ŕ-Žu•çAŃu8‘<  ţíÎWźÍĘü°îH^Kq×gÓ ö™ľo75ˇfsç¤ĆšĆ%Yźá¤Ř’ÄM¸l(šČň<Ťr™_My ӂ[p  rŽ’léĆĚSÚł­ĐúŽM&8m9ľž2’Ľýb÷ȡ8ĐťÉBn8ŸHžaâˇĹ°Áˇp†ˆBˆŸ”ok~Lšňa#Ay"d˜%ŽóÝ´í]<ď.˜CÚqC…ż Tk9A”×!܂•2Š[;qqăg‘†XˇŢ=ŽnýZEÄV˜G†ťąÉ,âťâSB}ß{ęóÍđŔO(żť•ÇĺGlĺZĚu@eœHN­đ†çPÜ â—%Câ†•Ż ƒÝń˘ÝřNdÜ9şš$Ƃ"žföˇ;°ŔĄ7Ö&Să­žsŠ’|fĄŃzzqBxς5đÍ.xˆÂěó*hɐůŚ´[!!řźÉ#„ÖsIfÝz佲 D˙…M3ŢQĎĂČ?a/‰;bä"V…™ŮĹ.݊ ź×&/-ć›Ă’m…ˆ Ý.˛RúÖ/gáę–o?× l“űšNÓąŹŠĘsböš*ÄrßZ|'›ĘT#FâˆÜ&T8k} šÎŠš:g0`Kxe˛íƒ×É]Łž\ŹX¤ SœuM]™ńP6Ÿ÷>SSMçĺ;C‡fžĎ$ÉďY÷ŢgŇ´=é>ÓmŇĆßgjÚ*1‘¤ŽĽŞČU‡ą‚zU ŠZ~݇$ÝgŇŃűLM3ňëKzŒŹ€ô.é>“Ž™›4ă&qz—tŸ‰ŽŰiĘÓ1+I÷™tSŰŽ54͐š+î„z"—ß„ëB˜ďtŸÉLXŇ}&—ማ‚~d÷hAŇ}ŚľţoŞ#,0ş ç÷ąhAŇ}Śp˙÷™tËé÷™ü‚ş˙>ÓĂ ţc ěfBGÜgBÖşqŸŠŃx˝¨űLúՈűLá÷rŢgňí‡ÎşĎT­?şĺ>“ úJ0ögݗľ´Ě徎$úĐ5œaě9‘ÜIҗšĺ×7‘ęntŐ忉¤r•ˆĄç2ŕ¸ołšDZlŞ…pű3KížÁՅévă—˘ř0+•ç Žç Žç Žç ŽSopM“ŤĆ˜?@˙štÇ&źÂ Ěú™'çeă1xg˛Ţdć…FôRtFĆKĎ$fžŒSˇźů|—qDË—qđ~yoăZ"˜ěěˇ_­ŠŐą¸Jp 휲{怘ŁŐ‘Ç":ŠŽĹhŁxĆÁЉo–€Yü]çÎé íÓŰ_kű+jŸŃjŸvłXCgôœNٓ—*H€œÓÓŽKM󴎸¨mƒî\Ę?Š&˙YMF5ö,*ŽÚů ;—ňaQ4ů楯™P|6čŽĺéφ˘™wZnˆîÉ{)K \ž}0řđ}Œ;7Đ9Wř‰zя텙fӞĹ4RŤ€Xšw­}éÎ!ÁźÜ+ î-ëÚëĎÝ;›M‰­ő-hÍőŠl7MžęĹ ƒĐ;ś`Ç˙řëËOׯ×˙\ż^–ó ŞM•?üđůŸż^´MhţíoןžüʊţyýöÇŻĹ_đŁz lOó(÷\š˜“”oKý–¨ożýq§çúí÷ożýňďëËűżţřýŰ\ůß~ÇŞľáIďrŤŽ˛Lƒn9mş2LV\žüüĺ›ă2Ÿ„Z~¤Őxc3Ô×xŐöşkţs×M˝;}1,bgآ‚TîJ1đţŐj\}čäwbtCšurü°żü×ÚţŠ1ăŞďdËKKgFˆç~ĂÄĂůŹcşRç×g€ô™ ‚ŚHďiÚ˙#_ƒź”Y_XBËZԚ5jŠmŞţ2ĽŽšiëęĂţëéýŚU M[ͨ"ŘVUy ćÇĄ˝˝^ÝţÔŐŁi^šIs7ߍÇyŁoĘş5Í+ŘÔ|,oÇÓűxń;*:ŸäÎß-îâŔůÉnˇČŽĎŽëňV!ë;Á)üŐóWa›§bžżĘˇ:z/ĐŽîJ˝v'{­7üHDň@+‘č3yń˜™ŃŚŇŒƒpežš4ł:ż) ÂhŐęŕô t–ř+żłŹGF"9vŒĹČN—›śĺi?dN×_ąq´ˆ7xĂD˜JóY™Ćśs‰îXC6%†„ťAÝŐËî =ĂAŁRĘ!ćÜëSUŁ }çݟrÚĎ{jnž;ď•<ľbdťBĺ̀g1Ú{‡ Č{Ň%ŞęĆߢޝ:,őŐ|Öř=*(Ąw7ň›TŹ$é*ÔDďRÍkůe**/!}LşNuóń“ÖĚřIÜ>&]Šbăw[óőHÎQŇľ*hmŰőŠů3Í!÷+rWš"ď´7BG¸ˆßénŐ2kI—Ť|ŹGÄz)Šůý*V’tÁjuŰ*Y‘(ŠK1R’tËjekVĐvú=Ť€äîżhőTÁƒKđvbGÜś",v㺕’ÍŘűVđnąŤ•s޸ňnžÎşrUŐSůçžs%)nĂ˝tUŐ}ú­+ىc3ޞĐę ;ď eÁ§Łƒˆ÷D čöŤXs—ęZałß)=‰źT¤ČTőX?o=o=o=ozŤ¨ŤÔśËQdËâwĐľ"‘ăa:yŽ gŒë÷Š`UÚtŻČ´RŸsąhňÍcć›EUÝö']-’MďMôĂ÷4}pOă‰ÚśăŇÜëů=w=ť96!­+öŸîRŻîŢČĄD_CŞ–ŃVx ´Ő–i]zӞrilĎ´žšˇŠŞ+´oýo ÉĎ/N“ŚŔ xđėY Bwˆß^†ż´ŔŰ.Anr`,hźăŇ,<$g‘7`Dz b—Ń'áu€xş3ŢߘJ:‰xKsŸ |&˝W‡Pa^­ží–Ńú>AnÉŘ<=g/ź€GH'V†w÷QAWjyBqKŚŐ´rą%ë]›žÎÚrÄŐ?ź}őŒ[\Ă;¸"aƒx/˜ą4B,¸‘Eˆ˘g×8UŇóđ/Ţüü.×ŕcę!-@ƒŒsÚÖŽü! ĺ-7‹U#íNvčQٕNűmćô•΃NL¨žŰzŃŕ8‘™@üZąOŰ6Í ”™çO㞟>1ĆĺNť¤eh‚,öÝfr;áCť ąv™—×Ă>nŇžŽÎ„MýÄ ů™ŃF˛ůź`ŁŠęÓ°Fbč§@$ů=›Í˝H#Mۓ€FˇI3šFĽ RaFS7¨ÁXAuŇO}Ĺ16´ b¤+˘Łiě9œH‘Ţ%Á‹tÍlܤ)7éŒÓť$hˇÓ”§3bV’`EşŠmP‚iěę#yë‰\‰ B˜ď„(2–(rŽˆ°)h{ÄĄI`˘ľţoŞ#,0ş áh(Z„# ÷?#Ň-§Łˆü‚şDôđ‚˙Řť™Đř!d­đĄŠW,…ŇŻF€‡ÂďĺÄůöCgA‡&ľÝţ3#‡˘Cú˝ĚŔĄIÝJô㆓ 1ŸYĂ3š%ǧƒdŹĄĐ÷ů] Ƹ#:GÝĆş‘ś<ĹkŹĎąb„Çş‹ţëŰË×/oź/X&ŘuîNOu‹ČŕQľD˘S_ Ź ËĽ˛Ÿ%!–é7cÓ]Q“ýĎř)î8ĘTć(Ië`m¤=o6źĂkMćəˇMhWŇ mńŽ(řý ʼnńeL &2&űôSăeOtç ĎPԇn@MĽW_ńÝf/lňĎž`BiÎ5[uOgŤß7[’₊­˙¤űĘő°uÖ{—ÇĎŃ×.=2ŽŰĂČĺ†_™¸çGXY}Z‰řšpŠĎgšË“(3rŰ981Ë_[áŔÇpP‡\”ßÄÓCה ĎŎźˇË áißBňř„¤Šˆ dÉ'Až›˝gc- KÂÎ9ÁĺŕîÔÚç‰K× ąžmŠSÚ/e06Œ‘EhŤRĺ;3žQjűqěW<‚<~+Á7ř¸.6坈lJTŕĆ` |đĆڐžúW>ń˜\(~Áś"Őx0Q:ă’Sű&‡ß9śFݏ|l úMî‡B˛~˜<(¤žœqŢ@!éÇ6.Ս¨‰<…4(+ƒáŠH“şŹˇě;—Á¤…+Œ‹/CńƆańD →•yăž°Ŕ[`.$. ^Ä÷ö*_đęÁ=B‘ł¨ľ/@^r WŠĎÓyAouţz>’śł]ÇÓ7.Q<˝8‡č?‡äA„0ÁhŤĹt' [ÁůŸ4ś÷<†ŒĄłÉ´›UH_žłĘV]:Ĺ_–3˛Ĺ"ÉDőĐ[)ťn^ƒ+¸”]uC–z>t°|aN ˝B…Ö_ŒŁŇĺ ¸?¸áhwِĄĚńx"ž\¨Ď ¨âÝĘf(B’„qa8 Î§Ś¤błxF‘•ŚąM¨&”šĆŤ(W×9é‰-âń?ţúňÓőëő?ׯ—ĺđŁjSĽĹ?ücţ篗JĽ|žűŰő§/?Ť˘^żýńkńü¨Ţ3(CËĚĘ=S.ś“f–ő?š]žýöÇuć’ëˇßżýöËżŻ/ď˙úă÷osĺ˙ůŤÖV–ŞŤ•Ăş˛Â†nm§1ŇY\žüüĺ›ă0Ÿ„Z~¤Őx<Ć aţ]ąÝG™őŐnŰŞ—J(ďÇŞéÇ2h6hvŰŰ+Âą˝K&gş÷ĽÔş–ĹÖŔčI(ă˘MpçFsCt/Ę<čOĄa08Sľ¨_¨%‚íáĐWqv†—=kŒƒiĹ _,ůĎś­ůĚ]§&NN_ ě?v†…nX* áEŔ)\RŽKă˜Eěŕ5ëdýü¸°ó+ţZŰ_ő™°Y~úć°ź´töp„äTfď ™óűgëԕr¸8ż>ë…o—…tΆżzOŘţůäĽĚúÂZÖ˘ÖŹQKm3ɧąÔ57mđúŰ=˝ß´Şáţş{•ŕzßQĄ ~ěúŰëĺŃíăą%ź'Á9ŇťźúbZÚ­HYšÎUŢ(|ŻO[q„§6’-wČénÝĎÝćmd°V  Š•@ŠŁđä&ěĹ5CŒzĎ琟:&_-ßö‰lľ hSŘƖ…kÁ ľxbíŚL=1é಍řX17üŕĺm7 ŻČ7iő°–Ÿ1î-÷ţh7ăW–eZäŘChKĽ;N”˘xŸN *ďâ­CÇJ/ô‹łfísČßs^•Q‰Ě+ĆŘF ŒD•|ÄäŠSĽç +¸Ţŕ„Gl'77ł“3Oä8°ƒ…ow%.{ HŒgQ”äś“V[N&Ç\jxŹßŘE–ěšáT*_„líşôĎô4ßd4LŞ4ä ď^€š:‰5L Śˆ%›Ď‹Ă 8ä–:Œ03 K’_,ć) ,Mۓ0XˇIÁľË:5ŒO:Ź (~a˜j?˘Ič+]_*ř2EZé1ŇÚť$䕮™Ž›6ĽÇM;ăô. uEÇí4ĺ錘•$ĕnjĘbŹ4z0d‘ˇžűc5„0ß le&, kĺ0aS@SŹëÜČj ‘Zë˙Ś:ÂŁ ZŁIŤp˙+Ýr:ŔĘ/¨űńU/ř-°› ­BÖşŹt,°(`•~5W~/'ŹĘˇ: U5ôuMšm6ßń‹Ô<˝=™âiU`nŞÇşVĹüƒ@÷É:.J˙ŕBť5űuܒKěň™ýXƒŇ'Gó}ĐÔđ8h§żĺśńN`˘ôŁ^H¨ŁQzuťN8Öě¤N§bí ęÄEéí:5ˇÝź?Łô>Łô>Łô>ŁôžĽˇëçĹQcvíűp°cSšCŒ€ÁFtށFćľčěÔz&ńXě}{ůúĺ÷ËäĆĽlYš2 m„N†Pœ°Ë(`E P őe=ä5ŻşӁűé7^÷!ނű{°>pźŚŒ81 ™Őţm茚ěǒeśö8ÚŃeľ7öeŚô{ׁHŔytš8ôF\ä\‡ŘËâ×úĽ!Řdô*œœL—kťžMc$˝ńůvÜ76Eś•(ŰBg˝Ŕ ô uâ•U…Sëe‹Ű¸^˜ôĽIâĂPyľTŽšlj:—ˆ´˛p\鎂čA&ZŽdÄĆIöĹ&A ^™BHĎäV#źŽŸóÁŁş‘ Q´Ľ]ć"‰ř•Iˆ€łx1śŞˆŘŻěÄ14´šˇ> ÉϤLxwYQb)tÉhcéz.KžË:kzÉíiŠpP\)32vŐťśőë#bŸÂ9ĚD¸‚ُ{ôrsėt’V\lŔřŇJŕBś]˘CŰ=l˜zšŽÜťž°—Ű:›=KHöH/vˆ5ď!.ţxfŞÝżŠĽgĹ­_ őō>ysE ;C)ä–ť†Wœ*ÎmĘÍąoňs"[vRĆ`~0Ľľ;°ŒŤB[łŁ_îčlÍĐzšż:rÇ[yMWŽŹŽ°š!8WlƒŽ\}qŔ&ą;!7Łű ×N ˝żér6tÖ—zĘď!QÁőí`wđjŏ^-@çéŽŃDfS Ě–‘)›Ď‹ČlŞŽ> ‘)†#̌ȔäçËg"SÓö$DćmŇĆ#2uÍdDfSŹĽŇ Ť–Îźœ82‘$!2uE‘ŮĚZ“0őYé]"“!…q“ŚL˛uěŒÓť$D&ˇÓ”§3bV’™şŠ­Š×›ú˜Ôë9ë‰\e^B˜ď„Č4–„ČtŽˆ0Tuύ´ ‘šÖ˙Mu„FTQJ ’™áţ™şĺtDŚ_P÷#2^đ[`7:‘‰Źu‘ŮTŠĽ˘™úŐDfř˝œˆLß~č,Df­r“D„šű,ÍĄqĆd𗛁ëô{™—u×;ńC>eŘ9MĆ3ÂÎ †á6Xś=ę\­3çtNŽđ´˜sÓ,,u]Ż$~úo<Śę,ĘDÍM5,›k6żřgsâ䛑Ąe3ňž#ËŘŕÄÉ7]Éćá{đŮ^Ĺ9qî˜ÍV%ÄzfłUěúĚfűĚfűĚfťj“xfłýôsčÍf+ΗĎlśß{6ŰŇY˛îœÍśęűÝů\hżŻć=ä3ě3+l0fŹČ 1-ÇeŻ@RŻĄż‘g˛đE&Heg•TŤúŮ %zîG OđvÍfŽÄ ¨ň.Ü*GĘ>KMŸqŽŞŚuĚĽjgçMÔ<ٞ0={•m„őlŤmCÁ°Šňž”p—đŤƒş7öY"fŤˇ¨´żP„á'ő‰.ó5§Ş§íz‹Ů,˝1a‚°°Ţ^EĽć{ăRÂ×?ŻWÄřMf#ŰÚ{„u^zÔ}ůp '÷S3Nlď7ĚÖ9§˜›Ńpg+ďwťv%˗¸ëĽŮŇl +đވˇáČqŢe‰J?ĽńSD¤Ÿź1 Pá}Dô%Ú­§Řńȝ:çpbo‡0AŸ_ďžAá ꂐűŠđ 'žq&+ś9!ˇ9=!ó#NZ;O–ä\ nËrëőŒá„a7„ąV4CPŻFxwqźű̧]Ô¨Şąů˙ˇw5K’ŰFúŽ§č‹Ú%@ }óFČ{ZGx_ 5j9ƞĐ:¤‘ŸI€Dţ0Áˆ*°{\vkUŸL™ž/óJŚĆŽýśTšyuWƒ>Œą1Yc§Á‚œekń^D×Ȑn>_Céĺ źš°Ą”ë)c#”$ŕĘ ”łAJŞHĄ&ĚژÖQÚF*)Á}Ź"n„şÉřqkk&wÔŁ}ŤČdüűÖ¤qU8Bk…™ËŐ4ÝÉÝş˘Lżăäűkč]âbqlZŤ˘qS/ë­d¤LRREĺ8DY%ëÇbr#*Šâs "Ačm×3:+÷<Ľă#lď|— ;ƒ×ŚŘ bÇź6].ł#|7ƒÚqđŖÜŃyşŠÜĄ”ąßťƒ ž˝nĐ;üPcz‡RË__X›w҉†ťĘ×8„ Y!”ś‡>y˛‡˙uůpM'Bi+ľ,2­MóH •Ě`ÚádÖώĎ3šö3šö3šö3šö•Ń´ő0 ŮţRőžüž ŹB~ß8 c<&řůݸ­­,銀ڝ¤Ç #jŤnŸ ?ö‚œšŮŽQ`_5÷ĐrŹâˇCđ#Ÿ~Ä(…Ę4”Ţö^ř}äÓLľkŚGe-?-ž›“#“ íŮ°ŻąLçtň¤ Á!ń¸Ąthčă¨ď€{`łŠ:y"CTg6 Œ˛Ýó‘%€]m [!ŔzĚV O§)mhŠ a)xx| &ÄÜč8 ęDŠŞwôő›C/cˆ{řę Œî͌A÷NA´Ą†i|qšfjÉC€¤$Á!Y !(“ŔnçŹŔŮe™†UśKϢ7ÜQÇY¤Ut ¨o6ńMčśÁŽ„}L!¸‚]?cČďśńĽďȂ>灃“A\‚hĄ€×Ā.ţ™T…nséWĺĘ ¨¤öuč=ß7ďg7a7oŠM:BF ŚVn_YpS_ ăFŁ4Q} Ęă9&Ľ9Ţ.&zÚîőšęçlŁB<žśCXĂĐ˜đ€Âĺ§` [žw°CiŠ’YŢÉĽž:]z6Kóö‘€n—bw°ťă“ˆügGě!jöí?ÜGP}r‡bž˜¸b…eË/R„7uA€HţŘ{Ă"AŻŇY@ÚejŻ^JőÚk9´PŘpŮNÁd u@3ü>Łéě r›v‰ašęłń/âÂK*’Ÿö ČiۂG;•vÄŻqrŰşăփ/ß"Ă!řŒřK՗-’fzľŁMňÎŕ&ÍË*‘闏°}ƒ|“‹Bb'QRÚî ŐNŒ–xÄQ—1ŹvâԘ‡Á›oKðzč.ca°Ą‡6&apńÓ}˛Šƒáe{ăśhóÖ̲¨&`X”śĎ}†/[5Qö.¨"_řŠ0÷ÂC‰~Œ¤őފxák&ăFM…qŁÎězWEşŔăŢ5%t†iĽŠpá›*Y[Ów÷ŔXˇ­'Ó\V@ľŮb~×bUXŐb?áĐZBQŔU4‹ŁţՑ^0ž@Qž.¨bX¤űŸ Xř–ëůňB=OŻx÷ ˙}/ŘbAg0+`jÝ VX˝LŠ,^…˙j­"ý˝–Ź ÉşŠT1ŒÓ(zü˜SÁĆöď”R1Řa—Ç´5Ł‚őa€7r:~ĺçMý=řs’… Ꙁníś Y V/ÚśçXjʤX˜i™Œş2,ž ‹'Ăâɰ¸”a1OĽý6ś™Â;,XmŇhšĽßżqd8"ŘÖĄt­‘éc'(7™~CşI‚‹›ن—lÎĎlĂĎlĂĎlĂţĎŕ‚é™mx˙†÷Ě6üáu(fNҞنąž™lĂZő),ꣲ ű$‘!ÝŻ3íł ť%ŽôuÍëqž2Ąy]Ú|vŃľVłcž%–ÖťćęĆcŁ_t7ŸvűŮď2œŸ÷Żřâ„Í÷Čô|çlŃWˆ<ďŹW•IŞw2Ń:“oż-…qn~ŻË$ŏ=öv™¤¸ŘI †ĹÄ{U&ŠŰŇ-Č$ŐOK„ŢęLR˝uˆä´¤lđ%$Kď:Ęé#%u™¤|M$“T? ”˝†JKPë2IůşéřQkëřQö}ŹË$…ÇżoMę×Q]&)ßZaúKšGú˜ĆeŢTž<[‡ŽĐ%ţ¨LRŤÖę2I S-뭤ׄ!HJę2I ˘Ź’ƒőJM“”Ôe’J"•Iʡ}‡LRňĘ­Č$őś‚wž‚Ë…“I ŚŘ­LR˝[ŚV^&)˙ݜLRé/6Í$%9O—e’ęi„ń$ëQŠc!•9˛…ĆiN†!€ŽJńcžäŹv{ „+ň ޤCcޤę…@âÍÓNńNřů߆áq‘CɆŰMű‚/}! ՙ´S˝ŇöEˇ§Ą˜Šß $7íTxžEđ$E>I‘ORä“y%)RšIŘČâŚ~V$¤2äÓVi§”0Ć$-,U†mĹi§B+łAş€9N’O¸)UWßz˘í—Š÷tÓÓžéL€#?Đóý¸yWîtd |Şâć ¨ČĹY6ŕ{=śžńźƒĹ5z)Őv^[I’Ěž1XBŁoƇ \˜ä …ŢŚ3"”m6!eű „¨¤ŔFČćD9ĹÂŔ˝ow´™Ž‚ŋ֤SĆ81č6äG"e‰1É^˘ °Ń50KM şĎ~C )‡5t̂XÁh @̤ Ľ8H•Aú‚ŸBË!HKdrLĽ?V˘¨{şţř8֜’•Č@í6Ěh=‘ç|đŔ•0uMŢ!ę{9ْ§Â¸%ôVlÎŤ#ӈŐܜ3´f'˘ľ•äqy!‡^]˛hPăBN F' ĽtťÄمéUÚ*łđŒ3”NiĐPņ8;âV׎@Śşi’}/ŕŁފŠĂeÄTđĚŠ…ą"ořOéü`dĆ1>kŽŸ% qDł˘4TŹŁó tďE°Űů‘˝ŚT ]1Ş˙íIžfF ’2çf€ fÂcÚž’”D˛ap|ě34Tö@źmNœ*äs˛M×PÁ § ž!PXŢHŮ1'oŻLڀśăŐt˜2™Ç*™ĽĂ %Čß§ŻFMľŤŠ§N™!¨łÉBä žTRi+ŔXóó1,:oĐfëKŽě˘ƒ!˘k¤ =çÉ0Š1íéÎ5Ôi×˧/äůáAÄX‡xäĂÎ7žěV6ňü‹t-AđůˆX8ćDЃ׹ÚwVĂ|˓lgŃ=“ŕÁsŢp´Ÿ`‘ôiĐŻ´ŁŢ‘֝^Io†ËœíˆŒš DÁc{n€qsrľÔđ0ä_”ŹüÚmLÜ$K>Î` w֒ĄWŽ6…ő…`ěV%śœp4ŰŘ×'wrş1 ËÎBů\qžžzâą őŐÇššô^Ůd§ šŞîˇ—&ÝÚ“‚_•ăý°¤đôĐ×úvręˆËŃ%sĆŽŻÂę˘Ű@¸l—s$†~MÄÖ0/î$4żÉf`‡:!`DďČ=äŁk7úBĂS{Ɖ*š6áuG~j.›Ś˝,›,ˇŒšˇěÍô•ćHäĹňI">îHČQ`šüěŐnśöô%péðôf€~AŇQę˝Ó¸éĹÚ%27MœŮ˜AƛoK s“ł—ńÇŘĐĂÓǸřéź­byŮ^Dť-Ú|îŘ¨Śąž:ćĆ ŃGF 0ńb>ąQŢ.¨˘ůŠ0klTŽRÄüqî]eĚ׌Ǎ›ňăƝŮőފ.†Ç˝kJč ÓJUĚ7UFŐ`ďÁi[OŚů­ ™°Ĺü –Řް*’ŘnÂá%ź !Wá‚*‚ŘQ˙‹ęH/_`(Ă TqĂŇýOPĂ|ËőĚ0yĄž'†˝ű…˙žlą 38a0ľnPÂÜä§S#Ě5ƒ–ţ^K>˜ä]EsVŃă˙waƒ1řnćÁ裺}emáÝ2ć Wœ‰dŽ ţmÍ#c}0p§¸tÄ>ŕ•|@'(ąěű;Ąr™[ iŐ5g‘{qä‘ČĚ´œ¨†yÂ=9dOٓCöä]Ę![ü4žm&óî2o}{°M(dnŘ1É ƒ•1ČB#Ć\C ”Ř˜?ćmž}Œľ|’=fŠ+c“Ž `s dúĎĹÔ0§f‡Y›öךŢůPűőŽB#ÓPťđ h Š Ă¨Çg˙ č&÷ívčw#šąKŮřŤÚ~ ]j¤ťTQ^Íľ3łNŐt>ÇóIIŒĆíuz)Ůώ$GźW{ Eç2ŔB0(7daˆY’P,ž šúi›°š|ˆâć4h!eé“qjńĎ$˘Lv_š4­íąúäĚh[_Ӊ6Böłg@b}˝ôdéľÎxNŚ„ ‹÷¤Źt$Łh_čűt˜r–VŸ‚˜Âdn§Ă~":”pţ%šŃ5#ĺ!ńHóDÂ3QP+‡ß~üĐ$ű‚ňS~fEžäą_€]k~ŸU‰•c7[żxb•ÇAÄńPD ’Ş€÷ŮŇ łoˆg“Ô)ű55 x˘I´ šŠ`˜ąd€Öž„ā$?ŠŮŢo$(UĹR¸Áŕ’üdä1ä*­˘śÓŚu7 [jĂâźÂ o„z”(Ý[äAJŽ#çŰEĘ)jœŇžĐĂËÓޏ?¨ioűâpřÇüď¤ ĘÍ2-Íďyz¸qó?üä3ţ_ŸśOq֗Ř{a͉֜1ŢR+ŇąÝ÷'ú= š˝„¨j&ęɤvQ QdH ĽáG"ěSץg”ÜK%8Ŕ4¤˙gp~1q§ HhŞaÎӆ­éuž˘i§MGœ"ó3qˇR!5čľ!Ćż5FżwÓŽyӘŘ÷ÄXŮčűħÄÄtslńi.şŞçœ˘X%ŒRNC?íú şšź ŽčQŚ$ŻŐ•y=MŻŇ ϛo ×!탞 φFŘ ĎĹ~m5@ŢËö"€ümŃćä{5Ůz€ź'„U(ŔŘS=i ÇUy_Č÷ĘR<ź#.Ŕ˝ŤČűšń¸qS~ܸ3ťŢUäń¸wM aZŠČűŚĘp˛˝ňyŞq˛mëÉ4Äx[ś˜_VßM8ź„×3€9.¨Čőż¨Žô‚ń†üqA@>Ý˙@ޡ\—ęy€üť_řď{Á : Së@^{°@@Ţ5 Ÿţ^K€źäŐäIňÎvó‰I[KhŐçáϧS t”Ő㾍]o;tť>ôş ŕâkđä‹Öś]š˝Z‚ă~&őEçżľ†”/ÁéčŢfQňĽPş(‚[DČ÷Ą-@žĆ Áđ‡ôţ=ĚŇŤ\T‚¨Uôďę(†OŃ5t°ł/ڜ?ţŸ/Ń賈ďŠ{Ň0×uv9˝ ĆçOłâ‘5Ă# ľhĆÔ-Ѝ—‚ŐכpŸ^bä­Îu´ŕŹ7 ­m‡‚% $…wŽKŽčša9| Ž"ź™?=ýé×ĎŻ_ţăżżž~ůü)4ËKđýĚĹҗ_Gî˘Zţ\)Ľ9YÜě˝ĹľěqžâĘ_=E_Íš– ‘lhť"˜œŞݒÚb<ŘÎĐŞ2ťV ĺ”pô%MŔutřôG:ł’ 6YA@ma;I‚"“ĐŔ–rd}—‡J‚ÉBză˜´IRĹĂ|Ă.Ic"<žöÂ_Łý’ąÇŽóčÜs¨ž‚faOŠ˜Tč°DŕI퐥,ný5ŽQŁýŠővZ"\>| Zˇ€YĆî]-ずEÉ}}㟤‡ƒťíűĂő†l&2Żř)u 9Ÿ•ü^ůÖ?ŽŤä°_â§˙œ-ʗˇ˝}yŮ,Ĺ2đĽôť?üá/óţ8űó˙ćßţëíoŸYŠţúöő÷~÷Ÿđ§žĹN΂]NAÝ'ĽŸ5şüŹć×_›Ĺţöuśr˙÷Ůŕýý÷߾Ε˙đËOPľˇ•Ę_U *N8řŻĂţîĺó/ŸżîÎë_†ZžÇŐܔýÁJÖőŠ[Ú5fůR×-IGUoÇŰď Gu}űŔ ÍxÓ¨gýůmßdťÝé2âĂţ ĎŕŇޛ—xŻÎâ™sÔ<.Př> í6jš5%~˜ż˜D†§M‰&@Ŕc—˝G˝Ý ‹â¸úr‚Aäj˜Ą ÜVAF\j”Ÿ8BŸ‡Ç?˝üDčĎńWGŐńWo”űí_߂ťƒľŃcC]?ý¨c†Žô+EÖ]­(ˇÍěđŠţáŘHŻ˙•$slXŇfí°ÁŘĐC!ŞóČE0"<ţ10 ľüoŃÃY*3o5]íYŸNPąĘ„‘ƒ:ţj˘ tŁnȗęČţT˘Ł­‡ 2Őűm}›ŽOkŠ…‚złLŃ~÷ŤE7%RÝŞ+ˆ|â'šý˜š[Pm÷`×ůŢçď<ÇŤ…v*˛ĽkoěâŇ4ˇĽĂ(L˛ćśt -žSź_Á U IQć6n Ě2v˜Öw0ç]'ĚyČ-îT™ńŒSśo^Isq²{â2ozŤlgó ŔMÂÚ ˇŰ"—¨ř™é}ýüĺí×őÁéˇ?†çŚţçĎßý?ă)pÖpkpgcounter-3.50/tests/runcolors.py0000755000175000017500000001361210671326561017105 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: runcolors.py 282 2007-09-10 20:47:40Z jerome $ # # """This document was created with the help of the ReportLab ToolKit (tm) available as Free Software from : http://www.reportlab.org It contains 10 pages, including this one. Each page after this one is entirely filled with 100% of a particular color, as described below : Page 1 ====> This notice Page 2 ====> Red Page 3 ====> Green Page 4 ====> Blue Page 5 ====> Cyan Page 6 ====> Magenta Page 7 ====> Yellow Page 8 ====> Black Page 9 ====> White Page 10 ====> The expected results. This document helps to ensure that the computation of ink coverage made by pkpgcounter works as expected. To check by yourself : $ for cspace in BW RGB CMY CMYK ; do echo "Colorspace : $cspace" ; pkpgcounter --colorspace $cspace colors.pdf ; echo ; done Please report any problem to : alet@librelogiciel.com """ lastpage = """For each colorspace, the results for the last page will differ a bit from what is below. The important values are the one for pages 2 to 9 included. Colorspace : BW B : 2.355336% B : 70.196078% B : 41.568627% B : 88.627451% B : 30.196078% B : 58.823529% B : 11.764706% B : 100.000000% B : 0.000000% B : 3.500669% Colorspace : RGB R : 97.644664% G : 97.644664% B : 97.644664% R : 100.000000% G : 0.000000% B : 0.000000% R : 0.000000% G : 100.000000% B : 0.000000% R : 0.000000% G : 0.000000% B : 100.000000% R : 0.000000% G : 100.000000% B : 100.000000% R : 100.000000% G : 0.000000% B : 100.000000% R : 100.000000% G : 100.000000% B : 0.000000% R : 0.000000% G : 0.000000% B : 0.000000% R : 100.000000% G : 100.000000% B : 100.000000% R : 96.499331% G : 96.499331% B : 96.499331% Colorspace : CMY C : 2.355336% M : 2.355336% Y : 2.355336% C : 0.000000% M : 100.000000% Y : 100.000000% C : 100.000000% M : 0.000000% Y : 100.000000% C : 100.000000% M : 100.000000% Y : 0.000000% C : 100.000000% M : 0.000000% Y : 0.000000% C : 0.000000% M : 100.000000% Y : 0.000000% C : 0.000000% M : 0.000000% Y : 100.000000% C : 100.000000% M : 100.000000% Y : 100.000000% C : 0.000000% M : 0.000000% Y : 0.000000% C : 3.500669% M : 3.500669% Y : 3.500669% Colorspace : CMYK C : 0.000000% M : 0.000000% Y : 0.000000% K : 2.355336% C : 0.000000% M : 100.000000% Y : 100.000000% K : 0.000000% C : 100.000000% M : 0.000000% Y : 100.000000% K : 0.000000% C : 100.000000% M : 100.000000% Y : 0.000000% K : 0.000000% C : 100.000000% M : 0.000000% Y : 0.000000% K : 0.000000% C : 0.000000% M : 100.000000% Y : 0.000000% K : 0.000000% C : 0.000000% M : 0.000000% Y : 100.000000% K : 0.000000% C : 0.000000% M : 0.000000% Y : 0.000000% K : 100.000000% C : 0.000000% M : 0.000000% Y : 0.000000% K : 0.000000% C : 0.000000% M : 0.000000% Y : 0.000000% K : 3.500669% """ import sys try : from reportlab.lib import colors from reportlab.lib import pagesizes from reportlab.lib.units import cm from reportlab.pdfgen import canvas except ImportError : sys.stderr.write("Please download and install ReportLab\n\tfrom http://www.reportlab.org\n") sys.exit(-1) if __name__ == "__main__" : canv = canvas.Canvas("colors.pdf", pagesize=pagesizes.A4) (width, height) = pagesizes.A4 xbase = 2*cm ybase = height - 2*cm # First we output the explanations on the first page. canv.setFont("Courier", 14) for line in __doc__.split("\n") : canv.drawString(xbase, ybase, line) ybase -= 18 canv.showPage() # Then we output each page for color in (colors.Color(1, 0, 0), # Red colors.Color(0, 1, 0), # Green colors.Color(0, 0, 1)) : # Blue canv.setStrokeColorRGB(*color.rgb()) canv.setFillColorRGB(*color.rgb()) canv.rect(0, 0, width, height, fill=1) canv.showPage() for color in (colors.CMYKColor(1, 0, 0, 0), # Cyan colors.CMYKColor(0, 1, 0, 0), # Magenta colors.CMYKColor(0, 0, 1, 0), # Yellow colors.CMYKColor(0, 0, 0, 1), # Black colors.CMYKColor(0, 0, 0, 0)) : # White canv.setStrokeColorCMYK(*color.cmyk()) canv.setFillColorCMYK(*color.cmyk()) canv.rect(0, 0, width, height, fill=1) canv.showPage() # Finally outputs the expected results. canv.setFont("Helvetica-Bold", 16) canv.drawCentredString(width/2.0, height-1.5*cm, "Expected Results :") ybase = height - 3*cm canv.setFont("Courier", 10) for line in lastpage.split("\n") : canv.drawString(xbase, ybase, line) ybase -= 14 canv.showPage() canv.save() pkpgcounter-3.50/tests/runtest.sh0000755000175000017500000000211710721275127016540 0ustar jeromejerome#! /bin/sh # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . echo "Analyzing colors..." if ! [ -f "colors.pdf" ] ; then python ./runcolors.py ; fi ; echo for cspace in BW RGB CMY CMYK GC ; do echo "Colorspace : $cspace" ; pkpgcounter --colorspace $cspace colors.pdf ; echo ; done echo "Generating testsuite..." gunzip This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ============================================================================= pkpgcounter BUGS : - All parsers need more testing, especially those which allow the number of copies to be specified as part of the data streams, as well as those which allow N-up. pkpgcounter-3.50/COPYING0000644000175000017500000010451310671324523014370 0ustar jeromejerome GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . pkpgcounter-3.50/CREDITS0000644000175000017500000000370710721520676014363 0ustar jeromejerome# $Id: CREDITS 331 2007-11-23 09:47:40Z jerome $ pkpgcounter : a generic Page Description Language parser (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ============================================================ The following people helped the pkpgcounter project : - Eduardo Gielamo Oliveira & Rodolfo Broco Manin : initial PCL parser. - Valcir C. Vargas : helped on PCL3GUI support. - Daniel Franklin : pkpgcounter's algorithm for the computation of ink coverage comes from Daniel's PrintBill project. - Aurélien Croc : reverse engineered Samsung QPDL and published a language specification. - Franck (?) : sent a path to improve the PostScript parser when the PS code generated several copies. - Yves Lavoie : reported a bug with Python 2.5 - Kumar Appaiah : put pkpgcounter in Debian. ============================================================== IF YOUR NAME DOESN'T APPEAR IN THE LISTS ABOVE, AND YOU THINK YOU DESERVE TO BE LISTED, JUST SEND ME AN EMAIL ASKING FOR BEING INCLUDED. I APOLOGIZE IN ADVANCE IF I'VE FORGOTTEN TO ADD YOUR NAME. ALSO, SOME PEOPLE MAY HAVE REFUSED TO BE LISTED HERE, THIS IS YOUR RIGHT TO DO SO TOO, JUST TELL ME. ============================================================== pkpgcounter-3.50/MANIFEST.in0000644000175000017500000000027110553521265015070 0ustar jeromejeromeinclude README FAQ COPYING BUGS TODO NEWS CREDITS MANIFEST.in clean.sh bin/pkpgcounter recursive-include man README *.sh *.1 recursive-include tests README *.ps.gz *.sh *.py colors.pdf pkpgcounter-3.50/NEWS0000644000175000017500000002141110726765337014044 0ustar jeromejerome# $Id: NEWS 369 2007-12-09 13:17:17Z jerome $ pkpgcounter : a generic Page Description Language parser (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ============================================================================= pkpgcounter News : * 3.50 : - Added support for Canon BJ/BJC documents in page counting mode. - Added support for Structured Fax documents in page counting mode. - Added support for ASCII PNM (Netpbm) documents in page counting mode. - Fixed a problem with the parsing of SPL1 (GDI) documents : all such documents should now be correctly parsed. - Improved the PCL3/4/5 parser. * 3.40 : - Fixed a major bug in the detection of OpenDocument (ISO/IEC DIS 26300) files. - Added support for page counting in Microsoft Word (c) (tm) (r) (etc...) documents. - Added support for ink accounting in Microsoft Word (c) (tm) (r) (etc...) and OpenDocument (ISO/IEC DIS 26300) documents. - Now automatically detects missing executable dependencies at runtime. * 3.30 : - Added support for all file formats supported by the Python Imaging Library. - Added a minimal parser for Hewlett-Packard LIDIL documents, as produced by the hpijs driver. - Improved general reliability. - Improved detection of PCL3/4/5 jobs. - Major code cleaning. * 3.20 : - Added a minimal parser for Brother HBP documents. - Added support for Canon ImageRunner commands to the PCLXL parser, much like it was already done for the PCL3/4/5 parser. * 3.10 : - Added a minimal parser for ESC/PAGES03 style documents. - Fixed another problem in the code handling the output of Canon's ImageRunner printer drivers. * 3.00 : - Fixed a problem in the code handling the output of Canon's ImageRunner printer drivers. - Licensing terms changed to GNU GPL v3.0 or higher. * 2.18 : - Fixed an incompatibility with Python v2.5 * 2.17 : - Fixed problems in the handling of PJL number of copies (COPIES= and QTY=) which caused the number of copies for each page to be squared. * 2.16 : - Fixed a problem in the PCL3/4/5 parser to accomodate line based report generators which expect the printer to skip to next page based on lines per page instead of sending a specific command. * 2.15 : - Fixed a regexp in the PDF parser which caused some files to be incorrectly accounted for. - Improved the detection of the number of copies in PostScript documents. * 2.14 : - Fixed a problem with some PS drivers which don't output %%Page: comments. * 2.13 : - Nowrecognizes the GC colorspace if you only want to differentiate grayscale pages from coloured pages. In this colorspace, the percents are always "G : 100.0 C : 0.0" or "G : 0.0 C : 100.0" respectively for a grayscale page and a coloured page. * 2.12 : - Fixed a problem with the PostScript parser. * 2.11 : - Improved overall robustness in ink accounting mode. * 2.10 : - Added a plain text parser, with support for both page counting and ink coverage. - Added a minimal SPL1 parser. - Fixed a problem in the PCLXL parser related to Kyocera printer drivers. * 2.00 : - The PCL3/4/5 parser was rewritten from scratch and is now table driven. - Improved the PostScript parser. * 1.85 : - Added support for Samsung QPDL (aka SPL2) file format in page counting mode, thanks to the work done by Aurélien Croc on reverse engineering the file format. * 1.85alpha : - Added test document and program to generate the test document to check the functionning of the ink coverage computation algorithm. * 1.84 : - Computation of ink coverage now works and is documented. The supported file formats are : PS, PDF, PCLXL, PCL3/4/5, DVI and TIFF. * 1.84alpha : - Added initial support for the computation of ink coverage. See python analyzer.py --help for details. The same command line options work for pkpgcounter, although it's not documented yet. * 1.83 : - Fixed a famously known 'brown paper bag' issue with file type autodetection. * 1.82 : - Fixed PCL3/4/5 parser to detect recent Xerox drivers' output. * 1.81 : - Improved the gs+Acrobat Reader fix done in 1.78. * 1.80 : - Added support for Zenographics ZjStream input format. * 1.79 : - Fixed a small problem in PostScript parser with dvips output. * 1.78 : - Launches gs less often when printing is done from Acrobat Reader. * 1.77 : - Fixed some problems with the code introduced in 1.76. - Improved PCLXL parser's speed by almost 10%. * 1.76 : - Improved the PCLXL parser wrt undocumented tags. - Preliminary support for Kyocera Prescribe commands. * 1.75 : - Added preliminary support for Canon ImageRunner's "LIPS" or "UFR" (I don't know which) Page Description Language. * 1.74 : - Fixed a problem in the retrieval of named media sizes in PCLXL. - Changed copyright years. * 1.73 : - Fixed duplex detection code in PCL3/4/5 parser. - Fixed PCLXL detection code. - Fixed retrieval of custom media types' names in PCLXL. - Added inactive code to compute ink coverage ala PrintBill. * 1.72 : - Improved heuristic to detect when ghostscript has to be used to do the parsing. * 1.71 : - Now uses ghostscript as the parser when the PS stream was created by a particular MSWindows driver. - Only complains about Psyco missing at install time, and stays quiet when running without Psyco. * 1.70 : - Fixed some PJL escaping issue in the PCLXL and PCL3/4/5 parsers. * 1.69 : - Improved PCL3/4/5 parser. - Improved PCLXL parser wrt PJL stuff. * 1.68 : - Improved PostScript parser. * 1.67 : - Improved PostScript parser. - Improved PCL3/4/5 parser. * 1.66 : - Improved PCLXL parser. - Improved PCL3/4/5 parser. * 1.65 : - Improved PostScript parser. - Improved PCL3/4/5 parser. * 1.64 : - Improved PCL3/4/5 parser. * 1.63 : - Now handles PJL statements to extract number of copies, duplex mode and paper size in the PCLXL and PCL3/4/5 parsers. * 1.62 : - Better handling of the number of copies in the PCLXL parser. - Better handling of the number of copies in the PCL3/4/5 parser. * 1.61 : - Improved PCL3/4/5 parser. - Better handling of the number of copies in the PostScript parser. Now the number can be different from page to page. * 1.60 : - Improved PCLXL parser. * 1.59 : - Major rewrite of the PDF parser to correctly handle all line endings. * 1.58 : - Fix for PDF files which contain several versions of the same PDF object. - Doesn't break when python-psyco is not available. * 1.57 : - Fixed a recently introduced bug in binary postscript handling code. * 1.56 : - Renamed the library from pdlanalyzer into pkpgpdls to avoid problems when the code will be integrated back into PyKota. * 1.55 : - Added support for OpenOffice.org Writer and Impress documents. * 1.54 : - Added online documentation and a manual page. * 1.53 : - Moved code around to improve maintainability. * 1.52 : - Added support for the TIFF format. * 1.51 : - Added support for the DVI format. * 1.50 : - Major code changes to modularize. The pkpgcounter command line tool is now just an almost empty skeleton, which uses the pdlanalyzer library. - Several improvements to the parsing code. * 1.00 : - First release. pkpgcounter-3.50/README0000644000175000017500000001511510727001400014200 0ustar jeromejerome# $Id: README 375 2007-12-09 15:00:13Z jerome $ pkpgcounter : a generic Page Description Language parser (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ============================================================================= pkpgcounter is a generic Page Description Language parser which can either compute the number of pages in a document, or compute the percent of ink coverage needed to print each page, in different colorspaces. pkpgcounter currently recognizes the following document formats : - PostScript (both DSC compliant and binary) - PDF - PCL3/4/5 - PCLXL (aka PCL6) - DVI - OpenDocument (ISO/IEC DIS 26300) - Microsoft Word (c) (tm) (r) (etc...) - Plain text - TIFF - Several other image formats - ESC/P2 - Zenographics ZjStream - Samsung QPDL (aka SPL2) - Samsung SPL1 - ESC/PageS03 - Brother HBP - Hewlett-Packard Lightweight Imaging Device Interface Language - Structured Fax - Canon BJ/BJC - ASCII PNM (Netpbm) The ten latter ones, as well as some TIFF documents, are currently only supported in page counting mode. By default, when launched pkpgcounter prints on its standard output a single integer representing the total number of pages in all the files which filenames you've passed on the command line. With no argument, or with a single dash in non-option arguments, pkpgcounter reads datas to parse from its standard input in addition to other non-options arguments which are treated as filenames representing the files to parse. See pkpgcounter --help for details and examples. ============================================================================= Installation : -------------- 0 - Download pkpgcounter from : http://www.pykota.com/software/pkpgcounter/download and extract it : $ tar -zxf pkpgcounter-x.yy.tar.gz where x.yy is pkpgcounter' version number. 1 - Run the installation script : $ python setup.py install This will usually install the pkpgcounter into /usr/bin and the library into /usr/lib/python2.?/site-packages/pkpgpdls/ 2 - Use pkpgcounter : $ pkpgcounter file1.ps file2.pclxl ... # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: clean.sh 335 2007-11-27 20:53:07Z jerome $ # Use this to clean the tree from temporary files rm -f MANIFEST rm -fr build dist find . -name "*.bak" -exec rm -f {} \; find . -name "*~" -exec rm -f {} \; find . -name "*.pyc" -exec rm -f {} \; find . -name "*.pyo" -exec rm -f {} \; find . -name "*.jem" -exec rm -f {} \; pkpgcounter-3.50/setup.py0000755000175000017500000000517510671326554015064 0ustar jeromejerome#! /usr/bin/env python # -*- coding: ISO-8859-15 -*- # # pkpgcounter : a generic Page Description Language parser # # (c) 2003, 2004, 2005, 2006, 2007 Jerome Alet # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # $Id: setup.py 282 2007-09-10 20:47:40Z jerome $ # # import sys import glob import os import shutil try : from distutils.core import setup except ImportError, msg : sys.stderr.write("%s\n" % msg) sys.stderr.write("You need the DistUtils Python module.\nunder Debian, you may have to install the python-dev package.\nOf course, YMMV.\n") sys.exit(-1) try : from PIL import Image except ImportError : sys.stderr.write("You need the Python Imaging Library (aka PIL).\nYou can grab it from http://www.pythonware.com\n") sys.exit(-1) try : import psyco except ImportError : sys.stderr.write("WARN: If you are running on a 32 Bits x86 platform, you should install the Python Psyco module if possible, this would greatly speedup parsing. NB : Psyco doesn't work on other platforms, so don't worry if you're in this case.\n") sys.path.insert(0, "pkpgpdls") from pkpgpdls.version import __version__, __doc__ data_files = [] mofiles = glob.glob(os.sep.join(["po", "*", "*.mo"])) for mofile in mofiles : lang = mofile.split(os.sep)[1] directory = os.sep.join(["share", "locale", lang, "LC_MESSAGES"]) data_files.append((directory, [ mofile ])) docdir = "share/doc/pkpgcounter" docfiles = ["README", "COPYING", "BUGS", "CREDITS", "NEWS"] data_files.append((docdir, docfiles)) directory = os.sep.join(["share", "man", "man1"]) manpages = glob.glob(os.sep.join(["man", "*.1"])) data_files.append((directory, manpages)) setup(name = "pkpgcounter", version = __version__, license = "GNU GPL", description = __doc__, author = "Jerome Alet", author_email = "alet@librelogiciel.com", url = "http://www.pykota.com/software/pkpgcounter/", packages = [ "pkpgpdls" ], scripts = [ "bin/pkpgcounter" ], data_files = data_files) pkpgcounter-3.50/PKG-INFO0000644000175000017500000000044210727050450014423 0ustar jeromejeromeMetadata-Version: 1.0 Name: pkpgcounter Version: 3.50 Summary: pkpgcounter : a generic Page Description Languages parser. Home-page: http://www.pykota.com/software/pkpgcounter/ Author: Jerome Alet Author-email: alet@librelogiciel.com License: GNU GPL Description: UNKNOWN Platform: UNKNOWN