relatorio-0.12.0/relatorio/__init__.py0000644000000000000000000000107113615410400014622 0ustar00""" relatorio ========= A templating library which provides a way to easily output all kind of different files (odt, ods, png, svg, ...). Adding support for more filetype is easy: you just have to create a plugin for this. relatorio also provides a report repository allowing you to link python objects and report together, find reports by mimetypes/name/python objects. """ from . import templates from .reporting import MIMETemplateLoader, Report, ReportRepository __version__ = '0.12.0' __all__ = ['MIMETemplateLoader', 'ReportRepository', 'Report', 'templates'] relatorio-0.12.0/relatorio/render.py0000755000000000000000000000162113615410400014346 0ustar00#!/usr/bin/env python import json import mimetypes import os from argparse import ArgumentParser, FileType from relatorio import Report def main(input_, data, output=None): input_ = os.path.abspath(input_) mimetype, _ = mimetypes.guess_type(input_) report = Report(input_, mimetype) content = report(**data).render().getvalue() if output: with open(output, 'wb') as fp: fp.write(content) def run(): parser = ArgumentParser() parser.add_argument('-i', '--input', dest='input', required=True) parser.add_argument('-o', '--output', dest='output') parser.add_argument('-d', '--data', dest='data', type=FileType('r'), help="JSON file with data to render") args = parser.parse_args() if args.data: data = json.load(args.data) else: data = {} main(args.input, data, args.output) if __name__ == '__main__': run() relatorio-0.12.0/relatorio/reporting.py0000644000000000000000000001136613615410400015104 0ustar00# This file is part of relatorio. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import os import sys from genshi.template import TemplateLoader __metaclass__ = type def _absolute(path): "Compute the absolute path of path relative to the caller file" if os.path.isabs(path): return path caller_fname = sys._getframe(2).f_globals['__file__'] caller_dir = os.path.dirname(caller_fname) return os.path.abspath(os.path.join(caller_dir, path)) def _guess_type(mime): """ Returns the codename used by relatorio to identify which template plugin it should use to render a mimetype """ mime = mime.lower() major, stype = mime.split('/', 1) if major == 'application': if 'opendocument' in stype: return 'oo.org' else: return stype elif major == 'text': if stype in ('xml', 'html', 'xhtml'): return 'markup' else: return 'text' class MIMETemplateLoader(TemplateLoader): """This subclass of TemplateLoader use mimetypes to search and find templates to load. """ factories = {} mime_func = [_guess_type] def get_type(self, mime): "finds the codename used by relatorio to work on a mimetype" for func in reversed(self.mime_func): codename = func(mime) if codename is not None: return codename def load(self, path, mime=None, relative_to=None, cls=None): "returns a template object based on path" assert mime is not None or cls is not None if mime is not None: cls = self.factories[self.get_type(mime)] return super(MIMETemplateLoader, self).load( path, cls=cls, relative_to=relative_to) @classmethod def add_factory(cls, abbr_mimetype, template_factory, id_function=None): """adds a template factory to the already known factories""" cls.factories[abbr_mimetype] = template_factory if id_function is not None: cls.mime_func.append(id_function) default_loader = MIMETemplateLoader(auto_reload=True) class DefaultFactory: """This is the default factory used by relatorio. It just returns a copy of the data it receives""" def __init__(self, *args, **kwargs): pass def __call__(self, **kwargs): data = kwargs.copy() return data default_factory = DefaultFactory() class Report: """Report is a simple interface on top of a rendering template. """ def __init__(self, path, mimetype, factory=default_factory, loader=default_loader): self.fpath = path self.mimetype = mimetype self.data_factory = factory self.tmpl_loader = loader self.filters = [] def __call__(self, **kwargs): template = self.tmpl_loader.load(self.fpath, self.mimetype) data = self.data_factory(**kwargs) return template.generate(**data).filter(*self.filters) def __repr__(self): return '' % self.fpath class ReportDict: def __init__(self, *args, **kwargs): self.mimetypes = {} self.ids = {} class ReportRepository: """ReportRepository stores the report definition associated to objects. The report are indexed in this object by the object class they are working on and the name given to it by the user. """ def __init__(self, datafactory=DefaultFactory): self.classes = {} self.default_factory = datafactory self.loader = default_loader def add_report(self, klass, mimetype, template_path, data_factory=None, report_name='default', description=''): """adds a report to the repository. You will be able to find the report via - the class it is working on - the mimetype it outputs - the name of the report You also have the opportunity to define a specific data_factory. """ if data_factory is None: data_factory = self.default_factory reports = self.classes.setdefault(klass, ReportDict()) report = Report(_absolute(template_path), mimetype, data_factory(klass, mimetype), self.loader) reports.ids[report_name] = report, mimetype, description reports.mimetypes.setdefault(mimetype, []) \ .append((report, report_name)) def by_mime(self, klass, mimetype): """gets a list of report related to a class by specifying the mimetype """ return self.classes[klass].mimetypes[mimetype] def by_id(self, klass, id): """get a report related to a class by its id """ return self.classes[klass].ids[id] relatorio-0.12.0/relatorio/templates/__init__.py0000644000000000000000000000041413615410400016620 0ustar00# This file is part of relatorio. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. plugins = ['base', 'opendocument', 'pdf', 'chart'] for name in plugins: __import__('relatorio.templates.%s' % name) relatorio-0.12.0/relatorio/templates/base.py0000644000000000000000000000201713615410400015774 0ustar00# This file is part of relatorio. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import genshi.core from genshi.template import MarkupTemplate, NewTextTemplate from relatorio.reporting import MIMETemplateLoader __metaclass__ = type class RelatorioStream(genshi.core.Stream): "Base class for the relatorio streams." def render(self, method=None, encoding='utf-8', out=None, **kwargs): "calls the serializer to render the template" return self.serializer( self.events, method=method, encoding=encoding, out=out) def serialize(self, method='xml', **kwargs): "generates the bitstream corresponding to the template" return self.render(method, **kwargs) def __or__(self, function): "Support for the bitwise operator" return RelatorioStream(self.events | function, self.serializer) MIMETemplateLoader.add_factory('text', NewTextTemplate) MIMETemplateLoader.add_factory('markup', MarkupTemplate) relatorio-0.12.0/relatorio/templates/chart.py0000644000000000000000000000516513615410400016172 0ustar00# This file is part of relatorio. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from io import BytesIO, StringIO import genshi import genshi.output from genshi.template import NewTextTemplate from relatorio.reporting import MIMETemplateLoader from relatorio.templates.base import RelatorioStream try: import cairo import pycha import pycha.bar import pycha.line import pycha.pie import yaml PYCHA_TYPE = {'pie': pycha.pie.PieChart, 'vbar': pycha.bar.VerticalBarChart, 'hbar': pycha.bar.HorizontalBarChart, 'line': pycha.line.LineChart, } except ImportError: yaml = cairo = None PYCHA_TYPE = {} _encode = genshi.output.encode __metaclass__ = type class Template(NewTextTemplate): "A chart templating object" def generate(self, *args, **kwargs): generated = super(Template, self).generate(*args, **kwargs) return RelatorioStream(generated, CairoSerializer()) @staticmethod def id_function(mimetype): "The function used to return the codename." if mimetype in ('image/png', 'image/svg'): return 'chart' class CairoSerializer: def __init__(self): self.text_serializer = genshi.output.TextSerializer() def __call__(self, stream, method=None, encoding='utf-8', out=None): if not PYCHA_TYPE: raise NotImplementedError if out is None: result = BytesIO() else: result = out yml = StringIO(_encode(self.text_serializer(stream))) chart_yaml = yaml.safe_load(yml.read()) chart_info = chart_yaml['chart'] chart_type = chart_info['output_type'] if chart_type == 'png': surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, chart_yaml['options']['width'], chart_yaml['options']['height']) elif chart_type == 'svg': surface = cairo.SVGSurface(result, chart_yaml['options']['width'], chart_yaml['options']['height']) else: raise NotImplementedError chart = PYCHA_TYPE[chart_info['type']](surface, chart_yaml['options']) chart.addDataset(chart_info['dataset']) chart.render() if chart_type == 'png': surface.write_to_png(result) elif chart_type == 'svg': surface.finish() if out is None: return result MIMETemplateLoader.add_factory('chart', Template, Template.id_function) relatorio-0.12.0/relatorio/templates/opendocument.py0000644000000000000000000013631113615410400017567 0ustar00# This file is part of relatorio. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import re try: # requires python 2.5+ from hashlib import md5 except ImportError: from md5 import md5 import base64 import datetime import mimetypes import sys import time import urllib.parse import warnings import zipfile from copy import deepcopy from decimal import Decimal from io import BytesIO import genshi import genshi.output import lxml.etree from genshi.core import Stream from genshi.filters import Transformer from genshi.filters.transform import ENTER, EXIT from genshi.template import MarkupTemplate from genshi.template.interpolation import PREFIX import relatorio from relatorio.reporting import MIMETemplateLoader, Report from relatorio.templates.base import RelatorioStream try: from relatorio.templates.chart import Template as ChartTemplate except ImportError: ChartTemplate = None __metaclass__ = type warnings.filterwarnings('always', module='relatorio.templates.opendocument') GENSHI_EXPR = re.compile(r''' (/)? # is this a closing tag? (for|if|choose|when|otherwise|with| attrs|content|replace|strip) # tag directive \s* (?:\s([\w:-]+)=["'](.*)["']|$) # match a single attr & its value | .* # or anything else ''', re.VERBOSE) GENSHI_CLOSING_DIRECTIVE = ['for', 'if', 'choose', 'when', 'otherwise', 'with', ] RELATORIO_URI = 'relatorio' GENSHI_URI = 'http://genshi.edgewall.org/' MANIFEST = 'META-INF/manifest.xml' META = 'meta.xml' THUMBNAILS = 'Thumbnails' output_encode = genshi.output.encode EtreeElement = lxml.etree.Element XML_INVALID_CHAR_EXPR = re.compile( # from https://www.w3.org/TR/REC-xml/#charsets '[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]') # A note regarding OpenDocument namespaces: # # The current code assumes the original OpenOffice document uses default # namespace prefix ("table", "xlink", "draw", ...). We derive the actual # namespaces URIs from their prefix, instead of the other way round. This has # the advantage that if a new version of the format use different namespaces # (this is not the case for ODF 1.1 but could be the case in the future since # there is a version number in those namespaces after all), Relatorio will # support those new formats out of the box. # A note about attribute namespaces: # # Ideally, we should update the namespace map of all the nodes we add # (Genshi) attributes to, so that the attributes use a nice "py" prefix instead # of a generated one (eg. "ns0", which is correct but ugly) in the case no # parent node defines it. Unfortunately, lxml doesn't support this: # the nsmap attribute of Element objects is (currently) readonly. class OOTemplateError(genshi.template.base.TemplateSyntaxError): "Error to raise when there is a SyntaxError in the genshi template" class ImageHref: "A class used to add images in the odf zipfile" def __init__(self, serializer, context): self.serializer = serializer self.context = context.copy() def __call__(self, expr): bitstream, mimetype = expr[:2] if isinstance(bitstream, Report): bitstream = bitstream(**self.context).render() elif ChartTemplate and isinstance(bitstream, ChartTemplate): bitstream = bitstream.generate(**self.context).render() elif not hasattr(bitstream, 'seek') or not hasattr(bitstream, 'read'): bitstream = BytesIO(bitstream) if bitstream: bitstream.seek(0) file_content = bitstream.read() else: file_content = b'' name = md5(file_content).hexdigest() path = 'Pictures/%s%s' % ( name, mimetypes.guess_extension(mimetype or '') or '') self.serializer.add_file(path, file_content, mimetype) return {'{http://www.w3.org/1999/xlink}href': path} class ImageDimension: "A class used to set dimension in draw tags" def __init__(self, namespaces): self.namespaces = namespaces def __call__(self, expr, width, height): # expr could be (bitstream, mimetype) # or (bitstreamm mimetype, width, height) if len(expr) >= 4: width, height = ( i or j for i, j in zip(expr[2:4], [width, height])) attrs = {} if width: attrs['{%s}width' % self.namespaces['svg']] = width if height: attrs['{%s}height' % self.namespaces['svg']] = height return attrs class ColumnCounter: """A class used to count the actual maximum number of cells (and thus columns) a table contains accross its rows. """ def __init__(self): self.temp_counters = {} self.counters = {} def reset(self, loop_id): self.temp_counters[loop_id] = 0 def inc(self, loop_id): self.temp_counters[loop_id] += 1 def store(self, loop_id, table_name): self.counters[table_name] = max(self.temp_counters.pop(loop_id), self.counters.get(table_name, 0)) class ExpressionCache: """A class used to cache result of expression evaluation""" def __init__(self): self.cache = {} def store(self, expression_id, expression): self.cache[expression_id] = expression return expression def get(self, expression_id): return self.cache[expression_id] def wrap_nodes_between(first, last, new_parent): """An helper function to move all nodes between two nodes to a new node and add that new node to their former parent. The boundary nodes are removed in the process. """ old_parent = first.getparent() # Any text after the opening tag (and not within a tag) need to be handled # explicitly. For example in xxxyyyzzz, zzz is # copied along the span tag, but not xxx, which corresponds to the tail # attribute of the opening tag. if first.tail: new_parent.text = first.tail for node in first.itersiblings(): if node is last: break # appending a node to a new parent also # remove it from its previous parent new_parent.append(node) old_parent.replace(first, new_parent) new_parent.tail = last.tail old_parent.remove(last) def remove_node_keeping_tail(node): """Remove the node from the tree but keeping tail by appending to the previous or parent node. """ parent = node.getparent() if node.tail: previous = node.getprevious() if previous is not None: if not previous.tail: previous.tail = node.tail else: previous.tail += node.tail else: if not parent.text: parent.text = node.tail else: parent.text += node.tail parent.remove(node) def update_py_attrs(node, value): """An helper function to update py_attrs of a node. """ if not value: return py_attrs_attr = '{%s}attrs' % GENSHI_URI if py_attrs_attr not in node.attrib: node.attrib[py_attrs_attr] = value else: node.attrib[py_attrs_attr] = \ "(lambda x, y: x.update(y) or x)(%s or {}, %s or {})" % \ (node.attrib[py_attrs_attr], value) def escape_xml_invalid_chars(value, repl=' '): "Replace invalid characters for XML." if isinstance(value, str): return XML_INVALID_CHAR_EXPR.sub(repl, value) else: return value class Template(MarkupTemplate): def __init__(self, source, filepath=None, filename=None, loader=None, encoding=None, lookup='strict', allow_exec=True): # assign default/fake namespaces so that documents do not need to # define them if they don't use them self.namespaces = { "text": "urn:text", "draw": "urn:draw", "table": "urn:table", "office": "urn:office", "xlink": "urn:xlink", "svg": "urn:svg", } self.inner_docs = [] self.has_col_loop = False self._source = None self._files = set() super(Template, self).__init__(source, filepath, filename, loader, encoding, lookup, allow_exec) def _parse(self, source, encoding): """parses the odf file. It adds genshi directives and finds the inner docs. """ if not self.filepath: if hasattr(source, 'read') and hasattr(source, 'mode'): if 'U' in source.mode: # TemplateLoader of Genshi <= 0.6 open files with universal # newlines which is not suitable for zipfile raise ValueError('filepath is required ' 'if source is openned with universal newlines') else: # source could be closed before generate calls source = BytesIO(source.read()) else: source = self.filepath self._source = source self.filepath = None # Prevent zip content in traceback zf = get_zip_file(source) content = zf.read('content.xml') styles = zf.read('styles.xml') meta = zf.read('meta.xml') template = super(Template, self) content = template._parse(self.insert_directives(content), encoding) styles = template._parse(self.insert_directives(styles), encoding) meta = template._parse(self.insert_directives(meta), encoding) content_files = [('content.xml', content)] styles_files = [('styles.xml', styles)] meta_files = [('meta.xml', meta)] while self.inner_docs: doc = self.inner_docs.pop() c_path, s_path, m_path = ( doc + '/content.xml', doc + '/styles.xml', doc + '/meta.xml') content = zf.read(c_path) styles = zf.read(s_path) meta = zf.read(m_path) c_parsed = template._parse(self.insert_directives(content), encoding) s_parsed = template._parse(self.insert_directives(styles), encoding) m_parsed = template._parse(self.insert_directives(meta), encoding) content_files.append((c_path, c_parsed)) styles_files.append((s_path, s_parsed)) meta_files.append((m_path, m_parsed)) zf.close() parsed = [] for fpath, fparsed in content_files + styles_files + meta_files: self._files.add(fpath) parsed.append((genshi.core.PI, ('relatorio', fpath), None)) parsed += fparsed return parsed def insert_directives(self, content): """adds the genshi directives, handle the images and the innerdocs. """ tree = lxml.etree.parse(BytesIO(content)) root = tree.getroot() # but override them with the real namespaces self.namespaces.update(root.nsmap) # remove any "root" namespace as lxml.xpath do not support them self.namespaces.pop(None, None) self.namespaces['py'] = GENSHI_URI self.namespaces['relatorio'] = RELATORIO_URI self._remove_soft_page_break(tree) self._invert_style(tree) self._handle_meta(tree) self._handle_relatorio_tags(tree) self._handle_images(tree) self._handle_innerdocs(tree) self._escape_values(tree) return BytesIO(lxml.etree.tostring(tree)) def _remove_soft_page_break(self, tree): "remove soft-page-break tag and use-soft-page-break attribute" xpath_expr = "//text:soft-page-break" for node in tree.xpath(xpath_expr, namespaces=self.namespaces): remove_node_keeping_tail(node) xpath_expr = "//office:text[@text:use-soft-page-breaks]" text_namespace = self.namespaces['text'] for node in tree.xpath(xpath_expr, namespaces=self.namespaces): node.attrib.pop('{%s}use-soft-page-breaks' % text_namespace) def _invert_style(self, tree): "inverts the text:a and text:span" xpath_expr = "//text:a[starts-with(@xlink:href, 'relatorio://')]" \ "/text:span" for span in tree.xpath(xpath_expr, namespaces=self.namespaces): text_a = span.getparent() outer = text_a.getparent() text_a.text = span.text span.text = '' text_a.remove(span) outer.replace(text_a, span) span.append(text_a) def _relatorio_statements(self, tree): "finds the relatorio statements (text:a/text:placeholder)" # If this node href matches the relatorio URL it is kept. # If this node href matches a genshi directive it is kept for further # processing. xlink_href_attrib = '{%s}href' % self.namespaces['xlink'] text_a = '{%s}a' % self.namespaces['text'] placeholder = '{%s}placeholder' % self.namespaces['text'] s_xpath = "//text:a[starts-with(@xlink:href, 'relatorio://')]" \ "| //text:placeholder" r_statements = [] opened_tags = [] # We map each opening tag with its closing tag closing_tags = {} for statement in tree.xpath(s_xpath, namespaces=self.namespaces): if statement.tag == placeholder: expr = statement.text[1:-1] elif statement.tag == text_a: expr = urllib.parse.unquote( statement.attrib[xlink_href_attrib][12:]) if not expr: raise OOTemplateError("No expression in the tag", self.filepath) closing, directive, attr, attr_val = \ GENSHI_EXPR.match(expr).groups() is_opening = closing != '/' warn_msg = None if not statement.text: warn_msg = "No statement text in '%s' for '%s'" \ % (self.filepath, expr) elif (directive != 'attrs' and expr != statement.text and statement.tag == text_a): warn_msg = "url and text do not match in %s: %s != %s" \ % (self.filepath, expr, statement.text) if warn_msg: if directive is not None and not is_opening: warn_msg += " corresponding to opening tag '%s'" \ % opened_tags[-1][0].text warnings.warn(warn_msg) if directive in GENSHI_CLOSING_DIRECTIVE: # map closing tags with their opening tag if is_opening: opened_tags.append((statement, directive)) else: opening_statement, opening_directive = opened_tags.pop() assert directive == opening_directive, ( "Wrong pairing tags between '%s' and '%s'" % (opening_statement.text.encode('utf-8'), statement.text.encode('utf-8'))) closing_tags[id(opening_statement)] = statement # - we only need to return opening statements if is_opening: r_statements.append((statement, (expr, directive, attr, attr_val)) ) assert not opened_tags return r_statements, closing_tags def _handle_meta(self, tree): """updates meta and adds py:content into meta:user-defined and dc:* nodes""" root = tree.getroot() if root.tag != '{%s}document-meta' % self.namespaces['office']: return xpath_expr = ("//meta:user-defined[starts-with(., 'relatorio://')]" "|//dc:*[starts-with(., 'relatorio://')]") genshi_content = '{%s}content' % self.namespaces['py'] for node in tree.xpath(xpath_expr, namespaces=self.namespaces): node.attrib[genshi_content] = node.text[len('relatorio://'):] def set(name, value): meta = root.find('{%s}%s' % (self.namespaces['meta'], name)) if meta is None: meta = EtreeElement( '{%s}%s' % (self.namespaces['meta'], name), nsmap=self.namespaces) root.append(meta) meta.text = value def remove(name, namespace='meta'): meta = tree.find('{%s}%s' % (self.namespaces[namespace], name)) if meta is not None: tree.remove(meta) now = datetime.datetime.now() set('creation-date', now.isoformat()) set('date', now.isoformat()) remove('document-statistic') set('editing-cycles', '1') remove('editing-duration') set('generator', 'relatorio/%s' % relatorio.__version__) remove('initial-creator') remove('print-date') remove('printed-by') remove('creator', 'dc') remove('date', 'dc') def _handle_relatorio_tags(self, tree): """ Will treat all relatorio tag (py:if/for/choose/when/otherwise) tags """ # Some tag/attribute name constants table_namespace = self.namespaces['table'] table_row_tag = '{%s}table-row' % table_namespace table_cell_tag = '{%s}table-cell' % table_namespace text_namespace = self.namespaces['text'] text_style_attributes = [s % text_namespace for s in [ '{%s}class-names', '{%s}cond-style-name', '{%s}style-name']] office_value = '{%s}value' % self.namespaces['office'] office_valuetype = '{%s}value-type' % self.namespaces['office'] if 'calcext' in self.namespaces: calcext_valuetype = '{%s}value-type' % self.namespaces['calcext'] else: calcext_valuetype = None py_replace = '{%s}replace' % GENSHI_URI r_statements, closing_tags = self._relatorio_statements(tree) for r_node, parsed in r_statements: expr, directive, attr, a_val = parsed # If the node is a genshi directive statement: if directive in GENSHI_CLOSING_DIRECTIVE: opening = r_node closing = closing_tags[id(r_node)] # - we find the nearest common ancestor of the closing and # opening statements o_ancestors = [opening] c_ancestors = [closing] + list(closing.iterancestors()) ancestor = None for node in opening.iterancestors(): try: idx = c_ancestors.index(node) assert c_ancestors[idx] == node # we only need ancestors up to the common one del c_ancestors[idx:] ancestor = node break except ValueError: # c_ancestors.index(node) raise ValueError if node is # not a child of c_ancestors pass o_ancestors.append(node) assert ancestor is not None, \ "No common ancestor found for opening and closing tag" outermost_o_ancestor = o_ancestors[-1] outermost_c_ancestor = c_ancestors[-1] # handle horizontal repetitions (over columns) if directive == "for" and ancestor.tag == table_row_tag: a_val = self._handle_column_loops(parsed, ancestor, opening, outermost_o_ancestor, outermost_c_ancestor) # - we create a node if attr is not None: attribs = {attr: a_val} else: attribs = {} genshi_node = EtreeElement('{%s}%s' % (GENSHI_URI, directive), attrib=attribs, nsmap={'py': GENSHI_URI}) # - we move all the nodes between the opening and closing # statements to this new node (append also removes from old # parent) # - we replace the opening statement by the node # - we delete the closing statement (and its ancestors) wrap_nodes_between(outermost_o_ancestor, outermost_c_ancestor, genshi_node) elif directive: # find the first parent with the same tag name as the attribute parent = r_node namespace, name = attr.split(':') attr = '{%s}%s' % (self.namespaces[namespace], name) while parent is not None and parent.tag != attr: parent = parent.getparent() assert parent is not None, "Parent not found" # add the py:attribute to the parent py_attr = '{%s}%s' % (GENSHI_URI, directive) parent.attrib[py_attr] = a_val # remove the directive node if parent != r_node: remove_node_keeping_tail(r_node) else: def has_style(node): return any(attr in node.attrib for attr in text_style_attributes) # It's not a genshi statement it's a python expression parent = r_node.getparent() grand_parent = parent.getparent() # Guess type only if it is the only value in the cell # and its parent has no style if (( grand_parent is None or grand_parent.tag != table_cell_tag) or len(grand_parent) != 1 or len(parent) != 1 or (parent.text and parent.text.strip()) or (r_node.tail and r_node.tail.strip()) or has_style(parent)): r_node.attrib[py_replace] = ( '__relatorio_escape_invalid_chars(%s)' % expr) continue cache_id = id(r_node) r_node.attrib[py_replace] = ("__relatorio_get_cache(%s)" % cache_id) # The grand-parent tag is a table cell we should set the # correct value and type for this cell. dico = ('__relatorio_guess_type(' '__relatorio_store_cache(%s, %s))') update_py_attrs(grand_parent, dico % (cache_id, expr)) for attr in [office_value, office_valuetype, calcext_valuetype]: if attr: grand_parent.attrib.pop(attr, None) def _handle_column_loops(self, statement, ancestor, opening, outer_o_node, outer_c_node): _, directive, attr, a_val = statement self.has_col_loop = True table_namespace = self.namespaces['table'] table_col_tag = '{%s}table-column' % table_namespace table_num_col_attr = '{%s}number-columns-repeated' % table_namespace repeat_tag = '{%s}repeat' % RELATORIO_URI # table node (it is not necessarily the direct parent of ancestor) table_node = next( ancestor.iterancestors('{%s}table' % table_namespace)) table_name = table_node.attrib['{%s}name' % table_namespace] # add counting instructions loop_id = id(opening) # 1) add reset counter code on the row opening tag # (through a py:attrs attribute). # Note that table_name is not needed in the first two # operations, but a unique id within the table is required # to support nested column repetition update_py_attrs(ancestor, "__relatorio_reset_col_count(%d)" % loop_id) # 2) add increment code (through a py:attrs attribute) on # the first cell node after the opening (cell node) # ancestor enclosed_cell = outer_o_node.getnext() assert enclosed_cell.tag == '{%s}table-cell' % table_namespace update_py_attrs(enclosed_cell, "__relatorio_inc_col_count(%d)" % loop_id) # 3) add "store count" code as a py:replace node, as the # last child of the row attr_value = "__relatorio_store_col_count(%d, %r)" \ % (loop_id, table_name) replace_node = EtreeElement('{%s}replace' % GENSHI_URI, attrib={'value': attr_value}, nsmap={'py': GENSHI_URI}) ancestor.append(replace_node) # find the position in the row of the cells holding the # and instructions # We use "*" so as to count both normal cells and covered/hidden cells position_xpath_expr = 'count(preceding-sibling::*)' opening_pos = \ int(outer_o_node.xpath(position_xpath_expr, namespaces=self.namespaces)) closing_pos = \ int(outer_c_node.xpath(position_xpath_expr, namespaces=self.namespaces)) # check whether or not the opening tag spans several rows a_val = self._handle_row_spanned_column_loops( statement, outer_o_node, opening_pos, closing_pos) # check if this table's headers were already processed repeat_node = table_node.find(repeat_tag) if repeat_node is not None: prev_pos = (int(repeat_node.attrib['opening']), int(repeat_node.attrib['closing'])) if (opening_pos, closing_pos) != prev_pos: raise Exception( 'Incoherent column repetition found! ' 'If a table has several lines with repeated ' 'columns, the repetition need to be on the ' 'same columns across all lines.') else: # compute splits: oo collapses the headers of adjacent # columns which use the same style. We need to split # any column header which is repeated so many times # that it encompasses any of the column headers that # we need to repeat to_split = [] idx = 0 childs = list(table_node.iterchildren(table_col_tag)) for tag in childs: inc = int(tag.attrib.get(table_num_col_attr, 1)) oldidx = idx idx += inc if oldidx < opening_pos < idx or \ oldidx < closing_pos < idx: to_split.append(tag) # split tags for tag in to_split: tag_pos = table_node.index(tag) num = int(tag.attrib.pop(table_num_col_attr)) new_tags = [deepcopy(tag) for i in range(num)] table_node[tag_pos:tag_pos + 1] = new_tags # compute the column header nodes corresponding to # the opening and closing tags. first = table_node[opening_pos] last = table_node[closing_pos] # add a node around the column # definitions nodes attribs = { "opening": str(opening_pos), "closing": str(closing_pos), "table": table_name, } repeat_node = EtreeElement(repeat_tag, attrib=attribs, nsmap={'relatorio': RELATORIO_URI}) wrap_nodes_between(first, last, repeat_node) return a_val def _handle_row_spanned_column_loops(self, statement, outer_o_node, opening_pos, closing_pos): """handles column repetitions which span several rows, by duplicating the py:for node for each row, and make the loops work on a copy of the original iterable as to not exhaust generators.""" _, directive, attr, a_val = statement table_namespace = self.namespaces['table'] table_rowspan_attr = '{%s}number-rows-spanned' % table_namespace # checks wether there is a (meaningful) rowspan rows_spanned = int(outer_o_node.attrib.get(table_rowspan_attr, 1)) if rows_spanned == 1: return a_val table_row_tag = '{%s}table-row' % table_namespace table_cov_cell_tag = '{%s}covered-table-cell' % table_namespace # if so, we need to: # 1) create a with node to define a temporary variable temp_var = "__relatorio_temp%d" % id(outer_o_node) # a_val == "target in iterable" target, iterable = a_val.split(' in ', 1) vars = "%s = list(%s)" % (temp_var, iterable.strip()) with_node = EtreeElement('{%s}with' % GENSHI_URI, attrib={"vars": vars}, nsmap={'py': GENSHI_URI}) # 2) transform a_val to use that temporary variable a_val = "%s in %s" % (target, temp_var) # 3) wrap the corresponding cells on the next row(s) # (those should be covered-table-cell) inside a # duplicate py:for node (looping on the temporary # variable). row_node = outer_o_node.getparent() row_node.addprevious(with_node) rows_to_wrap = [row_node] assert row_node.tag == table_row_tag next_rows = row_node.itersiblings(table_row_tag) for row_idx in range(rows_spanned - 1): next_row_node = next(next_rows) rows_to_wrap.append(next_row_node) # compute the start and end nodes first = next_row_node[opening_pos] last = next_row_node[closing_pos] assert first.tag == table_cov_cell_tag assert last.tag == table_cov_cell_tag # wrap them tag = '{%s}%s' % (GENSHI_URI, directive) for_node = EtreeElement(tag, attrib={attr: a_val}, nsmap={'py': GENSHI_URI}) wrap_nodes_between(first, last, for_node) # 4) wrap all the corresponding rows indide the "with" # node for node in rows_to_wrap: with_node.append(node) return a_val def _handle_images(self, tree): "replaces all draw:frame named 'image: ...' by draw:image nodes" draw_namespace = self.namespaces['draw'] draw_name = '{%s}name' % draw_namespace draw_image = '{%s}image' % draw_namespace py_attrs = '{%s}attrs' % self.namespaces['py'] end_cell_address = '{%s}end-cell-address' % self.namespaces['table'] svg_namespace = self.namespaces['svg'] svg_width = '{%s}width' % svg_namespace svg_height = '{%s}height' % svg_namespace xpath_expr = "//draw:frame[starts-with(@draw:name, 'image:')]" for draw in tree.xpath(xpath_expr, namespaces=self.namespaces): cache_id = id(draw) d_name = draw.attrib[draw_name][6:].strip() attr_expr = ("__relatorio_make_href(__relatorio_get_cache(%s))" % cache_id) image_node = EtreeElement(draw_image, attrib={py_attrs: attr_expr}, nsmap={'draw': draw_namespace, 'py': GENSHI_URI}) draw.replace(draw[0], image_node) width = draw.attrib.pop(svg_width, '') height = draw.attrib.pop(svg_height, '') attr_expr = ("__relatorio_make_dimension(" "__relatorio_store_cache(%s, (%s)), '%s', '%s')" % (cache_id, d_name, width, height)) draw.attrib[py_attrs] = attr_expr draw.attrib.pop(draw_name) dico = "{'%s': (__relatorio_get_cache(%s)[4:5] or [''])[0]}" update_py_attrs(draw, dico % (draw_name, cache_id)) # remove end-cell-address as the address specified could be wrong draw.attrib.pop(end_cell_address, '') def _handle_innerdocs(self, tree): "finds inner_docs and adds them to the processing stack." href_attrib = '{%s}href' % self.namespaces['xlink'] xpath_expr = "//draw:object[starts-with(@xlink:href, './')" \ "and @xlink:show='embed']" for draw in tree.xpath(xpath_expr, namespaces=self.namespaces): self.inner_docs.append(draw.attrib[href_attrib][2:]) def _escape_values(self, tree): "escapes element values" for element in tree.iter(): for attrs in list(element.keys()): if not attrs.startswith('{%s}' % GENSHI_URI): element.attrib[attrs] = element.attrib[attrs]\ .replace(PREFIX, PREFIX * 2) if element.text: element.text = element.text.replace(PREFIX, PREFIX * 2) def _guess_type(self, val): office_namespace = self.namespaces['office'] types = {'boolean': '{%s}boolean-value' % office_namespace, 'currency': '{%s}currency' % office_namespace, 'date': '{%s}date-value' % office_namespace, 'float': '{%s}value' % office_namespace, 'percentage': '{%s}value' % office_namespace, 'string': '{%s}string-value' % office_namespace, 'time': '{%s}time-value' % office_namespace, 'void': '{%s}value' % office_namespace, } attrs = dict.fromkeys(types) # Missing base type for currency and percentage if isinstance(val, bool): type_ = 'boolean' val = str(val).lower() elif isinstance(val, datetime.date): type_ = 'date' val = val.isoformat() elif isinstance(val, (int, float, Decimal)): type_ = 'float' elif isinstance(val, str): type_ = 'string' val = escape_xml_invalid_chars(val) elif isinstance(val, datetime.timedelta): type_ = 'time' val = 'P%sD%sS' % (val.days, val.seconds) else: type_ = 'void' val = None attrs[types[type_]] = val attrs['{%s}value-type' % office_namespace] = type_ if 'calcext' in self.namespaces: attrs['{%s}value-type' % self.namespaces['calcext']] = type_ return attrs def generate(self, *args, _relatorio_compresslevel=None, _relatorio_chunksize=64, _relatorio_zip64=False, _relatorio_compression_method=zipfile.ZIP_DEFLATED, **kwargs): "creates the RelatorioStream." serializer = OOSerializer( self._source, self._files, compresslevel=_relatorio_compresslevel, zip64=_relatorio_zip64, chunksize=_relatorio_chunksize, compression_method=_relatorio_compression_method) kwargs['__relatorio_make_href'] = ImageHref(serializer, kwargs) kwargs['__relatorio_make_dimension'] = ImageDimension(self.namespaces) kwargs['__relatorio_guess_type'] = self._guess_type kwargs['__relatorio_escape_invalid_chars'] = escape_xml_invalid_chars counter = ColumnCounter() kwargs['__relatorio_reset_col_count'] = counter.reset kwargs['__relatorio_inc_col_count'] = counter.inc kwargs['__relatorio_store_col_count'] = counter.store cache = ExpressionCache() kwargs['__relatorio_store_cache'] = cache.store kwargs['__relatorio_get_cache'] = cache.get stream = super(Template, self).generate(*args, **kwargs) if self.has_col_loop: # Note that we can't simply add a "number-columns-repeated" # attribute and then fill it with the correct number of columns # because that wouldn't work if more than one column is repeated. transformation = DuplicateColumnHeaders(counter) col_filter = Transformer('//repeat[namespace-uri()="%s"]' % RELATORIO_URI) col_filter = col_filter.apply(transformation) # Must consume the stream to fill counter stream = Stream(list(stream), self.serializer) | col_filter return RelatorioStream(stream, serializer) class DuplicateColumnHeaders(object): def __init__(self, counter): self.counter = counter def __call__(self, stream): for mark, (kind, data, pos) in stream: # for each repeat tag found if mark is ENTER: # get the number of columns for that table attrs = data[1] table = attrs.get('table') col_count = self.counter.counters[table] # collect events (column header tags) to repeat events = [] for submark, event in stream: if submark is EXIT: break events.append(event) # repeat them for _ in range(col_count): for event in events: yield None, event else: yield mark, (kind, data, pos) def get_zip_file(source): try: return zipfile.ZipFile(source) except zipfile.BadZipfile: # ZipFile modify the position if hasattr(source, 'seek'): source.seek(0) return zipfile.ZipFile(fod2od(source)) def fod2od(source): "Convert Flat OpenDocument to OpenDocument" odt_io = BytesIO() odt_zip = zipfile.ZipFile( odt_io, mode='w', compression=zipfile.ZIP_DEFLATED) fodt_tree = lxml.etree.parse(source) fodt_root = fodt_tree.getroot() office_ns = fodt_root.nsmap['office'] tag2files = { '{%s}meta' % office_ns: ['meta'], '{%s}settings' % office_ns: ['settings'], '{%s}scripts' % office_ns: ['content'], '{%s}font-face-decls' % office_ns: ['content', 'styles'], '{%s}styles' % office_ns: ['styles'], '{%s}automatic-styles' % office_ns: ['content', 'styles'], '{%s}master-styles' % office_ns: ['styles'], '{%s}body' % office_ns: ['content'], } mimetype = fodt_root.attrib['{%s}mimetype' % office_ns] # mimetype should be written first to let detection through 'magic number' odt_zip.writestr('mimetype', mimetype, zipfile.ZIP_STORED) documents = {} images = [] for child in fodt_root: for fname in tag2files[child.tag]: document = documents.get(fname) if document is None: document = lxml.etree.Element( '{%s}document-%s' % (office_ns, fname), nsmap=fodt_root.nsmap) documents[fname] = document child = deepcopy(child) images.extend(extract_images( child, fodt_root.nsmap, start=len(images))) document.append(child) manifest = Manifest(b''' ''') manifest.add_file_entry('/', mimetype) for fname, document in documents.items(): document_string = lxml.etree.tostring(document, encoding='UTF-8', xml_declaration=True) odt_zip.writestr('%s.xml' % fname, document_string) manifest.add_file_entry('%s.xml' % fname, 'text/xml') for fname, data, mime_type in images: odt_zip.writestr(fname, data) manifest.add_file_entry(fname, mime_type) odt_zip.writestr(MANIFEST, str(manifest)) odt_zip.close() return odt_io def extract_images(child, namespaces, start=0): "Extract draw:image with binary-data and replace by href" import magic images = [] for i, image in enumerate( child.xpath('//draw:image', namespaces=namespaces), start): binary_data, = image.xpath( './office:binary-data', namespaces=namespaces) data = base64.b64decode(binary_data.text) if hasattr(magic, 'from_buffer'): mime_type = magic.from_buffer(data, mime=True) else: # Not python-magic but file-magic mime_type = magic.detect_from_content(data).mime_type name = 'Pictures/image%s%s' % ( i, mimetypes.guess_extension(mime_type)) image.remove(binary_data) xlink_ns = namespaces['xlink'] image.attrib['{%s}href' % xlink_ns] = name images.append((name, data, mime_type)) return images class Manifest(object): def __init__(self, content): self.tree = lxml.etree.parse(BytesIO(content)) self.root = self.tree.getroot() self.namespaces = self.root.nsmap def __str__(self): val = lxml.etree.tostring(self.tree, encoding='UTF-8', xml_declaration=True) # In Python 3, val will be bytes if not isinstance(val, str): return str(val, 'utf-8') return val def add_file_entry(self, path, mimetype=None): manifest_namespace = self.namespaces['manifest'] attribs = {'{%s}media-type' % manifest_namespace: mimetype or '', '{%s}full-path' % manifest_namespace: path} entry_node = EtreeElement('{%s}%s' % (manifest_namespace, 'file-entry'), attrib=attribs, nsmap={'manifest': manifest_namespace}) self.root.append(entry_node) def remove_file_entry(self, path): manifest_namespace = self.namespaces['manifest'] entry = self.root.find('{%s}%s[@{%s}full-path="%s"]' % (manifest_namespace, 'file-entry', manifest_namespace, path)) if entry is not None: self.root.remove(entry) class _AbstractZipWriteSplitStream(object): def __init__(self, zipfile, chunksize=64, zip64=False): self.zipfile = zipfile self.chunksize = chunksize self.zip64 = zip64 def open(self, zinfo): raise NotImplementedError def close(self): raise NotImplementedError def __call__(self, stream): for kind, data, pos in stream: if kind == genshi.core.PI and data[0] == 'relatorio': self.open(data[1]) continue yield kind, data, pos self.close() def write(self, data): raise NotImplementedError if sys.version_info >= (3, 6): class _ZipWriteSplitStream(_AbstractZipWriteSplitStream): def __init__(self, *args, **kwargs): super(_ZipWriteSplitStream, self).__init__(*args, **kwargs) self._fp = None self._buffer = [] self._zinfo = None def open(self, zinfo): if self._fp or self._buffer: self.close() self._zinfo = zinfo self._fp = None def close(self): self.flush() self._fp.close() self._zinfo = None self._fp = None def write(self, data): self._buffer.append(data) if len(self._buffer) > self.chunksize: self.flush() def flush(self): if not self._fp: self._fp = self.zipfile.open( self._zinfo, mode='w', force_zip64=self.zip64) self._fp.write(b''.join(self._buffer)) self._buffer.clear() else: class _ZipWriteSplitStream(_AbstractZipWriteSplitStream): def __init__(self, *args, **kwargs): super(_ZipWriteSplitStream, self).__init__(*args, **kwargs) self._fp = None self._zinfo = None def open(self, zinfo): if self._fp: self.close() self._zinfo = zinfo self._fp = BytesIO() def close(self): self._fp.seek(0) self.zipfile.writestr(self._zinfo, self._fp.read()) self._zinfo = None self._fp = None def write(self, data): self._fp.write(data) class OOSerializer: def __init__(self, source, files, chunksize=64, compresslevel=None, zip64=False, compression_method=zipfile.ZIP_DEFLATED): self.inzip = get_zip_file(source) self.manifest = Manifest(self.inzip.read(MANIFEST)) self.xml_serializer = genshi.output.XMLSerializer() self._files = files self.chunksize = chunksize self.compresslevel = None self.zip64 = zip64 self.compression_method = compression_method self.outzip = None self._deferred = [] def __call__(self, stream, method=None, encoding='utf-8', out=None): if out is None: result = BytesIO() else: result = out zip_options = {} if sys.version_info >= (3, 7): zip_options['compresslevel'] = self.compresslevel self.outzip = zipfile.ZipFile( result, mode='w', compression=self.compression_method, **zip_options) files = {} now = time.localtime()[:6] manifest_info = None for f_info in self.inzip.infolist(): if f_info.filename.startswith('ObjectReplacements'): continue elif f_info.filename in self._files: # create a new file descriptor, copying some attributes from # the original file new_info = zipfile.ZipInfo(f_info.filename, now) for attr in ('compress_type', 'flag_bits', 'create_system'): setattr(new_info, attr, getattr(f_info, attr)) files[f_info.filename] = new_info elif f_info.filename == MANIFEST: manifest_info = f_info elif f_info.filename.startswith(THUMBNAILS + '/'): self.manifest.remove_file_entry(f_info.filename) else: self.outzip.writestr(f_info, self.inzip.read(f_info.filename)) writer = _ZipWriteSplitStream(self.outzip, self.chunksize, self.zip64) output_encode( self.xml_serializer(writer(stream)), encoding=encoding, out=writer) for args in self._deferred: self.add_file(*args) self.manifest.remove_file_entry(THUMBNAILS + '/') if manifest_info: self.outzip.writestr(manifest_info, str(self.manifest)) self.inzip.close() self.outzip.close() if out is None: return result def add_file(self, path, content, mimetype): if not self.outzip: self._deferred.append((path, content, mimetype)) elif path not in self.outzip.namelist(): try: self.outzip.writestr(path, content) self.manifest.add_file_entry(path, mimetype) except ValueError: self._deferred.append((path, content, mimetype)) MIMETemplateLoader.add_factory('oo.org', Template) relatorio-0.12.0/relatorio/templates/pdf.py0000644000000000000000000000307313615410400015636 0ustar00# This file is part of relatorio. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import os import shutil import subprocess import tempfile from io import BytesIO import genshi import genshi.output from genshi.template import NewTextTemplate from relatorio.reporting import MIMETemplateLoader from relatorio.templates.base import RelatorioStream __metaclass__ = type TEXEXEC = 'texexec' _encode = genshi.output.encode class Template(NewTextTemplate): def generate(self, *args, **kwargs): generated = super(Template, self).generate(*args, **kwargs) return RelatorioStream(generated, PDFSerializer()) class PDFSerializer: def __init__(self): self.text_serializer = genshi.output.TextSerializer() def __call__(self, stream, method=None, encoding='utf-8', out=None): if out is None: result = BytesIO() else: result = out working_dir = tempfile.mkdtemp(prefix='relatorio') tex_file = os.path.join(working_dir, 'report.tex') pdf_file = os.path.join(working_dir, 'report.pdf') with open(tex_file, 'w') as fp: fp.write(_encode(self.text_serializer(stream))) subprocess.check_call([TEXEXEC, '--purge', 'report.tex'], cwd=working_dir) with open(pdf_file, 'r') as fp: result.write(fp.read()) shutil.rmtree(working_dir, ignore_errors=True) if out is None: return result MIMETemplateLoader.add_factory('pdf', Template) relatorio-0.12.0/relatorio/tests/__init__.py0000644000000000000000000000022313615410400015762 0ustar00# This file is part of relatorio. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. relatorio-0.12.0/relatorio/tests/egg.jpg0000644000000000000000000007136113615410400015130 0ustar00JFIF``PExifII* (12iSPENTAX CorporationPENTAX Optio 550HH1.002006:09:10 16:56:46PrintIM0250  0220   |0100c    . 2006:09:10 16:56:462006:09:10 16:56:46   AOC)Iz=8b) 8.     Z . 2v !"#$ %&')(. .va1aDTl[.;]8' @Ej I*""""""""""""""""[_q[RHc } {iC {iC"0wwww"2$A{`RddI"%n8 qffff vdR980100KS([HHJFIFC   %# , #&')*)-0-(0%()(C   ((((((((((((((((((((((((((((((((((((((((((((((((((( }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz" ?oG͹' OͶ;_$Y^xjވ#/pތgޫ ?U"=n[%]+k*#׭hjk;U!R5jVyi4Kv: ~O(=3N'R~4\j Y 6ij?O\=Et$?ڭ $qYJCFŠVE Eo/@+F=&ݸh#?Z޵m ~wͧۻk]<~BIg n$r@UIUFS[S.m&6CDߋ0N#rv[\u=L^gO+ku,U#}NubRݍfw$1e<'v5Ӧ@xI'ftbղ3en8!5z>!$dTwV1@LVzUUϓ~1x+ORtŽSz~U控(5N@΅O؏q־06skeM5V<]f%σ?ʹz`2wkKGz>3N ?"SsU@>o%I6OQU̶g?UG qs)`}KKHH(+|ƹ /}+dLS죪;UaYIsFڶl=V\DΎ[s+ Ɏl[7ɚFxLV=8ZĖ^CTSJD+ x)r٧P1_A|L"|4^h{0ǿex33eoSɮ.tṦ[7(%k%oWV+ɀSR^}x⍕7m5nCHcU1z++Wod k!Qi>k}c{c7曑7bH>Nj[T5vt> f"G_Why ;O^n䎼V3/ʤIYl,,I޼UX7M V&G_fx[v\guE3^~jMf9(R!Я*R1U~1QbGISgeoC&NCYn/$ԝϫ785УdϧqYUWW:{;|tUSTU֞+F턣x+X׎HC봩>DX65h⹋ tp1]Q9Z֤ ȬKgj@jfm6jrqSqӚKE>:k7o"D}vOҽIvzWJwsETʫ-:mֶm)|Mu9Co9Zr>HIn hoJYOmbKeYS B @PStGfrkB?uh*}47*Eii;$ +/%MD)@OF]F~S(hft5#$%;YǙ,dzf?r(.c_֍RNZzmrrkNQ5*v+//-R^Yֺc*4ݛ= <|7vGg'׊E}MM5 2?C=ZNӧW.rܓ41Al>ތU' mO'SL:ir3g1)K[cdK}?N] {ݤ4\sRv2ٜy:V:?)ya&:f XVޅcPb:R{#H;_B3v8ZspE5v7CִS=j!kCh)t>;[u{T ^vkU 0-0-7fffffff-0 0-0-0-0 0 0 0 v JFIFC  !"$"$C }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzc" ?!X]$E'kWS7*̹y\jGKk㯛̻d뽁`2z=*ȮpcNy#ҭj3n`z7Rv;XT5lpé1UݖcA'{ciP ʐ`:ORa(|Q`[c=VF{RxH:HO˷qBKsIMՏ`Z۞yIW0OJЗĎLrWm]rKֹUजgWY4Hҹ&~S稢٦>F6==)X.x 0H# ֲ:,ǐZ]H$`5!O~5 }͂|NFhm)8]'3N +=?THia6 FN|9aA\S&W##rd O|{(dnː1Z\;3/9L(;PqZ n2\;S^3KGy;#Jo/^xQUz5U:2~篱 ZX'qQI&6IH 2Bc&Nn!N}iāƥ 6|ܞB_xBF9OJTH 探\K(|+ۚ8 qPɶT:qzyOTa8U'ǦOIF7i;W-0r>钰>v&8q^d@\u[~$yyJ~W0@\r:umbМq7b9'ֹY2G7zu8=s'u@8&tDYs=Fj@zG1X9Oqrt<⻿M1v8?^|-GoL %,ͱ9|tcw'OJKV;c>\W&㼪җ7cҐ̟1Wp03’qusOW69&Z7Bҥ >d {SF(8^3yFpdB 1~KxY !\bqU3y@yl cAn3R:/;yw!c_EGd B{R44|'5f͛8,ATo6yINa^)U1#ӚQr:S%E7vۏZWb99%X T׬X)^_νIz?xzfY!Lr"on;ӄ3d854(}psOiBRcuk It+7K lJ6wRV) }kETŏAKٸO>եjʴes2 dHOQO˟*nΥDZLq+qN[2O~)Wa=ϵ<ːz21<2hd1} $ӅǚOVhpNsR+1s lF=X jen1I zBHwqSQ*sAv5ho5k1UNHtP!sTPダp~ 9m[95Q,!,đ֭*Wq'`[:՘L)8TrZi~Gozm~}jIlĚȄM¸>P@8V[fkr*)Q̙(%G˞(aLyn` ָ;7y+d5ң9Sec5mqjuϭRrKSέ͢r]xQIspCH^]iԠh~5|۞kCRYs@ P~qRŔ68/"y#|79gv9㞔yq4@xRCmNܯ|>ŸnW?/j'ܮsדe*g @Nu!_I.ANF"ܷ^F^px)>UfJk|EeQ6ԗsJh77R8#.jFA'KD+{}W&{s;'kg'zgS֬ƠzS^w8 }FR9cޥ@08M?(ۊiKdcpynszX;`] bl" vWHL}1UŏZf؆]Va҈ s֭"F$x#@dU9.T,"PsjURRMn*Gyyd$^+HEjpLaU#XIm{hH G >įjdtylY.8z9ei_@ C NjUE|' ?~,|;v y4ٛ2~~ʸFRFpFO^k6yU"02qM*UPcF7g#zW39뚞6R$ W_If,g?J9zLF@m WnyҽJCQ0@^Z0e9 G5g{p)Ihx9d~XR1?Ɣq޹ާ)9h'v$X@h\ v[<Ǐo?~Chbb)-#HsHa󐼑X@HoN 4yYCs*̙A ngpCtcgBg"gJHH)9_8sKzR|@Xq95|7ޢ$G1{B.5MJ++u%azw'[Bv#$RmJҬbXc\*p1g[9 {c' ~,hDcvI4(#֐CR#frH`攜8kkKjs0)9Y\qWg|赳]NG13W,{y;H=Yd F@P 2$g5;Q2'15b6ﴀ}Wj\ :.s׎:$a<'XqЊ %qM@Ld3=9c #*h vc4 8tv=z(G<8#UĒݰ'8G֩ZסD!P n5}j 7'9HV2MUM֭' VdVSZDQxq֢8bVHzz{9枣#֗o=sGuA#A4!ӚyeP>l>͙fE{瞜g+撤[?~k60KD(6g/4[G>u`OO~ֱm=$8# q@ʏrRLBw3aOEq4 XaF;c,BS'ҽQP@?c^[+aqbqe+rcF\銑P6X4|W9__ Cfx# eSӽ'Q7i +?@|mz-sqK?*jpxG`^0H#JonMQQ\ў/Ꮺ0$8I#֝!̌sԞN=(x<QH0Nv}C+iK.oރוY@Wv ־ЭRc&ۑ=2ث1N,}qU-cոzJHcVT@t#iާެ&& Fs֤1{zЃ~xH -)r͑U+ A; 9[wirٛ IyZV?jˉG ֍7bkX"`|j¨!Cm 8բ!10ڭ'#$8@:؏{VXvHsT*qn3YO=j|c5[K&SU@j*dB,()QxW2Xiq{8iaQ= ZӸ\"j?ڇk~ X?)nKE~^Ҳ{HD)VSсdeR*J-m#$Q8|#x~O TaD~d#>rB<:zz~UziSO Tj[F\Ӱ 9␀ƀ`) b=d(t:u=(Ëp &v^!l]l=idY%3" ہW_}~U-VSF8]H& Tcp`gҬq4jJfS=UXNS)8Ca$;A)N?DrNiyg<ء(X$|8*֪X>< OSnNq:YvwuU_"w4 j$zVl2sүNG!(V<Oҭ@r Bju\U9^~b7R$Z")U,FqVLr0?e ?U'֧ROQ$vy2zHzӇ`SPqڤ L;Rcӥ(4$R$i:qUnE[> Tϖk7z_u;L_="<nNzEQBk(<h[lzvШOC,U,=KK4p<@my'Jrcӥ{*Y*`q^Y>s86IR e:0sΟ W'=*2G Vl`qvoXyɃ;gBE|-붙9zbxCM!şJ*vZ_W(yn~f[z7]xRq68R{~ԣxa^+^_:37͎sֹr1'rj\Tb~flya8? g2i33dOҐgSvt8,˟ߝ;DǥT-ҟ(UIv5N=d2_e܌]llwxt,Z\ EkpI5F)%bn6/Z[Gz΄A3VQr?BeqRǒ>ګ)RrO^{S O_jwlJ0_$ OsS1iX+m U9V#`ǓTf 3E[,Mg@9Z6|7hEե es޴δFlч=IP@=*$jGc!⬠~zUX=|ݺUؒ{rI9 UnnO]y!,dzK ʰIVssji#p9s.ޥ,V=}jL(88YpRGi-4xW?st4Yw\TCXԎGH vTW$攫sK]4ӽڗ矴b;YxF+CN Xk'n_jр`z׊{XS@CzߏƖ_F8L%z:;=EOap\g8sVtN1ʠsQ--(m@w7kO$D`AjDibAkj,#*8RO5jaz3U"`gB@GSB( |lT'@U&1Y8c,!lӣKs)%IR\(}1V9@[~S鎕j݊|gޭ6<|V'v8YIδ-I r}Tf5-(m[qֳ-m'1$r{3fs cBۖJ݌Eh.{{ոB2HVm8Iy7zާ\ǂGV2*Ҹl<Մ1 tDH-ɫ)PwNzt)qOd1KIisl 1NB+N1ǿe¦|lI a|b[Do3ZLFso*t6'y28=ɯWl`iWp%/W2gKܟ!HہwyQm;lv=(W*OCkڞ1`<`jSX46I'!zy?[ ǩZH.H9ubFA{&/%v0 Ǟ+/'F6wdpHa90]j31iq#ޣyPu!cս 3jg&UV+8ާ㾀H_zlʋ8C`XZ~|,Hbkzbh$2tN1:DR~b$ tSr<`J8`~td6}hd@c֤$T?xX:hB0wjs8W!Vjۀzѷ 9xX%rw;YH ׭%6g9 q嶃׎lŰG\U?h4I=YЇ;NO^D2OPIc. ک"nXסhAF㓊ڣըsӌUbYj<*R n2%#^j''(;4ia+{өpH&g9>qқ!ҾbT6A??Ҿ+ w w0QZ'&+l\|>'v99矛^Q6Ҙ ׯJ{fq${^T\ޫ#rhyPJكn%cG_J7>d`sU .KT3=M@#y9!?3>œC PyaC.t9ZFH[oAQ GoI~H%q^9oi36u8m1ֹ{X2.Fnd N7gQlfsM4*N<$'lĎj#׏֔0uփ[ɦR 8w@S{zeNع^}n虹dbAzd9ex԰9hػ!+j2Xb[rx<O5\y&4\,w*T,8uи+M{c@ޮ[[XBcZVn*|ʴ`<9Ͻe[aQڴmڶFlܳ'SִN9 dba y]ɗO^?J 5B!^Ʈ'8皴C4P9J=s{UhyqixH9f*dޭ*1V\5hOKJ Gj RBejq}j}$U30zzC隋ÚC ks L=i94 l$#W?}79M|\ݬ09eU| ƲS; ^PPc/'zvZ@]Tۜ2 )Jx>c-3r,{N1=)rUH?JzrGssҒ3X89~>eC`8$##-i%_BN␐lUKEGThx:`hL-4j=Nh';ǭm sNk>6-氉bnk:NdssSOI(⛜y9 yh [H'c~= p^-C;5#Ϡ9+3Ox(=G1 rj#ǡ~A2[;Q5Ev)g#8TP!;z` .$4$c4grO=(0\B@ΫӜKvhazVEyZз,݈i3n 2IAl՗bQ|s׭u`5ndٹh:JՀPǭe[1d+FROR>0# I8P:lFsu5DVn#qwVӨ=jmBq 9$֪xX%6Vj-뚲nsI玴CS$($iGNj5}6)U!<8g5OJ7D8O5v':VޱzIeX?9Q9ǣܟZRrXg׸R2dB7_t>s+ڧ|'ZtJgcm#SԍAJ}&݁ɨL:v֜Kmwq*X}<LjD;fl-}M? NFj I瞞֞]C 8טz˴{.}{m =)Ѯx&зlZp^<] }sWcnl.sTIh۶!@ϭmd8UGnis۩kS)>TVGXX,ǹf8[e$lK8> >d@9S޴FlԌn#Vt-r8zd17b~j"s8 V=JYizc5gIe;I_\S]xI{BK=O_ۤA4NodxXe(T䔵GKm<mFzW3x^¶ny[9ϵq OӔ<Fvrǀ07d92T/v\V ԕ,1EG"Pg=9t9JRG`x `VNL9z|ApsG`G)Rs?+_zi ?duYvz*+p64Q6$d=E p_W9 ʚWڲzCߏlԹ3um^bӫL =/$ұ%H?^hc.Ɠj󞦺 u#׌~+x\JmԄnRN+jV/u ~jU$!l29=gڹS$dO*n07~J;u1NON (F=|T@` ZMp9>M4Hy$s}y 33,GB:ucv I\`޵W bv gzg)9lt>Pø 3@Vh-XHGՊ^#Z>]HMoZW達ͻbYb;Z6'eZGiڶOj sWf:OPv2}Myxpځ1?ͩj7q#HpIU)FmI_sa՛6zO|qý2Ɨ_R8=;= qy|TPB[ש(fxvNw(چOsLoj8l\ԇA3L G=a ~E#K/aO?[AdXf4mavrCs1_ 1[c{ATn@4&L"VBM9\g=I0=֓wz$`Fhھq|U$>'|UA71'|1Mv^&gG ¢oKxf8) H11֟(Y!By> zB'&=#t :Wi,͡?)c޼y5zs]-*z@e>Y9yhʔ 95GLg?s3Cs&XQV83 <^l@=I ~HI?@cMzsnieWL~+Xp/-ѸҰ篊W0$sz?1ށ,{ƙ8{SSۊ,RS,vlj jX+3 >q#~歓ֵ<7I_ cxT`zgsq( )#oQ\2Zѹ'9?'C1R璸F m%qw\~#ҡndxՈ%(phĆl<2cqnsN3acn [SڹG%kjT`R2NدljN3&l'>^k):k3oC&|Vա!OZ)8p s]RkN:sWe,ZdiB5md3Y(9m&9SbljՅ|FGڰv7jepx %bW9L#(|=j*'?C4T9䘢◍m-y ›]Pb%%vyo9e M8 {|Uk]Ԯ5mNQ<ӱfϷz%wP9 1ۻV;&FDD*v??Z&vRp8?E+lq@^Aǥ8ٽLdWG(_c^ZXp㡯N7b|iWy`{tַc#ʧ~F#Gy'i\Tԁ\#rUF08*Q) A;E*F=Ny["D`mK|ܒv7i1L4=0g?tZ S>IzV RytZE$5NjQ{g0g<~jyFelҤ ggZd 0x{R8RcFr3Tu=B+i.&"($N%/u}/OUX\/x_o0D$z/]Ḯ`o y(g N8 J痉V©  SSH< is$<)|qɩ8ؐp. 8=G9`|4v'֚RRә 2"ӌWUT'W^hh;6C ` fc֓q\.8/pAfa:`vɮkrO.n 9ԡc;])\c5 ʑx4ȳ8̀sOḋir`;KɀO=lrGiq>J*(v E7HޡH:A^Kr3Ɣ#+JNWp(h:3~Iq[F͓5?8r:GMz %W'1\upx|lv7b;ۗj ?$0uU '9>68#^|Ӿ_T]dc⵬% '8;v`U^zvO-r94{]Pz޳m=둱ѐTVդ%xNNN,Ze=SҶ rXڰl>SkڶRf5S9꧝ҳ5~LiDP=EY2v55-F +gEDAs|}֭<>3%&k&$VgS5 e>wi hO(gi>w!_G9šgz>xIϵy)Gzt@ zm&6$Z=f xt:֗.6s:uD-QE2tJmvZq=(m*$Kپ]L̀}gt|ia-܌SL *-aμZGPѭޱU+TH?oJ7dۨ* Y-gi[zumPNW;A뎵i?O=A7LGTpI=[W 9]g4slhBHxzF ƷLţr2W<:"] \{Ԧc]e\&{p+|[g_̓)5Q0!Xj2qUPGxN¼;UOS_?x.KܺC#ҳ.5in#F~I<UE λQ.Ǚ[RN,It}D5 zk&u|sE?3KϑO-Lg*zϭ _FgrNFJOԌF3=E]D`BJ9RbzqPa{j_PpqJ8ݷj.Wqh P-X cߧZ$h55W$Q^ZK"clG+^{?H܃njҲ<ܺ#Τ? O#ȭU5F%M>ԟz\=C/3сOn04-HA Wn~'E'N]x_f\| _5?!ZGA|c Z?r˱i1׍KL3$\ZI~cٌ7 !b9ƪkˡJއ\ΖܼN0 V4nٮWi1*ZǞfO4끌,DtR[==SJc̉f Ju]'l33dsZ71 TC} #E;3GK;`sUmpWŲB΀XzROZ\M Fמ{kG/:,Sgːs>囉bw>9<9Y1[0koif݃qN|}co#_xYx{!#R"xڏExն:z©K6* 3]ѷR؆#o cBX3/')i4r$|=2v=ֺ*p`KzOO1xeRC)/r:boF1ƥ}#qO%c-G#OR3'Py=+nP:P{ R/t6F3KtVGR]Y+ ;LtxM݅#,9yJwP9JYy#;XvEQ$I*[9<iC;+,{vԸ`/nhę{E-k;d:țĺhrcvhNF-e^c^zڥgX`)r{3mQ*[#It9$rr^YU' NN9XD[6zxKL;U'W<^z {{sڏH_wm%Ҋ1RK%"''z@QI}7QvB7r'^xlG'+P 3NtWx85عz A{F`` 'gdaqR\';2s?5;V"l@#4`x8:LaݏnԙJ7<҄;rO$q@!\n#;Qq#% NG=Ҙ•R}ic@8-dJdpOCBXg޺/۟RnLgjP0]'ÒN1 F?iKG6;\UGZ+|l#(b Hi8eqڛ"16n6#@Ƿo_Ҟׯy,:8BPLb˸'NO@zH~14ۅDI(p;杔s 9Rwx֚F1)4-)?9ǚ:O8ϸ|n p:Wt|Jُ:}joCo/~o:]-)yן1[bqeqf_0/(`qN$KqCQ!>[[cBYXgҰV=W_$ޕuNaP?>yHW y#lہ֐n:{Vʏ~z>ՐmNRA H^ۏGz{.JFrOENW8ϽW<.H#R px'4Kzo?m$'^?ynH}+5j6M+̂E&9 @ tb/׶7@OPw î=8I=?=8aGp<}ku ssUɀXxo9q#A4U6pg# >2ziP/yiNLrs %tLם@Wn  syB|=[?98OZ2|àQ*.$;q dt6:R-RG>R^IJ7eI=0sZWITgj~}ǵ4E=-NU#_joz@y'<"d+uȠ#s;XgҺOmpnˍ_!Tk?r8\5|IP `%=={W.$(E_p8-;x`(ͩ[ Ī?Zds~wFfTjpΫ; x}qA8{{мzThpD158$g|gUF3ʷN XE,- bz R=>N;xfٵ#$P6V5`F8Na [~Tn4!ÀOѺOvHє-ҝE r]?Wy>W}խmScVzN=u="kE)}rG*?J?>R[i?)ӏM7֯q C4/ߏGQ=>[2JO Ҵ _>$}#\ͿOt>f'֕_ =csuSGUT[*'* 7s4֧oiOWAogSbWr_4ÓjΉ!+VN:'u=*^i^{Vz?5y}[5'.YcE4?o‹k`PR})-Ɉ'A-GBtRVujo[1&RJqZlWN=?VJȱz76_>b?o^ltkz+-ޯQy?H}ѹk"-?T'Y~֥S\eSJAyB?T5drelatorio-0.12.0/relatorio/tests/one.jpg0000644000000000000000000006732513615410400015154 0ustar00JFIFHH7ExifII* (1 2i\$PENTAX CorporationPENTAX Optio 550HHGIMP 2.4.62008:07:23 12:07:21PrintIM0250  0220   0100c    . 2006:09:10 16:56:462006:09:10 16:56:46   vdR980100rz(HHJFIFC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?Nj9 cDH R@fsƵy*?!fQ :ޤQs.x>#ZQD?\5GuSRo`:!T'UexNcMaRj٠8=H35kD 1sdi^ ,ʢ~fF0;SG\fd'ҤH9iG=M| kixva8?cMj筼}LCɦJ{c6TRQ@X{[1HDd!o50Nz}g9f#iP4o#{u=躱jNg ˟u"?{~.$.ߝ8]li^#tj7t)NzJh]oKɿ~fJ&noB㑦B^9n;sBǑRLjXF鱋N{c Γ !"歆i٣O&I/λ}co.+$,¼+ *AN/:ἿsK죏>:y?C<Ϙx#~䝮#gv]nfku#.[m\g5qqC 9.N.J73ďRx?ک{rUcLrBy=%Jư8j{_򚁾/c_4RXt亼tOPƠ!OF^!B )6\c}X+m H@ @ sS/'ڤ,yPqE_cR@K ]?2UTZ$CҦHJ*eJ+IOXYܪ>e5mS&Js]Я4E. UÏQYs'*?:KaJQ[ާCL ( `]ʑV`+2XW~5IV#fʗnAJsWu`kͪ9G\*ѭ0[U+ĺ^ukI[28Q\y%S\>bUꪊI\'^ܹojl@'ҮFr3^>\R5 sڦZE# QAI_4F:1pL2`spY Ia;{׸@I~WYId._9(NaM{5c(_ ܏K[~7x97֜Қsֲ$k ;E8 ;&>zEW|oOev<\g&^ɛxϪk+ݧ}ͩI֧rx7.,ZPN3YB@>fA?$߁VݮJmyCH#jo?1WE#?¿w'#?Z0>-EW#=%UHz^>QbTqQB6)1 M?ZiI=dC#=f%7VnZ0\G4y ֳ;) <=86FXk@oLAzELֆ:aW{U8*PJac<ջf8Y'Cj|4 f ֥Ӯ|y(91*rAgvIWlMi%7qٛ'[bl|X/ɬŰ ǵgh5/<zvPKuCxgFn`%7%uv=y[JBeB$Gc^}N ω%ۜz鱟ſƺ+X㷂8bPFG`1W8fmuUCC h1yu}Q; Ơ~E0E"sqUaִ4&7֣إﲾx59CHTRkV#+uT`9'K(wyqfv{zT e^c8:\V;c%%tkI?ƺ 9x+iAe08$V)rxZa><ԉk3kE&Gzс0z5n֌Rv'2jeMQWh6 qr8 Ҫ6w|SӰIKxג\9ydmެ߈5lGeM>fKkj6ቘq + V `cT䪟e<~TpIJqҊCd#j93TRiPo9z+3yuқ (uƛ-+Kٜٗя'8g<~gشG.1-"&8ˁٹdh3MM#G>X0*3ޤM2fYH|`**Q1҄r1ZW# YQG 'DۢFi+XnA&Tf^q[0OEL8ZMHos%El+>6U$W[ku3]4Pq1l㫍mxvZDm 'xS^Q7ўRWU3=rǚO#CqW'2_bg޶`b?z?JhgZMiETMoUUsǽ)o,z.h=wSSiQ]@3Ea3 }s'֦~'H}ⓩJySsA9iAdָqcսo) p>N?!|:djsRL3@9G(\T /\ s[:n+u[7N?*1#<;5[ t0jMD9֐vzڀ$R r?1Xkƶ)_01Wz#'wt848)GN sKAc{Ҋ*ŒcȏwQEC7BwQ@-Pzʊ*G^x<)Tl(,AJ~Yk_W8Ӵ?,LԽ?:(5bfPbAm[ȳsQEpa[2OU&~QEAc3ESC  !"$"$Cc" U !1AQ"aq2B#3r$R&45bs%67CtEFScu< !1AQq"2a3RBr45CDb#$ ?!\@&4;;1Nog phhw7͚q-P7hqvKp.NfsA3r:)\Ff?O,1\Ө[U 9\@-#*fٶ !B (: ] M?4l9@ raoTL'h68DAN,$9ԝkĉأ.s&}eul:"' 9^A% atHdchG{$0NzBS#&9>B%71k Rl :U4s]g0F.I鸾J0vc6@Ĕ2L:$9 @'$Vhv.qCT\H$A2S@I[S%w|%b!1h $e(9&r'K_ZZ<$ :v?4K,A&0.H2[| "ssPX@$?("$aw#Ƴo:N h9X Xr{V:n5Ex%zN°@gk`unJH !Y:nC?0l d)3c.ڢ\HHB$[xkŅJVbs@ 8$G:2wu m| m" ̏ZçD֊ FR|탵eS 8(ŶBZZ0f f2qF&̮zX1y 6Yqv`5> Lyh"YIˑ FF%~b yj{(7t3޵}ً9@cj-6N`50u9dz׶46}8hwA:: X̅qE Տw-G8[I|V|ItOE:Y˃Ix5+]Ng8 GD K88-d6 Doyd۪:vo%mC{א|R@4@{69ėId oGuSrrl4\F#M[[@vb=+iyѓ< ڈrnrU(:͋yW|BsǨ".2Ne,!l ~*r.t81>sIӞuP܂sI2S[L~ Fn!iqt>R f<ֶ,:Mvtb;ܑx)cf_ 7Kk3%i˭#DZk:b;"DT]ys] =?2+)t=,2+w_f6s ɏ8]ϥp@ \5"M&E}FL#5H9\8ڃ`v#$1Z7;,4D}I>jfm΢RIbu40MYf4 :'CGy27:;)N44`(E^(EF;[,̉.9\4hQy p' 9{/ᾢ ovFWpRGm[hΖ8EŎY΢Lc.hm2 ix u>$aSQK3V ()7w6w50ɼX}{Pk0"oVӣZ L']WkZc㉭5L`:a}@Xg tц %t-[Cǒd>kiv|+8p,o)MO{guɼƝR.ՌmM :J~>n ̭gl8Gw]:\.{YIC5J&+{K[C5IO"MQ9.b=fj)ճ GԉV Ah[M~Cpr&W>DVB3WvwNgE`6Z) r/$4qx cdpJF𺸘e*eBp((F ZU%7!m87n՛ÝuD%I9'sfe`ͣVYQ"ax;*EC~pD7?VxnQcwwVW>TZ#4s'‰w|Y{``v,TjǘN ˈ;8_tiu@@Y>`uSÞI;u9XW^k]J]/*o;$~lG&PJ~$O{;GԣE@[MF^f{N|ϰ`ᰍ-8.bCzl.tͷhT4*Se7dZB(ދ<:հt9yiU1ѿu!jAc7Zo \$Qi.4ɈyNW%l)4YU.QKA250V3 qN}+u.K\vUnM7Š]kIX%|fj?K)r>\b!Bm}5;NRX?D5:Bw|ԗel);ۥ 5 I+ThO)t Hsij.XgG $>$a4y,+G8AOU-Qy3 7VVf\9ҋJ72qJ oꃩ5s4'E uTzb#Tϙm7GcT e=t]* qqmIK WirC9H;y&8Z9Ak4E՚T{)u]óf+ pGNŊ3⢷V\JͯPvN#5dT'ښlK6b[Jd_iEj6PMykbD{8'PY Y Tfi*o11|WpPֈ_ʴ<N5͔SbZ]S8*Tpd{?Vњ.HM<:Z3ھ:MIƾ/U0`귕9oqpcaK-[ hQ8guKw^C{*r#qAu:0`|OJdؕ"9DzeRSwgOB)Eh"0ַ+`yGȘgqK&blUz`ϲi-3>hPa3) )Q \B)th˳'e:}%Y+" %$lěHxMTt!Q+l=Xnh 1J#opSI[C 4X}{ͼS|V3| ;̔%B8Z˜$~Yyb+*5SyhuGtoIg<{; Ĩ::;>P2yS$б J8th8Ek*^BGLkm}3̭Q.0lC徚${'xGy"DX_h*vN2#3^ s 2|ng@ʪ)pcðMi7RtVoXL3hҦֆ])dhyTc(I&Sk|jJ-)KSӪM7%C3H`}7 3a)=Lk"1Qcq*fao:M.m @<[+`F u `1"49=#@6EjEm%BD6HPi la:HQ ' $q3`$+e&0 uv nDf S$VB%@ Hp\/0#pcPz+J-1}\ {:o#YK.gpX JCEKI #'@+QSwj].$A"NUR. "@Y 4:ր7܈O1LfBw )n$u]1?I!d'w4{y5sKp,̹}4ZCsd ~#&^krK'<]cE2]LMH1IkHF_);4–@3]s@k ]"fCw*_-; 6HwA &A2HnG^pѽr$&+8ao\__S^;Zd-^opkԤfpM|3jb%^ {P@'rfe`\^Q苺M%}oxn")C qN%Ki/1uS8O I%W)p. [ ,.i #VTA'D{@'THscR)li91-:-xOMt;jym2:"ZFQ,'&Y8|ap:Alk)t-L GE M:X'@# #HtS4T*W M Z&P!pRoU 76'U`fmiLhLN@*.aMd̫1l:ǵ8jL9=LˇD ShiD&ln HmtŒn-)/"ިe‚Zq3*R؇I=Wc߇qqՋ= p~9# ͼ[ QbK~?4FjEx]{$!sX`+>?1\+n:_ StЏ8B8@?_UJ&1UZ \ngY%mCS%b0Qї naĨ&ֽ?wS!e7LYjr4mI+~H$^u+E}Nf˕>M&Fg5Q RK@pc -g4Hgvt۰lD2wK "'s" D`/$}),i5ǯṪ"-8HA.&P4̅p6%SS)1ȸRwN U\&a JIq `#"@:zy1(2-WUu%_ÀKy@AE]g]\x%{Z F*Pe 3)( 4 "?VDIU>dJ"@=[AQX @ }?L6ζE*܄IaHc&a]&$X#kOAv=H&|ɖFО@qwlhC muB/c #O xa$L{aB‘@+P ZMKD4)"V" T$̍Je:\34PiqMӀ!?J+76O0[T[c/[|Dxm @:}eVwPCK6sdJ"yPz=n'yQh61n)[O7{/4 vM}88%ZӨǂ$Eׅ-r31(-!6ZtXZKJD˟YΝ|8"&FFޗYMj$ ZT W #>t\r qewpA uZ.Z$ɝLW=QEPctY_PGԝ^"=M@ ֛!Ng)Jl=b[A›CQޫ`;@4{m `pVQU5v/ >RiL  K`5M- -Ѩ|U$"êJZ Xh՛]O'IEfhpTq3M?AC<$@$>I |* 9 2-tx*&alH,1nʮeXؕlJOú{U6#ؠ0>*uH o;+-S.$,ESi geb);6S DNm[ڈf|TzNi*]#&H2|@ǚfC@Tv4Jn͓ @N#1$")NT.GabʇqM)˜]J;SU|_ OJQi[ȪT󨻺&\Gx?HܿSyˊp71ƅ 4mR=MD*ںHNTN4Y:tȎ XiYpcN#I+P"5~$E[wzd^-9-b%K$'X<}$8Cww1겝$&&]D e*$DPbH"sZg $8ˑO4:YuHnC =.ʓ*ЯIREgܢ pjnڂIIָ RI)EsfUt TztJvTcw|ɞl=͵]نnW4dmjqfoP=,:l,s$LԦ;x mM'c.JĶ"%:-;ly0:4L^=cTr?-1$V\[y# ~b6=TVq%tDD1媟@*P=ܧ~OEdY[g@%NA\xn"Z'=FZ:Rx=<ť(Qi>.lwtJnq9!xVBGwsW3O 錨g٤->αWR1#լ%>ד?|?^mccc]R߾deK  #M’&Ady2 %Fdz}9ftqn6[l}V97It@{dNizf ̩&n[J{erwg$ΐq4T=__O`Sq|VNska Ηv H keo`^u\\G8[Gs7xbE$Jڸݣ܈ckB}5I7'nyF3w+X!t_]!kbIBeJ@[NQϥIΗ=U\#)7)D:F +$۾2>賘0ML p4\5sx'1d f5I 4InoKbNRR3K6;km 5ݒw|_^`|oC;hk~_SݿdSxF1tƳ/Bu+$B}=#z~NfSwd"(N 5Q j9!Ruvn'$&ȡJ;f#VF5 )x خW=gcW1ŧ ,g1ˇ?1+ ݣ%3mhsq8HZOv}>Ic[xC&#uO < $J+Rk{䙆Ci9P|Jp\oU'8kX0ceWE"_N%ի5m~g%T, hq$d}ۨ]I+-p :C~\N%ǛZ8 i!(|tU tgPI_}uY{UWR!uINxݨf6H%ԐߨO! jYRxT'65ZA7.2S#(Um7T;>XKeyWbab޶2\QNjW9l}QLuf;BbӷZw Y5VOOT3lc/n#, 7{"{?Y1&!szFZ w1l5:W@ml$ 裇w`MTa̎/sw&( Cvm SNTy?pjaMZ鹛!_w2j xŽؘ?xLZ16{!F*ޅK&JbC ދ"cr,S%>fdZ5 5R(<#H &Qrt=0cޗ=T"c vӪrI!BǬƣt,(FԺ 5Hh +-p4fGÉ _CeKA['06>* T17*e'@ 0.W]k=N>b+l8ްKdŹრVje3lwO'*h^>^벧a~OiooEʰL(TVJIt/DU9$)l&($K@*Y"O6d'ؤ4oitIKȜ,`ґ!D #D̥>bN;BQ/1,V@ko?bH^kXMx*W&d|6p[pO&o~YEl ;]tZm?c$!}b5GNњKKrA1,qk  ^'PHYj\&g :"= Q|o0!$9ni, *;]k.sduFA-kk¾5<L}Ni2M7}Z;XWTbDjOk 71UC5zEP$ rcp$F 8mR+ | 4w.g6lκ}F۬ НIθBAh#2%͙O4dT{!-`sn~I.%&jד7TQ09H! heisZ1UC`x:'Q}_ Zn@twD+ ,dHLde)3V4 LϊC}FʃFV6uVx|L_9 ։/uZS'N,/UHf]=,%&.^ ў:tNY{f)SWOg2\' ,m ]6[FQMXQ.=:l M h 2]u))-O(1CluKkIIr2 .&Bd'T`.lAc ī3QLU^FRqm/\Wy;^FS`w Nb0=YA`~`RTiÙ۪̈0n }~)ۘxi{`&utHy4u%-q䳝." ŤhK8 H'ed Hg%phLl[arg4[q½ 6g,A뽂Ό#''OWR6Y*<^a$JiAY&fQalo2 +"̉SI6/B.@ėRZsܮю% -c74Yα~)t+rл DGB %hQ=qdDȘI3К!3 i$F:@DJQ{/Ln =l'Dx zkdyZaPtUvmƪ s"+"]Ї4wA*~Z l%As USehz+Z9:3u>JƃEX:+ I%&e@րtU>+/옹{e=Dװ7uWWhP?Sg%IuJ&70 2!S",lQiI 9R* \k*H!הTIHP4R؂(ƗMЗ2CTmM"'}0='c; A0&5'^= W'cŹcI.mLK0gF dڍ .|-qsenidN{po!!gk+-юh"vܟt`1-A0K~^Es: pN2t؜f.eKAX,@ O;g"I]S9;X G=>c4M?%p{"d6CFb @'Qf0s'J,HII7$_ǝч \FjvGk\ل;PS,5bm'1nUer4==7457 a@ۢt+GAp^ C[f5 >^ _L* nYZ`U2 K39n Ni06UXRHgtrE/Bփ4ʟE΀m~.A ʔdIMMAd 2 Lyl}"%L" #Km?Y.*M DmEcM8tQ鼧iࠣ'IQJxn)1ƨˌ꘤i6&2E}'ugīФ\ĝ!$:w@? 3R40f=J]+Fs_ N?UqL|{TVc<:*I_SWQ79G3aWю1D3ΘnbZE>Po8Y}JcC͆%>ѩٝ#ۈfєRΜF H6% zU%UCxdp8).:rˆ^%I8(*EԷ8h g#Ϙ{8gޯ8A˂}"]*e :D,*R;GuDlB{KcJn @T3 2Lvo@a=2L8l;s#hAMX0T0 6[)wrNk%g1&WOB/5I0NﯩXF o"]33`Ť1" kNXhH-wJfb44L{"~ *kqS sH je@6Ϊ'>H #^)zDh6Ux$3#[|gEFb x)hp']!sJ]`L4E 8k2ÛUE0]+\+ V" 0UE ]* V"Y2:f7*$\uٓVXQvF)'U_BԺdΪNNP džC@mt; LmH6)>wb|e%<۝S馺4$5u ;$REG%0PN?ʧykXS:lj8?)Q\LD/ ss3c8z֖ Y\V1⦒XYP:C Gwxܑ]Pڔ~u;[uLwADxI͒5^䖇'uwY7gxsbcEp4rE靎1M붛F]H2WrZB 9&fnD:wFof%6-F3YBfb\Lc:!sZD9e Gldw&.q^pR53 ˸k|KX 6nCNckM6IcJ%ĐL:}:Kڑ=:łYvH:YAU6WHZ?-qJx\ oϪ]'ӖN7cUU!ursf|""MhO%WЫMUaynf%#oavOsCr6> ܶ4"T e%6 D-0fDpK6t*lq!8d~)5#1(l.46=^@.k\u|U)N'Q{v-ZMUU0+bfv}F YPփʇ P{x+ jHĻ@Nn9KZFNT_6-aX2V2 jǜ |TERlD&x:Jy tk̈L#Ta-FlХ >?j.6X.җ:[bTmf`Uٖ)vmP9gZMe`>vJKŸ#j֮O\ځrvqO}ݏ1e*-9jd|Pm'=L E) $vBDGDcf)i]. Q80gbY`hVK?;0];hU~#;ݛꎰ." >ru)ok4`KI:kdtyikZ"6ѿ h8` >r8;غ.xsEH"RW]NjnӪ@~Ii'ڑpke$9kߢ*n >@)>)h{^A.Ӗ8ЭOMM$%j\Q^ 9CToHU&H:ikn,zQT>}n|6: ܖe;FI1!A{%1dNI~cش=t=Uk[sU- ]_Z)rU_fǫ@mgj9r0pf|F! ƅIp=ʤZqMUx"%VS>S)?0uЫ[E 3UM{мKq\Vh(S&$X]?HOA'ל03g9貊ULX7A %+Me7 g)F$m3IA^`: :7Ah\.Rp%<X:P;XIp71=Ḽj\9<\憑: !eZOPڎN8١d UsjߘVy|M[ .hVk<?Ìbz({ȼDnC fa"-25Is6HXឱ7alsK7+n >Ѐ$8m梱^D}uOg/7uϚwFWp 6+lYpdL*<; _ue7Sy܋(ٌ:˚bu}2xGP(Z@WXJMMVrv2v^jeYa.pUuotZ(oJo1O:r̛(w%#9>aYi]Mp)^HUxhl(Y Jd#'Ѩ L)Ts3JC`.Y&c[vUsxfձuƁ'Nŧ40Xg+Tk$͗=3zOqjx?aKjQ+MqT|6JX|hVP."C$f#|(Pw.@1  0 r)2{L_]0=)3I17+I޽d%2` H. fDI2=uJ@5AB,4N3\ϻG"Vzi 'g]%ΤtV5ylph.=Fз誝7}  jI0&> =՛N:3 ;(F⤓AuS"v|J LiY}(:gS#ñ9A] MeZ/Uzt@St \G`9;c$A .%f@ zhX{O3#'[xf<чq={\AetޏvJrqeX.Dm [qɧiIA齃EjCARqx ]IRTM) hY=ͥQ) {:1Rw/s JeVFQK!h<i1SZڬi}Jd=>kW Rt6YCZ[yi }mqT1-mFK F?%wñlf6JsikX^+ Ukkޱ$*2L}343Tu2Fꂎ!L6V8|M6*Z/)%ڪFb N{ÙGPbݵ[6ؔL{`m ۃҦ͛!eϼC'vN.F*H9O tMiԯ?s7.dėq/e0mUUqTsI$29g6ˑ̭!RsLRL54~"`;: x_nP-LSr\O+Yu!ك:p}R2aަS&I%&L[SiN KsH2,A8-EB\R % fˬ @xC/%a\G rקG{QyC3 l u TJ?>EcsKV{_7pw3oUiY^sR|JֆظZb=MƢBo%`M~a3K+QnvA֪p.${48Y3$ ː&VkCd ټ0Ώ0;?y`\3(FJfpm<7T vn +Af}vi|ihW}*)8YeWÀ`R_bK.$\zY$f$)=!$uйl䗘;nvlMg .3&!g@;SrnI1 sEg41y>g YӻHŧkܤ2`6j:O3Lh/5~q>כ͝>k3|vTe&sLG|[)|[ĸAk\@ < =i 8L#D3;) vnľAD~fipߧܑD1'B3kMΗv=`Ю+Xυ:nwys uUGFNZ3vƍ1 -k骧Y*vl%^Ij{2N7 [܌^tk3ꦻ&`[T38A]-II"K.z{,P7$tq.d{͹@ԅ9B"Jm\ HKl5q(q ́ĸ8$\s:U1ZVЩٰAI'?`i9}`-uXh\NYKE?BOQ6ʜvR+ءUXŞ ǜ״7&ox#uN8U٪c+aш2~ڭQ  Yn=aEZ9x< kmx Ӵ`;'ᄵƫH|R_$<\i S;6Id_zw՚kh.t1O.m\dZH䌸Ene=NڳP<@<( ;B̛4q3D*ET lk5_H|744pY*F\ 7Ebe>饭٨d$Lb kHpbv,mSnSI|[6.*kaD0Ԙ*CEhNH-X5Y>Q]Ra!UyG1$?>Tyv$?^Q mgL9G ɋR7=Eh٪;x['mupg3ldYcvsy@0N {So3pZ,%3r2 wj&.@0="qH'Tt\J Y";fTK@f@1^z4DD: '@_ !C`ƤG8ؚO4Ԯ}gtYa h =!gGl<+?'׌dz#]~`/ _MӔg.Zi u)t:s\'%ByaLpn5*܃ SC!ȺMHPLQ[O,@mAs~ M$CwlǤ8}Md d'fď~9dHN6B˙ImTN`5H0Z_-SͪnМ; ,2H WG'g>ݳCy s0Cۖ:Y(6$VÇ9k7riq*=jIq)s/52H:X4A몍 M =H/"v@lLƜd̀'er-4>28%ge`A2/ur}AOI_Gs(32 i`T%jw65FAsP0-&- x.[IyuL=֒/dA# o; BH܉;s<Míb}]תSZF F]6: lD&˦uh3˙=I/:[m.1אI h~X5˴ >EuG@" iӮ˗4OJv>z h&MBv?$lm ](wD!aii>Mvˁ_1L#pb; @im>H6RBa\/NJP/!3:$j nC ߢIhh#,Nю{ћX fXq,0U⡸;4%7iiFo9}qڂ ,<ֱl.}-& 0H 9e6&v*Ejhlisn@r9tXY*NZGoR&6)aɕI#CC27Cuݕ|P2[F&ް3(̳{F `$qm<托`Вo* |guqp͔E`Z`8alLآ9ymqkfL\?k^ur09VsPq@Zkp9{?Zu{)5KpHCZIRl5$,Ekpߟ-//_aS2] @u be, CZ A%P!g.Ŀ7 ōNԣPAV7_mЕK?J\!Y>H OĚ>A?KfPoOA/@Sگ_ >tg zI/~Es8Yh _; c!Z~a) ^?:UAzB~FR~՟![gͿ07ȠAL<IMԢ×C8~Y?Y+qs.[W{zd LibreOffice/5.1.4.2$OpenBSD_X86_64 LibreOffice_project/10m0$Build-2 2007-10-29T16:21:35 2016-11-01T21:50:57.076430449 en-US 45 PT1H1M 6985 0 33842 15665 false false view2 15404 15139 0 6985 33840 22648 0 1 false 100 true false true true true true 0 true false false false false false false false false false false false false false true false true true false false false false false false false false false false false false true 1812695 false true true false true true false true 0 false true high-resolution false false false true true true true false false true false false false false false 1812695 false 1 true false false 0 false false false footer Bonjour, Je suis un test de templating en odt. Je m'appelle : first_name <last_name>. J'habite à <ville>. Mes collègues sont: Prénom Nom for each="f in friends" f.first_name <f.last_name> /for J'ai aussi des hobbies: for each="h in hobbies" h /for Et j'ai même des animaux : for each="animal in animals" <animal> /for On peut aussi afficher des images: iVBORw0KGgoAAAANSUhEUgAAAFYAAAB+CAYAAAC+qeasAAAAAXNSR0IArs4c6QAAAAZiS0dE AP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9gHBxADO5tOydwAAAAZ dEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAgAElEQVR42q19Wa9s13HeV7XW 3t3nnjuSFClSIWVbHhAYiSPEUqAYUQYYCOCn/IC8BsgvyB/IS16T9xhI3oIACuIkSmJHiQIF ZkxLskVJEU1SMilRJO/AO52pu/daVXlY8x769LnUoVrnnh527127Vg1ffVWL3nvvw39MhK8i /hDKj6Z/CACOrxHNvKH6oLZPcvWXQKEox2lfi8ejdFxtXqyPKiL5pBgAmOO3hQ+rCPLBpf4V /4gvSvo7HlxFy/P5c+XLFQpI/JQAohI/5/ORRQCCbCwHof4TzPxkWZHGiyZAFRSFOyfXseB1 dBeoen84JAGa/tapUDU+H4+tqunOlBtNoy/M56AAh3tNGj6jhHCMdA6ji1DVcoMBkFL5/ur0 FBrFoQARKB6ICVClc4sDf5IwqRbcpR+q/xG/XMfPFymnQzcXO3pbuXmE+v/Le4Pg49lCpbpp RBN1IFKo6vQ7D5CHjpUgPk9EsEsCzDpQaej4tSUZ04w2axICFznUFxMXQ/xgpXFUfuWDSTwa EyhqYfXW9pvr1QYN50Dl2g45//HyTOeabx6mSmHz8l6Q1LyG0vw3VvaTVMsrGi6Ixsu2FWEQ EnReQPFd1Opb0JCkqSg3ptFu0nLTJjegFk95nhThho0FSRxviJb1QrWShH9YHgs02c+Zu9kK mTBa1+M352ttPhs/ki5Dtf3+5n1pxYwPzdEIcG0nqbpZ7Y1QTTe60uAZZdHaKczojo5NQfUC ZekHP2AZgBysqQe8Rw+VfdHOKN3W3sanVQUiMZ5QBTGD2YBHutBooE41Hc3KWF7/xWEXDV+2 DxOLnYVtwdwu24UTeuaf2lzGu6lRmAzOK6M+g4vNCf7szdfxlz99B4M4nG+e4PT8E3jPsHQN L97+K/ibv/Vl/PXf/O2rncuM9s+fbxBRUchon+P5179rX6SV8G1etvPnMfpOmt51XbK+NAm1 UqhU3/zWRCi8CL7xf76Of/3v/gUuLk7xymdfw/XbwKD3cHq2w72Pd3hyF/jtN38H//yf/Us8 /9xn2pPVyzx5a1111ubqZOURKJul9hjzzpCxbCWbaIAakc07NJo4hFpb25AzO7N04hz+VhF8 9PFHOL/YwB4zXv7ca7h2/CLuPz7H0/MthDy8KO7evYvN9uLTrSZtzz07Qs3SbO3/wudTwEda Hjz5kLaPeVs7rx0Kio9Wg4mo+vp00tQkCNGE4vTsBO++/Q6ePtxh2DA622O1OsLZueDpY4/T J4rNmeAvf/Iz/PBH348xqC5d+t6QavYTVCcdlOPSSh3ycxRVXttwHSC0cSyNhNQGb3N3qhjQ Klnda8eWrFwSwOA9Tv0OvAYuduf4kze/CdtbXFw4eCfwDCgRdm6Dew/uTmzdoQ63sZXVlZYA oxVcjuaiVucbRlQ8RHUePHsrCSDSPTYCJSZNmU7+3H4nVq+u9gQR008FG4ANw7CFtR1EHaxh GGNh1IAoZBluGFrVm/n+yzLGdB2U/isZczn0KE3W1vhOFjMBsAdlpHM+gRb0M93pJWPUxC7a hEzEBMsGd9bPwezWkN2Ar/7df4ij6x2+8fp/xCnOsTsjsBBuXr+FVz776kxmTCWHHzmtsfOa OKDk2UGNAFOMqhNhaON867jWLoRnk5CiaBctOwDaFyTWQIk2N0e1OMhbt27jc6+9APv9LSwZ /Npv/ApEL7C5GKAqWB0rdteA49sWr732Kpi4Wsa6167uixDGQXHJvKpgXLUJxTSZFB0nDlUc e1AC0BhxnVsYi3ECRiFNMDVjIIOgKhj8Fv3RgGvPbfH62/8Gii1uvriFd4rtObA9AQbv4MRN kLD5u06zAq3/neJrWozYtNFcqrOSYoBLSjs26PtOgBpxEdq0YqzNNJE2pS+nyjlSFeZAoSqw a4ujGxamG/DRR/dgWGFtTE0JMBbwovDeFaepM5mY7tfQicbqnLPWsdUawadaOeSCH1ieC9Zn 4Ks5458MfrjbI++sNK85VCW0OrXTqgoyiq5nKBjiCYBv7DQZAF7gvc9Qus4ml6PQf4+tpdo5 6Sj0nPwZbHFwdEXB6nTYYpSutSBKCSloKcCmGe87UV6aiXnRxIc5aFOFcw7iBWQlIIQSLkQU cE6hShDxwRRQmy7PAxXLgFINvDSnqQufpGrJ09TPpLVoZSGypBizXR6X6kS4bc6K+ecUzU3L 90KBYRjgvMCIAl6gWoGdSlChXKKhanHQHlAESzmEjhAvDWtA0yKvnXiEP6fISuOFoTqKYydA 9iVCzfaxyU72fJhaDa8T5frmb7fn8BIFqAGoUQnnbbpgY1UEXtwEn2hyPCo3S1GD0yUyIZrP w+prmouF89lri0OnH8uTqsAVSi+H5OG0VBzDYgY2DNtYp6L8W0QhsYSiEuyCeDkQgyMU+e0D YQ4L0yaOvkI+09P8i5HiSD11X2axX8iqHiIeCsAnLDYUR3MVIGiwwjs/WZY5/aI6tKNFeHAS xOzJ3Ob+3Wh4ZXY/lWDr5Uwju6v7NHlcGa1zddVQVlaFSB1jaqmycgDnvUgGQ4iwP4qmaTSz dI+Lr7i8gDprBucEe+VqLC0Z46kmaTRtyfuP3x40koKWCkZRc7jOgCNoqPiLD84n2TlecJx1 sWukpVkwWUDUKP4+4e7DH+w+oY7tyWV3rg28aRR36wKQrg20pKqBkKGKOnLTCmSxBhggGNyu 8AxGxyhC0v11WJrjQFShEy3X/5ZiYVVt8diEbdYfODTvni2dzxlSqtRci8Sy8UcI/Mu5SMz6 Ehgd0C8Q4PwwG4DUGG8O6WiMZdA8AD2pf2iDZLd1V5qPGKg2BQso4bJpoLYK0BjN2s9qYwdr y1HnB6GCEGJT73wMs+pytubPBcEqnHctCjUxUVoVApZi8iJtIirmpDJChRpCE2c4L+hkCnSE O9J+WzIx/HPLYlzcWmBDELXBjojEzItKhYSqqgRREKwqvBsmZzOmli2yaxJ5I2f7VENBTSG9 zt/a4+tiCMY8ycyuXpmtTUjAVdEi37Wa6p4CSYxXvfcxoOeiuRGWZCKwCZol4g9NZSbR2LjE pJPUdL8fKStwrMH07OGWpoCK9ocdtFB2XAIZgZBRqXqwTYQPbWpnxApmgFijjdVF2dZLk3BI kjJfcp7GsPMHqt9jp8pztcxrLnLIHjmtZdXZdH3OMYoGGytOoH1NVqPoyIq6DG6XWX/U1NN0 XlMxB263qa1CW62uOWUjgRaIYQpi2V+EQMfaSsnLNza45hck2VQlkAw4C5wXeE8wdbEylUZS PQ4K54ZWPAs0l5ZbVSP9WliORNnWLkBNDQU4+ZAxDBmSJi2Ejdlw6ZL4dTZiqJh96UoLH5Vm 0pyWa6yqUO+hXjKnNR2H0wXGpwY3TDK5OfRpvgQzvRGL5ZrRzaF2IbZgTuSIWQLPnMrlgMxi GNZS82a5CdoWm4tAKOADyh6GFURlmRMhcxYosiKc21VLucqYlGcT67oMc5VaWCnDEBTSYLJ1 tSJHL5o09kCPemiaW2iOhx67LHlRBzIAdww2gtV6hWvPOWxPPIZNyMjYBue1220aYRHRcjnm yonPvL2mEeGzYbdXCYndA/JfOePSCAa02ZteusxyrUgB5xycAwCPF59/Bf/gK/8In1y8he++ +U2IkUDgswTbA49PH2EYBjDbmQpIsdtUJUCih1Ryo/hoTwxe12FGAPgUK5izgVfQXgKNSi7L FzBF4cNNufvgfZydPYBdKc4u7uOd9/4YpxefwABY9QwnBGbg+g3Cg0cf4uT8Mdbro7ZmNpNa jxE0PYgbT1i6ynE4Xvc1AArL3IYTegVhTonIM0uH5krP2gJNCpAqNrtz/Ojd72HYnWF9g2GN 4Of3/gKdJax6C/EOTgDPArkFPHz8Hn78sx/gM8+/kh1fc+t0DDviQHOgNV87lGomS3rWTeZf DPAipvgseDdVYMVlx83sPCgEgnd/+iO8+dbrMOsN1kdA1wPEDkQOzApjGb0lrDvCzVsGZn2G P3/rWzg5fYSalbIUzTSCjg8RmTxS50yAhTW2UU30vtCa0Pjq1L01iljo6o6rAZvpkhSTZrBD BT5+8AG++cbX8OD0L3DtJqGzBKYYB5BmcJqZwMzoLHB8w+OH734Lr7/5P7EdtuGSaDnMqgV6 2UMqZE1rraeZ6sNM4saHVA73gbyT1zTlz8t2eNw2c//RR/gff/zv8Z3/94dAtwGMgFnRGULH gGWFYcBwAc/IAKsjwsn5z/AH//X38fq3/xcGv2uQLMxAoUuCxMT+avlvlu/Vcie0wpdzgkAz dlIvtamL6juJvJdYKArFydlj/N/vfx1v/OAPsJEHMFZgLaGzQGcJxjCMCccQBVgpePZYtrnx nOLp/bfwH77++zhaH+FLf+PvgMDT2pWOIoJ0DFqOc8eJT8uD0NLtlKuSmslx0Xm1FHjFs0UF h2Qw9fPOD3jrvW/j2z/8LzjbfoT1mgAmdB1HoRKMZRhT6vahuCBQ0XjehOdfBh588Ca+9p/+ LZ6/8wK+8PnfxBKGVoSLBsO4vEuoLk6ipOEjgSVrvMCPnUJhhzm3ukvh8gD85/d/jD9/6w9x //GPYTuPrgPWK4P1ymK16rBad1itLPreoO85/F6l3wbdimF6wHaEF18Ffn7vO/j6f/8anpw+ KPFzVdlFZAaShH8LNAt6HJuRzoK4pYKutAyb6wI/luYItVcQ6SE/55unePv9b+OnH78Jr+cw NsCBfW/QrSysZVhrohkIJZsMxsQKbtDaUHhUy3julS3+9M/+CL/1xS/iq1/+vSknUlElMAJJ dbVZ4npJT2mMKaer1eVqNE+LFPTMoRYO8YQRwfr4k5/g7fdfx9PzD2E7BRuF7RS2V3QdYbWy WK169KseXW/RdR36rkff9+j7Dn1v0fUmvLaysCuD2y9Z7Og+vvG//xsePrmXAezQK15591q4 Uv0tEvHgoM373AhxaUgZBzmipVm+qvFfvoyXzIQeqK/bYYP3P/oB7j58B+ABbAJtyHQGxhqw SSfuQ/xqGNYyTM/oekbXGXSdge0sTGfj5whdz3jpVYPv//ANvP3ed2N4VHd6C/J/KjGcCgSR FL9qpYWH292pjvE4kFcs21ii+TLEZV8+PsEnp/fw/offw/nmPoxNwjOwlsHW4Pjaczg+ugNj DIgVIA9igWGJDo1gbLgJxhgYZhgOv++8aLEdHuJPvvMtbIeLxu4pAhkkPeoEQdPzkBy/Phvn ogq3mlLKp0jAxtHAfE6ueHjyc9x9/BN43YI5dHWwYbAhrLoj/O6X/inu3HwJP7v3XZyePcQ7 H3wTHkP1PRzK4PFchQJ+oPCwK+D2C4wf/PBNPHp6Dy89/3kkPqsuJArBdlNFkAsMx/DQK2us jIFujJKKQ/tp51GlCg+oShjeDxh0wPVbL0If/KD0H8SM6ua1F/DXfu13cf36Gp97+VWIB+4+ /R4ePb0HovCeFM+kSgSDoEzBLpLg5vMGP3/7Lu5/8gE++/znJ71niPZUJvAmzZeSF2L6Oa3W XJoZZ2NXQLbmy97FK2qTQ4fAfvA7PDr5CNvhBGyq8jMJQASvG3zv3f+Mo7XB0eoIxzevQWlX NE00xx8pxdVIS2JmEDkc3yQwPB4+vpftPmsZXJKKnKq+8eMJGQvHxDPb1yhYLkEJXS0pmGvU za08VHOD0sUwnN9hu7uHhw/fhmEDLx4KH7VK8eTiY/zRG/8KvV2jtz2Or69xcnYCJq7KhQk3 yFBDCI9EwWSwWjFUPZ48eZhLOTIzH6EhcM6YMNVnoQKEQ9pSAKtxSz04k5ot0DEBwg29Jtkw rx63ju/gxrXbGIYNBAxiA2Kp7KaH6A47L3BPt2ATwRdCbp5DDO5zSxAUAg4YQyc4OuJYE5MA LDBAUmNE80tfVQ9McJYrJzp1Xqmp5dnmF7RmAg3VqNw5wb3Td3Ah90HEkSMQhAbSGAWEtUtG wek9oEDWYM43mrWQkUkZEI3wInC0ttieDRFO1Mwo1MwsRJwHg6bw2fTN0uUA1LjTKNlq22ob njkqmGChlVOMtdrMGjk7PYU4B2YT+wnKxRNx5g0QRUQLQaAmOriMNmopjUABNQC5YEk9OZxf bGY7pObKQi1o9GxySMBSmLDB3JAWdEFQV7G91NDtqr4wERAB7rzD7tzA9gRPBIGAiSeMaa5+ B82e9gxwTHbBiXsWVv/FuYNXjwDkM1JLE9Fl3r5oLlEhYyxRW9sbVJIMyxxo6IeVXw4jb8yR GIrAGMerY6y6HsIOnDlfnC+GmWLQz5mFSMQtljsp9KfKBUEE2Fx4sJESQVCLTo2XMtE84EQ0 rchOzUBL/8w2lmhmcgbmG+v2BcxzIz3maD59Z2EswedmtdgCquXkONE2RxUJVcmzDlL6TSgc BEAjI1xhOpqJU2kk6GmEQzTONtHY2/F1Jtyhlpyt8cW53rerl2gWIgiNUT1xiBkFUI4n1Gie 5rpZKYkARL5BlSjGnWEWizbUnzDEjGGsGY0VGdWsIGV0FKYzxegS0t9Y2+uipSVqhzPQ3ACx T5nazuGZoYGj/tIFzpQGMhxR4OyAuAEoS2ch5VBHfGhZYjYzq0ybSCXNM8xmgqla/mOMZEnt WqFryrwmy5+AZ4iN91cOmnyZcy5OlbCSp/eiYAUMoRnS0OKkyLlywqRVKIZfQVV6a1rtRI3F joAW0oKKz8awY6aG5GM2pBSi1Eu7dBhdpCzsD5AvC8FSaCcVjT65dKlsVnCqzNqO8CvDmppF ranBThTiFWwY1najIqLk761B8zYiuEyj5mmg42zNLr19akfoUqHutb8VkC5tSbcsPWrT6pSG cq4iRTZfPdUiZzsRBvQK7xXOaQaxG8GqTBpHEqozC6pMKEm6YF7aHzuhJWmlVQfagzExbWly RfGcHCqpEqfUcRmTR6kXTBRCoW1eY4U2AS8h1CxC8hrmdYkgUO1dKDomMBsIII2MiBo17trE t1R7emo0cRwJtDeniQrQNOwutGRdWcizhAmM5yvEG5IjBFSECQk9tBrTAJWABSTtjDUvkSDU LFjnQ4+tVkN646BHkdDqJOIbza0pSbkCzK25mNPYcnMks82TGbN6Wd/rL6hnuZCQCaohG8oK nLq7o9OUVCRUEy4yRS6xqBiWfeTS5noVoE7hnMA55NJ4CIEkIGgaHvAeKn4kMCmdkyoATGjb J8oCS+df6WK8HjRKEU3BnqG0NAJq6dmc2OSmJRKvRAPLVLRDFMoCEc6TjbSKE71WzKTUFS4h xEq21bvMnoIXDyKKmirFyaUOyCYMrLVWYjhWfEKJ06dFyWwS4sOKzKdsCoymU7a096tCijU3 XbQ0oyXZUooEFDnNDV6cZkjDGBHaPLwA3gPeeTjvo/sgiPowTzu+T1RCV3ndQgUEc0GxUksC qA83OdpI731G1oB6VU0FXDG6R5pGyU/SpZp4sO0tXcjxf6nzROOIFG1sVNCauJwNNSljMBcS e8KicL0GwXqNAyQohl4SS0Iuv3diF6MpYImFVBF48rnkkNJakTqNxcgRthVeu2QNdRRq1R9a mnp0MM0zh0qVjdVo5+JkDU2ruTnhQJTyXqs5BgrvEEyBS69p1i4vPlKTgtNKzivTNeOPV2rH 6FUdVUQuIG2seapGKjQ2nITMaJcFwUb3XYIjvTRmPVzIVBn8QvCl7EA42yn1AjEEiIDIIPV6 SWTCBEFpaF9yCucIzoXogMmCyUBiv20SbC3U2sbWKqVqcuEu9MAEjINFoQF1L9Pno/0KZquy sfM+Rpsh5LMD4lRnOIrYH89WhLS85FOvVTWvpZmkEasEpBJJbZJNhfcebhC4ISUFBN8M5yka m53XntlbjTOjYsI4nqCSxvSGGu5mranpvO2cuo4BGF3IwBIRIn+UDgi46oFEWlqFKYVg2g4H SyQL+FQ6UkjEE7xTuF1ouBOh0NgsickocKIQ73IVt7GFI75stqUx2VBVMAuMMSHsY4WSgJWb WWHpvqQZC7pkCuZnDuASYOUqxDmuKGOjJmGkvTgo0s1nUC8N/bbiJYw99SGNVUkNzppvjniB jwN5aqGOnapCclTiASgxWDUKVWGMQpWhxFAuI/8pfU+jtcHe2gMlclCBkS6pg4GSVnIznl9i lTVMpshMgHpOIyThtFIJ1mtGqcIjZGqCEH/6QUMcW6WlzTzD2GigKoD4gstSiVCScJkZxpjI UCzbBJACksZM53ORtoIwyf33dNF8mmYQDWpRjXaocU0deWQFKeVZykLFNIlqjgKQaJ0JzAHB O+SUdnJtKA5HM1fW5zIRw0BhoBAYGADBoTGXsSiM0oKVm0CS88rtSBN+AKqu6mdHvebKN43x ToNxSwtN0745mi6Tf2WIME07qqZphjJNMBEicdRJVSdraZyREFdFDJQ2kdCAuTYVAjUx9OII DBVORnaswRTMDFaMXpDzLkLLCcGVRzkjTiJilBkrk0lCo/CsKtVQBlciLOgp7khUYbREsNbG VTHqiU94Q2VCxu1ICeniaL6EJGefpIBEbSwmoTjZVJ6x8xrVahZ9Cr7opBA5nsCRZ8twCMBp NPNgLGS0Q9YlolFlq5IY2RDnvLwUHdFs09Lm+eWRYm1RAsQHrqsGMoiP22UlRQBz05yXEoX5 8VDxgrVZQXowH3apZJOZ0LHEnXu4UlZDGFVFtaD6kbqZhzxGuDGBL8zagBwZFKG6Db4E8JMc P7fJhSSFVIJgo3ApbHGStZejUJcQrINmdKti764Vhwi5jBAp2yOxCVPfilBHFU9FU4JOFE6K EzlFIitQoiPMkGM9HmOMg1DUKoGqy0QOVAgVUaldVAcIYVmqNCRew4gBPmqr3yPUTxERzDbX EeWlxkzw8X3MBJBM6vktYqlZk+vgXiKPKzV9eI8x7XcmdtVRcTFVDKQIlEpZuWn5TNkgABbJ paJ2dMmnrMLOkTmWiGTa7KdFeQoQc709gI7qDSHj0VQQY44Qpo9aFjOzuN+eaKH7g1pKUQvv +QoEb4VcTz+mOo0ggHPBs+yARyP5aGir18n8lkatxwNmZtop56elLfQqUJkZIyoBA4VC1Wfe VPgqQd0SlDMxqUqNsetFCkMux5I0qeNict4y47hq+vyEMpfH+Y+Ora2AdU5jG1v0DBWa/c0f FYObq3pXFVinzCQhRQLNO84phcZlxPJOQsmSrU1ZnCpguOopoNLxlWLe4uR0FBEU51eEFkPD RjvSWJW6Ab+MObH7ytgEXM45upIpQXZgRAxxFdmiRoiig8jE4lTlIA8lzXisSCzHeM2bRgYW DGIQbypmSwG0FW11tYDUWu8yFtNpbUI9rpP7anOiPCk/nvMyCDMa2TOHtx46nbNh9eV81WC7 AWwfGy04EomFYLgDMIQal/fZUWgcAuC9wEuoxopHFGYq+xR8gUab8JDWzJWWb5ArCwSYparI WNNScsNVVSGZglTzmqNdNsWvZ2gDXRI+E4PUQAaFGg2zXryvEKMOIg6kPnh59aE0EidxOKdw onAQeA31rlB8jN69GVRJJUWFr/JIzVXbUg6XkulllUxYQ9Tu6BC52gNSRyEU5d2RtB2AOIlT 45JQXaKHH661gb8a4LyUlpIoPCngA5FN1ULFQhA004sPwyKZAPVwxfVDYjeOj0GF9wJEULxQ RKe7fQrGgx9kUrBs6nBVyFcT4SgVGEd0eMsCSM5oltH/OVbTkpbPxa+1tvuIpSacQyRoakgd DUQZij4XDZ0fYmZFZQpd0pzkmJrB6GFVJOyBOcQIIq1pyCz7yoExTOXYFiL50NOZhdru95VM QSQqjGeqjLFUzTSh+fdNqxB5plEm86VqQRJmDtU1lVEsjPRQdFAQDFsgtjDlskc8GSaCZYZh D8Mpuigj9INANWd19di/cf9vk95SEjIvbARMe1ZloWrazFMlSqFjO5m5GhSmM7a4GSRGc7WY dgM1qpxHmO9Ss1AYCgNCaFQ2zEGT/dPwfhPPw8T5gZZgLeB8PLIA3hKkU5Cl6Oz2RSgN32mE H7TrlGYI1nOd37mBLhFvG07VTOGw1thZujgUnIhtaRhknUzEuyUECIewiTn00Cp3cbcLCwMb WpAMwxgGxMFaG9D82DGoovAAwOHmGBPL0UywGqIEtpw7DCVDg1qR3WKEQNqsnBJOK+rQeo5o PLdaExnVJn5SgfWmUGGe2ScFPZ9obxqQEp1JZkDPzUNhhekURhE4rIwISFtw6ui2iO1HHUSO 4FwAnDWSM0KdK2ZZGiZ3SrS71jJMxyCOBDcaYa5NdhXT1dma2Hg/WxpFGzRhYmXuVmL1ZXwx jVUeOy8q1p6q8ghztbesloketd2vUTKFYrUC1msLzwy74jhCWsHchVkENjyC/+kA3UJ1A6jA CwfBDomoUSqzDIY1Bp0h8BFHM1PTkUqVwEtheLdCbScXES1pLPJQ9mlZX2EhyM0RyUjonJpX 9jJj8jF04swEnHLpuNomLw24MQboVsC1rgdZhqoJnTLUoVt1WPUdrGEwJYLGGoMYeFeYhYGw gSLUiPUaS+jAMOvAEk9cAfEpoYjJgPh2okYs9TDl0kHDIgwKpVX3TA3PxDS8mjtj01Jpsqk8 kX05bCpTfGi62rUi0UGr9qFC3yISdD2DjA3FOwqbT/Zdh74zgSIEDQU9OsLg19i4s4aelMBz a0PHInPIvCw6mI4jATl2KlYEOonkDe9dMQ0i1XExYRQmvgVN+CeauytrvMNKBnepBbMz7Lbg sOqe2dRd3WykXs3+q9JjEcXFiUAGwAuB4xCIoPIWJKENNM0mCGGXh8ERSDaAj1tRScAcjAlt ocEPGKhnEF+Hage3S6NJQqlB1EPUQeAg6iNhOXFlJeTMGhIWiECZS7obszeCghKvuYp1x5R6 m/ijY+GW6ul80xgqR5feT1SFV9XO7Y3HdIon94Ht6Qre7MBdbM4mgjEKZz26jmHjnBgAcOIh uw5uR3BD4Gupp6ZzRiRt9NPB+zWG0w7bi3eh59MAAAqsSURBVChUUKyN+cx9nda5NDPAhZNw PcRTbOlPldjITJyxq01pJi2VJnyoKqfj/tYx/ppLLlUldSnVDc0XHruNx/l5Dw8LMi50eTPB GIG1CmvTjJhw77w47HbAxXlo5RyGwNr2EgTBiDv7KAPSw4mFuzBwQ7CrRBRtazQDmYSctDU4 tbCgTeTIOqjawDWAhUDzZAeBBv6stmYJFXRoxUu7mU2GMHlie+eEnJqc57gJc+mvxnhyt1Hs JGzIQ0ZAJkyG64wPNtMgztyK406cYNh22GwIu63HzgW7qaIwMDDcg2QN8R1IGOTCFoHeOxBx RMkiMC4CEQfvA63TOYX6ALgo+xi9BM7WxFHFVSLikRRdkr1Hnl5UTMFEeKzNUPQlAV/ahjR6 LbABAe8YgyeoDzO3AtdAoIZjn5YHc6jmOicYBoH3PdSvw1TkncfgAYgBzAqKHt6F0MtAYTzg ncC5MCXJ+wDmhN8uCtTBOQ/vXMRwBQQPYQKrafJFxMREI+IliHCb5l8IhVya11iKnXUklwv1 kFFR4x/nHPwgwV4qQTgMgmSvMEbAUSNY4p4yCDDhMCi8Y6g7gneC3e4CzjkY7qF0BOcY3nOo 2BJAHhicxzB4GPYQP8BJFKoM8M7Fh4cfQvWRjMmpNWBAagILsmZuVjMJEnqWzIBkGXLQ2En+ m2xstp0zgh1Fz+N9EJbKvs45uMHDDQSnCuEALKe83kHAZJqioveJXahhfwQ6QmcI6geQWriB AtjtS8+WiMINDm4YIEwQH7VUAmXex7g2mAsfS+sEIhPw4sSKTMxtCYVHj9am1m3+lMcDSNBY rYYdzG6lNCNc0tHzTXm72nlTW+5sIADHfoG4vAhBsOG3REA7IWAEcQRxgZapEdnqbR/Acg8M nuAlCDZUGsIE5bA6HGAIzg/Rprpwc/0A7yT2FTCIOjB3YLIg6kBkgnCVqu4cSRW7XMDkbDoj TBkyrgWNrRMFTMMujDoYs1LqnoggHso5B7DE9neCcLBfJp9wYhICwwbYnCnOTwTDoIAB2BC6 NYFMqGklLc21UyGoAZgCe3DnN7DKsbnDRcH6TOxgNjDGwpgehm2k2Ns41SWwDFUYPg46K71j FXkw2dscTcUEIcdpYw5p2dlhcZeO+u/c8K46z/qgUPIW1gpBq2njkd8qirOnhNOHis25YLsT +LiLn0DQd4qjG8DqmNr9upKPAMX5iILdsIEYLiksBMQSFrqJo/tMD8NdAH+MBbMFc9BYldSS Kg12YIjz0Eiq5pzn/bwSo7DuTMljQuJgciz0clFFxcy7YNP8tif1tDhiyaRfImlyZVLg7LHg 5BFhuACGIWir86X5bQfF2Znixp0g4MwEp8imQcBj2SpEtwikSi2DJ0jjZLoOnemiUC1sJdTx ttl51leepDQWZmB8JxKKFUimfIfOPwHFqWtMjKXyeL39xyxTZrw5biVow0GbwBVTJbJdzk8Z Zw8VfhdyfRVqGuZSA7JuA2MbChwdM8iEEVMiCmMJlhhk4jS4VPOqSrjGWFjbozM9LEdTYEKn zWiEeC6lh+E/phIsF9o8hYEraWCFbXsJqG2xMYrLJhZoJC0oUaOxNGbWVFlwsI+hIiCmDNNx A3DyicdwXvhdpa7EDXcKnjA4wuljoFsTupXm47ClsBMoK7ZbDxGKO8JpvLEdjO1hTQ9rV0Fr TTedQAoGMYPJZOyC2cR5YTFyqIgFHKmjOhl+Xg9l3DM+elylrScDT/Z+mUkYbBpqrokMxwAE 54+Bi6ehnmw4AteJuS0BtEmNa2kA+uYp4eKY0PdB3ranAJKbcB7DRiA7n8Giru/QrVbozRpd t0Znu1Bby76EY8nIgMkEQVbCZLIgZphk0xOZqe5rkJptmCufC1HAgknY1/I5z+sidL2F7Qg2 zkAUKM5PgKefAG4Xp8aZEnyLQzALg8+MQkkbrDvF6SPBasXo+lD66WN6HAqXIfQiCsVJy2t0 5ho6XsNQD4KJyy4M5wmRQdDM8LAAm8DnrZY/T4pdFEvqiKNLqG1I5khYWBrcNSbFXfUGGGOw PjqGsQxyIQoYLoCTB8D2QkNwy0FTE8MECPu8+jSROTooid85bBQnDxU3bofV7o2CeoJ6E3Zb BsDWYrU6wtH6OlardbanRBz+bS2stbBswNQFB8am8jXa0ABES09c3oSiaga0Te1cl7cX3zc5 bg4zmCuhA4A1He5cfwEdVthtCNsN4expxGh97AJH8ODpehSBlQhTQj+SqhfBEzbnAW/wLtg6 BwbfsRiGAWQtrh3fwPHxTaxWR7Cmi+hZh67rYG0QrDEGhmxuLy3JTyQz12VYTPvFahTe1qGO Qif7jV7WkHzIfgfjnzs3XoJeXMfmicFmR9heUIwAgjA1tiESxYYKE1otLYXAXuJQScTeLoqe 3jlg2AJbMdh6BVmPndvg+PhFXD++jfXqGvp+ha5boe97mG6FzlqwMTl8akY4pa7DiiubxvhX czlCvbei90o9ukQxTx+6ynyCfX2qNb3o5Zdewa/+0l/Fz356F9uzHUQG2A6wNrVDB86/UEwl M8GY8uaTirCFauLMqhLcBYF3BqYX6PVz2F5w48ZtPP/cS7h+fAtHR8dYr47QdR3YWJAxFWGu FDtLJlnF9lnIZWgZ5T5laWgVBArFxKuQ3S4T9NJMg4wAicCaDn/rS1+BKPDGG3+KDz78ANvt Jgw5twRjI2EtFvS8Kz1bCVFKzouEAeEgKGvBDNy8Y/CFX/0V/PovfxGvfPaXcP3aTRytrgWB sikjT2sl0nZJ01xvcc32SHW9aqfn2jrYJsbXOFT3Cj1clw2HmOw6FMsiN49v4e/9zt/Hr3/h N/D2j9/Cuz/5MT788EM8fvQUm+0Gg3OxWVignqAS2340wnIMGGvRrzocXVvj9u0beOmlz+DV Vz+HL/zyF/Dyi6/i5vEtdH0fMypTbgjaSfNANZqMyvP1penMFrAVyT47/1z+lnFKv8e2HuLI mpPQ+WFfBII1BtSv8OrnXsMrL7+Cr3z5b+Pk9ASPHz/C4yeP8OTpY5ycnGKz2WDY7eB9AOSN sej7DteuHeH69Ru4efMmbt+6jVs3n8PxtWvouh6GwiRPju1CTbs8Jzs6v0tdLteNeyLHI7BQ WIg1r6Bt7qBPz9xesq9zbex5PiwzOgCWGR0zrvVrvHjnhVIfS30KEsnHWo0oZc6QXZlJ2DZa 1E0aqV8hkVMU492OCiO7zNGleVbMaHJfetlX3cG26XYBHeTVl5b8/gwt8v/RPkolnSt7Pdro V01DVNM8ppRSb12h4ddMbqbSpUM6WpVjJzw3HnpJ0+pIqmzCrlU0YVF5r8sIxXOCXNwPYGYi cJiJXZiGmX9YUZWaAWOZYmr2TnofJynN3oxUbS+0d8ToXCreLvHxhj9KZfB666sAW9CRFpG6 LFU9RFOXjsHMed+CttuxDncoc1TrXoGlGYRzQp6Ui7RuZdWDsJDxJI0Jb1NTA13ctDJuPhDY hjis0fhZZh02rkF1sU2/QeOrdxU+DeHSbdx0RDBu7OeU47pESZ0KOFGI6tfrrhuU3ehS93dc XEIHDo3d1304L3iZmP8yW6uMh25wXEUjSM37MKZ+1jIKr4DoWpqH825ntatfXpH7Vli7oc/4 xlZdCSI59CIl+f+WNi6p/P/9dgAAAABJRU5ErkJggg== Et aussi dans des boucles: for each="img in images" /for relatorio-0.12.0/relatorio/tests/test.odt0000644000000000000000000003106713615410400015352 0ustar00PK|R^2 ''mimetypeapplication/vnd.oasis.opendocument.textPK|RConfigurations2/toolbar/PK|RConfigurations2/floater/PK|RConfigurations2/menubar/PK|RConfigurations2/popupmenu/PK|RConfigurations2/progressbar/PK|R'Configurations2/accelerator/current.xmlPK|RConfigurations2/statusbar/PK|RConfigurations2/toolpanel/PK|RConfigurations2/images/Bitmaps/PK|R manifest.rdf͓n0Nы~  Xpmk83:[UB"5(c4r/Y9ё*}FĶ{-Y}6/^X%PDKU<V3e^7#k%(?bAA7TѦ ctQx 'yQdIe/[42̗>}XWmN?F}8b1ḧ́]0FT tj"ݘtt ưH avNxmyGm{wxwERc@v cGY)Mtq?ZwW bkK%-D|[PK[DMޏvMAA nzh(NROE(bLVk×@V7/D}dF8*$ -]ߠMI ZKX 1GZ <y7?]\[HnKSDS.qI&F̃Ko*MzbBxnry$ >I3T1~@G іb5>[%{>Z fcg(®rZ#|LԄ S4yރmKc̑T-F6Df NG-J^5CY|s pa. ,Z {~5M@`jqG5 m|:~1 ?H&i q_F.3,o+ydEJSe;=!ج0WP~2RCP(P:@8psȈCqT,&x};E#P [bMZzt3/R0m\>2KPp9}@ Ro;WT(=7;|qci cFpndB͆eΟv?aNY5j2a1_gʂޏ–._ʺ( u2K-.w/fn]3SZH<\Y~%5 =Rh9FYҭOɡKc Pl>PkGuzRBMӘwyo@]Սj \PKAm0PK|RMkƂ Thumbnails/thumbnail.pngPNG  IHDRPLTEFFFLLLVVV]]]bbblllttt|||[[kkppttzz}ŐǓɛ͠Ϥѫ԰״ټ݁đǓȜ͡ϣѫ԰״ٻu YIDATx휋r۸w'$1%K6Yker$BBɆB=8v&ٍ"r"x\?1O:P@uԁ:P}R1R3VJjm `c AVQ&!VG;j6R-VFB JqHD'0=(5QGR(wF#^iBI(19(Ă9yj)QadC!"E 5C)T Eڡ5,e 6ιv8~װ c7Pܾ޷_O,8I&OۓLӭ+ ~Z/g?uu^.VffҔIL&8:6ol|WNsLHNf iӍ+4/tn]>7WN9(:L1(j~]]:cZVfSUuUgf}kÇ^Х1Tب;csc̈T0kb3h%T3Lj(05(aFz&rfAKRD(77f^Նŷ>m*c~πRCP,IbG8~ L/D|xRKљR >"ןR*Z{g1j؞5߰CM>N8 xl WWMU5S鶮)+^eڜ,xᦼ8+Ն=:DAE5hh۳_W\گ_ʹLv YfӴ~ du~tWb;w\[]9HEo\9)8ٷX^Wҹo uH V*fUo^^_]]Wr}ZZ6\ؾz/BpӔg:6wЌ|tT Ȩ% Y1@=Zj}g~ j~ *)e.!b>GqQGqd8&,¥8QDG)XH4BRCcF 7̐Kf(dm@M?_ QݖuYXTfZ:ܴYu{]4Q3$u֞ڬO`"WC~)Ri«MQ"+RHy;4޹.n\ԯ^y5,_C۞QqPDZyZc"Or^! 1PC)0*;:׫!\XŠx DLI'&kLaCX&sj@bGh : Lc17JDLM& +j^a;鬂3C 4 XzŲn[f{fnK},yZmUee{5ۊ[^*6kysnvZjw[ǚoxnNxSr{nVԐ9/yYfyy;<8F!___߬\܌xz>?v~z~=+_ɰ\.gj=!V1Fz2#~]nlvu>SĊ wnIT~NM;c+0h]=KIS?9 h;(dQvL ^A"H} 8b w8BGkOPVw$yk;\՝ڂ-K Pu>_4jt@L=8F!,PRAãu|V>pvlSDJH 8c*A2AF(!%!$8m"(;"=:!]{-]b=k퀨Y~a$oڡPK_xfm4+Myݔ9܄]7IqR*[ Cz+^_Ǫ˲*i )lUiΫ~w֩qPwZw6j~^ߍɓD@Z:_k~z=UBH}k7gEhGDu]fe>UuQVnV N U tR3 $X>EaR*$F)O(THA^PdŵG|ǔT2 |$Rs!AOΉ݆ !xIf*m}!r_YGyɎ-&9i 8Vף Q @b`%3QpH$_`X)ۥiAg`Zixy"?G*9$]I2)-,zǒLIe _I/7I;Bҷf?X~( .޷ϗXn25@?Sv5M9p*rAqV]kFG|wp@76c]oEGUl&xov7? ~aؤOÂ!HLU܈L"O45EA]96+d|t-#W@&zW~ܻU dwϣ2ں5/&)NP5oǬmP[_H-~f:oD[ ]EP9x}Cxjj-6ݣN$3j`-b8U*pw7.7ÞgP/pg_lcAN:Q@@nfuP+kJzJzxz}z{z=RvTuWO`*}ȞYr81=n'}jǾ hIdpnߴQ?QNR )s.K(lY+imʷHr1\}m/셩@^J(; ?DA8e { yaC2cg[TGdƍǿq/PK9amA/ ,PK|R content.xmlMs۸_fڙ%)e)wNfw D$@޿CoumFIIR$%JdIvZ {~ &1nj^3 4$kW/hC NTS>ֽ+s&D6vTڔM9,p}_,W7rd%pJ) ø F"9JۙHZ1h4,2s+)J0 3"yFR@hYg4W승9@ 'DX&o0Q&J0Xg9X88ƒX^0CL "NxR5:7|> `Iĸ>HТ(쯎.+][wKf];+WZljN `%a6-{+:-nPv~:qs  kAJTu4O&u"ϺD|Q%$<ѝEs!X%]\0u}=)ϲozA~/{d3\eu׫N'o.8߃y P\! P+' 瀉ѐ.]sRf6c82y)#t8a\|QT}M 'B?6 Yz#Je(]3+"Jh h`.dC8,j l6y MRIu]6j Kw݃cPޢ.t1緐Cǟ9e:D2͡J^nk{KEVftвip</=*ϽX%{ nuoL,)@FͲWEՁN=&؝U*z&gE+-҉ rɢІ-;)!©]E8$S(]}y|')|D4tsjg?T< ĺ/s`i3}yË~i迭fT,)>>.G^1;goFޅOcd2ڜ'"znj(1P9z3:ZyR;e&>&3yʀ߶%rl?F`ଉb&E1D& hvB+lU q NGnt݋򯜬ۡ1R^zN'pA\!ߛccjd8EnCȘrS9Y^ȟGԕ6ժռc7vdT?.J--~u>-.Cgg$HaM譼6)7g”ϊ* f\%шew(J1reqzuCx[ÿO#dZ~mg 0zNvjcKW,J3u믛woռc|):s.aOd]ᆴW 7^9wq^PK| SPK|RMETA-INF/manifest.xmlMn09ϦYT fL,(ܾ@U% jv-KY[t(: foo ''' interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() child = root_interpolated[0] self.assertEqual( child.get('{http://genshi.edgewall.org/}replace'), '__relatorio_escape_invalid_chars(foo)') @unittest.skipIf( not hasattr(unittest.TestCase, 'assertRegex'), 'assertRegex not supported') def test_directives_in_cell(self): "Testing the guess type of directive inside cell" xml = b''' foo ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() cell = root_interpolated[0] self.assertRegex( cell.get('{http://genshi.edgewall.org/}attrs'), r'__relatorio_guess_type\(__relatorio_store_cache\([0-9]*, foo\)\)' ) child = cell[0][0] self.assertRegex( child.get('{http://genshi.edgewall.org/}replace'), r'__relatorio_get_cache\([0-9]*\)') def test_directives_in_cell_with_children(self): "Testing directive inside cell with children" xml = b''' foo bar ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() cell = root_interpolated[0] self.assertEqual(len(cell), 2) self.assertFalse( cell.get('{http://genshi.edgewall.org/}attrs')) child = cell[0][0] self.assertEqual( child.get('{http://genshi.edgewall.org/}replace'), '__relatorio_escape_invalid_chars(foo)') def test_directives_in_cell_with_text(self): "Testing directive inside cell with text" xml = b''' bar foo ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() cell = root_interpolated[0] self.assertEqual(len(cell), 1) self.assertFalse( cell.get('{http://genshi.edgewall.org/}attrs')) child = cell[0][0] self.assertEqual( child.get('{http://genshi.edgewall.org/}replace'), '__relatorio_escape_invalid_chars(foo)') def test_directives_in_cell_with_tail(self): "Testing directive inside cell with text" xml = b''' foo bar ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() cell = root_interpolated[0] self.assertEqual(len(cell), 1) self.assertFalse( cell.get('{http://genshi.edgewall.org/}attrs')) child = cell[0][0] self.assertEqual( child.get('{http://genshi.edgewall.org/}replace'), '__relatorio_escape_invalid_chars(foo)') def test_directives_with_tail(self): "Testing directives with tail" xml = b''' before <attrs text:p="{}"> after ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() paragraph = root_interpolated[0] self.assertEqual(len(paragraph), 0) self.assertEqual( ''.join(map(str.strip, paragraph.text.split())), 'beforeafter') def test_directives_on_self(self): "Testing directive that applies on itself" xml = b''' test ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() child = root_interpolated[0] self.assertEqual( child.get('{http://genshi.edgewall.org/}attrs'), "{'{urn:xlink}href': 'foo'}") def test_column_looping(self): xml = b''' Brol for each="title in titles" ${title} /for Truc for each="items in lst" Brol for each="item in items" ${item} /for Truc /for ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root = lxml.etree.parse(interpolated).getroot() child2 = root[1] self.assertEqual(child2.tag, "{%s}repeat" % RELATORIO_URI) self.assertEqual(child2.get("closing"), "3") self.assertEqual(child2.get("opening"), "1") self.assertEqual(len(child2), 1) child4 = root[3] self.assertEqual(child4.tag, "{%s}table-header-rows" % OO_TABLE_NS) row1 = child4[0] self.assertTrue(row1.get("{%s}attrs" % GENSHI_URI) .startswith('__relatorio_reset_col_count')) self.assertEqual(len(row1), 4) loop = row1[1] self.assertEqual(loop.tag, "{%s}for" % GENSHI_URI) cell = loop[0] self.assertTrue(cell.get("{%s}attrs" % GENSHI_URI) .startswith('__relatorio_inc_col_count')) last_row_node = row1[3] self.assertEqual(last_row_node.tag, "{%s}replace" % GENSHI_URI) self.assertTrue(last_row_node.get("value") .startswith('__relatorio_store_col_count')) @unittest.skipIf( not getattr(unittest.TestCase, 'assertWarnsRegex', None), "assertWarns not supported") def test_statement_no_text_warning(self): "Test warning for missing statement text" xml = b''' ''' with self.assertWarnsRegex( UserWarning, r"No statement text in '.*' for 'content:foo'"): self.oot.insert_directives(xml) @unittest.skipIf( not getattr(unittest.TestCase, 'assertWarnsRegex', None), "assertWarns not supported") def test_statement_missmatch_text_warning(self): "Test warning for missing statement text" xml = b''' content:bar ''' # noqa: E501 with self.assertWarnsRegex( UserWarning, r"url and text do not match in .*: " "content:foo != content:bar"): self.oot.insert_directives(xml) @unittest.skipIf( not getattr(unittest.TestCase, 'assertWarnsRegex', None), "assertWarns not supported") def test_statement_text_warning_closing(self): "Test warning for statement text in closing" xml = b''' with foo='test' ''' # noqa: E501 with self.assertWarnsRegex( UserWarning, r".* corresponding to opening tag 'with foo='test'"): self.oot.insert_directives(xml) def test_text_outside_p(self): "Testing that the tail text of a directive node is handled properly" xml = b''' if test="True" xxx yyy zzz /if aaa ''' # noqa: E501 interpolated = self.oot.insert_directives(xml) root_interpolated = lxml.etree.parse(interpolated).getroot() child = root_interpolated[0] self.assertEqual(child.tag, '{http://genshi.edgewall.org/}if') self.assertEqual(child.text.strip(), 'xxx') self.assertEqual(child.tail.strip(), 'aaa') def test_styles(self): "Testing that styles get rendered" stream = self.oot.generate(**self.data) rendered = stream_to_string(stream.events.render(encoding='utf-8')) self.assertTrue('We sell stuff' in rendered) dico = self.data.copy() del dico['footer'] stream = self.oot.generate(**dico) self.assertRaises(UndefinedError, lambda: stream.events.render(encoding='utf-8')) def test_meta(self): "Testing that meta get rendered" stream = self.oot.generate(**self.data) rendered = stream_to_string(stream.events.render(encoding='utf-8')) self.assertTrue("Greating" in rendered) self.assertTrue("Testing Letter" in rendered) def test_generate(self): "Testing that content get rendered" stream = self.oot.generate(**self.data) rendered = stream_to_string(stream.events.render(encoding='utf-8')) self.assertTrue('Bonjour,' in rendered) self.assertTrue('Trente' in rendered) self.assertTrue('Møller' in rendered) self.assertTrue('Dog eat Dog' in rendered) self.assertTrue('Felix da housecat' in rendered) def test_render(self): "Testing that content get rendered" rendered = self.oot.generate(**self.data).render() self.assertTrue(zipfile.is_zipfile(rendered)) rendered_zip = zipfile.ZipFile(rendered) self.assertLessEqual( {'mimetype', 'styles.xml', 'manifest.rdf', 'content.xml', 'meta.xml', 'settings.xml', 'META-INF/manifest.xml'}, set(rendered_zip.namelist())) def test_filters(self): "Testing the filters with the Translator filter" stream = self.oot.generate(**self.data) translated = stream.filter(Translator(pseudo_gettext)) translated_xml = stream_to_string( translated.events.render(encoding='utf-8')) self.assertTrue("Hello," in translated_xml) self.assertTrue("I am an odt templating test" in translated_xml) self.assertTrue('Felix da housecat' not in translated_xml) self.assertTrue('Félix le chat de la maison' in translated_xml) self.assertTrue('We sell stuff' not in translated_xml) self.assertTrue('On vend des choses' in translated_xml) def test_images(self): "Testing the image replacement directive" stream = self.oot.generate(**self.data) rendered = stream_to_string(stream.events.render(encoding='utf-8')) styles_idx = rendered.find('') tree = lxml.etree.parse(StringIO(rendered[25:styles_idx])) root = tree.getroot() images = root.xpath('//draw:frame', namespaces=self.oot.namespaces) self.assertEqual(len(images), 5) self.assertFalse( images[0].get('{%s}name' % self.oot.namespaces['draw'])) self.assertFalse( images[1].get('{%s}name' % self.oot.namespaces['draw'])) self.assertEqual( images[2].get('{%s}name' % self.oot.namespaces['draw']), 'One') self.assertEqual( images[3].get('{%s}name' % self.oot.namespaces['draw']), 'Two') self.assertEqual( images[2].get('{%s}width' % self.oot.namespaces['svg']), '1.732cm') self.assertEqual( images[2].get('{%s}height' % self.oot.namespaces['svg']), '1.513cm') self.assertEqual( images[3].get('{%s}width' % self.oot.namespaces['svg']), '2cm') self.assertEqual( images[3].get('{%s}height' % self.oot.namespaces['svg']), '2.2cm') def test_regexp(self): "Testing the regexp used to find relatorio tags" # a valid expression group = GENSHI_EXPR.match('for each="foo in bar"').groups() self.assertEqual(group, (None, 'for', 'each', 'foo in bar')) # invalid expr group = GENSHI_EXPR.match('foreach="foo in bar"').groups() self.assertEqual(group, (None, None, None, None)) # valid closing tags group = GENSHI_EXPR.match('/for').groups() self.assertEqual(group, ('/', 'for', None, None)) group = GENSHI_EXPR.match('/for ').groups() self.assertEqual(group, ('/', 'for', None, None)) # another non matching expr group = GENSHI_EXPR.match('formatLang("en")').groups() self.assertEqual(group, (None, None, None, None)) def test_fodt2odt(self): "Testing converter fodt to odt" thisdir = os.path.dirname(__file__) filepath = os.path.join(thisdir, 'test.fodt') fod2od(filepath) def test_generate_fod(self): "Testing generate fod" thisdir = os.path.dirname(__file__) filepath = os.path.join(thisdir, 'test.fodt') with open(filepath, mode='rb') as source: oot = Template(source) oot.generate(**self.data) class TestRemoveNodeKeepingTail(unittest.TestCase): def test_without_tail(self): "Testing remove_node_keeping_tail without tail" xml = b'''''' tree = lxml.etree.parse(BytesIO(xml)) target = tree.getroot()[0] remove_node_keeping_tail(target) self.assertEqual(lxml.etree.tostring(tree), b'''''') def test_with_tail(self): "Testing remove_node_keeping_tail with tail" xml = b'''tail''' tree = lxml.etree.parse(BytesIO(xml)) target = tree.getroot()[0] remove_node_keeping_tail(target) self.assertEqual( lxml.etree.tostring(tree), b'''tail''') def test_with_tail_and_parent_text(self): "Testing remove_node_keeping_tail with tail and parent text" xml = b'''texttail''' tree = lxml.etree.parse(BytesIO(xml)) target = tree.getroot()[0] remove_node_keeping_tail(target) self.assertEqual( lxml.etree.tostring(tree), b'''texttail''') def test_without_tail_and_with_previous(self): "Testing remove_node_keeping_tail without tail and with previous" xml = b'''''' tree = lxml.etree.parse(BytesIO(xml)) target = tree.getroot()[1] remove_node_keeping_tail(target) self.assertEqual( lxml.etree.tostring(tree), b'''''') def test_with_tail_and_previous(self): "Testing remove_node_keeping_tail with tail and previous" xml = b'''tail''' tree = lxml.etree.parse(BytesIO(xml)) target = tree.getroot()[1] remove_node_keeping_tail(target) self.assertEqual( lxml.etree.tostring(tree), b'''tail''') def test_with_tail_and_previous_tail(self): "Testing remove_node_keeping_tail with tail and previous tail" xml = b'''tailtail''' tree = lxml.etree.parse(BytesIO(xml)) target = tree.getroot()[1] remove_node_keeping_tail(target) self.assertEqual( lxml.etree.tostring(tree), b'''tailtail''') class TestEscapeXMLInvalidChars(unittest.TestCase): def test_valid(self): "Test escape valid" self.assertEqual(escape_xml_invalid_chars("foo"), "foo") def test_valid_control(self): "Test escape valid control" self.assertEqual(escape_xml_invalid_chars("foo \x09"), "foo \x09") def test_invalid(self): "Test escape invalid" self.assertEqual(escape_xml_invalid_chars("foo \x00 bar"), "foo bar") def test_replacement(self): "Test replacement" self.assertEqual( escape_xml_invalid_chars("foo \x00 bar", "?"), "foo ? bar") relatorio-0.12.0/relatorio/tests/two.png0000644000000000000000000052050213615410400015177 0ustar00PNG  IHDRcNhsRGBbKGD pHYs  tIME >T IDATxڄ˒$9%vT{Dd֣opB!R;+~|l73]̌U.TyD]HIUEz գ? N_P QRpok)X?_glB20NE{#x})){sŶݱ, ~VϐN(@U1֊R ̌#n t~#fQk""R!"!@UmmbH) 1\TkU_3^gRh>7oLx>x[o(??ӟ˖w zv3%0V,ia2P2`&m!"XKw%AX0J)شb&iV2+~3+t+X )D-WT9ྮӟ׿)%+B0g+N+;O>y3cgL_ 9gZqz:Z`& PU"R1seCV{WԟƗG+ T(*l LRJ;jkB}B)sA!"}m*uE)g!XJ)9{|.+j`&>UlU B{-! J>S}uԪ`(J)^VUP`#*)F&g*NiO?beNRp" ܷ K8=t>{#b1a&|/?#=R D˲֊?>gE=1MT;MӄRtfRJ "-Be_EVƼ۾O@IMg-еܾ؃خRsX0۶aWmRT A<3~Bޯ9|a]`WS7 % "-*_|R`YOp{WfKjEJ#sh| P=P?тZ~afn݃b=x??[ & Lkn| !HyB=9Y~{`U~`Uɀ)D5R)Y m"P j@LK&Zl[s^mhQv֊/~yyZR̸^X%ӧOH\^q[7l1̾ VnWT- &R,cX`Xg-} pۗlA,CV$iP 6E!z̖7VX-@kEi[JAl?۶ %gRd()r*lÈ/ ac('QhHYK1MVA E1*ip^*3Ǡ1\w T Pg63lox@IJ#( Ѫ*=3  `۽eU{{DwZ51cU8+xC1ZN >Xa"B"0~7+ô4(R/nh[[ vzBDp\<5̦O_!PFmmسQ c5{/c9v{˜PIv$)ASDaJ@b  MwED/$kbau_"L,,ؽgO-HkԲO;0*@ &QPXZk^5(0€1!ydleL!aN'WNz:a&;H *l4 2K)%DÈȠE_ };gk^zzyR Q?c%`CUlM1!ؓG(Uqcf"J i@Ase!ȶAC%z1Ƈ`ڵ}Cne];{1@ Uu]q:b ӏC}4MxyyAV>4.$Ua+j[Ibb56ZmmLkȄwxﶍʍ!cn ȏ)ۮ ]+T{+ٚ? P+EC7a#UAi ʃG$3}QgThƉ9,"$9 W9Mj2–ag?6@T5UX=CU=o>#*@*2Uc b]W##RU:*VaڛU[C=@ vlƑ@Z0~\cbecÛy5gA5|(5}R iqĿyC2GZ5MHQ!z7^ ܘ`,T#h{dC&U/1 KE|~~O? ? 7KyO'3Jǿç />=7é\ -Eyb8L E^}yvBղ3+: oQV9>g {YI, iv8looo:Xm=ön=Um#Ќ+bK^)Xt ~ |œ&p@ F P\0P)~ho8*!ؠDc|MGˍ01Yh%t8oonDSz*3װJx#m, Hӄ۷oxyyAJ oooX`fDrM ! y@ ^RAp)ۖJF,֯a\0k`RK@zF"P<`ÿ )}o "+#8XVf?6jҸ7j_v]7>J-Z`';{oyFL }|iT)*Hs2,f;ء,et1jA BaZfæ^)amYq3gl9J4O*b/cZ~ [ٺ>"! 7"3yme3 +> ϸ^u߭SQkoFۃ񤫵Z恏=` #5p13t*_Fp#ߖ[b DgmUͶ3,pgvXR\?l:k^.1mp^1i8\{Բ3׌ej{orX~Xmޝҟ; bY<==!猷7y^pߨry}}b@ `v;u\ RC\߀*lYWWYoJ93!r̀[1ܖIQU:a);̇R{^cs}<6{eڄ$3o9 O52PKMXma(Г!Z:ʻY:t֎E,dɕ{Mp2&]gdD6 N )=sy'i}:pq,4M}Sw]מn7ׯ_/o_ nȺ잞SB ) #j6bRśt\ q\>7:fZOKZFWMJD;H阍y "<4KFfya-{B MV]Ϙ_~_tƗo.`2.冩 $dQoy7 Ol/DTQ!z-5>.kcp04TK׎}ۗar&R!=h+'@_nS=01.`#lmǕ>ʠ7gw[v̕` 8&Qttv; eQq ZK@8h#}$1q :BHs"͟FUZgُ]Ϳw?c϶e~3X [p '({D)&f(bD?93 @˰?:=+QwPhdtX:o_+oD;$J9V9$PP<1Zӎp_˻d@y-GQؘ\5Sv̭,@g*}O8|c5vX|ރq6bN'pLgvZ+rܷ gg-źF78L󊧗=17AR,KGec5n1Ԏ:UA,kȓ= uF.\Vk9Ъb`?MaԳV)eswŹCSWfsE1+DdvɚHZ ;6@tx ҒYٕ-0L |ӟPkz=@ eCʀqvA -zCE)w40*j_U:RUkuHccf`I+m?y@%ccӦ'` i |a ̹ {OQB@Cf0j)F7 !|{{N 7 ///}_Ħ/loS`g )%,a0UFD\oϸ\.u;ʺ|~@0)o0<κz,kݿA߱Ho?գȴy= ~ٛ[!FxEP-z?p!4Wk!u;jpl2-@bt]E.@l r +c؞hs^1M8*0,˂VcӰRU =oeJ|>oUG@arg"ƈt>?Yy'ϸo' XKAnar^QԠ?%83VsVTRH2s/@q&!~#ºm z_q238" 4IAb/߾BJ~Y xjCJ"neB {6sFlAtHqiJ[y^5,X Uj)clXGЖ=7E}D9kǥ#n {߇R)1H`1v^#WL W\ZQheJR1&;)$湬{"?l+G !tT/4TirTf#fnBUJi^`DSmyr=Me* }M-NdD[a oW/9ן~64l㾮@KSU0;ըot]WLѼJxsVH)d%̜J.w;!?^z6a䑶ϨY:7#6|l|;G<%TfT3c7 w # A/nLY4o ) nP]hS)0 &7J"Hk0۔lؘ%ƽn%q(e_Ծ-!cp_;vk7h:7OHѪV'|H<7TPHȵ wE$fqgo.v~'r]jljgJ4OI[\y#7Zϰe<_;a T0;'RYGKIulM|oXoNʃ:"x+ϝZr2t4AؼWb%n&dq^ws[vE\d\\ɞ[vڴ߻}ߺPo[zLv #zv>dKKKn;H:Lx?ۻ?F3Lf!tG ܪFFBCe/z&X#V{\?-C1ADCi3p^ӥCЦnNA"[b~p`%DF$mC acȭid`[O5CwmWo: M;[`l^{l3;ֆAswơ`OHKv8:@-n =&ʃ$9SoH&D nsm]$??}C={?iƶܮwcKr=9i5wuBFyd݅˧'\K5)jjQ{^q>=%mF&YXvR||[̣$;5eFx#.IШ}D쇖 f74l1 isZV5~k"K[Kܨ<ތ)1c8sD!P5FC;)iUm)! g/==s8rͼOOO=s#&^ 1:dho-S`BP@  5Oӂ%wCV3r6r>#Ue֤]j\w^ b#J Vtj= 5`=)L3+=a‹_;K hh)dԭתN9۾J>o۶N}{{y FB88l~*-{䶮h) <jSV39f9ː9;`wg)Y/:3r}0*3G>G;s>0;c,?1mŜsFbzT2Vrl-cRlՂ4pݪg}]t`G {W&c?irkSE3Gk>qr9Y0RpՇ |r^3"e % BH|T#=p>>w{g 3of8c&;E@#tȍk(" pPԡ_4PSEҳNS)H*Ұǹ{%mo1([gTl T곞0)D hRiq]7|7۽;!ԕ.mnS~:AĸH@X,yFA*!s[csb٤x= z;\ȹl0ɣypt"AsֲeY@|h< 8,V1ɔͯi+\60dRj5)8)Pk:=L1H&9jix9,wTRlں f$Z@$Pa~:#a'lf'e/ɚ|3je*lj^v=zS* xJ(^k}L&8G%h76_8{Cuw0Apɼm 6J"):kmlJ#$2ּ= =v7+hlkQk}I1Φī1t~]3lR  BJe+az2}ŏ?|z3o|߰UXepæ3iFw:T @76ּŒu@@v^3b ?9« >}dV\3M&mZÑgࡱ񣆽mf8أNm+"s,\@$~Y eB6,`!M:M}G1̎=ASJ#-Q+V=>iqC r\W}ryСywA?ge3jԊ&lwˬv<[ѹv"4-9ȷ+}Og~1"! jabKn) ? %" Х;½AisE8P7i+n3jilj6m%l>- $%!lrh8t#($ yYVg߾}v4ͱ+"e^3z{{4O s" FY[`qCaOs3SCod4s~?Aܦ+>p}zw#ֈ(53M*GvsJI }c)YBF/zPl#PARmc7>ecу]LΝrvPAޫzo{4(36Y`qNZ[c)GjW N$2jBa<H<Ҍ#w t0L,́{CM Ъ]ʭc: {aƖЅPR{cCFVmpݬ !}4}fSml&H.0Uh~>ń0+M." uPF/tZ0qORqү7:R/y8l\7qiG7ikY cA LV;әlha i=@1;Kf>Dd* v߀1sxˍzxl LѼgRhu^*Rڛ `fB,Ȍt9d C<;,H$ёTAWk[ǚּYW|xC,D[[F#"sYQ\ך!e^Ώ.P5w4֠u[ qȨ6zΘihGkqGfT[꽍[n"궓{8P0JݣكNSCoұq8w1J3ص ;\RL7>4l6DLSCvm7v1?B%Xv"^^^PRǀ>J떫<b,ȳ;{vJL{yV+'!ε;=kVj7~c{MUc'a =loIY9u nhҜ"#kMtnʊZVSI$|4NS)N#74<ղ]{cʪhY? ne {!ۆ͎`S]zM}UNkN'3BXC\ ;Di}G [HE5"1PA-f(8˼zqOj?NNkz7KGkZkW_!_;dzb D}hJP 4Kݓ\.>&xC Ѫq̾C߫ 3Ѓoa/nG耺oeƏSG5,`/Y,2 *[NiP>q-Γg(|̀3$<*#\ɊoQu+(j~zrGV"x 6kX}qEOOOP+N'36(`~ӓ{E!!ټ/Ey 5){Oo]oMG~(nu_;0PIn4C7hIɯ{VM,Ǡ5F+q <А%,5@+J-@1K^һ5 qQxH5{=UânsyY "iC_YNK*Gxݑ ule9+]fJ єtCsz1猅=9h{'r2e$>nLkͤ:L4 a(X:C eu79I]gF{PtUh71G3.2eA}*b̢ٱ{X3sPQM 򷯮5P56>%C!Xg-`f,ܧ!r[b9ZüNcup 1bRR@H~jE֤"W`< >o_p\Rk5[!I౳;vhNkrg)x<&*r̳SSDl֖<;DԧVdZUeY5F!TʨEL -ER8b#V2 r X , qY|UfȺd㮘 |Q)7sSkܐ1vӔ~jTm]2Z7ܸ&%% J]mZx 6'1/;ͨ!|բVT73vyXEi j#ߋdH!d0J "'$1b](uŧ;21L+ۡgm{&F9_|&ԃIPvMtA Gՠ&}I 1w0xi!Xgt@6)z9frP2Q(\$f{PD=0! ng48y-Y; @EPrKVɍd FބތA'LۊZ34qyp)9Iw@*b03j Bf\g 9'QED"u} D[8„-o@PVb7s3T51%䠆Cx! ɭ "`ĺ1`lM>oz_QViBPJre3-6Pw#}B'N̘o7"Xɮ[ D*8F )΀u1DTՠ0 E.0Pl",X$h]qD !cDJ}l֙3q*LcO] 1av؅Èws)v !vCׂ=7Ld#)܍#!'>w? >_?t 3" @} fJ" w ƿj9DM%۪frT*6HbRHhe{ѥ@oghJ5FPUme #ls1}`4m*3`v diC',>#-';U![F/d c9f4bح>k4iͳ{^P9k  IDATm9#炧|vB.fKx}}NWRfeq}`;"M*uebֲ%lv~(8 K٠3ɳ\-P_0:䙹)E@~&q;Ҋ,|-*$ռoɽV 9p|fnAGH*CPx4@5!`_kXν<#RMbcВn`EEb 6=# 3|EJlYni1/3Dp~ZHq|Q楋/Vlۊ/s9DV<  ,}dPn`@١-).FWcUmJkP%& `w  E bJ-SD Ϋs yC7ЪJA)@P1f{ T] ZfA`/t\VQln=j)&lRP`\o& |t3_ΐM#b8J>b4EluyNX8ASD&/pӯC]LSS Gg +cG퐁UT_4 |B*46X5W\/0$ǰ]X>ɷ6"AP}HhnsͦUWSѴM,*j?9Y8E K ۊHiʄސoW`9a9@lQIS\PF]Ԋ*N,mcmaAlmJ wq gkFʶMi1Aׯ_U 4ݮ};u-EJTsML}B.L R Rw(Hd~ (lb\NY*HɤyAomh}+";PR30u+n@u Bke{fIR(mɪ:~@a.l?VTߚ0WoMbЦk6wA*FS2YV>i2, PƦ H}BV=m,!_%ɑd]}G Tw 9l8\3FU!f"\yMId"f"~׉wmO&~T{Nj%0ǀnpy e_Q@ʊ2LG] iƈR J+eXA ǒ+~󒂤 =ZFT:;ŽVA1'j}qe ruFGƭUF Zf qx:Y^ހ8z`EJYVhsN蕠Z\>4Pl8N.$ S G6vP3ǀ"ӏaᥥnkv+iAqXU =A4k#|2G\VtȨ`{u\&ms>ezh{Rju_dlfa*81Ь2 d)o" B<%Hif;bcXme kAnp5@ (W,:7r*JEۉLg;/n~rIm,% %#5A6 n ^t IAA "1 rma 2CI=o!DǍm8gs-,MZCi-v6Ȋ* sGb Ț;RL邎7B{ˆhfU.ah>hbTQ sݎ֬)&^v 1BƬz@*3*jOGaBiX#O]*&j, bM-.{6@J@-㱴UU3!t&o4ja ~3HbbG OǻcXj?.4Vٛ^zu[(l& oWIE4,4Z+d^,>>_PcZE ďnH/=o7L>`BQ6IFBbWK+ځBԲ;&ZˇRe\##q=U++ZkH i8JѪ-pؓ*JAA{|!S4Dlѳد-Nx:u4H놐]]"i/1*. ve+{iA+~r-8Rƨ#6550cۃH} vj)s~5tqf=bYc`Cc@P& Ng||#[lR4lQ`~!1O֚{Y9$"|-+""H#@DZlAJ MR0b ֊Z!^چC;MBN(e9TO!a& &VHl.C &jxp8mqhNP?/Rv伀cUIHCMM%#65GKX(Dyz"wD08N<5Wg7LB77hNIOVl)JaYTlb`LqBU.au=1YcM (*(Ґ ^X R8}wl0GMVh lPĖ"6`՘ؐ5&[mEw,,CRFBE0%FДB@:[s2+lbԏ|(E eZP8*LB)&H`TxbI hд߬1K*ivCy\MM=YĎ)sU!Yܳo6=eP$T_CZ-3ⴘC)&hȈ3 )j#E>J'0&&RzM3>d)maZfY! R|GjΟ;N~R=n[0=mryi9id] ۶#NNl2`dG馂)!t*b7gl z %ё0c+fnWP$LyF U`2R2niBLmV)Mˌ= Ű)d6.2/]t_>|ֲBiYwm uk-X( u߾~Ǘ=_z8N'U?g7\_r`weF(sζY&c"dCۊpEj&K]ρCDz &4-w7E4)jvex51[PkU1 b2eQm@`a1&YrLڇM!lmR!vzGכO _D'VMC % hR7g'$JݭG:&lyZ3n4# @pn'4bhΨPmq2ѯ/Dv{p9bVB-PJa_c4a^ i$}ħ'oߐ>~jv,r(g֐`g%6 D5$ilU2ߴ,}FRΓ "J,%P ިacBe=|=}D0'Rv줠T-)  - pt>#ʔZɒtt!J׶fs9M&7OR ed&dkj%hsW4S_kw}3mAV;T}-p>t!{'_{-PR2Hx:!n @d$1fHmTH}Q4_X bl&w U4-6!fcdF a^=⮖yQRMvƀ4^ hS4AAÜ-;C HѢfo x%Tϐ|hlZq ; u3gLju:T  -؇VT`rT1Ê fLEAp " @$\o_o/R{)h_op \vyA6hjZm!j,4bF@BWBRB#" s`, MpN '8K;-ȥc@V5hFjOhjŋt(z]xnZDSg in[!CTTh}n+l6 )С:\q@[))";+CUo#QԦ FPj!s^D9֮oe3`=T'i5/0HhLiƾ혳UTħYptG ؅ISϫI"GC税U̚F77' И`]N! _'ewMLh^M%4* fK:r%?)0R( 0dH@q"F& bf`b Q̄B RŬIH8']w`}D @WK]mT:ӽY+*k(p. QGh{G 8Jj)Vǟ.!OثV`7mXIB[( Ogl"O Sx6əl@vW^0s6eī3&$z A}UkQ%py+"]%EF H<_"B2RkfQú788nQ+:%Ig39"PXUׇ=yI5UTPBP_VH L1A$Adv Oi6V_"Thuԁ`EAjR4ݣg|9vUt"A΄ PwB@Pk9ɶuNooobFi sz{#r o+"b֊t>tӵ=6fqOJ\e{=TPpm^¦hцocu-W* рGFm+DL`یܔ! 7Cw'&7D2D&G𶽠[mX܏x /haM(`е+⡣~ "ڮα@ 7XP y{CCI/bTޠ1Rjz[& 7h[Y۪S"Z)TE M PTuCp>t`GB#7s6:K َyh$r IDATM,PZ5R _jNA+n),, LzEPL)U;KhL btֆTWd!̘KARE`T34v0򾇛e"PHdWy׽!BJv,vm3$Bys6:4^30%G+"JݲlOTu``̊[RvĊ_CW ]mbp~6tgBEs(cݫ8f+9k߿a0 $pjF=ݫt2#M3T}C՞m+ }%+` ΧNXKO! UA%g\+sY )Їf>َEb~ӀoX4=$^ЕtRqBm]`H7k͝g* W{O?|op\PkŇفG1:ngTJ3zHhh[YMj#r4r촺k )5iӄ-0?/@_ uh5|߰;8{:{kJm> ƈ͋ tm i2DmrPf+Ɋ=Viʆƶ ĩfeQkO34ZL=W쯯Vms,ŤbZ5"}&#wb1٫̏!l|tY1!ۼvB#Bv&ŦZ=&R͐4ϸ`KY5-mAZV ni2y)d 6z<\m~<.j!e¦sȂ:gr$U K,aC4LsG۟_\%b2e+PւuEk4D}srB' *߿oV 6 " `p\k۟!'@՜ǭTl_ k)x"Nfﯭ!r/FF\744R/p6BX)'H\*6[۴"zv<9_fxsv v_ ~o7K=L%YUQ쥎$lEK EmZTO8Z" d Dr@ lZ-͌LS0m[QV)c S4J  GL1ŀ3r`C{˪JܙP> '=TmGOo/s }w{&d%Hv-e_=hu(>U>Al<9eݡ,Yߩ`Y ۺ"?=TSNmߑ4ֳ U܉ZPtfmN͔t݉GJ=ux8R17=P0Р'>5`F6zШכ}b_pbxACM&?>}` @_r9M/{)RRQ$%8 m $FĽ`i"33<]p'9NH 'N9#1mZO!1k,DUpld#wҶ߷y|XЍ'>TmֳߧwՈzQцiĀZF# h9PkZ&)?#^ RPԔ*v56o%vCHEV.IQnZ#hK{,Űf0H eU-"HZ E{-FF"uͽs{"ʆ,Nl7jvUGRk&k2ma9* NjI]mmiI&tGRJ: Z.Vqb©U,L\.h3~x:2͘sDv1#;ʹ7٦y/%_{cOHOq;TޥXLsOzɎExz.C҇d'"։Fȭ6v/8 e_q>/eU"%Zn?o+5a]oiT G4EwNMfZ97\4t̴| %+(,޾$E]cqﻮFtU1{1UK;6ӴwѵVPy%X̂╱<&Ti+! R4yzbrXP 0kk ^NVmran7hJ ;I "k 5B$D#w8j/C7*R66=:۔U&OpG/\S>?h7B{5}F.pd1E":Y)%wxG(yn)ͪ77ntP8u"[{?_!`:I nt!\oȫ݀$', dmd1X!%>,ε iIh2ݒk7޻zE|\{ƇyTf菋J Z~#SScc K;1:liqJZCQ{z gdamS9>_~v3˲5^iF욆*ē_B$hW"tpd'MLls#"1-6뼊y!q@BϵJOI-J|ڻ&9`}C觿Z}&! >d]ð V ̒Ld{-zQ: ͅ TN7387,|ZDZ_dq=xc6Rr1FB 8 ҦnsO'r:V^ǴM X؄.V* ju Uu %5Z( 67縩 -Ԕ3!5(K n_= KdYnVprѧ%D'< '+0d=AOm Sa qH6jU^-cxp{ӡ'{pa1T z(Drne=)eM#T KIaAF 0R!B+栘-P1/?r:+18o/9/wՐjkRjv]BJUNZ Z ayN|6tGdreJk\2EcHBke3LQǠvwkPML:Zwpx|@QkQݔ2N"VūL ԆRv)cJϕL<a`noWKIgض֌7# GBd 2qB~_< ch6G/B$?jHϘcr@Km 6}vt(nIj˱MwXlkWlP&Pή6PДoLK=惧b 41ծ"O N3T {-6!%Gt& 9 Zvd",>?~xzsL|>/A-H̸,3yHCLO%t65dg $f Ub#m-4<5p`'m~4PU _G!X&$& <[zu aTdDk''1mU Ǿ#oE>p0\UPT7&cIq (Bh͎gEJE S+ {x>OL> >ͿzVCKپa(7_㨖{NmGMVo%g'{Qvw|a}S{Pv8 рTㅜu@MECAB3Nd??/|}A) , J5Yւ2ޮE^$mۆՇ8=M7pv˻:q+ӂ8RK))gǖanK%eQntK7re߭e7(NY)ZBϻkFd S`ZS'ޯalwMGB5F۝Lo5ʹALs O>&/~Y,L:c`kR=9J ИLȃ;8dje ܇tn䡄W|`qEAh8{Hg=uڥ:ck%{xFSgK+)۟РBّӇ'|>xy Rk ^Ȕ[@, 9{]7Xx#1=1Pn AG-ƊR+Nc]덭) *}ߓz/ Lgt߬{·a2q1ơJhLA &nNcX6c{UJE`qƁDX޶Q@ȑ7//Ϊx[747sh/E N X6d# '>꧃ߪI'lL("f5Ӹ4)\;+b!-l k?</&K*J _ц3d]#~[7'aLjƵi yc 7fydL(ŢFm:L56@'l3#E=x٩G:dffm 8vbn;ԫ޳<ʶ%\[ &l 7drg?4q}] -*u7hV֊G'5Ku$4*"g^ :g|~p~yYp@a %)Jaw/vίVz_CaHrJva*?8>>nͳfRWuCHwy-Bя7 {ujő=@wVIqд}zz?Kz*"̈ D>^>*Z$exs L'i ϧ3>. ?vCbN9JjʈWaX r14) i-xђlBW6>-d+ I)9&MT^bS(ڡ6`Խm;ڶ;ypWc_GSJߓh0 S~8,8Ml Phu;IxCv.Q!F&X{#X=kz85kw2 IDAT9FPd$bz2+~.Ľܗo4G%:hx\tG_mŸ UgN&=ez3c?K`7Didיa1f[ER4I"pbtZ?>O|xm!yxt]ŬXNj> F렢nag#X!pI7Q}%|\+C޳/s}~oQWĈ36SSz]v&6fzlH)Y<Nx>pzzMןmoW@`2r鮌kZ=eb)wnЊW]*?.{]x\U1 F(]zIՙ=%'M7AX]ԓ-bvO1M3~Oħ ӌ2cqnjkC`NOjXѫ5\tK YGh7$y?,\Cc+o=9SJX![Oc:y<@9gJ\:).>J"Tl@CއCb#me9`c̴cݒ54#1 Ӈ3@___ ϓt-K=ófmf׼ks*@baA> xﷷZ(twlBbn)A!PFĪAXKm/ `b @ڶ~ᠷ> b)7X>??|9p>/({C8&3Yѻx<>JԜC4}A=¯Uuz^ 9yYzIӕ/6山?Bh놭a׎CȞwbd*FޮŸ_]|^d{؁򯞞#hBҰo G hc-Ue`Mn4)Ai>c!GQ\I8}D2XJEX/ "(! p9h#V"|0ozX4I# TL ';s&h``LFǜDn~ҢL"0 13Kwbg)Q0i5Ąp*jFqP"پ#Gi:$$ܥږ<2_"OoS1#m}3ݞ"!FĨCm,ؕQƢ?`5^?H%CH5І5ABj %,ZY˃6 1> A+thyBw߽7_sBZR k/7vxH- LK)l8F}u{WZ+4#1b>L Q(AFEɰûί<4rsulיrA @^vU2e*83 G6OK*P-(&fXk|,jgà6)0=(-$2OpeC8zmq{777x)quuံm *M3A%~NX{qb/uӵsۅN9hۺƖe\=R\V40zC'bYY@odh ,φ{*U \aݴup=xۻ4_~xNN)(6D2-ql}bJحMTs1%x? "Usx ^侀UbpذpBCN^'eeqM??ʦGbbrޝxК"<m^]ٓ;z/V إ"7j-JkMC4gTU8U锷Wox)u%^GNF6vuKMWGJoCs,c?ߌkߊ-œjuQDͨ_^LvP ^={9gd,d >P ٢morbH{eM=ΰt~T- BL񈈠zav-SÑ0K}3JabI&*fbzl8Wu6b ) !zzcS"LTU b9B^nZ>eԫ X\- WUkܶ6klQ [O|H>#:;r0}^^SFr2pQ+gsu L R4PU1R`<& y 8U͜pRUL<fQzfiuO1XӦ4ZC]fYL8O*^d>H (.**OaYې*3CE_{(*g3۔Z0ZE_?FMrI*$Ȫs״SznMnee6MÞs'xm\>}?`G>] XȒ2o񺪡g7f,"{hLkTIAgl)];_:ybƱV Pr3NH[Z]ThKf7$4$L 'Lu%~LΌƢCf,>Xz|bbV9\F5 ;R1O|}d)@V)J5Mg ϹLJO!EyN%&L"W!\\\dwHLH0jWü>!0/0Ye5E IWKQ񸪚:ӎ.6.oq?KRaG.hz e1 )ӆ<k\DϑIkg4^=rGX\v\GծOhLVJ XS 'lP*'ɿ--H,@KS8khlŇ7:  >M`{8CT9 =

?JO^b02OiÞ& F-74b17^ed+ݵa^-D(O#:gTl娡FEňF\t{<wW/gaC״V?O@J0>CqRvI1V,hHs7[$:(I!oYGjN5τnGX}؞<6eՌ6F#9Lqe-'-ԛb]Umk)v) FV́&`4<~_@1R;4Smwmi~)Wy%4UUX1e{,.Ytvuu3-Y32QVV(gueVG??%cM\Ckɏ ĵPI-Gɇ7)v${N)ƶ?m Q+.*q՘נ59QQX{Yf nO0ҔqF4ff.EkI,#Zw{mݎqRDug3e愳SحtHzh6W JTƌtl&<,sa@@a>A-HBmJތװɺ]6E(kA Wt:0߹77x|+b@H̔FRU9,"G)|ʹJA{3[gVAMI 3o*ڭ* ~zC4f J] ].cvK V}f8t7X>I$WL[߼Kا4PDFLh&Ӡf|ScBk[XOo?=.ntύacu3#j3jepI|Oi5."}t MF? ɻ6葰Zgfi91eDmSHiCB7C@nB*&8fp2L1fS" U-vh]6C9`XaCԛjM3SLIIj=I,*MJe#7RZ>̆%R$C} ^xW/ Z8Zms;.ayj2~"HuqU ]g7- Uh,1Wh៹BVˍtQꊲ9qͅ;&`LJ3k5ŭ]ǽE1W K#сs ^ݢ?/[q{{}%_D2yJE,sY=h T%D),7<#we,YKȦE!ZYBG,mGzJ*ylaJ3L/yh9olc BB{RV3,βfP(}eb VblFk2rG%asml=l)AG}ٓ'Osހ |= :SO: gtaXˆ'![֌§F:;Twwoqyu (5pto]OJQ\8x^aD at1b!!F >ot1CA:_X䛆-XXRHĮcD#sRiR !jȜoE5ysHmSvmȇ\!N)쁮ABnyjۖdmrN]5{b꛱2ˆC^'/_{sZpJf2+crex'۲:ag '^Mk}<m:*6Vf_Z.ru6xUyg)!aH|kPe'ʒl:Z#%yChSDitK$XNQ/9满z$Ԗd VgI8=5j1װH ުج=YA8C_0!x '?fBÜ}5&>{{!*RyF  BgRiM]u֖ s&uiHw*dwvv5YPQJp m\TǖIKf w0)! ]q752$rjmp9:Z D0\:02ȠOEzڗC{yP˟[%W9CHЌ `h IDATz0q}sϟOX30aܻ{(hNr6_ɘpa 'éρ$Y*`-ba&hX.*i\ec&d `f\mc̢T:{,Ł4zVxdlW5TL݀MJ8sڈyT3.x 2xF5 8pTUn۴C%uNi4p㫿)om:x nSCi|SPrRîNelJKh,Xa[8qf\Tb1ģk4oyjm`s k28F,#t ֬ ^gke_USl}chctE+*)kmڰJІ.tjF0m1񽣨%I'a]1RWүf>/Qҍ;ɟ"XZki|R"&\PI"4|$zƒB۴ƻg?8=./.p<2˷_K3CE- V} 0Ox.DXQE@iELm#gu>bwy /;k|pN;tLk{;?:69 ?)gJ<׬Ϡ {-HÎmP|m` \852@R"UתڒX40Zi6vXÉצ5fUF{ƹLi{ b¾m>}O?yۛK1!'Eh?}5#d)M?HCB:~>ӌ.B).> gXc_ ވXv$Ezr3S6okr5 wV9Me-@U5f)!b˜]5KK ֘ *f+k5xL~nM鹸ZAG,~ TsQеm62Rq⏾/;tA? //]#K}`(()dPc)}YtĀ0qT<@ُv .4Y@CDN[L1fGt߿ > LQcx(Ӳm@Yғ1Z(LBҢg2(TskPܑmmWCs&դƁ )D77x$w)QM"x~ДT2Qu4,@maT 1.QܲMҤ*O?LƅyXg0QM}k#z󗸜*^M.iQWߒה-aM[oJ` ˕5(5mr[X8v?AӶ9@)9(| c9&H1b^{R!&8̅e3di5p>ʳt =䃒*35+ /8cg u^a3FQCSNCw\HذO $(&76~+r'_޴ UgqCZ ҂ BUM6.N>8ۛpaVebo{ LfXnb*q ύ .ݙq81nVU[z*;1^ײ~lWA[L=N-W"b~)b#a6Qw5~=f[Gi1m3 R-Q{hxqw/'7طN#ɡѶ*6Z#*6Hy= |И&kB'!MZ!w|J]8!6b% 9艦ٹ0% )񄇇f񈄇`H"0Q4Wʳ] ldg!bλď˓1,7R鶨^*z K#-F9@O7uiȌ-O> .fI3z34|rJR.t"1Hv]V6 M9^rVWdLP*ѦARh/*8LKy =#zs}[UvΙ/ճ$(ҫ)@&M2WRo/~ ?pJ, vb'9NQԞDaG%m HA 12$@m}ж)vI8`09"tUoD6HEj[4M.@F@ݤhh)I:¸(ߙΖ=%1'$Hq%Yf79+} rݹEN[]u[- f1 옍S~ϞӧmgGlvV͹3`Ŭ1彖ЇUcփy=H'6Ga[BM\WO(x<"&JU-ںEK[s|Ĩ;UD9$pf_PE\*?͛wo߽CseNޣONĆlZ^k-TT!Ktb#.6al#�Zl>O,R,ZuL85!cu&'q1{q)i!v5iR#2+9Q3Xςк'#M|{M(قPxZkjRhωش +ք[UɚuY֩HeF^</^5R,ܒiѰ 1Ac']+(ya1$2'E$*8l!-]MjXs)ͮaYPnbQP3H)4lӁg_Bݨ3gm6lǟr󳁪r|IĬi$P!U뗯߿OP i&arX 8$;*#oTqŭ{1lm-!H@`v+0n-ʽli Qb8'>PxX *%15A=ݫ%0)Nӡ*6 8Œu+VkV^Xඪ5ڰkvR*QB,x%=l ub9~<.Ɖ,[l}gH̩+%/mظFˡFS=.-JϜ߳'T$M9qETnx ϱֹ)P͍ʬB%CgKAWdl3o Dp]͕&CJ Jӛ'{|1xk€͞3y UTG%2c3[c8 BNB52׷pMCܼ8l0)(M}əfV%ɂU2fz>sZc2jVȷ4OHjTd@{4!pܶ-,Z1+g+Έ:k$HDTS%D!hA =x9.{zF۴pڑ'ҙ=#ku;"OӴhێkmk<&rCߟa-3?\r0dz4eL1pm4`b6'.ͧkb-1r8t8"xF\B9 cTS3ϒt?UHR,y29Q~3HmITeEޒv8ݕ.kx3,qǫy`^]~G<{??1#N}k }c77YO`ٜ}L;xb\YgI@œݦip<>`#G(4wO1@ӏE80 DI"[ygHHˎ,I H8?1l-`RDTX MVNpfU&ijUuXgR"8crJZPcj5=lqY5Hkڳ5O{`@ nnXGO8m[/KX^VuJL?ݏe&[9[N)5w̆+گ ţ?]k<18L-_mWs@k4s sÿx^f D #B1W^o}hE=>,w~x7ob`g v;1UbxBKT#*z[~'|\4Y5u,[%Nܑ e̗/e`qC5`G/SlJ6I ģW+běY['Jc2Ji68筱&RܝE^(Dr`fhEA M?kxOnWb8~q >hx5˔Q h'SP`j*v*̳⼧d Ic QGÁ^A`uwd0ڨ9 ZmWsm"U^;*(O\SBԘYTP3&IP0 )"C򡚆viff%^Ք:Nv40 %gUg=*lc Lj,V-I 6o8c6ӌr$iGYB‘X [jf--o35ZXFN1a=<ؚi.\8dZS2@,wӸLG mU: 6%7E5]'OS\^gMi64hEQ;8Պ*6<1[gW7Պ=`l)*5ְjS= VmqmXMs>묷-1w*6sc{T7J9#; C<<<ogooÈ ܿZ=}/޽GAu&,Ut *L襨rh1D#c|QG75앰! 'ulcɔLRuvoKslBDXJ;KuR>GLYfleKYnBRKBC0-ł*50],!khVq i{uuׯ_vp1 bj5E曉ѹ3\6}/;rRQdض= QkڀlmNH ZWR)B.yuJLKڢa6H,LM85hfղd0n٢mXN^l<)l1]zu3]SǏGgm[8G)/ 7Rlfdp׿5|̣9㋠+eXfC۶ !c#hal I\V~'t.c%2ڈˇ ĺkQq.ViaTZMfro=|xߛuв]B-c!w5iq^6 L4 :k~ dAᬵFvRH/~W8 =~ cCl Saw gRgu K@GzK= I4;VmrV(D 䭵PZ /_dŻG ,cP6y Z5<('nk'CT̴2\k(gs0&V)4 H )hyz`]~xɖR0浰H27y!%T q9-6c-6l hPI )tg'x)Xas;D79G9`V#D'߿X$q:>#ňqq{s?iXCd!tkM5FXMaE6 8ɷiH4,9`b>*umJVQZ͓Wsdkx-5r$uA&^Ji8kdhJqxf8R VӃڐD.YZd{bol/+13)>c0H3 γ- SQe={k2"GxGF< S4 g-޾y}o0zdzv=ݻص{V*]Sq0)f#]+$Mk#O!4=hxj\;~="WZ&JTx$~FH@ ad՘8]"vB#'ONjCkDqqDp+P=Kw5ē:*t4Yʦg`zZMD7Sn4lK X\xzs۫k C.ؼ#] Rd%8>})^|NPoS)ܚ$M6<ˬ#+ FHVU62-eLͬՎ)VʵʘI*EXӃSx~] ƦXo~$Ho(h'ݼ+}֌ZX?ƕ\׃:/w3ڡNg李=x^)?ı?- 0W)Cy8~n̎ Eh| s]ZƄ~#hɿ7}hg3_Z% CˢUkro#kbdw6:c7|M'!R 瀑K.Z|k6HqO1 kbvÚ]OW=wY+?x`fa4IZ^S:9#h=aJcN&aaN^JxD\O}?3V Jnv0?0EQ3JZqY&)^P9^9W[^2K+Yb+ acA0]JėV^q= )+ycZ%kf/|+OIm Y:݄mnQ>d~ZYvJ=Ά`JRY&d5xT ;\_Ż8%M !eR|4DYGz~ڶ'g@0!YEQDޖԈ=%gX8&[;e3jq=a؅c&w]GkZ䑂%>7X\]]t< ' _mEJE(-$ u3qꟲV  Ilb@$0pg Qsc"S74'(R,=O7ᠼ/͝vnM=uJHZpspJL,)KF*u bLqXUs֡WGy$k?WnM2}|U_#bK"J@h=C>|?@m)<#b8Ǒ-ڦTR87p?`}/JaqK,d[bpx]ɀ?wh:"1kE9a6%ЀQlua{1||'uʩ+33ies\%bܒܖn ă+6gt0`TZgquxݎN]agOiڝUDGa!~g'2<#\SKXfR `ba %b¤>I~QC f5]>P1wʃy}˦4 rGrC۪k¼U>f8w+|aP<:UG<ҧbD˧~7!?G88 J)mߗ`R16MC-IT翷0\ F*ZK%IPG65ǿκ M)N̈z=)QE*ogFiAgcPThHD('6ԂS[˭@9g(_)  6/4i ?[nOp! 1iXc9Ex-֢q4x?|04_.5战sku*k82^-)z7[o6`HIɫ ơz<W&^VYƸ5}Zu=]oW IXQiރAُ1HB%]7uF2=FomCk|8>pwb'**m9{hkG 5;2Lj7ƈFq7M=T8!#$HbƬ,tYf,dΒG@Ir"hԥ&LX U}$T1XyN!A r5׭]#`-#=@ՀJj;Ԕ +?_bTȡS8dRdYkI&čH%\yw]digQVe)NY.Z;VF[ǔ`k-i9P wZ,mK,1p54jȴk{V!4\Pk?]b q}youƇ geʺ?2D'I!}?!:z 0 EK VqB1|z4=*r5OɃNT%("e0*oLVy)e5VIsJ\ 8t;\xi ƶ8Ĭ"MJ42x/"\UY)o% MRfkEὟqy:Ogz)q5^4 *LЕc| mkhn6t'jY?G,58kďAC)}TU='D&N~Z wZ8&$؃'.~_>v޾y/P Cu4&M7F8RrD(D45A1G`F\ٮTFϒ%yGR8e-'B联ؗC<-HP H F+gUB4|ĻTsjXoƳd芣y&F6ItD2r Ϟ= v60гd*=o= V+"\Mˍi?C'ps~߇Q,SS$ cU!։ %壯mF#r44`$Mח7֯~ ] H/͔~,%v8Jpf_ D4$ B!&Z ֦LF(|(@692DŽgUi RrT|4 *u;%U֍h)d#mqk|gecpyyv|Ug SvBc (Q!0Sq8N9QWWY`ƥ9~--Ґ_Wc< jϢ 攝zl}f\7L \ͱq=7tu_{~d6\ز<<];0J^[@zd(9ߨ!5KЈTZkqb|8\_C5YVѵwl*0EcOZk]eog,1H12׆ [̖ i%;89RM|^+ȨQ foRHР(5\`5>%68=mD0UYy5m;80L~OJl 7zPK ijkJ))H)yì2R^_*Ft$+wHԔ:93TS}UmcSKlleeEVݮͭ-!*qzͱg@RC?FqA=m:N"xrso;S}v#aD:YqOHB1q ǀ~VfhY1̋ "Ě7eA٘cBg7Q5uTk[t&?j/Hq P(>X>`>eK/Hc-O ESi$0VE->OM%1BoHD:O+(@L܉CkS|//Y^`~YtJ>n#<bH0 ˯E#˩E:]WY]4,DxVEhz_LVXjٲZ7@TE)dҒrWa2Y 5>yBvQ[޷Ȭ2F""*,%XO<5aKMFFGK݀Uʹ )E$* <-|nlQZ/Z=M󷆲kqW[\?g1WZHݴRb xhc0ƀfR1c~G"t| t8O@H8HsE8HfGp;Wh/{m_/~:v@P7q?!p%wc]VчLeuMCL>sd9/!FLHSE q?0R)40%ˮb^ba2%+Pf\L^PA|Dy kpsugwOp?@pD򰬬jFO`_q:XҶs&=C[]b\ID\+8{>!` r5螋aK­Q)cf?`Aۂ. 10CECmU~cy-Ų;0iMtI$T\a8B%k_*~#_a N Mw͎"O=SֺIcm֑O#3Mَ@)D*˖l:mR+mۖLJb\v?)Mqz/imJi4zʨ۴+S1p0UE=S$~kmrlDq7%WHd[9ʒ֔V@38Ӂlik[XKW|1\<џZχXlƵd\f#V/C5ͼJy6]:9cc9"uҭ.:Q 9&mxBc,>y X t:* 5 %IK %_OJU): 9PV:G»zK|E]sTx^ a%[>uΡ#N7nBiӃuk)H("Se4UGDR̐ ҍJX+z ϟSȨp}H[Y9VK6Hο+yTsHY88CYd1zrƁ rңO9D<#!:j=46esd楯dz&q{y5?])}5.uw:Zh_*~g?+/:(. N {ûm;σc9__;;?p$M QRhT"$OGACT(jBDQV(@Z&N1{9{5cxǘs̱\{cG@u^{xcM@?vGgYƪRbb5YB2 jK`5V [9yĥ'd`rM9rQfӜƕ"$} lvk˘W@pyy gӇ777iz8*#*뺅l0Cp,K%ntkrǂTtl;u@«g2qV?s?o:<ә!Ba!a)LGY0)9Ko R P!*L5-l^Gc/y]:z;)E8>Ř2+.22κ2BUB5Ĉx xGx Àa_?l*k[vVvjjTE45rt+~kh9ǺwaMSM ]sq 36⹻K?nյ-EGV7LtCVi\{w}Cxw"HG}?XZ@٠'.ac%v>iTLqqg,t BI\ְIu[`R]4bN&Sz9\6vw \I_Zj҂quu5)a@4pMR2dbW!M̷܂"O5΢?qB14>ɝY@"D[-ʀ4Z|.+߿ì<޻y8(BR8lHhe+cCz6[֣V,9 YM#@"c p1VIA"Y 5 aWnjb[7k$X.")Z=93tap5ϳ8bm!XuS1* CK6Q눨Qb\^\k҇1 7.&ܫLX^֝\rN^͖Nu}\Ao I]@!ywjCȍpOryvn4-,cWkxmm(&ēDDpVq6l:v 4~o!|cx)Lv~dߣ:VY_CwԖS"X"ռ̐IPqS\bL qoZc5[=ײ_$!IJ"״@ca//`/w% Ak+s]A/C?tȯ(l#Y=G4ǎc=!"(ZeF|'i,95!ODB/\(¥12KMnzݺ#V9;SܤItu'ԛEwJAɭ*CCcfrYbsJE x M>|:4} ȗ""Y`u7S1@4dD⦡˛0ڍXّy9Ζ✣֤ rȷ/峁I4?Gdo)2s 7e49Ogp{Ńk#n2go8˫+`I.ݯHulwhOo2=@B4IfY s֎^ IDAT&M: |]5 5YZ )䕷\UGKv@SXrȅ0[銛=\LPjΠ=/4R)&lsJ}Q|N8y[UHrPl_'Ꝛqk*UMzgy{5ϝmQ~oC 'Np.r>%kLv)e TZluyvDU=<#LVX׺19?:ǂ{Fpq_\]=ӧO85T^Rr;[Ρ 8^짨.7$zWFL?1N&&͙r dmVJߘR [։5b #LeaSPJ>xЂ!6a⦟5Sy}} kUj1j=Z7c.J1DH S #233g 8c֋ b%d+4M9zA!N mi q\ڄF׶B\Ļ s\5uerO@d`uxGgzo.vErU8qb@$e/қ{#._G'a\(-:m~8}pcA5M!a#==[Oq= UG^Ըռa<k!! NdZ9Tf9.c(0CbIW t2S"6(qRiWR8?Mc;Sskp6_KYsn+\t-gY eJZ1;q[~r6S8xUvTg:V²pE{ގɳQֹk] x|sUy~CaoKv4Q/<^z%# 110 '1A ^@nnƆ㈖okM/5 >us,9q9ȖuB.[E(ŵdQvI8Qq\ZӢ 56eLIb7b!*}صUІn]R ߉uaS-rG]9Zx˅j+u沖Ӫk%1wU/;xnEܬt\ˋvjCqNU I-uz-9ϐԷAr,|ol,^Ή{H{a47`]q?'q#|b$2%{,v0S쒄 Mk}]"bA-Z "𤑸*匨-i=m܌d CgEejK{8qZ02 ԇmK<|]L \^^.!732#@V1F`fQ1[AkBͶ0,C /(ݍN?FWr+V}FuxjI!r1_l n-Aнm9|{igq̹-}m0:vKбVω瑂-Fi `83=noo}lr'G+ˁ1*55`NB GqCj8@;cY r\Hˤ: 8ƈl(g.e(/W2-s}\ٕbaАYrdIѭ7x~3kmM]SE|I\.Nu3 Ʈpuq:LszoooaT_9eVTjI>,|' Q1lĝ e.lqA:?Y*E$-]wayr/qrAΦoE޻X6sn*ҿy?y^4cSlxq-KA)9m0!KHxd~7qf_1*K Ҁضk`>Nx&;*1`3РPba2`dWix"0,  zC{@$X ~J5&JRAM#0 h #ö-kAca }E{e.D5`Ea!:&F3: p4x\DVe'u>4yA§۟8&i(Xqd:($- @k[2cDfƱDI N;߀ &X8`\^^pjTLu^5@'ui8 ?#kX'ҵV Uf!LkbWB2"OXM9ٕLxo#9'~@!8. }~kV%|bbN?]@c! 9 -EK6Ԋ~uNF5w%Դ̺1qfi̬+`R!q{P\5?:?` ZtM q8vgA2tl(K<7o)xt8h.`Dp{ԈGkuw@CV&+aVxfF>4djiQdr?b YXRL58Qܢ.kT'F l<DBBlnx[&]G9%W6mG\~ Di.@!Bxr#5F&H'!ח%(Mt5nZXsz5?'KN6\`š~<dzϤj9:a]*׎Cm4ϲk.M' j9'.nj:X WHJ0z|q/p4( ˫{ㄯv0LrX;EK^iWR*s<:u9 S*Uu 7OWߍo{׫_aF?BB:ZH 1e dYGMyls8yn/dA ʨsF_djǐXF$ us~_Rt6*I5s>w} ר`SIdAm5B[3[J  Q-VXB]縸c"HtEEZkآO )0_NlZ9k EE^hخ1`wˮ| LD_ۺ'i-#] W0߻KC' B͓b%0 #:>Og{$X cGp0#0 6=CTCUy4rAAaF tVI.)S*fR," 2*,CqW&D_^P sk!IJF3k qL6TTqH)g3]avjit. #e7?)&%aǶtZLRwcu^[ly%RH0 VZOܒ(Ђl ̂^ 7QnʌUX\{C^8ԃsCy!LVof,I8sq_|2厩| Kyglt6"!0c T!̾F" "DDfX0( R6G8 uȩNQthy-4r g`Ѩő9a0K0 f@ڄ~mT;.Pl ے8M̷LV>"8,mp)2Y;%~5Y^9 emUoOTmng¦]ԳtpZ,Snb|j-k ixg+ waѫ~b|=͟7A*㍀U1"Xw|e>bw Dk#%75PY& |>h-jhL0Mӌ@ WedC:e9&Y M2ljc\1>úHI=:%GBasRͲjz?bLF5TbG!5wFOB!mv"hPB]pMEHqřbȖ/ֹHer ;:gI7\>m*-2êBcuݒi6H].tat]AP[\^^LI T e&e}e!""[o//}w`|7z <#` b@>*ޏk)r1(Eed+QLKqȹwcYع]"j krf:LqsfKߞ Jߏ:y cqoqć?/AӌgயLj~4QύqVE `ۯ>hqxCt >bR f:kf7F<7[p'p8ptvi\0,|WThyai ZBED~ZP-\E'?0Qb  836fD&)'pq0a1Ʋ.P[KkT"ٶ ...$U]إT2 r@]\j؉l%TeŚhٹl 1w*/&%gw͏aAU"6!Xk0-.+ydU%Y^_o}_yǏz=p{ -~ >>G?:)YUzTWٮaς*UJ.蔛C{2VD^ss>7ԓ̀ So}#E8<9a;p8`.7p}g^]#- fٺ!c28JD ۵!ZIGMB9 ^5 I"Swalas LZFfۀ Y80aT|IONIS4v?LCԣ E0[  phzסx˕9-!k]owveOj5J,&S- ?Uù؏@ SKJ'B7Zoҧ?7?}#2rfڲUL*]jTm(I&^յBo)3?.|q RGGs'ۀ0nv-a</jvhE0$ƅ@`1 ,r40;#|ŏ0$5fm z.zZ6$\M;"A[pša̶i] }p25l-L:Ydn`\ &])&[D A<̐t&[R ߼=uROG%(,!8N|{Y"z*_K^sh7^k";dӝQiuL+%O.->r!s2w|Rx+m.~Ma}5&NUԷU.Jp/c Qf4$u/J">?YC au\5n IDAT)<7mx5T,zaP(ևȧYsm La8bo$7~ ,#t |!~YHBQim2à WrXcO[rFeIGIx'5{H d fby3q .H0ȶi&}-MHeMq,G0F@B\9f )b: C AOa*tZU^W"pYx=^v@vt:{|Xs_@4i8 }4 zH@~Lz8 SRտxaB'^eI-̯iD]:U%mZ gjsh5|1w/_+IL W;z'&҅LT a*[NtFIL oC'db݇$ZF&Xpb0჏^>9)(Ei h_o20 N x}x 4D DE04Zxph+k > Vfߢ'fȪC!ISFH5V;b72[^u` @mxPiQ, pM^ޚb|[Ox a}l))JѺ[U"%Ha@$-ri5{ovՁ\.GC֌[ʝjEI W} C1 oNxJbCd, n2(е@.1ʖJp}sX( jZ F.^y%WF/"5VA0pĠa77op{Xw!Bd,xE״8zoĈO`1e[vD.t,͜ kIwW+K0̊y AT_4&NLMxyZzG "`vY!'$5gW ˶+X.8f&"n2\gTG% ůƏK#]Qj1w%c[SDkqxpx{1 ˯ vM 믣ʗoa_{o]1G\?W,QN] B6[}[KBs,c3`) 1dhqZ\# H@ע1 2aN!oɛ8bx~20uqU^-.C8Պ=Z (s`%}C(9#QFy; Mq2KjD'D*bX+gf#FbBc-vv0 nۦ('D1FaR_I7Lޏ4{bXG+69xolQşS.;0rJo=$"އ>1C8}s)} ƮEiXxb / 3JDFUuw2b·,!A)%Kl8TKU2'0K*ݹl5KX2Y۶8sir jyI Ƿ'x{o}݁RUOIb]]KZ; oOo-<&pzy?_ӫEO8|3dW^7q譅yOUɰڬaMxgD:I 2)7p|>  hba!"N`ߴ@0D8'#{Dio’ZXzqᤦ(h"}$5yBDQ< H8JQsPE }Zc@$\9x0<ٴJ^̀5rZJ!1YhѴSiaۢkZX:WvEg֚&N' :1yvxLGbҥ˴ոq==Ē.n0yD_1\]>|_^xj|;l9UvZ&rux7?WOSA|| 8>[.P/b|3>ˉ SL/{8쥒n|/:t#&P+2njkobqԝ8 X0Q AX1{Z o xAI $ԡ2k(:Y㠞9H {8Xd'Qӱ%(7@4w8 {xMJ!;H{ bYVYA'am./:ـbВpSrǮ`H;?FVb QMq(NtfXzYCEqkiVډ'{"GnPڶ]$dhЩqs}%|~}8 "'Z1/+c // O>b/'[.1NxkVgyGJNjC` E$`Gp#GfbdJ8u aU@Ҏ)[YaN3=|к,GP*15`ZQR" i Y`QR يq* 3Ϝ(Z(6noo{R}L# 0ZנkZ\/5n}dxKDA85Yl3|3go|[sQm3̑}JVGmSjq1Q Q>Y({ m|0G엑Zz LH&hZk*d{7_B|]x_O; |ɓZ&]ka/mo:R.XUtC",+@n^/. Yxaڙ\R+`a`*\!a6tp]C46O\Mhn[4]x` n6@lq 2iZO}Du[qoqB#"g (2QH-۾uI*T4 Ǔ2N'yVQh Y_P1dXNq0 %?c6&3J} ڱ82b40r7kdؔ)&yWa/t//ȏk!}O Zc ;[+@:xO7x?s3i*[ƳXXNz ^X\í1'hi/ d֞KnJJ0٫7 cj.ck;1EuxGŀW5* sH6Q@lS3pAkq7* hlaMD0[e2_1zDˊdLki=B0rMKG/qĝS{"nypb&,7dWITdVCS$saC0U$DޝSGl+T1eŮ,u/rNN1IY-K<غ |ާ K׷̙t*9W$L_?X?NӚX\J1^,D5$ʦ-#oxENw*r%6;B6'xlw^,9NU6_t!NCXL9܂|?h:8=Ј%YȚ ca Q01D`@a|`,!XT du'nLvݶ-kzF.JՀ1FŃEi ˜+yWni2_K\tUl!¾Nl#u I}z/GMKPeiYBmXe`T~ ̌òS ?;h G>O h>ro*w7ֿjE?> _z8b@KW>'ΩnM|܀lN6;u=4+;ʵx0 \aQ#0|ȥ#|c\ ÈQbXɣ[B*Z?zI0k6CY">̺*B!0ږb 1- jI U-4oY*R`#M+T4a͸K˫9fB[Ĝ8k[$5$ xKm}))UA x\<Ok'=h[7~ڍ,\aaٟ/Dzw|38ȸ9fqv!ԬŲ6C2yQ"M;22H~>~' (;eԭ=>[t%^+Εh[+V3)} 2X<|05%n8#F(NE&uMTts$\$M+} -W%P8g ,V!F JDͅԷGkfMa{?BL2 ÉG 174A0gV(L)':g_Bi}PDҲY(8e9c:cc @21 ąrm,`ν<,=+jX٭l ŤmV؉wY?CNyus'?/N ko*އUae/q!t xڕ'󄚝?#C_~blᯃn` ls"ܭŰd;'Uskur-E\}Vd db3YbwUispAGk8gtC ^_/Sh1Xq<`H XKA \9"@$Qq M\~ b䢉.˒5/. *H<9pfGQ(AJrèq_~!RH$>$3Ab tY$]Bν4g&A+K&[ߦϊp*&Q]2 XQ.:rǫ f`4ƪ!DmSmÈko&RtdjTd-#R8"=H$zcc2,#cH~"ZkT,2bNvAe< @+^4'Ds 9#5)OX8m Ӽn"@#E0I!P2QuaD$P3SVp"t,41z6K̶_'j&]p=F JD> qD"ڦD}a'>0 R0ɔTBDu6.\/6#`*r-_nZ"3jKV0tћwH {O?sAGc콙./Sh``N"B{F"$ 3eD[oM=WЃm!DCxijT?BTLċz +?(Ðy H}ߣulTz8}gZ0 c "6~D, F?,Mע5 k?{|TVF DQ3!QJfN"ʒKҠ OFqJʦzv;1ߖ`CuxssNGdnCk pBD@5 !!u! )R薔~MpD7Qy(=Sz"TnSnb<"VWj ,!$̻V7n2Im'sL\v^"aD%ʗ&4N:b 6u<씰fxc!,Ёs03b O١/ zS;4фX%nI UR8rqj,V*k?B]VLMvp qAu nZ8>~=߆lMgZ ㈁nנGH]q8(>xD #a?b`;k-#0!Z7`Y=7H," Yb 1=u@]j#, Mۇ$@ŏ. U 6yąlSt"S.Ɋ3RoJT'@Fu3Nd^vLliW)GSRno Zk-| k!"(8m|ŵ=r4PƊVl;V_(4E ٵ|2n(&,IiJTcoOö=e>LM}b_^24.PU)S%hQOY8܈@zO:΀jRӏGEY6"]ӢuBQ6 Ċ #kR@YM9 <SzHJAԠƨj Q*OkɢiDat L0V&E)*>(XE؅ĸB)qJ39p&/]tt$) M+.k7jy{V{[eg %JJbȡpZԐ!ej9~Q뢚[kQF[.`'t~%^^1@n IDATWOb\RnjFy夶F{/vFk0'O]j,YĬ 3ef{ui7'YFQH=6f]m.\0S?=G̔5Q_9G5';chru$.!J+"ԫo_%L ,1װnB`lO—߹iZ5 sNM ͽJ)[(b Q*+5l0MvWX\`zjt?7iƖ^+ λza&آI*|+5ʳvKݣL^QiwTrvVޮe-9 &ӽU,k61F1^Kj&K>w26>o[;N8oYOn|'F5[Tj*5 qXٻg)KbHQNnRY)$| 0PPR\s,;W8xmHдM"\l,I}5ՌfV̊2nnO w|Nl .+ 4T#̡F"$$nĪj #QNn.v ۬%CaAYIefL7ns]k s8=pZh 6j%#i6"5[ѤUTˑ#XJՆ!U z/s<s1|;^߻||3~RvZK8wa1 U ?~فcs<˹ͣqϸO}ܠj[\s_} puc'5fR_)+uۺ3"p4nnnpM-J87A ؐ=R Ha sg(e0mq_i}YTFPH5FWa`ݔU#ARfZ8s`?$b8#ȹy y;a`L"K]CbJʼn}q?MdGgUliU\:N]Ue7_ʔ"Rʂ伻v]G|v:L71| ڑC r]ŧq:Ssex)UU17R ɸI/tq >XPf_%cD,]{3b D* #M^ tؚ̝Z/oa}8\fn 1mThcZ>q lrя9xɰ<7c&G{.8@S'ME""u8Pp2\ nwmU?N!u}fphx8Zߢ1X< mE%J<\U`sˎq&-nҸ71`(ѵN[ _8 Lת1qB,+o.T\+4hgE\TۗLU"XTbJNlMK-iViqkkDl&BI5ݟx\1L&[=]}rrW e\Ro-`v"&@ޢu,$( FK@;3^h23]-ʢ{z)JN*XFѹ~km.^\A&bD dR= da Fj(q> ,ob=;6^ %Wv@X8G}eUFtf:'xT%yj`s 4 C~ø,{mS+P8Q+)4ArG2(i%Ox-4`=UTg^k0o5SbJ_)RBGc¦{&uO{k”Pl/cÈ{bS(f 㹁y="LHݮӛ'qȮ!ʤ_T@9ua&h'8ga>5et_O35{a8DoOO$zM+Zh("En4Uf-.5A]^{ӥΧ1b]K0;w `{p  (mj f\3Woop~_f3Ϸ4jRLFQ]ˮ3A LwKU+ Ne_j&w9Ko ~)i؏>+~ s~%'q}?+^s\>.ֹ"A(wB$?ud ?aE(ч쌨 +HNs AF$3Syx:9RBQ%J!wYmXZ4ʏ8V@KrBGLWK|ETuZKI~đ9ZcZQO.To6<3EihUC+ZiڅZuM: B!\rQ̲ɒVŒ8C"1F8(lb8oȱĕnub(끢NE=fX>iuA^l&\z\W_`rNJ(^a%սy yl/˚ ?/#1?Ẕs)3%G05!5b.R1j$*]Z[Bl$p:4a)9tNs(όH "q|cSt})L~t¾`NDebΘCu]@ V)W|_`3bYyj\L!YW 9x'b$*ӟ6e:era-96a:^-dm` E T;/Ӷ@zbeZC¥ZìZw\‰=ı{wOMB!?ܴ>^|ť eQh100J~UlWňѝq}u({p:qc KiÐ:TҨ~0# ]B,:CZllv:_F:6 86IJI2|R`rh7BhDj}wCV`7SJB('p(N4$/4|)6lOJ>3Ն@zL)\$?,̲P*J [5ftgt]]?@F % ySJZl.N$BDӪ4AꚎuBh>,~Hqi8wp͘  E,j 2#:m`M]J|"D4/h<%2Ԗ=ypBbV9 N{DquK~B DBpi!fr G Fa\ȗFZ ԯiS@bOlv|e;phNĽW9rRG?bt:'kwӈKǠ$|R^{\ =N;t}xr~O5Qի;xo"0= $)^b=p x%vJL̢$ő^:L@1(!bXfQ&SǒelK!_tiYUJXa Ȝ'6,1鶛ө(LٽV",l6\3]fTƛK,\QXxRpnL_}ϕsdF}MqdZׇX-Tto2 #0GUDc+>Sd"lŮuNGvGHoW_faD:j1PN}8,$)faP ` t P"${c4X3d%oyH`s Yó޵>=&/ȵ-c*"'4!>.:!bX婲{ٚi;q(Jt5sa!Zd<\͑Y]z^`lx>皠`8KuET)kM3Q+8ꤡJaY@6*~|+8Ǽ 2L"(~㊙;D))l:JpX=ujCr`$E_@@~[?SkHq+_={"0 RDdHFj(({(+L ^3WqZ<wiPe>*As1b }=ӵL4)$D 4{4fr T*4i3?E!( b9TǕèZh*mEyxL RY)td|]ƐJC&rSm*C;~j.RQX_ֶkTr5xl^zjG4Tӆ-jt(3 Go?}[BtFBW쵍1 V:M|XrAMp{ =VH X2 eUQJU5elEMYyNZP($~O$H/b.Q|x IOyʞoAWQSv6I/]]̇pH.:J(;nJh"ct-\s)z美5o5쐋ZB,2OY#Lt|J& E&c%lTfnp)BT<*vՏwſk._b\:w%x1NvA{ S"n9V?{ yinSGIe΢N 5 Rpiz)GoI0ʼn" pZHxiJŘ)G:gHk@ 8 p.ySH!ZRb&YD tQ[Um.2TX~)>FX!P.Y-~>1K _b%gV5,h0cms[s>Xi>V{޵4MU&[d{f6:d ]# x*ctޠn?#mk-a{k~Wɦ˜u{DKخ},֌JYZ]q2u!zd٤Zkav2ۂ74brVp4a^>BK<0J#8%y! G=p gցN<ϐr |%z8Nɮ0cIٛ"'Aq'fq>#9ϸqYx.U./:WU\@J)J8wr}_Un\6`" cwbK-סȴgĊX[FI7j)6ea=I>v }T!ЊRf$OS:iq K'-??"p=3#Z灷>Tup.0pg`K,mIt@tD\b~ H xpۢx[|Bu]Vjx YEkHH=|RH {= OJک0@ P*R.񌃧Ȕ2jt8!94 JBAڍyŔ?@@H6L0EHn7 0ER:Cz 2yM73ySj+ V^ZRMk+F Y0ˡL&(12߻ԬؔdnVxʛ\Ck#|"ƨ-Rg&s,$ntϵoUjӣ̗1-]ˇ0yR) Qn=kN.FRJt:p87{W^7xίs*$C/!\:DD1x IDAT6xoŗu~q c|JR.%_g"v?,;}C  '9UG:[ 'PƦ:\¡EN?AvPCy9xڐYHStuN^tZ|Ƈ@?'ۯCo}z[JKh*lR ,J-q_8C<}2bY)!yDO,5X#˂ am"%D3s$ NM^"+YLRWiFҠBJ)ܠ{|y;{{d"&LȢ.NFH!G=|Zsڰ6gm?GF!0y2^ڕ8隀#t]ݮ [B)*aB;yXڛ5MueW^b} 6Ṱhj?ٰ(RJ 꺲aܾƏlء"F|/9 ]O_psڵo?xa[zHS!əc3׶5 -S޶;bX&v|0cT֩ geqF_!{ّpK.J^ϸ8~6dm&ȅ(2[t|h6j76CO3#ƙ+]bvr@_=fK3g|/.7|3>na)*v j~ͻoő[7ǡˮJc |Q}^zT8+b^k TtԘ-C!.NWF \2i›o#}S$$d*k'W6Ĉq4ࢅsih))[m1!qyb#X֐FY' kstJUZN¦|>Hm2J>hwiE}Gĸt[@õ!$599D fBT`zZ~ YEǰ0 u7\!f!q9,! 㽹nm1^ !£ow[ O]u$)~ $ևݥ}Mԑ)b" }|ˎ˴*Yj: *imtq"D`Ϥ4PJC!P*z⽋Od9H;CƠN.ae^2 ^97=u^aC+ 9"C:" 5ERW{hM++ a!._x7$e }?&; SFc,]! &Ð VR 85FD(-s0f`'(#CtFCRPܶ#p4" O)5ΓAhrO%l: FeSҺA!H*x^H2}ͦ5x/* h9)X1xçk=n(LIk,/Гq@) g s]r7}C6&АY!c; dxRrMG0H\6Ta,!IV/,I^τ\}|I,k>o˃ϟC vu{QĀi t t1҈C:]\y!iiC@N2AcTI*rVұZTmqI)+ v.SL `Jqeͭw1;+8#Xl/K1p\'sxd@y`R,%,}$,> P?нΣ x} d66V]sh[˸l%׊Dj[xbA~!:'{q>qww71%jUdfv-,gRe8/[o(EnTP:ϙ9aH1a?{m/Ʃ3f*s`La)SCƆB& 8MË65%-6md*8HԳ8\yĺĆ rJf~5u~( tL1&7XިKǺyɮR4n]i"5*}c- %> b7 >ikCK7ۢP[LCn fÀpx?хx?aWmK0#dhx pgx񺟭仓OJ }2is@H'NfH#1KBjc tpF S\9/>qr#P#J "bTRHVܝ JoV)ra̝l fqm J+`@*Z{>ŞyZ/H`R*;_yXtq_̾ 9aXQ¼'a"|/ۂ8KoLYfH+hXy{}}ȍA$wr?/<֯'a]Vr]MBjSf}E4\,v%&aI~ɮ/+˄l7uzi̮Ɣ*c J:JgmPOA)'{~O4QBIIʿ| f%]lމgyg%MTC)>VUb RYb]*$0;pk^Y9Ya'Zf;s~92/d8oI:|bA9.;1/wuyWrAݪhvr;pR45lc7;ň/<~gO'!>y 7ZQ[>v,lu}rLӺ S@d ޸xs&? /I{!6E1!hɅN@6c>N4H :0DjC. *@J 4|.tr0fƙ@)puuEk<2cdyg!&, `Xp/D%"^eS,RH{RE:s]G ]9p:u]+^꭬. @fX $Tp:\( {tE׶g&j74XR3&a1ґFّfdKZ~ǚȄwI9Hכ3\QO#> ?.7o67ބ be$n8͚ؑ_%ťue]3jk Kkw_QB,θ҈p>#ɧtӺT5.zZj .Z<;0CgO¦jD,!֖U4|8bg6:|1;L|HH|cD- =a@>+_ܔ<& PT}El+|s3ΘM1)YxJp}0{Aa1ߔEQ ps5i.ac*j="L'yę dI;/D)I|-)7p)Ƽ5{U<bD~bAk+㓼܏}_хIPx2@+apN-RȳgDy#tWWW8={;j3̫lM x={/_R=sЙI)D+)%\yPDPؔ>?񭰿Uzi0YE:Cq\HC3D^2ul+U<W{q{()eWL(;9(%8I3gB"HE6A sfu`\! ѭ*T^__xB |eSt;Z PODG>jaµBήok൶\N7<kF%JC66& (()B1:yst|4{#*ΆBtҩcиY1&w෷\'Y@琯 7*:d(cAV !`|sYk!\: -\b~ (r>JgCFqVa.1' QJ"@EG=wIjE;ul4uW3O15HZ &Y LhM>wH~'X}ל8y|!6C~-Kd2!.yfN=35Y}cQUվ.&|_X*7;s ^%'7~5$Rn}\A'?(/ͫщr>lZzqQ[^ -a%SƳ5g[*bm,e:̬./1-}ոn期v 'f0Ƞ4{\G$Ssp>u~*- (yɧ)4n}xLJpvK^IB*v<gOc8)p*c)1q{J.(ZJN>q f EGq!# ] "f]iҍQ|_kK_{_yH+WTZIl*uωk@(]2S~vlc|o Z?2*gCl>1"?հ0 @wJX1)EQ"l f-SHc2(2f O^_]~3}fT[b cvPfUREv}&"0);roH ,c| up.qxt J `EEWS-a{1dC*<:MB{(!gnp~gOnO+R z0)A;sxM7:en):J 0M"P>`i'*)uu}|O#Ȕ{XOxroo?y_藿kޗ6@RHgL~щ Cn$`%C@5]̅6r2;fF]p5 IDAT „^&Bp[L(иo~eyI5&xW9'_.dkA$@Tу`a:эB(-aevz{0PA@o awxu<`g ; Rxy{.!5Л]:A+C3wIkϟd$ j;\=!ޱ/} A HyHIֱ[ptC Q:vG ĪOnycrv.# Pր"l-,L~;##8[70iC%lv, aXy|T び(}&@6R%Iy% D'33.F+x? '+J\`|!naN2jU}e>j|*Pr[tLtdZ,V)Fk f?w1, IS@tpݽJZC=lgi."Viwɹ6LiM.!s );xSxSD)&|]!Á~U?xۿ2 ʀ:SjݷV %[ɚO%ײOͱIxYO|=(YI9\ ynH0ΐǀl 4rcG6$XG=uKŚ QZ^2|cJ&1Q5 ZwpJͱ9Q%]L*1[_\785cz Q0 1{MZmC% JJ^f.Y{Rz-omd`!)YZ.hq -*9AH>"-J CET/⯫b(4>c|/'kg?vpˁU]4) nUS5$̀yvl:냼KS! MkL;'N 8q䙂{;u)PB ўl~ðEb('94bp \6L hQ 薈/(e_ҐMh[Ӧ$oZo&n!# e!4/_Jbx'%חe Mmyᠪ2}1 !̛L’NyhԌ c^M)t%x2׎?H_ӿ`Jvݫ DT-UwDXo/+SD3vYůʼK'Uy DDHs*Y| QH>8bya+uГw;D1N20?9ZKl a#񈫫+(lE0q(lCQRb -[6$WD[]vSk=Y4 be cx#$3&x1c|J|~.~(Mbq;-Ts.ġe{nkR{7~>ЉO^<~wl?o >l_&NQ 2!YyĢ}H"_0(Ci툷m~ɓA=3^|w^R@5 %OQa~8_a`',~y{ >~Դ}O  {:f7qs:Zp ~ē'Oft^RkM { {^([WJrbM?{⣦u] % ZCZB#Wpn ;DO}C g+_,F[hAkrWMUW50cR6cinQl,cēE_B2tܞ*wQ}^3_ Dz먄ddX;e:V%5[j(u+^T x[F%)JKK[YkQNk 8Hdk]$ J O8X1xf}O 0ՋvvAE!B $61tonL3?&nEMӔC! ~,>~ʸ1 xC:~&V G#DDV%6e^ebsMw\HMR 0+v]Ypij(b`H԰MŮȐbh VΖZP1?oYx< F+l'1)&3LBƨD͊ P@D/.a upb9%V!JrV@z8 z 3݆x2mJH~ɦ OِO^$H^ T m$`z5!p9Er1/Ȕ?U_y )n_lk1  Әޏ Ua%IF,"m2ɜ:RUP|jgK&[2efSgJ) ]1  LPd.DK|w}'v/_>>a?].H~uy}|:jd\e mQ VI/c]9Q^+)]H"DA' OtܥSRZkȤws ev8'54i!:AȘL=6Q0F'O \vѧdtO6 g"HNs!xhG[Qе .i-sꄃ5G-iꍓe3ꜧ`4 9ڛ/ɧNŢ$1dBUAx/CȸrskYzNӄ0TTKZ;/7,d~wLe|v;H)i2IZlx%M#軾韁 x4xNcu(˼N\㽧5#KK*vd՘{o-cuXm.r]@xeab)!1vu0 tpSDRKx࢝C#evOE$֯^J+1bz}$cLwww쥴7h4doDC Evش[;/s]TZZJ<z%DDt6ys'z7Td 9z,f.u9%7- >ύiuch1 )JO9yr1lM YJ̸pYx0Z&J~Y$O)fߍ'G[o㧾 <}]tJHtnPlwyIcRoč \sUaT2 P._o/%K)|h'boiI`Ml5 9>,?Ӛd$`mx=8E m-D?}- \P0I!=8-O~+JB d=K9:JLOJx[^L"WPiAH'"@ $;Ĉ @ ^D(c{ɭK$(#FRqejZD>&dsg8~z'Ddd hX*"qU\jB$@޻HdYbCU=QY5=\ Wܓ w\̎ tLuWUYYY>q"jjQpxx+yio<. 后V,L) sq~OyTq1[+q)LEx<"G!E$v0 j 60F9@ Y5t;]'Z[I !ǙڪӮgYKxf ҩ?~$CJ+,4R|Y,2BȄ>]S'ٺAdH5~W*cEcT)F0l-N\8FepN*yF9Xnn.+@ք53|> s``%p_ N%φ襩7JOei(Njl YrkL+ [E_˴H&JkPV˅Mip/_Bv;ſpW1–۞N懰_dԕ1ԬV\ύsjD] 5?[ϡ_pL1D#OO=)u{IQxEEBj5IB3BT 0n UrB9'2&G4yP(:sym AQ^%[h79kM+LPꅾ[`̲l,޺k۳" & h/aMA¾IMiE/:vx~`@f>%IT."<ոR mxOMV+WB0(AGϚ{R# _Է-8⟈Db_R^&ԕ"|;V3n/6j߻{pkm,6v!9#0ŭObڨJ#*`bN;}VT0r/ame}"EqL(+p>BeFWĝ/a~&FfM^s$ YVi8RpjbdwaJ bz=m|y A_|frpRVL V'4ŀ85d44In=-YplFkLONlta=]vɠP@>R] m̰X(c +]S$˥c8N @`MQQ/:T|>K"oO_Bl H/@JV&,R\uvt!JX֏_u[bumk]5aX?ψXx:]ʔLtD #?'l`HaR,〃Oܑ@ NQluΝf25y1Fܵ;*ѹmEч̠JƔEۈI|{&4}ߣ m0[qs)Ds]6'P"ud!L`B*%w~CTKVI_6`#i[v N#ɔ;M/ so[XLBҳK| 5ܵ*{L[ v ! Dg4i{tStnR3J@,ClaO4VAt HoPZƣc?ǀwke2Ark!MKib?.fYжmÌ0Lժۍ e'47f1Dgb6SNZ8iswJ̊ܕU &TH^, b=s?9֖@EPZ|G3-*wL6z#|4 CkZc *D1xR ޽{A t`Ȍ.Ԋ14hAI^ A18 EʑB mhfnBk B=+6FWH. M2TI9~0A$c\^M$0墚 b%\Nl$ɇ%Q!cJQ Ed*(Rɦ gף7 5Diw{iGƮc<=xeJ58gy!<Ll4 ̌`0C 4MijSB)n6%kV,&:t|In쓳\z^(k%s'+0f%jÁo&w%=:}+ƑբY7 ZLaJ^ V >xFF$h &LKI*]:0dCll.hV2CCSk':2 ƈ=x7ν]%):g 4-l@Y f89e$ȋOP@ NɯPTHQQ9!=#WT'%5s,QL}/~D+i,8BRa$oV =vd.PK:T.Y˞e.D_ވZkX4 &D1mV2Ù#ʼnUE%(pF)ƬM6IQ^݆)XnNeGm2T +7aυu48GFg,G2#z?7F 2B MtU/<&nĎ@iCcaFdQ >B[#@5 49SNXƃ=!NR|I8&QHesZ"CF_f#4U5Ϛq"LށLEgҞJ`R@$3> hR`rnqeX#oaH()<^bc~0VX8np8F.A, _օDNoPAi9dDVWL5젵Dn(:)UtOrg\b(7y~HQN)9{sc^ctGv_t%yOg5Aj #$ê)J,) 3408MQglLVY4Zqqp>pnq:$-D+,lԏ -iR@M !U/vLD.rx'H1B"HixM`e*DdIB)Q#c0X O8DNk/pc t&\2^I1Lyp8XHs).4f˸PvdZFI?1֒8X#?U 8Oot)J)12IFu]eGI1vu,L% 񛥘c)g5c5ʁ/īs;kkk߻kOR&^η>|\&8~ #ӄ- `)&Q""tHAN%i ۡ(ࣜ }n 'qixz|Fh2y =N B'ҿN8)$i% +k2\k {@ur%ɧ@*.t]_..{q6( 0U 4Щs d-t@g5-LcѤ=Q#c[fm(fG5hLpIt{Ƥ@ՄPLsQ>2$eMsl*xZ۠iK*6czZL S k_:GNHn[>pX~4D9]5o,Y}u:)D>80g}+K1{I 1nQ`m8'$4 jW/ПNL5#t8A%R)(\qV\[̌/ L>u{l,-0f߁Bɮ1 ox<$EP1$/N:0cMVZpJЊ`d4V+qb9a*Ɯs Ѱƀ.hQ?W.~h#*\w /ł/r\CM:M^CEN%u:C$.]ŠD6u”ō>&b^zdܺ#R*&/ }ar#9#{qL"˷w[kX.W=1Vx-k0H%c=Om˝q숼]dwzޝg՘HUgF# Fc1M& {p{WBnDJ6^UqNnQZZcH(p3qJ #C"QPER0m6;OJ1C-s|öJ`破*őhY`@+)Aj4x%+C$.J-Z"V ZMl0( =t hM3Tbnө\܍F:0# 7m e>ta2 F0'4 ! H頴d '*E0M/wm}Dȑr$IgaYt?3& ն|1'_2,,4|e3o1FF~֠/d=:X5*Ϣ%(" n1@E0Ĕf%#'ѦpmANLˠ}zVڶJkrwxߥS+(Ǥhay1nw4] "qV@5dKĜ*ٮ(Kp L81ű?;I IT `NmxOO@gԔc3Hxu^D=n_^0/|Фm[]WsNۖGt]nWvaQEtR T**bMӔA^?b.m;p 6+t.k4L(#]nwH^ts1m 6 fhQ=iU0u!(a"qױ6;ɮs֮Z٪̙vg$w WE{4O`Yu+U(oH-ɍ7m4u=mZ]$ qVlq"$Jl\\rE~/jp`Ϋlcb&4Q1"DNZ~>?%LU!Eon,s.U`h :ΩN8rwdMkEaH25V Q6I0iB(YmۢgY9CI-ӛZԤ[vi O%FI8VJaCkq|RRڠmQ}>y%.;p>M䅭|QmW*/mf sŀq.;ZZ@4|6k(mN~A<¹4VZ8Ǻo9>#}Q+|<}O0GP*#:?Iohj7) @# #,$GBZs8K㹿P䓥 ͮ+"5CRȧ~k -a6սfJٵv§V &<Q`-@;K$0c/y(&zD掠w1&JVR#KKQ]/4!*'(F k8WGiH1, Fk3)+p>Gqi:Z: i;%v0y]ȈzR̝mPD8p c ]lv0; SPul3_\9P0)4\RAU{ #!%iI0 cx0]f ]0,=Z"RJ "R,U`@e6O%ydǷaHS8ժ@n| N^?]?_;oKA9 {|o߽fV#Hc8P` &~vgO'0'f>$3W4y@~z2^11`SG T\rltdYs8V<ՀYxn3TCPLP1"\W-&eHJ*J!j l9h#@Z6rJ":12cFvO҄'(s7⊱ E|1 vj3G8D13#C 7R[Gm_PTrqW#Lۤ"9wu Ed5iz쾶m4L#iY, N;|:! &;bi1@ZC U\rnC3Ɇ0nⱯ)֏]'[?[]@Mn=yYْCTqB`t[cfrk1cg̈DP&7ϓL,ᵇo|<1 G|(؟48e 6C ݡl4 "y[ P0GZ{xw?O8 E ӄ^ʦcʧ9C$/^ (zJN}>aOp!3`5<9u6-乍]3z5lq>׿ï~K|)Z7^>}$(πq q|Fa{Dψ,qh5=T8IYICyybȲC*=)%9"Q'j[L,Hb #Ll4I&r:\Js䠡XJQ?{oO%-HB3H'Q ,Fiμ#JO+;Hŷh+EZFe`ppdR@?44F4ŋk5(c/Z[X"XB]N'IijPMcWGf_hp9T6N&v@ZwUꮼk˝5lƢdu3{f+99o3:܊rbN> _D֚[zcilbc352.!F~%F?pSY&@'0PJ^dMg8h".(EhP0)H&u0,ĐNmR{#BKS:x#Q|ia}HXp91%&kk>V%M8bi ڶ-qB@kB ; LTv]וb;<뺮ISJI>Zg9!yqvgt]n/1NaG#"(hVBRA(馏Vt׬etv1rdܐk_Êܤpa+YEdp>{~3kVqn=kE*qQ|݊6G ݧ 4$jHÑ.iFItMB8:hQ >=Pl@1ByK4!( 0ƠrsczI. GqJ-{xKn%4bmuժ Vakp.&BT\R :Bo#B`Lj|២Zpûu+9z…w8@2Y;)n9īyߗx{=ZI%enQM1nx׵::'k 2&rcftaG4M/^4}cwՋm! fED_ג]!mb&RFղCP%o(c;B] O\+sm.udf[T،S IDATud>7W".r(ơk롬2\p|_?DL>ԫm:硵 12arbpvz Lע0^յ mP|鑵8!Iэ&A[9}HiD,ct^|0tϙ fHIkU˿r<\0k,3vG)6>{"sR)r<5LcҒnb@w8gɪ 4yUfvYuyGOc>uwwwFX`1,0rel5ȪOu2KC 3VJRc`ձ͎VcTf j\kT躈/ yA z%bpX*߷\3i.t*;w~?'"ppQx ~1HN%E骭1`u%K>hG,E 12JvbO\`FL<ȻXR924nj(%!_]|}WU|+fI#mN9we'dItu6t\VyXD|4=|zBk {=1T>$[ b(_~a6 KESUfXptBR`MjxMYy%o73)I~=mכ+lL+D5̌ eV-N;93PBjk^ Jdb67sy먩c[s`-*3[|eٯ7NyGӵϳ5~>==xOMËp$ ,g>ʩ0bߧd=Tc0qĩ?cߧdZLѣ{۲}lDH3t!DȖ`OV⪗} Rɹ.gB!H4&jx#*Ql2vXz.C 9Gυ]@Ty8HUU+/F) = M~IݶmIa)C0frVx^+^rA/4C2m}\\r1?Jݯ_ILQ㈧w? h+h*AU/@#qv&,; ᠚T4 yB@g%__T(8I1Jfǜ`RJBD&޺Bh7EМa &UyuGq59o ,?(|##$%ζ="Ϙil4 >==b8-3.I@'ʘp% E%5cz5^Ww3TM*IX/H5=OW4DL9f9dxl6ܰ宷\ >ʕ)mtEwhׅ|mrJ#?9fsSEӵeyA|xhTmC+38+\%~o[Rn8a=nwDTcđ;@0QDy% PZmfAa71ū>%dvZB:2֋(Q m8͡Z4 ]ס{t]WٻS^k ? */RL3f9)6䒻6 ^.`/2);/`2n6xeìa4w|Aq:»F]V6>׍uͦUZ2⼀vߢ?mn=aI't@48[%& sLlbQ[ִJkxl#"̒5Jèe#!ze(OO` 2&{%D%z'(CDWReWБŊ.]Y3 ?S׉edVwjDfe@jRA#z ~qzx%i,U@HD&y fqk !NxB]t養\5jhbbYȳD/ҳs&>K،#*'1/آ.Xxc*vuw]_қGkìfynAuq.\ >WQ_\⺻]ܙeAok׺fiHu㒯t} {k`QH"@cxL΍Ebǀ) uv'ПC'Oq2r@ID 1!aMQv;Xi2 ``*b* 88 >bKF'7}ݴ7&6f&I\mPn" p!BAA#O#l#50ۻzX+O@F,+6auS,2a(qƚ۶-=G$qSd%d"d1O0Chm4L{>%֯DdTȒ F:t>@S} ՐTmFY.髝wa };2SwT|w\ٖCڎfS.nD]/x%Z}| fd\׬ J1 *S? ThȺ9B̉D sb&~!<</}p5CQcJ)(4dॵe mZC\ *5Zͧ Z4N (5*Y iIV8*DM~_#+0DLKFMGI?).(d2έn0 %iQc`9Ig0{Ę|v>d n- 5^x?xh0{ͮA?x~-|%e`4~;(p:?aIGȘNT}4FGX_4\eĚ zGm$Qm+I(̠f9%b*;FhqAg(hu@ajmP"\ 61CYA8ٌ`~*hc1"n|--Ni׬KM:E]tGbXw=R\?!t܅FG'l˛[LӀ/^QGV"f*[1+N\Ǐa䄅̒&tde0Uz3SKg%JE-J!q!&BuYMr䌿kE/ː o R\Xemu'>?c#&r۔GgnbE/Ы]j ǟKX޴c-h}^֪̙dɰT`:~wi8)'>_¸2<%M)F˩Ͼġ+NP#GPPʤdd"(WnQglv@a8s" F<.TX`JK9{4\#N.Ѝb[qc-KPx<==?t7SB*de֒"qhWs/_L2ŋΝXNu4K6GR'PWq툡P(dl_%~lΫĎ4S.[3_qa :A#R|!&Ɇ5V7Y u!-cTs>}~--{۹y EpJ9=7Ae.An[3$ @t"T%8cNir 03*?0 E%ONȌD>YLOyk♅sRkz۵Nc]ZIDx:/^ ͮi!Z KMӀ}y8u?<<uQm x?j" ;dX= ٹtbs!J|̠ɮ8wridX#> YpʐU/:{6x2c7-u|Ew(nvVcJ7mshMMz6q)R n{f-5چYbfS%0Cy|o4QP8RIФ]t?Ő+nMbxKdiSX֛Wmi@P2ӚkfW_DcɃLՉe 7oX |J:V/œB'|w޽h`Y$as?C2r_qLk#ʯ?8_TEMReި5Mz,$j2$V].ohYtqsV^\WWłMy+/9sLҺ oI)Y[֝1#,۝sDff_`7Up,|᱇,Ʊw}N g4bK‰oRZ 3fi"b,=bB0 kixW(RZkK1RhD_cӵ=4V#FY>΅EzM7CƤ9G^>Fn>C Pq'|zz,aP;,LY۶fZS>gx|SSbT,e'JNfb IDcݙxf>fo$Uixb-HɫBBaĒ- N'&[+lIJW2A+11_?1BssE^?o.όYD/ rX}VKE oA(TO}CaŚ2.<fNa_@=ap@ A @-E%+ڵ 1)Z3!ŸJp'r4q[\+kS-Kυ)h%ߕI{r{|:a֘ L/CBvFyOOO]Lrep-TKw8-|*pGpHfxFͬDT:zeG<%רkcR5Ʋ@H1ōeéXp9jQr-{7xk]Y+m |adTXA 4w!\eokߒhהZE §|W_x7aQd2~/ AJ,o坏k5UGeel^|T*,0 -ݐL!_fkQǩacmk$芺l 2▏.mx/帘Ծ2ks|;C" _F,-ЭSZG‰A#;Ïoc@ۃb<þ$jyK,5"CAhRwOA4 4K%o.Wi9#q03OWK-s@A/̨hC$* f9n9s V'Ʃn Aփ5ØopsO\gi?N8"e8O=^~"x^B?a4M o޼=9)"|w/~c ޿;hVI,\)Yx %i_i76c棘s*q3kVD݁4: XL~7Ɣ&TT- nU9o:w:1 `kL뼻98edM9jPJ^03SA_ge.+E3ݘ RqՖbqb'c:klAڄ?U7{UU+?Vݣ10#".xi! ijVa]"V}e%W1{gI^N}8´Mi|NDž fS|9k4 MZ5+9"X2 qaTT0E q4r]Zsҭ#`͞NQ-6P!PZ⟢>==}ga[O>ocox|D(岏q6C޿7/\ƙ1MTJǭ8 %p 43I=vwq9"7FLtpJי*o؆Һ֤ J,kt3v]o#'5+%Tn@-v ״-#B|qoIm9gIܻ1 FRFPO7Kc13 }r:|>~X>Q_4h>F`wEk8AwAU bf eE~S.]R jܺ[jxmK47+sk.8G+#Ԗn Z{onnŃKwzѭ;dxD+xq:hqu ;|h?~'bgv21 G/q8[?tS{k N|3pr˔iw^\v.+, [Yb`m k4QO6bKFTecc[jP̛"U뼐.^.;`-W.y-bسnN] hˀTZOm.tV1^z (,]Ke,<`m,@*e1W {P4,1R [(]Jb?/<ְS)-d&M9L\ļ ;Dyk^ [Ťِ_9HAN&[wg I1@MF(FdBGVIu>]U¶Hk3b9 L|0:<|/R3_޼ɍ\=p$3%rgk陻֭JU*,p mZKI"9Cna7%KkNֈ[K}2M3Prul l--V'c^d1 t/Zm'ӒvHc s8ȑq>\^'^u-iR ɽ1]N@QY֢sR)"'?5IBWW_wY"w$TCV4㊵v; 撁cːtbP10xLӼ0d[B NliD_ϭ5UЩH~k W5mjUS(Kҿ3[w%I8\CΚOY;Vpqc!]! cUiwg#Rj8&ޭ>kY1)c`(޴Hpq605 Wܲ'u`%K*{Ԙ1r0֖+afNY6mX "˒E. zmyd!i/@{LJ#R @xppsssK|EV@AyV%|1J -F(b7U'OEϯː0 h2uP< 3g 3ګ"'k@,Dʘ$ r4i,a7yin,R+FZ5۷Ohe7Ej ;=o+Zx[ZQ'X;+EUA; _;%ͿμymqBc 8i#Ƿ9`B[3rb=ܣ`yAtxuOv& rf'< f;xC)VjEY~"0l[gˍ)2Ӽ2k+i ufpJ *(l[M5u4WHӰ)Jnyܒ%UU6%.]ɉ@,}KiUMa_{ϟ9^Axӄ1Lv=nAulbJkJPFSΪ>T:yß'ypssSM}/hO1k2 ^hdf!θPCybe%u/Y E3!Ͷr`\{kMsjHe.6-5Th~x2)5ER6jDfV -[-S~7|WGB0axd ,1IF}T򶻩5Fi%C?"(hVRcNrIAeo)=bX\k,moZPJi9##%ge5[\͗oV M:X𶆃morHe̸҄)yį #yD΂$pS-a| /iv BA~[Bb 6PU(wuRVzE ?Af'c9}\J[ yó>4zR9_,7k41p8]8yvC]aH@HQ2/Q{x:O)6l)p + h@*ొ֍i1uL#F`L%m1N {q|s 7T/YWUEa[. ma2{MSv^o]oyWtU*m 0d1N޼"qs&{ӟԝUh 3צ8ϺJq}6FUtBHV U(c;#hp󄜥wO-D``Hs"LJav0]WVVzyKN)ImyT6Wх KSOmK>Ե~+la,-xpO^=6q^ܞ43GtnWo^ởO^b#]SY?_~)E3T> R>ė_www5{<<c#s t{: N56$5 LWxT]ԵJ+juDW&pW!Gar48זA@RkϼbtikotIWup򌗭dm{ ϟ#s;*q1t;YUڃklܮJ#װֲ/6Jf/D/.0yv{P 2Q5͠Q$@mX[5̵snVOv4 n^%rb~oOb1WhѶr.I/Χ8"|GK8Gp8`j(ROir}/r٬ \::jAm:2 GՙG-,dJʤ& si]A=rS4-?_2 #>X3li"bi[[9Et`q{x*&$ETessC_sNiUA7U;~D kyh|ϣT1t6 g`rvq P}'U+=7=[%]HbUfE4M!k"HQtkQf W͡K`ga#1Ea|Qu=NG*ʚ% ear ;i1 P;uC`Xx) wӄiͺ^@EO쓳5#>j| nN\\l`b m/k [⭍sOw-v-36'[:Eyu`mBl` 1p&?:gBN{|gȖ{GY~w `EEU9MnWb=%X%M*r@ E^A.|ŴtxvẉA֚) €&dPP#Yҳ0@j.](8LʢWFJAg YcVR@zܢ4)[bm< /L%%$`hZSc҄՜JUݻi'M*YfS%1\lBx$_'|9<}}%?Njgӄ:''% kTb<ƅj 'K欅5>Hڻ˙E=R M%+N#(;ژ t<X]" *nadÈAۯ4_TWIRUIF5͗ .B+_6O;~4_3:MGu|ȋvʵ4kR^S}`wwEֻz3;>#2Oj~$ݔg9 08{RֆBIv@0E|Ll$ T`V}UsT9 GmUP0یοjAf3-$W<>ҶOG|mlEEbA/z7a;)5ĊyX$^aMS8aN>|x>ʧ(RX!kaw:}7b -wdu:<\ˌb[NVfYX1LRdVb yP`$MrqivV2SK>.\} }旅 I)f#bb ӈ_~_' ~kt23~X5Xz(#[Vu@2#.F+v"3CB=) 80Np)#g#7RRŋ0Lnݱ1#۵KH{n-Ha3o_]rc+/{.S~k٧M[;Vu \5Y*yVH WUH xwWDx nȍ|w8"rxi"B|9gUt8Y(5[Se/RynSr0hXS ZS݃z\, 576}P=vk&̵¼ѠCΧSFO^QsQjcM:B0՛[GXkq{{)?N XLp NrBgYX0" kK&D]QhJD&%X9NӦwSSm{Nx5؝˂iC ltZm @[ݩtZ-'lf5iVpk/vvK˥~9@R8 O#Ni{OgdoouxwgϞԌ/~9778N'i~/}㘦*'lIbB8BɏQя]ibI Z*/NIԭ,HX[/"AD7 IDAT@ ^BғנVnmJJ[f#b]WkPB&.eU%NY k6P6܄VT{94p#/_}-" bfw<N\p-} nr ~ubfqB&``;gTG51|':p# EYҍ@;}\Gy5*GgF+/¥ !k beAw8NPb FINr"iYu9)똬Q8`X["+NȒ4 q* 땤 Mo]n)Rp4/ S|J(j?DrpysĮ:];1^C gr;9'DeN0!Lw"a*;;y8{ἅu28"YK9X+ks(!Xo%S,4g`U`A,U A `WGT1v6ygZ̖H,[XuY L)'$ ty NG.@PC1--Dy(-~WUmۡΤ0*a\8kbFNd,,%D+Wr R /Y~Zx Db QFѴ^44g {9B8={0A @o( *?v8M 0]y8v!nn_`o8(3t|@8D4bgge 6p])˜*8JPʑI```0uN tփ@mAƂHQÛ A%B485.cr RMy[S_Ѭ(m\Osd%{$Nѻ0c8^~۷o?n;8GNu^0){%Tx< S+s9ZeZ/MaLpH94j_Z-K u LImph(U:svrrY(qdbTJ̺ƞk'GQH6[e`-+N:hH;3`"][ߋcP)'d8 g|Gw_a M/1,UD3JLs@E33e$`1XaqZHu= :ta #`ZGapF)V'ifXd gAHIP0+dmŸ*)4E^ ͮhIגi5YI{fZRz}^+ #6op߉Q" # t:FHQ~ .yTݐ b7Sm0V]+mV^Xy Y>)3 U.i>0R̜ ך! C9ۡ30"MoLT\\k£vIe5/i-[}gE@iڒVmb֖TѤe~[Rٌ*L +k#tI*1~k|WNz/U),L%ZUA_.KZe3&"8!a h),n*4B:m2ݫt˺nG:0ӂKK`4y7gz a.br#(X7N ̘'H*xw)[ҸJoYAkJ;4Qe]v;i4Mxs^~1x~ X )H]Q͸#&f^HʀKQR5d[re3.UŠl Leå&,ζ/| /-3ò{2qY-oi+isZښ5u\یs]ܴ $t)&qۏ_}gݟO8O}7J̒+9'sa9Z"G[?y\Rp>Gdcp:Z0X`HsẄSo>>|wq:px~NA2 I&V99%Lk!a.-f,"Wrط4ddMJڈ,:?.ilwq*7ƩUJBv+(3Csj\ܠ խڡ󆶱ue\J Q셶k{Zh4i\"{v] -ol\qQ\UF3Eg#CIEHyroz {XPά ^J鷕\!-ΑnbP7jjg7<)Muʍ%ۭKq5覼.e0=ʋiqvd^f)uZ+iO?ٴm:s !Y ) _|s/ޒ?"kAJZϽ`0S nS ]p83'IzԶ ǜԐҺ Ub%1uvZ b[ /QV͒ql8sH]K_{!gHX ļZزkXAm|L~Um<4R}>/[Lf *1; q aY%;Ώ軽~4M} %d9j `E(CNYvdB"0IB%2ϙHp.2Bպ9R#[ pgkHP[MmK4C-D=8R`69q]5 CȰe k7-20 T 5]&W໗?o}鄔3þs<}7ee=G# X`]{ފ#19B͟G !F){a4ps==f˷0) >j,5c1&gkUC6G1%0lbnKpsb o)ReaV, +Uƃf̯i2md! kӕ3u_NWgmՎ;Ā!8W?#iDc<>>VB6Lq_ |)`Dw{/,hXw0SB&zW[ A_sRL%zeAg,ZeZL=XBZyK^8u]'o0@-hƀGe0/6V Xl/k1AK!xfg5lekc}?o,1 1D{)`80vSFzĘ~&d Lӄ 8 A̝(NϣgϞ)~8Ԍ zc8Ow;tCΒVyB;Yxg1 wƳ0ZsD0TD!] cxJ$/qȫוlN3]+* q|eyk@v |ض  $nK3[a6M f1H1e`'+_|H˦s bpTgz~g3+\ѐS#WvNy႗)"sBʌ ;v]ͺ |4$s%8oTS܂-:,m*VD/Xyw1b Ga7#'&VzbD*F3紝_jH0ydM8۱SJ6\lso'%[g4'g1&`޼7:b'#9sj*BZ劳}!xҧZ=B-!LVWdC]M 9N\:"XO1! FUKY$ۭTf,eCM>2U Ki$ӱ1:Eni[-ƜC,mPS84 8;|'|x r69tfཟNZ;ujZgc=X۠ #кEhE_*1U-QyWbT[N:+13k ipTl6P]O ֍lƼ߷!MSYlLå n{kUXY6㵎yY LC%MJ>oR+MufvE gbHR8.E4W5P+ 1dq^PNm9=Ua16'LS|A :cK/c{k1'tNZsH<~h&î\:>܄f\zGs~,\C*Zr-y>(~: Ҷs="'|8>_~_k96i1yLjBqQB,,{AV`9j .j$;ZưYkC&\)="0X0*8Z& *ֈl 7Aj,#MqAe%=:0mkP8F"*R(*zg扊gS4q!/U:Kmxf)cfN整n*)B88^;XA(UMTSRB88dgVΚa|l7\5`@R{jdD*sתs~}ښZL$6^6|&c6):-O,V CG97_Cm'zMqiI\n ̌1dG8 ^BNpp`"<]Ku8{S К*w쪭X+Y$i(K>GJl p>pZ`Jڛe;IJg{Y\ !cQl4T*JyjJ%U\scI"իqΊ1K,,\jJ AFF^EV+eʉcf9/~Iy>iˉ\\AWT6zs"]/2!e]Msn@Nep}qsٚh!ןr u4豶`),y=NkRR6#5 Z$~dlgJZbǕ|uڿgZHmPM]zD¤P,Ho=X&zVn7FNy7k͠Wڡzm ݘ0[|7x 5q{p:DYT:MSm?MIF}SBf'&M`;Ñ@<%8C gLukrSx5QA2~NUHSgt!\~-, 9nՁWT\A9\=mֹNxU&4|kI yh*Z9=?el \_g*oBOLRv_O tNT uǣTϞ=Cux=t<Q+/U|֞|蔸#ݬDWOݮ1 *pVnP"[pkZ^ʫs <'X'򹝀zSicm;ChۋVI'ϯs<l/O1ʬVR,X~9]o&v^%wwxxo~/0,v}ͷL,!$٨sGwq>XJM#1*]%7c4I$g)nWxIlDJw=zaHipn@sV:aI &cYݙkWIAC}Yxʘw(3zqbz^27%dvX#ՠ1kUs9d24W2˪h?A^o+ wVB8Op>]RəM2ppJu3i@Jn!̎.٪(EgXJ&S-x>fyPtw*kN5NV]i_8|G /f<k|s!rW^闙f̟qFYD[ 6-DU"hc8a ޿_w^Wxisf$1|Dw&YjfE붒 #QF*߉H ΁l}h(P 8&(㨢\وm\f8EuvHS^ wcV䬉DTˮKKēiT9ɖT]O:MФc]7_rF%i ,Wm#3?R_I]SOl6.}jijӐa)L3i@2 B p_f !` "p<ᝯɴE~5I bq=%Ʃ2YMNkL$p;i CsŲ6HIRS)ExRQt 2ƐqCֽ'9.6y.!JAT%~k@R5(GK,ZR:$NAk˭ @4([=Ā^+{޼!F=jغƊ4ou|FQY(D>j 빁!3rx:"[OUq>ic8CVJ %x~C 8; rms^E !'`"7rŁM}.i$d T(U:U,#֣:^)"(w +uxTU.\U((oN[3B%_[sQj}E0 *EbN5Xa#Ny g[ۯ82({^%UCP{@H8U#(##IzKŒ&)gp8@VN `aJcHhCWXS̈c=;q&+PzL3,Y8&>dG(.E+ Da5WXwґB AU4Ȗ!c*(SU3 E ˂ @:Y\C$Jtx5/7*3wB:dWkP4, ʘ1+*'m4 ;tT0S~Dr:UY4L#zCG_{JtQFϤ:QeN!`;^r̊ IDAT:AYiҵyða:ȣ+}ŶET~h ҂Z>aYw2P,sۇm[v qK.z qg9C՘CĈq/n'$5##JYE1͐Ts` aC~'3A,_5U9]Vz5@z:@͆hQDtfcFF}*hr@=@ո% LkK'<rc+]B&9\Wi5|])JWLH~ f `c{ Kp]'}GC<REL#l;‘6E23^?~f@G:bBuH)YQ0͟8MX^m^THe&V]J .>X->u6."߼ehc]ߺ{ ~VP~meVH^:3imsT3cθ?=;ïo^8 8rekomVծbDԃ $&νtsXzTݞq:)EtdfV֒%\+JxYLb&j!iVAgEpLRcLyDq&.[6Ղ\lTchXxih;lM0Zkb-J¸"q{ŦjY}mmj>F2LA͍c@VcRF؅cZW[3YlJVU0#sZp;;Y6h73զ- o?oo7OSa"ȻІ~1g1!H~Cy&a\5Vcw@akA(Ls917rX A))isZDBMXRu-Qlde$DD,%)$sQHcrF/YnGd2Ȟ89c(EڸMPOWkXؕP )VZX !c<5 hD1E QN(aG$d (p D ;I⊟D]oE2ȕkALt2R1؋ʶ^iȴǭfֳo+K5b&˯nIТ[$d-hV-1z|<ϐx5| IzegEeۼ9"z p>kSvQ;_FG)Aj/,a;썅SR0PWnYV٢nWN8q^(Z<* 1/?W&5 Z b#YgnK =!Y&fC]B. VD2AyT+YxKri" JIY["wrU IA%WM̉ӳIfw+T h@sSfŤ)~w :yqssY88 Y''qps{#!1cnq:I`| C&Mʈ5)&pb4+yi*3[u O=H|!e֝sV4MeYȺm6Զ/mf{-mH:+I0G휓id&ѺR&4* RNVIiĔ&i?}^x88bR%ZRv܅u0 3$p|n!jœL" F߇XϺYwavgu8 xc=>3Sp}1L8q}vϟ?A֢#twӇa8,{Und 11a7:])y1p6n X iڔi A(ZlC#sZ~q"9hګq-%3u1ϭ`OQZ(x)=Э|O ,) d ,AU r kY o8sCN1"3$3:rd ',@˫~$oqٳµxRDUt)G$pe̟Kِ~OZ<^TB H1_&{kxM+_ph_<䋫[i$fQ/(Z\I!GNM@EE-+S)q?>_~}3a͆4..YKa稷̖ڍJ8Va.&V [0.\ k-:aarB O^_ L# C7lŶV-e!o9[ߌLǀ=k0Y3]JB&r QTT5!JpkzFD!'hcedXfH\d-[ݣ i1j Yf  MvLy8pŌ!;*cz @RqD_b0ILOwWre9)NF5QA޴N,N|[%e:k}[^Om {^[ߗDC$b@m:Gf}M[tXO1Z$x%WkWbn6*nPoed׾ւ`ѪU[t- `^daPֻ o4&5~{ ޼ƫ7q> "#k?6yg^WU:OMo$r)2f=t62eͦea`] #MHl6w@fg]fCyyϑ]ՕI@ۦC<$G Ss35sc|ꠙsaZhu2aao$tA :]Wݔ!#ú-w4.:cqxi Hq6N͵#ߵ8n^Ww_}N?Cz_TJFշΙ85~Op6>6m>;Olv[Gطhw4ka;y8 JpNgi[lRx>xĔ:;4}V%e75M1k!MZ4M6rl4F| 40W?bG5Gt|~wzCB{$iFt+ew3,gAG1D;+F>oi҈f%r qo>diw!N8BۂjK7Ѡ9ݪf~ $*=byKSd/&1i?xZ?}J8Z߉>] #z9d{IuIcx7ƭwf7-s3+t[%`&s}}}< 'vPVwog7\wv޽#jZyc-F4dVq ҆HjJpZvt=h?_~ߞEYu[iRBάZQƯKX?J1B޿oALg7h%]y|wߏT7r:kEJ悋=rgQBvxZꏼ1ܱFP앖cFCoqK_GADRG"l52c Ak'N)v i֊?ʹpxz`~vaBCԊS}ւ$(;s*~(}xGl[>*;EuJqd;f6bQHR;q/<@;.&)U:2\ʿ,`<>(A7NDwB,+VX/NgZ/7{cf5gP >yjE9Q\ڿ$ו*4GRBR>Emk<ϴ}9{Mӌ󖎍cvo.U{;bu NjHucӞfLZS⚏TjĮkΪ#艍\qvfe0R(odZ-aa5y 6k3˰XQ p瑩6a D%:oƛ"YyP#g584cׅb!F%M3ki&(1O'J}=Wqpqf= ė 7%5F.PA(yթwUG֔Cʼn{W~Djp%<M7 U O/zdI"6bg:M#t eΧGT-nT"7f)Ҽ*c-Ieg[7jG CΒ}Dl:tNFi&-*IJ,DQ@CYLV XSN0M1`h] 2n>B4tk5kyBZB iJ*4HL즨 xL.hԮh=T D7C$-!$m[N7kX*WDžxb6YZRj|%B6ћLf%uQ¿wQGή*S[*m8Fzp<ݲVa+U4ǀxhiA h uL<}Usr/SQiPU15o坈>UjT-<#9hc IDAT uNI:o\4}X@qI T3okQJ%L\2kdJ&GYr>(04QļU7M҂yӂ3[Q@.HM[4̞9չ޴ڨ*/vB=Z:OA'f1cHy'T&7 sQ{[ sɲlU„Pf3N8{pQ7wMe4z{ ܠ_9afq^cD1# GW[!]bYH?rbzVySjSK8 Ho8~abtՄRDO!<З3oӛIiJz TN:U' =z%yW8)t ktCɅ) &tRt 2A$%, gU¾ZC"XR!/UԤ9}C1^佺]nivpRf 9=W34lyۯ|zсr83!n9z;*U@!;,mN43oof'z"wy|wVԠAkwd7W%޳JHmQhuC0ٽW }Ģ>W1HHMGqfd"'?~dO3mݑț/eй-ye JZ&aqb;XT2&bi"1Z3p'wt3 ݔc0X f>}Z ڀ$Zc@87!UT#dwr<~:w{Gh"L* ev׿}mRZM¢;4{ !ZYoGo᫂cJU^9ݫQ\|g[݇4MdiLi&n2#糶>G. 0r,4GgϔoI $AmY 01;>Gh0 )Ho>uӢ0 ECC\ ;ցC]E`VLz%9 }t+_~_ZGI!Bt8ѵz) .cR3%ѓ|¹T&/"jq:sTV^+{Z)Hk)1fi@:A!+sÇCLo$,˴>^Vi^=wCt< F8S> QxuRzW>=~vBgk#@$[H( 7c]檛Wbt$\FltZnj!QMݮ8ps&}Hϙj^ ݒȽXCZwen[D֧lnj7ZajD6@ݤm0+ҡOͻ>)́!3Z5,VͲz$-)ޥqzMˍ׊ܹZRk/S' {SCBAӑq'עXJP=ѫi뎡 )>yRR{_Az?4g##ir-790> W^!D?D}{WxMNUkŹi-}U-pZ;rV9it% O7fc/ *S<˞˶UlgH\10y˵nZ6`Ќfm )K:"lJgs(l"[_d$:@ :4WBw:b{zэNn>Ο>ϷJM+n!JfŎ0tN F+BԭQJc+O~J!׬xYz<ءaCꘒ7|>+˲iqh\lMF$`jo⼆tnzui}"YU:fWͰHaW-i{mU9H#Л XnصkWw!8T%Jn `vjt|DPʊc_s-BZM{a9-`PjcYǶt:SN9Ľ6"̧ ]t)[;X!ze]tmcj/8ŻCpDpykoc%> 2BbRiƺ|y?~_PjaqώVQ!4O.L10DKtԤkաWyNxe(X5>kJJ4%KwΧV dNˬJ-Ds38fbhFKU=9Z),D6RT\z~OY:߈[Ԅ~]9eu@&!l۪_zqN{HPZ;,DQçPrě;C{!%c>ɷC@Vwhs6^MýːN9zH\zu\o۰2]#7z(ވ1w-<-䕓8tHS£XNa\}g^y}}㙷JYDࠋ] >m+LIZyv+lwoQZNSkȊY_w^vj:{{c6~}O? TO)Ńѻ)݆]+-(59|G:Wh?%e z$ e#8&X19Ȉ=ZVDӍU]^tSZ^erAН赒s4 z.Lu#؉Ը 9 N9B*>r(_>83ЈgZ3x|J͔c`CZaء08&-XyWCww:<ƑOl+Rw֘Dm "-$D}>МC-olU5GJ7n#QM ,ZY<@;$!A}>^!!B7?!Nխl{i4qĘTm{UCN5rF5yՑ?g:;l- 7nSثfHJe*G7$F#tAt\׋uHMh)75$$4Y x2"5WNUc$.32OH fEhZHh%jڄ9+78))ɩwzJѬm| rD q ~v2OHuʼn棾qH)iC<C:4nͫm5i.zLUD1z2'U.^WtLtYʘRzv<&#;p^>.nfWY}R LJ ve9Cyی7ܭCͷN7vj-z]Ծ41YF_UL%]Un6A]N{$~0w>ӊ5.0vୋ};J9ryo_'>~e6.J6`qz ̣*VyjWcQǜ1;=D GfZx@[jIw4)(~Bĉ"ќtN>ΔimH $*ڣ vn` TznBTև1Ct)&'.yW?/%jg`YĥE4sM .E߇3tZwtH0Gʶ[!.h7؍J\u :թn)o7bĥ A6Z yQsk㙇n=^J i^= N>;Hmz|"fփlMs䃁|=t;} -*; =|C,8SCt53-r@70 ЏÀJc%$1»AIaN7oI +<5d 51^0NBy[Y>g&)T=tO8hm?~~4c7&@4|>SbO?tTqۼRVuU\$Н&/|(qx_=07!˾>bdzE%v=ũ§ײ؃M aJkU޳|x65Z]%RR9u\@rY649bÛJnݛ8z1[f>~ܴrWI4RE󙸜UބyN">~dBw:Qjp8@&&0۪ʮBVzi>xL#ѫyX۠U}#8b*iS"G ׄ%&$x^N< MOS#~|gg3tY~"8Vhs;V0wCi ؟Iٮo>]JqyиzB##kocQ+l`No<\w<>ER-E!=;2/Z{ݐ4MKkB(;U5iʥeTY> 0)%&d5baێ5Q_{+5F4?ij&.\lםGN^H!ZuBE66q RMj9M]/U+zi1]9LLOOsەy.Nf{VLJ'bp9r>6Qo\ ",¶m Or>!٬XBDM)"Nyʜ4'׌,IyEH!0M ':ʡ#IģO#"ӤpJ)Y+#y*{0ciRgMy_p-[.llv UZc6it:<^y~~Vղ0x|zbY+1FAl,ݜUdg̦q:7YϗX,.OlG@0 xz῟Vپ&N3酏.sTx.zg~edj>K<7%?2NHXl@ l4IMnцb񽑲*%UߴǙd8|ȧOs<zڮkhzSaĨrWٯ;_߯)\WtojB'#_ǥDK%Dt5udIc2Nq)L8sy\.|8sf2)Μ1T*E#o{atׯ_y4/Dm˚!'k.+)%駟 !x+'eۘGJ'ھ^yp Z#9Hy )?^.+iy x-?pNM1ДgZx8?t2Ն> [-TkTEН#;aZ3[+~ oҨڕu[ 1**`c`\ ,xf>EULJ IDATL)m4$ݙ/ (U xֵfpŧ8:VQCQ%:\}8?)Ϫi_Ɵɵ MTȻJTSoy8G mqL!Y8-O_$^r)yHC'?Aq"^__o6v.bK%ZFtPƔc$Ƨl 7BjڇuN=MB^"u?cYOakg>%z/'4fs+q`_v[SbBzW(t ǟ7X.myOi۪n@wnq(6q 0O  mTv۾,k\ig{#ͯn9Ax*Yo8g<΋ \^AtRP'ӿ-m}9kԂk*q-0[5+z+YRU-B+Fe<4NU_JoMyaҹduXxJTy7{mGD_@ ZQ?'ɜf^T A`Sw$򾼽@)TU\ʩCFf뮓#r{5if:p7B:bC1MHF O ;iy\[QxN17DIH8bégUV=?)R< T=#EMz7rVf&8)z^weQYkjTiƔ&%΅3t׎fzە+B3[=ً0JJz@Vו5ތB"xGޕ⚶\zWVyÅ@tt3@Lq$Q{ֲ}hs6D*H`)UVʭUkr+8)fjD?*^ &4~F-PQ.FJe)ȐserC׏VI꾫&ow5GNZl6]:A=l{ϗVT,Pr0!ˤ)%2 ҩE]TfL7BTUC`*VcNReGjfJ UM\Ff)q|:iY4]w|bN*FzeS"9 ip *UwtKv3F(`[?/iTtɛhr,R O$߬tx>Q,(aaMYÜѻ.no#IHz#o:4t,E!\XqZ'0 ȺYM]qW컭 kΜ3OL`  L.\31DJ8*N(9dbX(%0;u 7F7V{־|"DĎHP. ]mHS.CdQU[A:V;J.ni5bLUKT Jeo < ALJ 뮃 煿w 1BB["Tv4tV o`woOw+`6*X4v[Iz_D]vjS)+Ym#J 7=8;MMI5T gnK:v%ozx;фCTeYmm?f2WEsȞWA tC0b;qٯWNASsWd/jJBh̒lozeigʺܸ+{j)Ջ@?SB㗦7ryDn_q=`i--ԢHl;9gҔLxzlN1 g!Z] Y<_ҕZt0g:Iio;>U?S}!Q|egՆ8 =Nq>bZ*$˃Nr0yfZLDج{b\^VT;B+;`>]*Q^qM-LpºDOd9xrK^LuWOu݉IÿZzu0i<_y6B'g>WB;Z2Y.Mc񶭔i>Y[NM64}dPF^qZ*͏tw󻥕^ۑfh OY4$#ޛEGʉ= yhM c:`\aƲ4 -qo6(/~ji*BWkm.v^> v0Mi#w^ nv_z^)Pʎ#huۼH׭k!_mSb] Z}||ӾsM6Z+ޫ/j6H:Qc])ylbT4`atw'SY?c$o|T#-g. =S0.X;?̨>-j=q)unxOw#a轀T$p|OI~EwJn'} E'b ?/;RJ襠x>ŴM '%ڟEPŋ1JS*A +=gϿ@^LAd.1sC 3߱o!//whO(M]c9^[s;JJXV;m큺mH*TzG.x'AAĸ|{pjcX?@"Z6ɢHԝ T(dyg1ixiu L4#~Dc7;reGj 6|t[bc :XcR񏏟9ObFud,}~aY>'@=P݆_"ޟkߟBw* {?Lϼ#PhZ.(ҞɾgMMBrv3נGAm/Hx)}NR4C{R@Yw/%9Uk"2@E1?zGuD39ºb [9Xtv{n. vyfFEɨ7~V!^wl?,P?>=g?b{> &loܤx0>TRLXzG ZݺHoۆ 9/ I+#jiP` wJV=d[; P[QO4H_˯78(W pixBeiJZR\kւZd8C^'0 Fk2!0#hv}!s7m%dVXR{h nև>SAsREKZjt8@;UW$6hw}N*yВ( JV:0)lL{?QpĎ+\)>RaaPzem\]kJ!m&aN$P'qhk:r js"0 [m(Mm^]]-Z5&GDr2$q_VP5E&(ŋ'ATTJJw|_2)o('*r$ ,9&D@#9;OU[jd4s'4O$] 3[Qs zt̍~HXZfǐtDE02uNDL@ 0fڀD#5]UC4<ڶK2@.DW@#z1!&ϳz-p#EIK,:3!8F k r!sgC;QHm=w45 <<˩㶮H^ G)D>V4T g;pѫ **zY7)&WF{,&$yjQ *{ kFmSMQn d1A:t`;ӉvE I"Ix!%׻No#bt`G 4%6qsGZ ZsG0=;&VA-Bn)"OBH]MXE\5yBsދ2cH*X&@Zݍs@Syy&T«Ws)jOYVg_V!(RTtFx|GX'pHY;6*hu_ޅ C =X;au‰^>:J [0Eʁ)A !Zz]+h8mAy fCMWli) nּ ]X6c`z‹@"+TbbԗWpʎثA &:CCj'8mb@eK͐4(~jb:Rgi3@(<ź=4$"(;7(!8XS’2:;j &UF { G)Ej]UDH(AI ~6YTQIdJ&2#eVL&EEOAz*{C~fw>Be8M1QU0?MLUw BbM#;> 5GuEG q!94o l)D:2v*&MQVItףW%H+vg O}$-J6jh͊ aDdނIzC$PCk ),)#$M6w"b߀.;p7, D'7@ut8מ.{;i7x/~_* 9N/2xS} 8.0\e5ss<%PC2K&J &S(#' Uj&&kLvUXTSV9a D1ݍJbSDU$HX! K s#ZиKR5miI #d3} :I$&.iMlv+՗m/O4̊ qS hQ NOqdTzY1gV#=n±7Z(Aim#(̉@%YOEmF;I\O¬ݕIj:4a ߔ,0<-Ih7Nw4n("I)ƽ#8e0lLiALYmX pJ&~zUf#)) ~Alt*^QAu!!>>XM4jEdFS ֪(;OAXUeu^zC)E0"M7_e:v@@x}GEh/mhE SweYי~$jUR.Cy] ;K<:} hm<7(ӎY5H5$z6+>d6LT*x'L]j+$z׵x{Pa 5"dR= L]PZa6h{. 0ӌ5xI:SkMj] , xu'5܉&|Q9'n ODsC˘Xk.zyb37-M2 bB^Bni ]NI0EbNyE&2#u("){`JY])rٓ(ME(B޵GLCG ET;oOdG@g3Qڱm2(b8\E22O!Dn`!xqcaaGEE\|^$"!czӬ]#L>3}zPc dbuQuZ [0H^!b#JRnco=l@P%aUyn:س( nWf7q87gD?,/%Pw늿JKU؏1JҠ+t7=i D1E'EܜG{AAЊ;H₥a$51Rc IDAT+cNw"RS=HW VZ '+Kާ f .*kY3xd*y'gu%"t''xz$ :8TrI:jZ >!= ܰwa&rG&n^}BK?KYT+ہLH*z INF Is"y"൏#"V9*m2t!}?9ÊG=ariﻖ"f$'!m w*VI*>Ԗ)bhI RԩdgT2wȌ=bt# HAT@VJnezbM]B88/z1FI5ºϧ$s(5pf1A'9 X5!Pv UL]-ٝ%Z wDPܰV'T⩍&V`αx1zue6<蠴cWJ ,Q}۳o!v<ȸX)-N!"D{/hjp Ln҇afd}n %$ݍ GQ.J>J-Y8EYDN˻~H)'t& 2#o.Kd`T3nyY;x{SElXzAh1@|D r*^ȂkDJ z?>ɣD'|o%y:aYnhMvcۄ߿,f!`YZ#1gUG5j(甞>3hV;RS\@9-sF =EׂX /%I=w;TNX$uV#$ A""Y%9^״&N9el8h۬(Q.%Uc/;ĚC=J0}{EL1dkhBIRAPԌ=sP֣f 1V}9W"LTos_7VvHctX"f SD4rVۋ&V meYdc{"ѽ6fc@ Z1NI >zĎ;gГvT#RSBJ %HqÂņ짬q>1s2ANGJܵ̚Q-K1 Tv 2C8*\PP_a @hAa"7i%*@i !q/eǺͦex'j]q`1 40ه\N?{Q̆hHhIe̔" $й 00X {N>H6؞Y)|2.+RZFߺ0Oވ~Pp)m p)~W`CN{Q>9U:nB:s0?B"90{M=H޸'OArb]w{zP2gޥ-?pn ,[178IVJADцc{d;Z"x=@Ag=!T篨a7V:Ǝ?7<rH!cM%XMءzE)0(X;%qQ>Z^AMdc1⚱=C:{v#Y9Nn[kdR rs`wP]2%ณhOTؠ ;z2=UϘ`p`M:M'ɪxX͆y]0%Y L!LY}`U e(꠶ٙ03T}YqlUd1A!b*G L"-Dtɹî^2,@_T$syKx}L6t^;wqu*'Xm>[l(-&m 0~;tl$r~%oI<O<@5}X'j NB'l/ b5}=D}jNN1A&qNsfD?3{FdI"#Oz)%E5x4&}U{XJMԈ!yuGed͟o+6XQn=tK@HO̅ U#aBuyɋXT4X-^^|Ϝysuk: tüvKVasRz]4?qG>?klq|Fas+jljH{>a,ֱ{ģ=u+FsSq'FA}me2q8I) Tuߵw/]^,(D# ƭ5sF`_;&ƭ+cY2 Be@ԭ5!E:/%ez%UHx;r\thy|1 ^ .YNw'FƎ=N-GblN|$'o<2~8X'4jLSyC;Wx84g 9]JIZXsƶmY倳{fOeYܦZWr"lJ Lnl${6I6βo2YMBJL8@ezq`ݳCfq]!-!sШ53'BE]dRF08%sCIEbE&l; w#3(nK"c}a9L*RU/ drʽjbC0UuE)' VN sXS0L:A<_vLb,CIG&Jt@^t'Hym c8UҿOصc26¾$(.=O+;Foo;4Z45ȘVbAGS=2w|jo?6yY;2gms >[+usg A༚ʳ|0)T*_:>E+fX 9 W=OIcf~Q휇}&7kjvR[$,=b'xvAoNpxLEk rNFYXr> RsT+a .N ٪ކ䯭3E M:nr^T!XX vބ9 LÁ%YѸMʿ%hMlwmC_WuAY񉐗\*v2Cx1|띧nB`^[!lS4HN PPje:|AcT'~/' ]Jk7mWBGI(5h)q"^ No.7d1=)iqlg]8 ǰ(qsΨf$"+  u a 1ܧփAxZ1Ih >[JID*Q(%ˌpgmXbvy<)5+ Z)[7.u9zj4f(z'u8 1-ԋ51ژc\2sp͜`o7 } b>9pnR=tFky]Hq>ƚo*~5| ixucX}_xݱ?n&?pxG!+{aZe9#Q5/}ig̴93Sx>ͦ^NR|Rn,菉K?%A\2{lڟ29 sj]*7!,9;,,B$(ZfauyW~Vmv@O@!ܞsca<8έna۶c Lsn;y̖Ҳ]k Vpұ4;(!˝ TLAi$0Oس$ωNUܜ̭-xz[ڮ/zD$vKmaҘ=2ZGR0gA}r/~8&pQ\j-(Ov_x7|||pFc1.4ރ4'r߾!x1dWT%yIff KEbI+zї,\. xg* qXXZְ"Ь1VHTQlx³49%Z3*%h>J!&-JMѠЫ986spEQ('vFace'Ay?e*xcK ;^d젽8bhvw s+Iri"n뢢G(} P<qp4\$x2fX!ih? l,|m0ĦI +u]1$]Xz~EOnvni rǩE"OPg8c$6Ľ֎۲3\x Ÿ&֮b/&lhG}*!uPiWKDg$uDu{ݼlm:{T *q&K_~u_pb"n@|FB)|Ip)́}<;a$)m`7:emOW3Tb:Mզs!Yes|q_')W'GWX I5(Pgvi8O?۷o m?~x(BxGZ!‭aB]JI~>"ūƸVð><]crLʦO~p1'Лj1@x"vLה߿}b J\VC(Cq7eͫIHsg,LYh)<6Hj Zy%.B}uMweAjZk|Qc6.IDAT̽()`^|IBfڕ>9J@&J9j]x A<'>჈2"Pw!fn7!@hm2%(/hu ZhE'JcF{,h Ԋܥ, FzJv`Նl| 5($+k@ G.lFoǪ}bjV7 vHs]uǡzo`QU6cg5EvNIY*zD)a<}߇EԤ"NH/_Wo eϧ ߾`A%< "< +kP*lvdStkZF,xWQb]DNXGW: ;;X+]OLAu&;a`Ŋ* ۺNaJcF)SeEPǨ͜t{,)u;RF@oXؐpHEFvp jak  y!E"pHyAZV5T%c[eׂMI2&#m{toضb!(B` T Q^@Uc Vl $Yֻ Y,%/荐T07Ae883oT@eGNB+NK `{-2;bdyȸr`z"@5wύ"agzu6c: %Ahq &>a5 z!:3Uы8.ܡM !/+A 6$<(! x~`R 8We|;T~  'w@uZoG& {yr2c)E⒱mXbpI 9Rf'cC!8yPS?+9mт]5=,BzB{V~%I]ida`.ݜz“A#'Ǥ b F af\,tRK`ﳝylY>,Sxyy9)7kˀlߐ`Ym7CgIJ:uQKAk,KF:9Ncu-͟;7jnl;78u\m8%A/R btÑQ^ghW6\{?]++YhȄC_UF3sFR>' ^pۂ(,jź"Gz OH Eǹ;)A2ٌI>>>, /om?S:֫TׇPix,4=?)O8҄6ieϽ_aW([t-_i^p)"\ݵ _'Ȟ"ƂWq~s+ls4t̃@YL9Xb9iס5+ S+*B+ATNF%"%! WUJ9h4T7Oßw+)/4gy_ٻuN  ƵBOؗߌO%6J>>>Mؒ,92xǶmGڠ? )gAgُ?3}jC<#-b2O Pa10M۫gR3tQ2 Y&nd>Y̕Ӌ!X3fi1|8 ?x:c ?o=Ӌw֐`ZQ9sN>S.# >Hm)y̛|fg(۠_0a3|dj?i~Rܶ NAz0F X(!n2 J )?iמOwZ;_ e|m [,:Xja'/~^ù25(~$?O˂":XCZ&>C8)ǟg2XN*2 بLiN'^nb3nI6͠bմ K]X_) EaºT+d] ^Uayq"ޔik0ԊCJvъ1 5ߙyTppBu{Cr//ïO,;Ws;Uaˬt00+YG"zXt Qv*Zt!m"),1 !Ȫ΄Zq X2*;[eAX)@{™S,zyc(:v<i\'so2s>+W>bh]<-4{JK>e.Wn4Lᅢ]~Y|w{eYURY]\'uޘf^(¯kOo֕\m'-w믿K^>ۘDy3b^=wY6` a `;1m5:t27$ܳr_LSf3,]Nzs]ۆs4vm-%08,3#i0=C3@ bs=TQ{yy?>dvy$i{'$dկA]j?~;ZPC6tf50izl؂`h.v)bC Oi yJZGSS'J@]*_J=hǮDtL PLu8?گYK]Dy:LҰ>Nj/ĝGgˆԧ3C3gˉ!wȬijNB;m`/=Yl{fӆ6 Huv'k Vkfg۾2 CXXn5異d7£bCbi)AؘpyW׵6?(A;ua= A9?. '!u z%b{k؛z|@ KJ:+ATdpӨ0[CfIDJi*zثtԪcl ڰ wXESt !rtxI7=H_[ 9Nh fF9g Z^\3_}}.xRK3o>~Xǩ/>Ʃ )1/9VZCTd/6¸ԲA,_J?яg v)GYoH"jFaŭ5<~ķd-5ZBܑsF+ kxS/ĀZ%FQ}pCܐxRJ8N+EŌC_ Sε-qELLʨtHOh/Q#ɁA|ơFq+{篆3fX<-N*y, L6uK5Q f~C˲}___Oxmӟoo˂}Mx>7Ĝo#˂AU?ohrXTr hm-?|tt۽Sblx]U^) ܷ zJ)߿$)+W†SCE G@Ck:J0|2&~[@|PvC@mu,Xtjvnе:1,3xJJ0dq@C< ah"tvmarO?pgS\gBWֹwS%zKaCB _+A35%+8N|^WdtSþmۆWnl: +o~z7&ZvߏtoН\FڜURX/8/S_s 1YBa3[kƤϜzv'҉ m7Kg-Rq ďunwFgea)i}G]f7?.>u^澲aua< O0TA(#P}e6;\g }g7X/կi$֫03W ;!:o7NXb@A'~6ޕ&г l=g, ?}ULmGe\u]Q:¢AN-Fyl:3ޅy|< {YYhgΒBMY'JZ ApbC{ΦbvN'pU{K\uJ6S˺D^ŽSir2 >8'kJ29X8 q_Yۼif̥ /jըOA c@L9B!F"p=eyaM^ _G+4rELjuh i\ ll3_ >]!jg: ;K} mbOh_ V1kOU X])@*߯Ml;,g3k?)D<&%{.FnA֋BJ aNVCi@;0觳%3K2$~e z^LD$UefW]t/ Y)"cl=jʫvC~u>J>y@Qp ٳ`beKYc1ZЪ.{ \!n>W1n1Υ=Y=hY42W߻$.*` QJq2Kt0(k@;1ڔ쫽!3a:L|-n^׫dwNJczM'RFUH{/wPĀDk65ǿ_2 f|ug ޾7.c=Dkaqt2t4Oޗ,[6^a91{5h x8e!NJ93mu]O'2hs_Vry'!s%lƒ?ܤ#=jt[jy;fKsPg4M fGSŢnS)]^2yޮ9#WtpYϕ1qgsȯ ښė|ϸ#D#,-M<*aՙE{6XұwoJPM,.ֆidž4}}}rSh%gN:xl^c L2MX)Q;}COtH?e3_ ;Ɠ=b8݅v Gs?Zd_9 *m'ZFT<>h,:vνK?:ʜ]z;[|~AX=8dgT>aVVQ<F9Qz?z>|$@)xG7ц&=ĪqP#tQS@2c8tShY/1CSܿt?@&>7 3SGR,'aRC p!(fߋ0Hdsv31XO&VjH1ԓ%U㤽9֔VV\-$hCٽa&l,2ީݤsxǺ([EK][H$p{U(~ޡ9 [0i8᤮ÑiB$->$;\:goz;6gq0Y]~w cZ zwQ\MOy_\-CCq]7][Q fud/DeFQEm;,cvm#bpż>. q_ m{Etnp[;x<,b Op1nOHpK+OX n<4wMv[Zor[q{@y2徲,JcBDF # @@]!(ݩ낲UԽvA+;qS.o-XnhZEz@.nuQ[a‘F2pQ$ SXQ[r  !+D\v<ضin<UxcF@%s{h$%Z,qՒsA"hYɜU/%wByY~dAs\]A=GsY#*C(91B[7b jIFg^F-ZbN~7JoI?Nl_15SĜ6'{͌t^ҏw˚.$* Ӹ{mRku`ƫ5Fas!!|t^ۓ\DtBv-DpP5.ua]0R9xuofHP4 }b *2(219"øBJA7Z"f+?hI YSy"" HWjF3g f>?nf:OX ,scZiNu_tx˹IENDB`relatorio-0.12.0/relatorio/tests/templates/include.tmpl0000644000000000000000000000003113615410400020165 0ustar00{% include other.tmpl %} relatorio-0.12.0/relatorio/tests/templates/other.tmpl0000644000000000000000000000001713615410400017667 0ustar00Another Hello. relatorio-0.12.0/relatorio/tests/templates/test.tmpl0000644000000000000000000000002113615410400017520 0ustar00Hello ${o.name}. relatorio-0.12.0/relatorio/tests/templates/time.tmpl0000644000000000000000000000005313615410400017504 0ustar00Hi ${o.name}, It's ${time} to ${func(y)} ! relatorio-0.12.0/.gitignore0000755000000000000000000000000013615410400020501 2Sync/dotfiles/git/dot-gitignoreustar00relatorio-0.12.0/.hgignore0000644000000000000000000000023513615410400012315 0ustar00syntax:glob *.pyc .*.swp .coverage relatorio.egg-info/ examples/output_* examples/hbar.svg examples/line.png examples/pie.png examples/vbar.svg dist/ build/ relatorio-0.12.0/COPYRIGHT0000644000000000000000000000167213615410400012013 0ustar00Copyright (C) 2008-2024 Nicolas Évrard Copyright (C) 2008-2009 Gaëtan de Menten Copyright (C) 2008-2026 Cédric Krier Copyright (C) 2008-2026 B2CK SRL Copyright (C) 2008 Udo Spallek Copyright (C) 2007-2008 OpenHex SPRL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. relatorio-0.12.0/LICENSE0000644000000000000000000010451313615410400011523 0ustar00 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 . relatorio-0.12.0/README.rst0000644000000000000000000000061513615410400012203 0ustar00######### Relatorio ######### Relatorio is a templating library which provides a way to easily generate various kinds of documents (odt, ods, png, svg, ...) from a template. Support for more filetypes can be added by creating plugins for them. Relatorio also provides a report repository allowing you to link python objects and reports together, and find reports by mimetype/name/python object. relatorio-0.12.0/pyproject.toml0000644000000000000000000000261513615410400013432 0ustar00[build-system] requires = ['hatchling >= 1', 'hatch-tryton'] build-backend = 'hatchling.build' [project] name = 'relatorio' dynamic = ['version', 'authors'] dependencies = [ 'Genshi >= 0.5', 'lxml >= 2.0', ] requires-python= '>=3.9' maintainers = [ {name = "Tryton", email = "foundation@tryton.org"}, ] description = "A templating library able to output odt and pdf files" readme = 'README.rst' license = 'GPL-3.0-or-later' license-files = ['LICENSE', 'COPYRIGHT'] keywords = ["templating", "OpenDocument", "PDF"] classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing", ] [project.scripts] relatorio-render = 'relatorio.render:run' [project.optional-dependencies] chart = [ 'pycairo', 'pycha >= 0.4.0', 'pyyaml >= 5.3', ] fodt = [ 'python-magic', ] [project.urls] homepage = "https://www.tryton.org/" documentation = "https://docs.tryton.org/relatorio" changelog = "https://docs.tryton.org/relatorio/releases.html" forum = "https://discuss.tryton.org/tags/relatorio" issues = "https://bugs.tryton.org/relatorio" repository = "https://code.tryton.org/relatorio" [tool.hatch.version] path = 'relatorio/__init__.py' [tool.hatch.build] packages = ['relatorio'] [tool.hatch.metadata.hooks.tryton] copyright = 'COPYRIGHT' relatorio-0.12.0/PKG-INFO0000644000000000000000000000331613615410400011612 0ustar00Metadata-Version: 2.4 Name: relatorio Version: 0.12.0 Summary: A templating library able to output odt and pdf files Project-URL: homepage, https://www.tryton.org/ Project-URL: documentation, https://docs.tryton.org/relatorio Project-URL: changelog, https://docs.tryton.org/relatorio/releases.html Project-URL: forum, https://discuss.tryton.org/tags/relatorio Project-URL: issues, https://bugs.tryton.org/relatorio Project-URL: repository, https://code.tryton.org/relatorio Author: Gaëtan de Menten, B2CK SRL, Udo Spallek, OpenHex SPRL Author-email: Nicolas Évrard , Cédric Krier Maintainer-email: Tryton License-Expression: GPL-3.0-or-later License-File: COPYRIGHT License-File: LICENSE Keywords: OpenDocument,PDF,templating Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Text Processing Requires-Python: >=3.9 Requires-Dist: genshi>=0.5 Requires-Dist: lxml>=2.0 Provides-Extra: chart Requires-Dist: pycairo; extra == 'chart' Requires-Dist: pycha>=0.4.0; extra == 'chart' Requires-Dist: pyyaml>=5.3; extra == 'chart' Provides-Extra: fodt Requires-Dist: python-magic; extra == 'fodt' Description-Content-Type: text/x-rst ######### Relatorio ######### Relatorio is a templating library which provides a way to easily generate various kinds of documents (odt, ods, png, svg, ...) from a template. Support for more filetypes can be added by creating plugins for them. Relatorio also provides a report repository allowing you to link python objects and reports together, and find reports by mimetype/name/python object.