pax_global_header00006660000000000000000000000064146301354340014515gustar00rootroot0000000000000052 comment=6e9abfbf3d67b02e9416044a189d2fe1513ae387 rst2pdf-0.102/000077500000000000000000000000001463013543400131035ustar00rootroot00000000000000rst2pdf-0.102/.git-blame-ignore-revs000066400000000000000000000007201463013543400172020ustar00rootroot00000000000000# Commits to be ignored when running `git blame` # # Use by setting this config locally: # git config blame.ignoreRevsFile .git-blame-ignore-revs # # or by on the command line: # git blame --ignore-revs-file .git-blame-ignore-revs # Run code through black 825ba00bb95c0a9bb801ccb4c6dd74ec7b59b59e # Resolve various style issues a6aff6bf8da21a4e6377238ae95b3c9bb941d655 # Move tests to root directory 0ff65ef842524ea50c90fa5a1566b4fa79805caa rst2pdf-0.102/.github/000077500000000000000000000000001463013543400144435ustar00rootroot00000000000000rst2pdf-0.102/.github/dependabot.yml000066400000000000000000000001521463013543400172710ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" rst2pdf-0.102/.github/workflows/000077500000000000000000000000001463013543400165005ustar00rootroot00000000000000rst2pdf-0.102/.github/workflows/ci.yml000066400000000000000000000025621463013543400176230ustar00rootroot00000000000000name: Python package on: [push, pull_request] jobs: build: runs-on: ubuntu-latest continue-on-error: ${{ matrix.experimental }} strategy: matrix: python-version: ['3.9', '3.10'] experimental: [false] include: - python-version: '3.11' experimental: true steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} - name: Install apt dependencies run: | sudo apt-get update && sudo apt-get -y install plantuml libxml2-dev libxslt-dev python3-dev - name: Install pip & test dependencies run: | python -m pip install --upgrade pip pip install --upgrade setuptools pip install pytest pre-commit - name: Install dependencies for Python run: | pip install -c requirements.txt -e .[tests,sphinx,svgsupport,aafiguresupport,mathsupport,rawhtmlsupport] - name: Lint run: | pre-commit run --all-files --show-diff-on-failure if: matrix.python-version == '3.8' - name: Test with pytest run: | pytest -v - name: Archive test output uses: actions/upload-artifact@v2 if: failure() with: name: failed-tests path: tests/output retention-days: 8 rst2pdf-0.102/.gitignore000066400000000000000000000003041463013543400150700ustar00rootroot00000000000000*.pyc __pycache__ *.egg-info .coverage /htmlcov *.build_temp log.txt /tests/output/*.pdf /tests/output/*.log .vscode/ .python-version .venv/ .tox/ dist/ snap/.snapcraft /pip-wheel-metadata /build rst2pdf-0.102/.pre-commit-config.yaml000066400000000000000000000022771463013543400173740ustar00rootroot00000000000000# See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks --- default_language_version: # force all unspecified python hooks to run python3 python: python3 repos: - repo: https://github.com/ambv/black rev: 22.3.0 hooks: - id: black # NOTE(stephenfin): This is needed until the fix for # https://github.com/psf/black/issues/438 is released exclude: tests/input - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.2.0 hooks: - id: trailing-whitespace exclude: tests/input - id: mixed-line-ending args: ['--fix', 'lf'] exclude: tests/input - id: check-byte-order-marker - id: check-executables-have-shebangs - id: check-merge-conflict - id: debug-statements - id: end-of-file-fixer exclude: tests/input - id: check-yaml files: .*\.(yaml|yml)$ - id: check-added-large-files - repo: https://github.com/pycqa/flake8 rev: 3.9.2 hooks: - id: flake8 # NOTE(stephenfin): This is needed until the fix for # https://github.com/psf/black/issues/438 is released exclude: tests/input rst2pdf-0.102/CHANGES.rst000066400000000000000000001003131463013543400147030ustar00rootroot00000000000000 {next} ------ 0.102 (2024-06-05) ------------------ * Added: We now set ``supported_image_type`` attribute in the Sphinx builder (PR #1201) * Changed: We now support ReportLab 4 and xhtml2pdf 0.12.2 (PR #1214) * Fixed: CI now correctly fails if the tests fail (PR #1212) 0.101 (2023-08-02) ------------------ * Changed: We now recommend using pipx to install rst2pdf. (PR #1166) * Changed: The manual's examples for embedding fonts are now better. (PR #1156) * Fixed: The ``twocolumn.yaml`` stylesheet has been restored after inadvertent removal in 0.100. (PR #1160) * Fixed: We now use ``ConfigParser`` so that we are ready for 3.12. (PR #1171) * Fixed: Tests now run correctly regardless of locale. (PR #1145) * Fixed: Arguments when calling ``DelayedTable`` are now in the correct order. (PR #1150) 0.100 (2023-03-20) ------------------ * Added: New command line option ``--record-dependencies`` to write out the list of files that were used to create the PDF.(PR #1111) * Added: Python 3.11 is now experimentally supported. Please report any issues found. (PR #1133) * Changed: Updated tests to use ReportLab 3.6.12. Note that ReportLab 3.6.5 introduced some layout changes in rst2pdf's output. We have noticed that header/footer spacing is different, the space before nested bullets is bigger than before and that some fully-justified text paragraphs now wrap differently. (PR #1110) * Fixed: The ``twoColumn`` style has been reinstated as its used with Sphinx. (PR #1126) 0.99 (2022-01-08) ----------------- * Added: Python 3.9 & 3.10 are now supported (PR #969, #1043) * Added: Sphinx 4 is now supported. (PR #1020) * Added: Can now set background images using ``PageBreak``. (PR #1050) * Added: Can now set multiple style names in the ``class`` directive (PR #1048) * Added: ``pdf_smartquotes`` option is now supported with Sphinx builds (PR #1045) * Added: Add support for styling separations. (PR #927) * Changed: Outline entries that are deeper than the ToC are now collapsed (PR #1049) * Changed: ``math`` directive updated to support latest matplotlib (PR #1047) * Changed: the ``--very-verbose`` option provides more information when things go wrong. (PR #1025) * Changed: The default stylesheet has been improved. Use the ``rst2pdf-0.9`` stylesheet to apply the previous default as per the "Migrating to the New Default Stylesheet" section of the manual. Also, the ``twoColumn`` style is no longer part of the default styles and is now a separate style. Add ``-s twocolumn`` to apply it or, for Sphinx add ``pdf_stylesheets = ['twocolumn']`` (PR #988) * Changed: Stylesheets are now in YAML. Migrate to the new format using ``python -m rst2pdf.style2yaml`` as per the "Migrating Stylesheet Format" section of the manual. (PR #956) * Fixed: An imagine that is too tall in a table cell is now resized to fit. (PR #1024) * Fixed: rst2pdf now writes to stdout again (PR #994) * Fixed: Ensure table columns are wide enough for use (PR #992) * Fixed: Better error messages for malformed RST (PR #990) * Fixed: The Sphinx versionadded & versionchanged directives work again (PR #982) * Fixed: Hyperlinks with embedded internal link aliases no longer crash. (PR #972, #979) * Fixed: A more sensible error message is displayed when importing an extension fails (PR #954) * Fixed: If rst2pdf errors, it should now return a non-zero status code. (PR #925, #1041, #1046) * Fixed: Various documentation improvements (PR #913, #933, #943) * Fixed: Addressed regular expression FutureWarning. (PR #908) supported. (PR #937) * Removed: Documentation related to kerning has been removed as it depended on word-axe which is longer 0.98 (2020-08-28) ----------------- * Added: We can now create coverage reports using ``tox -e coverage``. (Issues 890) * Changed: Update Pygments styles (Issue #882) * Changed: Update Pillow dependency in requirements.txt. (Issue #858) * Changed: Use content-based comparison in tests. (Issue #854) * Fixed: Elements with that that don't have an rst2pdf element (e.g. subtitles, inline references) no longer cause a crash, (Issue #889, #899) * Fixed: SVGlib is really optional now! (Issue #889) * Fixed: The README, LICENSE and CHANGES files are now packaged with the release tarball. (Issue #867) * Removed: Support for pdfrw has been removed and hence support for rendering SVGs using Inkscape has also been removed. (Issue #896) * Removed: Wordaxe support has been removed (Issue #887) 0.97 (2020-05-09) ----------------- * Update Pillow dependency in requirements.txt. (Issue #858) * Fixed: The styles directory is now packaged with the release tarball. (Issue 857) * Fixed: Sphinx config settings pdf_real_footnotes and pdf_use_toc are now boolean. Note that value of pdf_real_footnotes is not False if not explicitly set. (Issue #846) * Changed: We have moved to pytest (Issue #850) 0.96 (2020-01-05) ----------------- * Fixed: Manual now builds again (Issue #834) 0.95 (2019-12-30) ----------------- * Added: Python 3 is now supported (Issues #744, #745, #780, #788, #811, #814) * Added: The code-block's language attribute is now optional (Issue #823) * Added: Inkscape 1.x is now supported by the inkscape extension (Issue #821) * Added: Units can now be specified in spaceBefore/spaceAfter for stylesheets (Issue #754) * Added: Frame padding can now be specified in stylesheets (Issue #753) * Changed: Migrated from svg2rlg to svglib, which is maintained and supports python 3 (Issue #745) * Changed: We now use docutils math directive instead of rst2pdf's (Issue #722) * Fixed: Internal links now work when using ReportLab 3.5.19+ (Issue #772) * Removed: Support Psyco has been removed (Issue #756) * Removed: Support for PythonMagick, GFX and SWFTools has been removed (Issue #756) 0.94.1 (2019-05-25) ------------------- * Update urllib3 and Jinja2 dependencies in requirements.txt (Issue #775) * Fix "reportlab is not defined" error when using ReportLab 3.5.20+ (Issue #774) 0.94 (2019-01-24) ----------------- * Added: ``:hl_lines:`` code directive allows highlighting of specific lines (Issue #623) * Added: ``repeat_table_rows`` is now supported in Sphinx (Issue #505) * Added: ``scale_width`` is now supported for ``--fit-background-mode`` (Issue #505) * Added: Extension metadata for Sphinx is now returned in pdfbuilder (Issue 640) * Added: The Sphinx ``today`` config setting is now used if it is set * Changed: ``:start-after:`` will now render the next line * Changed: Updated reportlab dependency to 3.5.12 and Sphinx to 1.7.9 (Issue #718) * Changed: We no longer logging.basicConfig configuration (Issue #509) * Changed: We now use PILLOW rather than PIL * Fixed bug in token replacement that broke tables in headers/footers (Issue #612) * Fixed handling of empty documents, they now generate a single empty page (Issue #547) * Fixed: ``:alt:`` option now works for plantuml extension * Fixed: ``:linenos_offset:`` now works again * Fixed: ``rst2pdf.createpdf.main`` now releases the input file handle * Fixed: CreationDate metadata shows correct date using Sphinx (Issue #525) * Fixed: Error when using --date-invariant with newer reportlab versions (Issue #678) * Fixed: handling of non-http/ftp URLs (Issue #549) * Fixed: Inline ``:math:`` works again as we now use quoted attributes for HTML ```` tags (Issue 567) * Fixed: Made literal block shrinking work again (Issue #560) * Fixed: Removed debugging print statement when using line blocks * Fixed: Removed uniconverter from setup (Issue #487) * Fixed: Renamed links now work (Issue #569) * Fixed: Sphinx config setting pdf_invariant works properly now (Issue #718) * Fixed: sphinx+rst2pdf now works with automodule directive Sphinx >= 1.4 (Issue #566) * Fixed: Using ``:start-after:`` with ``linenos_offset`` now displays the correct line number * Fixed: Using ``:start-at:`` with ``linenos_offset`` now displays the correct line number * Removed: Our own copy of smartypants. We now use the PyPI package instead (Issue #694) * Removed: Tenjin has been switched to Jinja2 (Issue #696) * Removed: The QT4 GUI is no more (Issue #690) 0.93 (2012-12-18) ----------------- * Fixed Issue 447: Double-sided always starts on the right (By Rob Ludwick) * Removed --first-page-even as it was not used anywhere. * Added --first-page-on-right * Fixed Issue 464: support alignment via :class: in image directives. * Fixed Issue 482: Line blocks with indented parts get extraneous spacing * Fixed Issue 470: Support for :target: in figures. * New style "image" to be applied to image directives. * Fixed Issue 485: Better styling support for figures/images (spaceBefore/After) * Support rst2pdf [inf [outf]] syntax to be more compatible with rst2* * Implemented Issue 389: New --strip-element-with-class option * Fixed Issue 474: CellStyle1 is not there in reportlab 2.6 * Removed default padding from DelayedTable, which looked bad on headers/footers. * Improvements to the math directive (font color and size) * Better support for styling literals. * Fixed Issue 454 (Splitting failure) * Regressed Issue 374 (some literal blocks get oversplit) * Switched from svglib to svg2rlg * Removed uniconvertor support * Fixed Issue 477: Sink footnote separator (patch by asermax) * Fixed Issue 473: Support "code" directive like an alias of code-block. * Fixed Issue 472: Implemented MyImage._unRestrictSize * Fixed Issue 471: Respect class in lineblocks. * Fixed Issue 455: New pisa/xhtml2pdf has very different imports * Reopened Issue 289: Broken bullet customization. * Reopened Issue 310: Line numbers in code blocks are wrong * Reopened Issue 337: Bad layout with inline images in tables * Marked Issue 358 as fixed. * Fixed Issue 410: always include full lines in code-blocks (mmueller patch) * Regression in fancytitles extension: Issue 486 0.92 (2012-06-01) ----------------- * Fixed Issue 394; missing _restrictSize method with RL 2.5 * Fixed Issue 452: applying missing classes to lists crashed rst2pdf * Fixed Issue 427: multiple spaces collapsed on inline literals. * Fixed Issue 451: roman.py was moved in docutils 0.9 * Fixed Issue 446: made it work again with python 2.4 0.91 (2012-03-06) ----------------- * Fixed Issue 438: sphinx support was completely broken in 0.90 0.90 (2012-03-04) ----------------- * Added raw HTML support, by Dimitri Christodoulou * Fixed Issue 422: Having no .afm files made font lookup slow. * Fixed Issue 411: Sometimes the windows registry has the font's abspath. * Fixed Issue 430: Using --config option caused other options to be ignored (by charles at cstanhope dot com) * Fixed Issue 436: Add pdf_style_path to sphinx (by tyler@datastax.com) * Fixed Issue 428: page numbers logged as errors * Added support for many pygments options in code-block (by Joaquin Sorianello) * Implemented Issue 404: plantuml support * Issue 399: support sphinx's template path option * Fixed Issue 406: calls to the wrong logging function * Implemented Issue 391: New --section-header-depth option. * Fixed Issue 390: the --config option was ignored. * Added support for many pygments options in code-block (by Joaquin Sorianello) * Fixed Issue 379: Wrong style applied to paragraphs in definitions. * Fixed Issue 378: Multiline :address: were shown collapsed. * Implemented Issue 11: FrameBreak (and conditional FrameBreak) * The description of frames in page templates was just wrong. * Fixed Issue 374: in some cases, literal blocks were split inside a page, or the pagebreak came too early. * Fixed Issue 370: warning about sphinx.addnodes.highlightlang not being handled removed. * Fixed Issue 369: crash in hyphenator when specifying "en" as a language. * Compatibility fix to Sphinx 0.6.x (For python 2.7 docs) 0.16 (2010-10-06) ----------------- * Fixed Issue 343: Plugged memory leak in the RSON parser. * Fix for Issue 287: there is still a corner case if you have two sections with the same title, at the same level, in the same page, in different files where the links will break. * Fixed Issue 367: german-localized dates are MM. DD. YYYY so when used in sphinx's template cover they appeared weird, like a list item. Fixed with a minor workaround in the template. * Fixed Issue 366: links to "#" make no sense on a PDF file * Made definitions from definition lists more stylable. * Moved definition lists to SplitTables, so you can have very long definitions. * Fixed Issue 318: Implemented Domain specific indexes for Sphinx 1.0.x * Fixed Index links when using Sphinx/pdfbuilder. * Fixed Issue 360: Set literal.wordWrap to None by default so it doesn't inherit wordWrap CJK when you use the otherwise correct japanese settings. In any case, literal blocks are not supposed to wrap at all. * Switched pdfbuilder to use SplitTables by default (it made no sense not to do it) * Fixed Issue 365: some TTF fonts don't validate but they work anyway. * Set a valid default baseurl for Sphinx (makes it much faster!) * New feature: --use-numbered-links to show section numbers in links to sections, like "See section 2.3 Termination" * Added stylesheets for landscape paper sizes (i.e: a4-landscape.style) * Fixed Issue 364: Some options not respected when passed in per-doc options in sphinx. * Fixed Issue 361: multiple linebreaks in line blocks were collapsed. * Fixed Issue 363: strange characters in some cases in math directive. * Fixed Issue 362: Smarter auto-enclosing of equations in $...$ * Fixed Issue 358: --real--footnotes defaults to False, but help text indicates default is True * Fixed Issue 359: Wrong --fit-background-mode help string * Fixed Issue 356: missing cells if a cell spawns rows and columns. * Fixed Issue 349: Work correctly with languages that are available in form aa_bb and not aa (example: zh_cn) * Fixed Issue 345: give file/line info when there is an error in a raw PDF directive. * Fixed Issue 336: JPEG images should work even without PIL (but give a warning because sizes will probably be wrong) * Fixed Issue 351: footnote/citation references were generated incorrectly, which caused problems if there was a citation with the same text as a heading. * Fixed Issue 353: better handling of graphviz, so that it works without vectorpdf but gives a warning about it. * Fixed Issue 354: make todo_node from sphinx customizable. * Fixed bug where nested lists broke page layout if the page was small. * Smarter --inline-links option * New extension: fancytitles, see http://lateral.netmanagers.com.ar/weblog/posts/BB906.html * New feature: tab-width option in code-block directive (defaults to 8). * Fixed Issue 340: endnotes/footnotes were not styled. * Fixed Issue 339: class names using _ were not usable. * Fixed Issue 335: ugly crash when using images in some specific places (looks like a reportlab bug) * Fixed Issue 329: make the figure alignment/class attributes work more like LaTeX than HTML. * Fixed Issue 328: list item styles were being ignored. * Fixed Issue 186: new --use-floating-images makes images with :align: set work like in HTML, with the next flowable flowing beside it. * Fixed Issue 307: header/footer from stylesheet now supports inline rest markup and substitutions defined in the main document. * New pdf_toc_depth option for Sphinx/pdfbuilder * New pdf_use_toc option for Sphinx/pdfbuilder * Fixed Issue 308: compatibility with reportlab from SVN * Fixed Issue 323: errors in the config.sample made it work weird. * Fixed Issue 322: Image substitutions didn't work in document title. * Implemented Issue 321: underline and strikethrough available in stylesheet. * Fixed Issue 317: Ugly error message when file does not exist 0.15 ---- * Fixed Issue 315: crash when using an undefined class for a list. * Implemented Issue 279: images can be specified as URLs. * Fixed Issue 313: new --fit-background-mode option. * Fixed Issue 110: new --real-footnotes option (buggy). * Fixed Issue 176: spacers larger than a page don't crash. * Fixed Issue 65: References to Helvetica/Times when it was not used. * Fixed Issue 310: added option linenos_offset to code blocks. * Fixed Issue 309: style for blockquotes was not respected. * Custom cover page support (related to Issue 157) * Fixed Issue 305: support wildcards in image names and then use the best one available. * Implemented Issue 298: counters * Improved widow/orphan support for literal blocks * Fixed Issue 304: Code blocks didn't respect fontSize in class. 0.14.2 (2010-03-26) ------------------- * Regained compatibility with reportlab 2.3 * Fixed regression in Issue 152: right-edege of boxes not aligned inside list items. * Fixed Issue 301: accept padding parameters in bullet/item lists 0.14.1 (2010-03-25) ------------------- * Make it compatible with Sphinx 0.6.3 again * Fixed Issue 300: image-missing.jpg was not installed 0.14 (2010-03-24) ----------------- * Fixed Issue 197: Table borders were confusing. * Fixed Issue 297: styles from default.json leaked onto other syntax highlighting stylesheets. * Fixed Issue 295: keyword replacement in headers/footers didn't work if ###Page### and others was inside a table. * New feature: oddeven directive to display alternative content on odd/even pages (good for headers/footers!) * Switched all stylesheets to more readable RSON format. * Fixed Issue 294: Images were deformed when only height was specified. * Fixed Issue 293: Accept left/center/right as alignments in stylesheets. * Fixed Issue 292: separate style for line numbers in codeblocks * Fixed Issue 291: support class directive for codeblocks * Fixed Issue 104: total number of pages in header/footer works in all cases now. * Fixed Issue 168: linenos and linenothreshold options in Sphinx now work correctly. * Fixed regression in 0.12 (interaction between rst2pdf and sphinx math) * Documented extensions in the manual * Better styling of bullets/items (Issue 289) * Fixed Issue 290: don't fail on broken images * Better font finding in windows (patch by techtonik, Issue 282). * Fixed Issue 166: Implemented Sphinx's hlist (horizontal lists) * Fixed Issue 284: Implemented production lists for sphinx * Fixed Issue 165: Definition lists not properly indented inside admonitions or tables. * SVG Images work inline when using the inkscape extension. * Fixed Issue 268: TOCs shifted to the left on RL 2.4 * Fixed Issue 281: sphinx test automation was broken * Fixed Issue 280: wrong page templates used in sphinx 0.13 (2010-03-15) ----------------- * New TOC code (supports dots between title and page number) * New extension framework * New preprocessor extension * New vectorpdf extension * Support for nested stylesheets * New headerSeparator/footerSeparator stylesheet options * Foreground image support (useful for watermarks) * Support transparency (alpha channel) when specifying colors * Inkscape extension for much better SVG support * Ability to show total page count in header/footer * New RSON format for stylesheets (JSON superset) * Fixed Issue 267: Support :align: in figures * Fixed Issue 174 regression (Indented lines in line blocks) * Fixed Issue 276: Load stylesheets from strings * Fixed Issue 275: Extra space before lineblocks * Fixed Issue 262: Full support for Reportlab 2.4 * Fixed Issue 264: Splitting error in some documents * Fixed Issue 261: Assert error with wordaxe * Fixed Issue 251: added support for rst2pdf extensions when using sphinx * Fixed Issue 256: ugly crash when using SVG images without SVG support * Fixed Issue 257: support aafigure when using sphinx/pdfbuilder * Initial support for graphviz extension in pdfbuilder * Fixed Issue 249: Images distorted when specifiying width and height * Fixed Issue 252: math directive conflicted with sphinx * Fixed Issue 224: Tables can be left/center/right aligned in the page. * Fixed Issue 243: Wrong spacing for second paragraphs in bullet lists. * Big refactoring of the code. * Support for Python 2.4 * Fully reworked test suite, continuous integration site. * Optionally use SWFtools for PDF images * Fixed Issue 231 (Smarter TTF autoembed) * Fixed Issue 232 (HTML tags in title metadata) * Fixed Issue 247 (printing stylesheet) 0.12.3 ------ * Fixed Issue 230 (Admonition titles were not translated) * Fixed Issue 228 (page labels and numbers match, so page ii is the same on-page and in the PDF TOC) * Fixed Issue 227 (missing background should not be fatal error) * Fixed Issue 225 (bad spacing in lineblocks) * Fixed Issue 223 (non-monospaced styles used in code) 0.12.2 (2009-10-19) ------------------- * Fix Issue 219 (incompatibility with reportlab 2.1) * Added pdf_default_dpi option for pdfbuilder * More style docs in the manual * Better styling of lists * Fix bug reported in comments in my blog where a stylesheet with showHeader=True and no explicit header caused an exception. * Fixed Issue 215: crashes in bookrest's background renderer. 0.12.1 (2009-10-14) ------------------- * Ship local patched copy of pypoppler-qt4 * Partial fix for Issue 205: KeyError: 'format' * Fixed Issue 212: XML parsing error in bookrest * Fixed Issue 210: pickle error in bookrest * Switched --enable-splittables to True by default * Fixed Issue 204: syntax error on font importing code 0.12 (2009-10-10) ----------------- * Fixed Issue 202: broken processing of HTML raw nodes * New "options" section in stylesheets. New ["options"]["stylesheets"] subsection, which works similar to -s or to an include file: a list of stylesheets to be processed before the current one. * New --config option * Fix for Issue 200 (position of frames was miscalculated) * Fix For Issue 188 (uniconvertor "'unicode' object has no attribute 'readline'" error) * New raw directive command: SetPageCounter. This enables page counter manipulation, and use of different styles, roman, lowerroman, alpha, loweralpha and arabic. * New raw directive commands: EvenPageBreak and OddPageBreak * New option to make sections break to odd or even pages: --break-side=VALUE * New option to add an empty page at the beginning of the document: --blank-first-page. * Fixed bug in authors field width calculation * Support % in bullet and field lists column widths * Use bullet_list or item_list styles for bullet and item lists respectively. * Support % in field list column width description. * Fix for Issue 184 (font metrics go crazy with TT font) * New admonition code based on SplitTable (beta quality) * Fix for Issue 180 (support for very very long list items. Needs testing) * Fix for Issue 175 (widow/orphan titles) * Fix for Issue 174 (line blocks didn't respect indentation) * Worked around Issue 173 (quotes didn't indent inside table cells) * Respect spaceBefore and spaceAfter for footnotes/endnotes * Added tests for (almost) all of sphinx's custom markup * Fixed Issue 170 (Wrong font embedding) * Fixed Issue 171 (Damaged xref table) * Fixed Issue 159 (Admonition and table widths were miscalculated) * Fixed Issue 162 (wrong highlighting using sphinx) * Changed default language policy as described in Issue 53 * Fixed Issue 148 (Images should be looked for relative to source document) * Fixed Issue 158 (Some admonitions crashed pdfbuilder) * Fixed Issue 154 (incompatibility with RL 2.1) * Fixed Issue 155 (crash when sidebars split in a certain way) * Fixed issue 152 (padding and alignment of table styles, like when using literal blocks inside lists) * Integrated pdfbuilder sphinx extension (more work needed) * Kerning support for true type fonts (thanks to wordaxe!), added to the docs, added convenience stylesheet. * Fixed Issue 151 and behaviour on Issue 116, about images too large for available space / the full frame height. * Fixed problem in admonition titles. * Fixed section names in headers/footers: FIRST section on the page is used, not LAST. * Fixed Issue 145: padding of literal blocks was broken. * Fixed bug: paragraphs with ids should have the matching anchors * Fixed bug: internal references were not linked correctly * Fixed Issue 144: PDF TOC had wrong page numbers in some cases * More sphinx compatibility * New table styles code, also make class directive work for tables * Fixed Issue 140: html-like markup in titles was kept in the PDF TOC * Fixed Issue 138: Redid figure styling. Also fixed bugs in BoxedContainer * Fixed Issue 137: bugs in escaping characters in interpreted roles * Make it work (in a slightly degraded mode) without PIL, as long as you are only using JPGs or have PythonMagick installed. This is good for OS X, where "installing PIL is a PITA" * Fixed issue 134: entities were replaced in interpreted roles (not needed) * Support for aafigure (http://launchpad.net/aafigure) * Spacers support units * TOC styles now configurable in stylesheet 0.11 (2009-06-20) ----------------- * Degrade more gracefully when one or more wordaxe hyphenators are broken (currently DWC is the broken one) * Fixed issue 132: in some cases, with user-defined fontAlias, bold and italic would get confused (getting italic instead of bold in inline markup, for instance). * New stylesheet no-compact-lists to make lists... less compact * SVG images now handle % as a width unit correctly. * Implemented issue 127: support images in PDF format. Right now they are rasterized, so it's not ideal. Perhaps something better will come up later. * Fixed issue 129: make it work around a prblem with KeepTogether in RL 2.1 it probably makes the output look worse in some cases when using that. RL 2.1 is not really supported, so added a warning. * Fixed issue 130: use os.pathsep instead of ":" since ":" in windows is used in disk names (and we still pay for DOS idiocy, in 2009) * Fixed issue 128: headings level 3+ all looked the same * Ugly bugfix for Issue 126: crashes when using images in header + TOC * New tstyles section in the stylesheet provides more configurable list layouts and more powerful table styling. * Better syntax highlighting (supports bold/italic) * Workaround for issue 103 so you can use borderPadding as a list (but it will look wrong if you are using wordaxe <= 0.3.2) * Added fieldvalue style for field lists * Added optionlist tstyle, for option lists * Added collection of utility stylesheets and documented it * Improved command line parsing and stylesheet loading (guess extension like latest rst2latex does) * Fixed Issue 67: completely new list layouting code * Fixed Issue 116: crashes caused by huge images * Better support for %width in images, n2ow it's % of the container frame's width, not of the text area. * Fixed bug in SVG scaling * Better handling of missing images * Added missing styles abstract, contents, dedication to the default stylesheet * Tables style support spaceBefore and spaceAfter * New topic-title style for topic titles (obvious ;-) * Vertical alignment for inline images (:align: parameter) * Issue 118: Support for :scale: in images and handle resizing of inline images * Issue 119: Fix placement of headers and footers * New background property for page templates (nice for presentations, for example) * Default to px for image width specifications instead of pt * Support all required measurement units ("em" "ex" "px" "in" "cm" "mm" "pt" "pc" "%" "") * New automated scripts to check test cases for "visual differences" * Respect images DPI property a bit like rst2latex does. * Issue 110: New --inline-footnotes option * Tested with reportlab from SVN trunk * Support for Dinu Gherman's svglib. If both svglib and uniconvertor are available, svglib is preferred (for SVG, of course). Patch originally by rute. * Issue 109: Separate styles for each kind of admonition * For Issue 109: missing styles are not a fatal error * Issue 117: TOCs with more than 6 levels now supported (raised limit to 9, which is silly deep) 0.10.1 (2009-05-16) ------------------- * Issue 114: Fixed bug in PDF TOC for sections containing ampersands 0.10 (2009-05-15) ----------------- * Issue 87: Table headers can be repeated in each page (thanks to Yasushi Masuda) * Issue 93: Line number support for code blocks (:linenos: true) * Issue 111: Added --no-footnote-backlinks option * Issue 107: Support localized directives/roles (example: sommaire instead of contents) * Issue 112: Fixed crash when processing empty list items * Issue 98: Nobreak support, and set as default for inline-literals so they don't hyphenate. * Slightly better tests * Background colors in text styles work with reportlab 2.3 * Issue 99: Fixed hyphenation in headers/footers (requires wordaxe 0.3.2) * Issue 106: Crash on demo.txt fixed (requires wordxe 0.3.2) * Issue 102: Implemented styles for bulleted and numbered lists * Issue 38: Default headers/footers via options, config file or stylesheet * Issue 88: Implemented much better book-style TOCs * Issue 100: Fixed bug with headers/footers and Reportlab 2.3 * Issue 95: Fixed bug with indented tables * Issue 89: Implemented --version * Issue 84: Fixed bug with relative include paths * Issue 85: Fixed bug with table cell styles * Issue 83: Fixed bug with numeric colors in backColor attribute * Issue 44: Support for stdin and stdout * Issue 79: Added --stylesheet-path option * Issue 80: Send warnings to stderr, not stdout * Issue 66: Implemented "smart quotes" * Issue 77: Work around missing matplotlib * Proper translation of labels (such as "Author", "Version" etc.) using the docutils languages package. (r473) * Fixed problems with wrong or non-existing fonts. (r484) * Page transition effect support for presentations (r423) 0.9 (2008-09-26) ---------------- * Math support via Mathplotlib * Huge bug in header/footer page numbers/section names fixed * Several bugs in nested lists fixed (not 100% correct yet, but better) * Lists that don't start at 1 work now * Nicer definition lists 0.8.1 (2008-09-19) ------------------ * Support for more complex headers and footers (including image directives and tables) * Optional inline links * Wordaxe 0.2.6 support * Several bugs fixed (issues 48,68,41,60,58,64,67) * Support for system-wide config file * Better author metadata 0.8 (2008-09-12) ---------------- * Support for vector graphics: SVG, EPS, PS, CDR and others (requires uniconvertor) * Support for stdin and stdout, so you can use rst2pdf in pipes. * Works with reportlab 2.1 and 2.2 * Simpler stylesheets (guess bulletFontName, leading, bulletFontSize from other parameters) * Some support for sphinx * Fixed the docutils Writer interface * Continue processing when an image is missing * Support for user config file * Font sizes can be expressed in units or % of parent style's size * Larger font size in the default stylesheet 0.7 (2008-09-05) ---------------- * Automatic Type1 and True Type font embedding. Just use the font or family name, and (with a little luck), it will be embedded for you. * width attribute in styles, to create narrow paragraphs/tables * Styles for table headers and table cells * "Zebra tables" * Improvements in the handling of overflowing literal blocks (code, for instance) * Different modes to handle too-large literal blocks: overflow/truncate/shrink. * Real sidebars and "floating" elements. * Fixed link style (no ugly black underlining!) 0.6 (2008-08-30) ---------------- * Stylesheet-defined page layout (For example, multicolumn) and layout switching * Cascading Stylesheets (change exactly what you need changed) * PDF table of contents * Current section names and numbers in headers/footers * Support for compressed PDF files * Link color is configurable * Fixed bugs in color handling * Multilingual hyphenation * Auto-guessing image size, support for sizes in % * Gutter margins * Big refactoring * More tolerant of minor problems * Limited _raw_ directive (you can insert pagebreaks and vertical space) * Implemented a "traditional" docutils writer * Offer a reasonable API for use as a library * Fixed copyright/licensing * code-block now supports including files (whole or in part) so you can highlight external code. 0.5 (2008-08-27) ---------------- * Support for :widths: in tables * Support for captions in tables * Support for multi-row headers in tables * Improved definition lists * Fixed bug in image directive * Whitespace conforming to PEP8 * Fixed bug in text size on code-block * Package is more setuptools compliant * Fix for option groups in option lists * Citations support * Title reference role fix 0.4 (2008-08-25) ---------------- * Fixed bullet and item lists indentation/nesting. * Implemented citations * Working links between footnotes and its references * Justification enabled by default * Fixed table bug (demo.txt works now) * Title and author support in PDF properties * Support for document title in header/footer * Custom page sizes and margins 0.3 (2008-08-25) ---------------- * Font embedding (use any True Type font in your PDFs) * Syntax highlighter using Pygments * User's manual * External/custom stylesheets * Support for page numbers in header/footer rst2pdf-0.102/CODE_OF_CONDUCT.rst000066400000000000000000000041211463013543400161100ustar00rootroot00000000000000================================= rst2pdf Community Code of Conduct ================================= The rst2pdf community is made up of members from around the globe with a diverse set of skills, personalities, and experiences. It is through these differences that our community experiences great successes and continued growth. When you're working with members of the community, we encourage you to follow these guidelines which help steer our interactions and strive to keep rst2pdf a positive, successful, and growing community. A member of the rst2pdf community is: Open ==== Members of the community are open to collaboration, whether it's on patches, problems, or otherwise. We're receptive to constructive comment and criticism, as the experiences and skill sets of other members contribute to the whole of our efforts. We're accepting of all who wish to take part in our activities, fostering an environment where anyone can participate and everyone can make a difference. Considerate =========== Members of the community are considerate of their peers -- other rst2pdf users and developers. We're thoughtful when addressing the efforts of others, keeping in mind that often times the labor was completed simply for the good of the community. We're attentive in our communications, whether in person or online, and we're tactful when approaching differing views. Respectful ========== Members of the community are respectful. We're respectful of others, their positions, their skills, their commitments, and their efforts. We're respectful of the volunteer efforts that permeate the rst2pdf community. We're respectful of the processes set forth in the community, and we work within them. When we disagree, we are courteous in raising our issues. Overall, we're good to each other. We contribute to this community not because we have to, but because we want to. If we remember that, these guidelines will come naturally. Questions/comments/reports? Please write to maintainers@rst2pdf.org. (Thanks to the PSF for the Python Community Code of Conduct on which the rst2pdf Community Code of Conduct is based.) rst2pdf-0.102/CONTRIBUTING.rst000066400000000000000000000145541463013543400155550ustar00rootroot00000000000000Contributing to rst2pdf ####################### This project is actively maintained and contributions from developers of all levels are very, very welcome. We recommend opening an issue before starting work on anything big so that we can discuss with you any details that might be relevant - but an issue is not required. Changes are welcome however they arrive :) Start by making sure the project is running from source - instructions in the ``README`` for setting up local project. Code of Conduct =============== rst2pdf is an inclusive and welcoming community. To participate in this project, everyone is bound by our `Community Code of Conduct`__. __ CODE_OF_CONDUCT.rst Open an Issue ============= Issues are always welcome here! Please give as much detail as you can; small replication cases showing what doesn't work help us a lot - bonus points if you can turn that into a test! (more on testing later) Documentation Changes ===================== Documentation fixes are *at least* as valuable as code ones. The manual is in the file `doc/manual.rst` and gets converted to both PDF and HTML for https://rst2pdf.org. Please go ahead and open a pull request for each of the changes you think we need. Open a Pull Request =================== We love pull requests! Please open a pull request if you have changes/fixes/improvements to share. This project is for all of us and we welcome changes. Your PR should include: * A detailed description of what is being changed and importantly *why*. * Tests to cover the new feature, including reference PDFs. * An update to the manual if needed. Please be patient with us, we are all volunteers with busy lives. Project Structure ================= The code for the project is in ``rst2pdf`` inside the main project directory. Tests are in ``tests`` directory. Within this folder: * ``input`` holds the instructions for running a test. - ``[name].rst`` holds the rst source for the test - ``[name].style`` has any stylesheet that should be applied for this test - ``[name].cli`` allows adding extra commands to the test (look for examples) - ``[name].depends`` allows specifying dependencies for the test, so that in case they aren't met, the test is skipped. Each dependency should be added in a separate line. To add a new one, first add it in the ``check_dependency`` list inside ``conftest.py``. - ``test_[name].retcode`` allows for specifying an expected non-zero return code for expected error cases - ``test_[name].nopdf`` is a text file whose existence indicates that the test does not create a PDF output file - ``test_[name].expected_log`` allow for specifying expected text within the log output. If this file exists, then the existence of ``test_[name].nopdf`` implies that any generated PDF file is to be ignored. * ``output`` holds the PDFs that were generated by the tests running. * ``reference`` holds the "correct" version of the PDF for this test. When adding a test, put the desired PDF output into this file as well as supplying the tests in the ``input`` folder. Run Checks Locally ================== When you open a pull request, we run some automated checks to make sure everything is in order. We recommend you install these tools locally to check things over as you go along. We use the `pre-commit`__ framework, which you can install with pip:: pip install pre-commit Once installed, enable it by running this command:: pre-commit install --allow-missing-config .. __: https://pre-commit.com/ It will let you know if any of the formatting/build tools are reporting problems. Run the Tests ============= Please run the tests :) They also run automatically along with some style checking when you open or update a pull request. The first run of the tests needs some setup so check out the steps below. Context ******* The *rst2pdf* test suite generates PDFs - stored in ``tests/output`` - which are then compared against reference PDFs - stored in ``tests/reference`` - using the `PyMuPDF`__ Python bindings for the `MuPDF`__ library. *rst2pdf* depends on a number of different tools and libraries, such as `ReportLab`__, and the output of these can vary slightly between releases. The *PyMuPDF* library allows us to compare the structure of the PDFs, with a minor amount of fuzzing to allow for minor differences caused by these changes in underlying dependencies. .. __: https://pymupdf.readthedocs.io/en/latest/ .. __: https://mupdf.com/ .. __: https://www.reportlab.com/ Set up to run tests ******************* To run the tests for the first time, you will need to do some setup (after this, you can just work on your given virtualenv each time):: python -m venv env . env/bin/activate pip install pytest pytest-xdist pip install -c requirements.txt .[tests,sphinx,svgsupport,aafiguresupport,mathsupport,rawhtmlsupport] Run tests ********* To run all tests, run:: pytest You can also run tests in parallel by passing the ``-n auto`` flag:: pytest -n auto Running a single test ********************* To run one test only, pass the file or directory to pytest. For example:: pytest tests/input/sphinx-repeat-table-rows This will run one test and show the output. Skipping tests ************** To skip a test, create a text file in the ``tests/input`` directory called ``[test].ignore`` containing a note on why the test is skipped. This will mark the test as skipped when the test suite runs. This could be useful for inherited tests that we aren't confident of the correct output for, but where we don't want to delete/lose the test entirely. Updating dependencies ********************* The specific versions of all dependencies that are used for CI testing are stored in ``requirements.txt``. To update, change to a venv that has Python 3.8+ installed and run:: pip install pip-tools pip-compile --extra=aafiguresupport --extra=mathsupport --extra=plantumlsupport \ --extra=rawhtmlsupport --extra=sphinx --extra=svgsupport --extra=tests \ --output-file requirements.txt setup.py Tips and Tricks =============== Git config ********** After the mass-reformatting in PR 877, it is helpful to ignore the relevant commits that simply reformatted the code when using git blame. The ``.git-blame-ignore-revs`` file contains the list of commits to ignore and you can use this git config line to make ``git blame`` work more usefully:: git config blame.ignoreRevsFile .git-blame-ignore-revs rst2pdf-0.102/Contributors.txt000066400000000000000000000006121463013543400163400ustar00rootroot00000000000000* Roberto Alsina * Nicolas Laurance * Christoph Zwerschke * Yasushi Masuda * Josh VanderLinden * Runar Tenfjord * Patrick Maupin * Joshua J. Kugler * Patrick Maupin * anatoly techtonik * Joaquin Sorianello * tyler at datastax.com * charles at stanhope.com * al.yazdi * Dimitri Christodoulou * Paul Nation * Robert Johansson rst2pdf-0.102/ISSUE_TEMPLATE.md000066400000000000000000000017331463013543400156140ustar00rootroot00000000000000 **Description of problem** **What is the expected output? What do you see instead?** 🖥 **Versions** `python -V` `pip freeze | grep rst2pdf` `pip freeze | grep reportlab` `pip freeze | grep Sphinx` Which operating system are you using? **Additional information** rst2pdf-0.102/LICENSE.txt000066400000000000000000000021231463013543400147240ustar00rootroot00000000000000Copyright (c) 2007-2020 Roberto Alsina and the contributors to the rst2pdf project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rst2pdf-0.102/MAINTAINERS.rst000066400000000000000000000020741463013543400154120ustar00rootroot00000000000000=========== Maintainers =========== There aren't many rules for maintainers of rst2pdf to remember; what we have is listed here. We don't merge our own PRs ========================== Our code is better if more than one set of eyes looks at it. Therefore we do not merge our own pull requests unless there is an exceptional circumstance. This helps to spot errors in the patch and also enables us to share information about the project around the maintainer team. PRs tagged ``[WIP]`` are not ready to be merged =============================================== Sometimes it's helpful to collaborate on a patch before it's ready to be merged. We use the ``[WIP]`` tag (for _Work in Progress_) in the title to mark these PRs. If a PR has ``[WIP]`` in its title, then it is not to be merged. The person who raised the PR will remove the ``[WIP]`` tag when they are ready for a full review and merge. Assign a merged PR to a milestone ================================= By ensuring that all merged PRs are assigned to a milestone, we can easily find which PRs were in which release. rst2pdf-0.102/MANIFEST.in000066400000000000000000000000731463013543400146410ustar00rootroot00000000000000include README.rst include LICENSE.txt include CHANGES.rst rst2pdf-0.102/README.rst000066400000000000000000000072321463013543400145760ustar00rootroot00000000000000.. image:: https://img.shields.io/pypi/v/rst2pdf.svg :target: https://pypi.org/project/rst2pdf/ .. image:: https://img.shields.io/pypi/pyversions/rst2pdf.svg :target: https://pypi.org/project/rst2pdf/ .. image:: https://img.shields.io/pypi/l/rst2pdf.svg :target: https://pypi.org/project/rst2pdf/ ======================================= rst2pdf: Use a text editor. Make a PDF. ======================================= The usual way of creating PDF from reStructuredText is by going through LaTeX. This tool provides an alternative by producing PDF directly using the ReportLab library. More information is available at the `main website `_. Features -------- * User-defined page layout. Multiple frames per page, multiple layouts per document. * Page transitions * Cascading stylesheet mechanism, define only what you want changed. * Supports TTF and Type1 font embedding. * Any number of paragraph styles using the class directive. * Any number of character styles using text roles. * Custom page sizes and margins. * Syntax highlighter for many languages, using Pygments. * Supports embedding almost any kind of raster or vector images. * Supports hyphenation. * `Sphinx `_ integration * `Full user's manual `_ Installation ------------ *rst2pdf* supports Python 3.8 or greater. Version 0.99 was the last version to support Python 3.6 & 3.7, with 0.97 the last version to support Python 2.7. Install from PyPI ~~~~~~~~~~~~~~~~~ The latest released version may be installed from PyPI by using ``pipx``:: $ pipx install rst2pdf rst2pdf also has support for a number of features that require additional dependencies. Installation of all the required dependencies using ``pipx`` may be installed using:: $ pipx install rst2pdf[aafiguresupport,mathsupport,plantumlsupport,rawhtmlsupport,sphinx,svgsupport] Install from Snap ~~~~~~~~~~~~~~~~~ If you are using a system that supports `snaps `__ then you can install from there with:: $ snap install rst2pdf Install from GitHub ~~~~~~~~~~~~~~~~~~~ Work on rst2pdf has restarted on GitHub, with the goals of adding new features, addressing outstanding issues, and not breaking anything. You can clone the repository and install this version:: $ git clone https://github.com/rst2pdf/rst2pdf $ cd rst2pdf $ git checkout # if you want something other than main $ pipx install .[aafiguresupport,mathsupport,plantumlsupport,rawhtmlsupport,sphinx,svgsupport] If you intend to work on rst2pdf's source code, see ``doc/DEVELOPERS.rst``. Usage ----- To convert a reStructuredText document to a PDF, simply run:: $ rst2pdf output.pdf For information on available options, use ``-h``:: $ rst2pdf -h To enable basic integration with Sphinx, modify your ``conf.py`` file to enable the ``rst2pdf.pdfbuilder`` extension and configure the ``pdf_documents`` option. For example:: extensions = [ # ... 'rst2pdf.pdfbuilder', ] # Grouping the document tree into PDF files. List of tuples # (source start file, target name, title, author, options). pdf_documents = [ ('index', 'MyProject', 'My Project', 'Author Name'), ] For information on the ``pdf_documents`` option and the many other options available, refer to the `manual `_. Contributing ------------ See `CONTRIBUTING `_. Code of conduct --------------- rst2pdf is an inclusive and welcoming community. To participate in this project, everyone is bound by our `Community Code of Conduct `_. rst2pdf-0.102/doc/000077500000000000000000000000001463013543400136505ustar00rootroot00000000000000rst2pdf-0.102/doc/DEVELOPERS.rst000066400000000000000000000116211463013543400160530ustar00rootroot00000000000000--------------------------- Help for rst2pdf developers --------------------------- Guidelines ~~~~~~~~~~ If you want to do something inside rst2pdf, you are welcome! The process looks something like this: * Create an Issue for the task at https://github.com/rst2pdf/rst2pdf/issues * If you intend to fix a bug: + Create a **minimal** test case that shows the bug. + Put it inside ``tests/input`` like the others: + Fix the bug During this process, you can run the individual test case to quickly iterate. For example:: pytest tests/input/test_summary_of_test.txt You may also wish to check the logs and output:: less tests/output/test_summary_of_test.log xdg-open tests/output/test_summary_of_test.pdf # or 'open' on macOS + Once resolved, copy the generated output PDF, if any, to ``tests/reference`` and commit this along with the files in ``tests/input``. + Submit a pull request. * If you added a command line option, document it in ``doc/rst2pdf.txt``. That will make it appear in the manual and in the man page. * If you implemented a new feature, please document it in ``manual.rst`` (or in a separate file and add an include in ``manual.rst``) * If you implement an extension, make the docstring valid restructured text and link it to the manual like the others. Initial checkout ---------------- Clone the repo from https://github.com/rst2pdf/rst2pdf, then install and activate a venv:: git clone https://github.com/rst2pdf/rst2pdf cd rst2pdf python3 -m venv .venv . .venv/bin/activate Ensure that setuptools and pip are up to date:: pip install --upgrade setuptools pip Now you can install rst2pdf from this source code:: pip install -c requirements.txt -e .[aafiguresupport,mathsupport,rawhtmlsupport,sphinx,svgsupport,tests] Note, that on Apple Silicon Macs, you may need this to get tests passing:: pip install reportlab==3.6.12 --force-reinstall --no-cache-dir --global-option=build_ext (Look in ``requirements.txt`` for the version of reportlab to use.) You can now work on rst2pdf development. Once complete, you can deactivate the venv with ``deactivate``. Git config ~~~~~~~~~~ After the mass-reformatting in PR 877, it is helpful to ignore the relevant commits that simply reformatted the code when using git blame. The ``..git-blame-ignore-revs`` file contains the list of commits to ignore and you can use this git config line to make ``git blame`` work more usefully:: git config blame.ignoreRevsFile .git-blame-ignore-revs Pre-commit ~~~~~~~~~~ *rst2pdf* uses the `pre-commit`__ framework to automate various style checkers. This must be enabled locally. You can install this using *pip* or your local package manager. For example, to install using *pip*:: pip install pre-commit Once installed, enable it like so:: pre-commit install --allow-missing-config .. __: https://pre-commit.com/ If pre-commit locally behaves differently to CI, then run ``pre-commit clean`` to clear your cache before further investigation. Continuous Integration ~~~~~~~~~~~~~~~~~~~~~~ There's a GitHub Actions workflow that runs when we open a pull request or merge to main, it does some style checks and runs the test suite. Running tests ~~~~~~~~~~~~~ The *rst2pdf* test suite generates PDFs - stored in ``tests/output`` - which are then compared against reference PDFs - stored in ``tests/reference`` - using the `PyMuPDF`__ Python bindings for the `MuPDF`__ library. *rst2pdf* depends on a number of different tools and libraries, such as `ReportLab`__, and the output of these can vary slightly between releases. The *PyMuPDF* library allows us to compare the structure of the PDFs, with a minor amount of fuzzing to allow for minor differences caused by these changes in underlying dependencies. .. __: https://pymupdf.readthedocs.io/en/latest/ .. __: https://mupdf.com/ .. __: https://www.reportlab.com/ To run all the tests enable your venv first if it's not enabled and then call ``pytest``:: pytest You can also run tests in parallel using ``pytest-xdist`` by passing the ``-n auto`` flag. Firstly install:: pip install pytest-xdist Then run the tests in parallel:: pytest -n auto Running a single test ********************* To run one test only, simply pass the file or directory to pytest. For example:: pytest tests/input/sphinx-repeat-table-rows This will run one test and show the output. Skipping tests ************** To skip a test, simply create a text file in the ``tests/input`` directory called ``[test].ignore`` containing a note on why the test is skipped. This will mark the test as skipped when the test suite runs. This could be useful for inherited tests that we aren't confident of the correct output for, but where we don't want to delete/lose the test entirely. .. note:: Some tests require the execution of the ``dot`` command, you should install the package graphviz from your packages manager. rst2pdf-0.102/doc/RELEASE_PROCESS.rst000066400000000000000000000071441463013543400166660ustar00rootroot00000000000000=========================== Release Process for rst2pdf =========================== This is an outline of what needs to be done in order to release rst2pdf. #. Install dependencies that you'll need :: $ pip install setuptools setuptools_scm wheel twine #. Update ``CHANGES.rst`` to add the version number and date. Commit to a branch, PR and merge to master #. Ensure all PRs are attached to the milestone #. Close the milestone and create next one #. Checkout main and ensure that your working copy is clean :: $ git checkout main #. Use changelog-generator_ (or similar) to create a changelog :: $ changelog-generator -u rst2pdf -r rst2pdf -m 999 #. Tag release with version number :: $ git tag -s 0.94 $ git push upstream 0.94 #. Build manual You will need the `White Rabbit`_ font installed. We check out the tag first so that the version on the first page of the PDF is labelled as final and then generate the HTMl and PDF docs. :: $ git checkout 0.94 $ cd doc; ./gen_docs.sh $ git checkout main Add subject and author to manual PDF's meta data using ExifTool_ :: $ exiftool -PDF:Subject="v0.94 r2019011700" output/pdf/manual.pdf $ exiftool -PDF:Author="rst2pdf project; Roberto Alsina" output/pdf/manual.pdf and upload to HTML and PDF to the website via a PR on the rst2pdf.github.io_ repo. #. Update Releases_ section on GitHub project and paste in changelog #. Create rc distribution package :: $ python setup.py egg_info -b "rc1" sdist bdist_wheel If you're doing an alphaX, betaX or postX, then change ``-b "rc1"`` appropriately #. Upload the rc distribution to Test-PyPI_ :: $ twine upload --repository testpypi dist/* Check that it all looks correct on Test-PyPI. If not, fix and release a new rc. #. Test Test-PyPI release into a clean virtual env :: $ pip install --index-url https://test.pypi.org/simple \ --extra-index-url https://pypi.org/simple --pre rst2pdf It should install the rc release on Test PyPI and be able to create PDF documents from rst files Delete the build artifacts and dist files with: :: $ rm -rf build/ rst2pdf.egg-info/ dist/ #. Once rc version is working, release to PyPI_ by generating official release and uploading :: $ python setup.py egg_info -b "" sdist bdist_wheel $ twine upload --repository pypi dist/* Check that the release is correct on PyPI_ and then delete the build artifacts and dist files with: :: $ rm -rf build/ rst2pdf.egg-info/ dist/ | | *Note:* create a ``~/.pypirc`` file to make the ``--repository`` switch work with ``twine``. It should contain the following: :: [pypi] username: {your PyPi username} [testpypi] repository: https://test.pypi.org/legacy/ username: {your PyPi username} .. _changelog-generator: https://github.com/weierophinney/changelog_generator .. _White Rabbit:: https://squaregear.net/fonts/whitrabt.html .. _ExifTool: https://www.sno.phy.queensu.ca/~phil/exiftool/ .. _Releases: https://github.com/rst2pdf/rst2pdf/releases .. _rst2pdf.github.io: https://github.com/rst2pdf/rst2pdf.github.io .. _Test-PyPI: https://test.pypi.org .. _PyPI: https://pypi.org Releasing as a Snap ~~~~~~~~~~~~~~~~~~~ 1. Update the version string in ``snap/snapcraft.yml`` as desired (probably to match the new release tag) 2. Run ``snapcraft`` and note the filename of the output 3. Now publish (the ``rst2pdf`` namespace is associated with @lornajane's Ubuntu account) by doing ``snapcraft push --release=stable [the snape filename from the previous step]`` rst2pdf-0.102/doc/assets/000077500000000000000000000000001463013543400151525ustar00rootroot00000000000000rst2pdf-0.102/doc/assets/biohazard.png000066400000000000000000000002631463013543400176240ustar00rootroot00000000000000‰PNG  IHDR%=m"gAMAÙܲÚ pHYsÄÄ•+PLTEÿÿÿUÂÓ~tRNS@æØf6IDATxœb`Q`à``¾Á cBöêê.y3Lì!Þ Ì@ˆýPÿÿâ™ ±A5IEND®B`‚rst2pdf-0.102/doc/assets/config.sample000066400000000000000000000047211463013543400176260ustar00rootroot00000000000000# This is an example config file. Modify and place in ~/.rst2pdf/config [general] # A comma-separated list of custom stylesheets. Example: # stylesheets="fruity.json,a4paper.json,verasans.json" stylesheets="" # Create a compressed PDF # Use true/false (lower case) or 1/0 compressed=false # A colon-separated list of folders to search for fonts. Example: # font_path="/usr/share/fonts:/usr/share/texmf-dist/fonts/" font_path="" # A colon-separated list of folders to search for stylesheets. Example: # stylesheet_path="~/styles:/usr/share/styles" stylesheet_path="" # Language to be used for hyphenation support language="en_US" # Default page header and footer header=null footer=null # What to do if a literal block is too large. Can be # shrink/truncate/overflow fit_mode="shrink" # How to adjust the background image to the page. # Can be: "scale" and "center" fit_background_mode="center" # What is the maximum level of heading that starts in a new page. # 0 means no level starts in a new page. break_level=0 # How section breaks work. Can be "even", and sections start in an # even page, "odd", and sections start in odd pages, or "any" and # sections start in the next page, be it even or odd. break_side="any" # Add a blank page at the beginning of the document blank_first_page=false # Treat the first page as even (default false, treat it as odd) first_page_even=false # Smart quotes. # 0: Suppress all transformations. (Do nothing.) # 1: Performs default SmartyPants transformations: quotes (including ‘‘backticks'' # -style), em-dashes, and ellipses. "--" (dash dash) is used to signify an em-dash; # there is no support for en-dashes. # 2: Same as 1, except that it uses the old-school typewriter shorthand for # dashes: "--" (dash dash) for en-dashes, "---" (dash dash dash) for em-dashes. # 3: Same as 2, but inverts the shorthand for dashes: "--" (dash dash) for # em-dashes, and "---" (dash dash dash) for en-dashes. smartquotes=0 # Footnote backlinks enabled or not (default: enabled) footnote_backlinks=true # Show footnotes inline instead of at the end of the document inline_footnotes=false # Cover page template. # It will be searched in the document's folder, in ~/.rst2pdf/templates and # in the templates subfolder of the package folder # custom_cover = cover.tmpl # Use floating images. # Makes the behaviour of images with the :align: attribute more like rst2html's floating_images = false # Support the ..raw:: html directive raw_html = false rst2pdf-0.102/doc/assets/cover.tmpl000066400000000000000000000004451463013543400171710ustar00rootroot00000000000000.. class:: logoimage .. image:: assets/rst2pdf-logo.jpg :width: 50% .. raw:: pdf Spacer 0 10mm .. class:: subtitle How to use .. class:: title rst2pdf .. class:: centered Version :package-version:`rst2pdf` (:package-revision:`rst2pdf`) .. raw:: pdf PageBreak oneColumn rst2pdf-0.102/doc/assets/flowables.py000066400000000000000000001133641463013543400175120ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms __docformat__ = 'reStructuredText' from copy import copy import re import sys from xml.sax.saxutils import unescape from reportlab.lib.enums import TA_CENTER, TA_RIGHT from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import cm from reportlab.platypus.doctemplate import FrameActionFlowable, FrameBreak, Indenter from reportlab.platypus.flowables import ( _listWrapOn, _FUZZ, Flowable, NullDraw, PageBreak, Spacer, ) from reportlab.platypus.frames import Frame from reportlab.platypus.paragraph import Paragraph from reportlab.platypus.tables import Table, TableStyle from reportlab.platypus.tableofcontents import TableOfContents from reportlab.platypus.xpreformatted import XPreformatted from . import styles from .log import log class XXPreformatted(XPreformatted): """An extended XPreformattedFit""" def __init__(self, *args, **kwargs): XPreformatted.__init__(self, *args, **kwargs) def split(self, aW, aH): # Figure out a nice range of splits # # Assume we would prefer 5 lines (at least) on # a splitted flowable before a break, and 4 on # the last flowable after a break. # So, the minimum wrap height for a fragment # will be 5*leading rW, rH = self.wrap(aW, aH) if rH > aH: minH1 = getattr(self.style, 'allowOrphans', 5) * self.style.leading minH2 = getattr(self.style, 'allowWidows', 4) * self.style.leading # If there's no way to fid a decent fragment, # refuse to split if aH < minH1: return [] # Now, don't split too close to the end either pw, ph = self.wrap(aW, aH) if ph - aH < minH2: aH = ph - minH2 return XPreformatted.split(self, aW, aH) class MyIndenter(Indenter): """An indenter that has a width, because otherwise you get crashes if added inside tables""" width = 0 height = 0 def draw(self): pass class TocEntry(NullDraw): """A flowable that adds a TOC entry but draws nothing""" def __init__(self, level, label): self.level = level self.label = label self.width = 0 self.height = 0 self.keepWithNext = True def draw(self): # Add outline entry self.canv.bookmarkHorizontal(self.label, 0, 0 + self.height) self.canv.addOutlineEntry( self.label, self.label, max(0, int(self.level)), False ) class Heading(Paragraph): """A paragraph that also adds an outline entry in the PDF TOC.""" def __init__( self, text, style, bulletText=None, caseSensitive=1, level=0, snum=None, parent_id=None, node=None, section_header_depth=2, ): # Issue 114: need to convert "&" to "&" and such. # Issue 140: need to make it plain text self.stext = re.sub(r'<[^>]*?>', '', unescape(text)) self.stext = self.stext.strip() self.level = int(level) self.snum = snum self.parent_id = parent_id self.node = node self.section_header_depth = section_header_depth Paragraph.__init__(self, text, style, bulletText) def draw(self): # Add outline entry self.canv.bookmarkHorizontal(self.parent_id, 0, 0 + self.height) # self.section_header_depth is for Issue 391 if self.canv.firstSect and self.level < self.section_header_depth: self.canv.sectName = self.stext self.canv.firstSect = False if self.snum is not None: self.canv.sectNum = self.snum else: self.canv.sectNum = "" self.canv.addOutlineEntry(self.stext, self.parent_id, int(self.level), False) Paragraph.draw(self) class Separation(Flowable): """A simple
-like flowable""" def wrap(self, w, h): self.w = w return w, 1 * cm def draw(self): self.canv.line(0, 0.5 * cm, self.w, 0.5 * cm) class Reference(Flowable): """A flowable to insert an anchor without taking space""" def __init__(self, refid): self.refid = refid self.keepWithNext = True Flowable.__init__(self) def wrap(self, w, h): """This takes no space""" return 0, 0 def draw(self): self.canv.bookmarkPage(self.refid) def repr(self): return "Reference: %s" % self.refid def __str__(self): return "Reference: %s" % self.refid class OddEven(Flowable): """This flowable takes two lists of flowables as arguments, odd and even. If will draw the "odd" list when drawn in odd pages and the "even" list on even pages. wrap() will always return a size large enough for both lists, and this flowable **cannot** be split, so use with care. """ def __init__(self, odd, even, style=None): self.odd = DelayedTable([[odd]], ['100%'], style) self.even = DelayedTable([[even]], ['100%'], style) def wrap(self, w, h): """Return a box large enough for both odd and even""" w1, h1 = self.odd.wrap(w, h) w2, h2 = self.even.wrap(w, h) return max(w1, w2), max(h1, h2) def drawOn(self, canvas, x, y, _sW=0): if canvas._pagenum % 2 == 0: self.even.drawOn(canvas, x, y, _sW) else: self.odd.drawOn(canvas, x, y, _sW) def split(self): """Makes no sense to split this...""" return [] class DelayedTable(Table): """A flowable that inserts a table for which it has the data. Needed so column widths can be determined after we know on what frame the table will be inserted, thus making the overal table width correct. """ def __init__(self, data, colWidths, style=None, repeatrows=False, splitByRow=True): self.data = data self._colWidths = colWidths if style is None: style = TableStyle( [ ('LEFTPADDING', (0, 0), (-1, -1), 0), ('RIGHTPADDING', (0, 0), (-1, -1), 0), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), ] ) self.style = style self.t = None self.repeatrows = repeatrows self.hAlign = TA_CENTER self.splitByRow = splitByRow def wrap(self, w, h): # Create the table, with the widths from colWidths reinterpreted # if needed as percentages of frame/cell/whatever width w is. # _tw = w/sum(self.colWidths) def adjust(*args, **kwargs): kwargs['total'] = w return styles.adjustUnits(*args, **kwargs) # adjust=functools.partial(styles.adjustUnits, total=w) self.colWidths = [adjust(x) for x in self._colWidths] # colWidths = [_w * _tw for _w in self.colWidths] self.t = Table( self.data, colWidths=self.colWidths, style=self.style, repeatRows=self.repeatrows, splitByRow=True, ) # splitByRow=self.splitByRow) self.t.hAlign = self.hAlign return self.t.wrap(w, h) def split(self, w, h): if self.splitByRow: if not self.t: self.wrap(w, h) return self.t.split(w, h) else: return [] def drawOn(self, canvas, x, y, _sW=0): self.t.drawOn(canvas, x, y, _sW) def identity(self, maxLen=None): return ( "<%s at %s%s%s> containing: %s" % ( self.__class__.__name__, hex(id(self)), self._frameName(), getattr(self, 'name', '') and (' name="%s"' % getattr(self, 'name', '')) or '', repr(self.data[0]), )[:180] ) def tablepadding(padding): if not isinstance(padding, (list, tuple)): padding = [padding] * 4 return ( padding, ('TOPPADDING', [0, 0], [-1, -1], padding[0]), ('RIGHTPADDING', [-1, 0], [-1, -1], padding[1]), ('BOTTOMPADDING', [0, 0], [-1, -1], padding[2]), ('LEFTPADDING', [1, 0], [1, -1], padding[3]), ) class SplitTable(DelayedTable): def __init__(self, data, colWidths, style, padding=3): if len(data) != 1 or len(data[0]) != 2: log.error('SplitTable can only be 1 row and two columns!') sys.exit(1) DelayedTable.__init__(self, data, colWidths, style) self.padding, p1, p2, p3, p4 = tablepadding(padding) self.style._cmds.insert(0, p1) self.style._cmds.insert(0, p2) self.style._cmds.insert(0, p3) self.style._cmds.insert(0, p4) def identity(self, maxLen=None): return "<%s at %s%s%s> containing: %s" % ( self.__class__.__name__, hex(id(self)), self._frameName(), getattr(self, 'name', '') and (' name="%s"' % getattr(self, 'name', '')) or '', repr(self.data[0][1])[:180], ) def split(self, w, h): _w, _h = self.wrap(w, h) if _h > h: # Can't split! # The right column data mandates the split # Find which flowable exceeds the available height dw = self.colWidths[0] + self.padding[1] + self.padding[3] dh = self.padding[0] + self.padding[2] bullet = self.data[0][0] text = self.data[0][1] for l in range(0, len(text)): _, fh = _listWrapOn(text[: l + 1], w - dw, None) if fh + dh > h: # The lth flowable is the guilty one # split it _, lh = _listWrapOn(text[:l], w - dw, None) # Workaround for Issue 180 text[l].wrap(w - dw, h - lh - dh) l2 = text[l].split(w - dw, h - lh - dh) if l2 == []: # Not splittable, push some to next page if l == 0: # Can't fit anything, push all to next page return l2 # We reduce the number of items we keep on the # page for two reasons: # 1) If an item is associated with the following # item (getKeepWithNext() == True), we have # to back up to a previous one. # 2) If we miscalculated the size required on # the first page (I dunno why, probably not # counting borders properly, but we do # miscalculate occasionally). Seems to # have to do with nested tables, so it might # be the extra space on the border on the # inner table. while l > 0: if not text[l - 1].getKeepWithNext(): first_t = Table( [[bullet, text[:l]]], colWidths=self.colWidths, style=self.style, ) _w, _h = first_t.wrap(w, h) if _h <= h: break l -= 1 if l > 0: # Workaround for Issue 180 with wordaxe: # if wordaxe is not None: # l3=[Table([ # [bullet, # text[:l]] # ], # colWidths=self.colWidths, # style=self.style), # Table([['',text[l:]]], # colWidths=self.colWidths, # style=self.style)] # else: l3 = [ first_t, SplitTable( [['', text[l:]]], colWidths=self.colWidths, style=self.style, padding=self.padding, ), ] else: # Everything flows l3 = [] else: l3 = [ Table( [[bullet, text[:l] + [l2[0]]]], colWidths=self.colWidths, rowHeights=[h], style=self.style, ) ] if l2[1:] + text[l + 1 :]: l3.append( SplitTable( [['', l2[1:] + text[l + 1 :]]], colWidths=self.colWidths, style=self.style, padding=self.padding, ) ) return l3 log.debug("Can't split splittable") return self.t.split(w, h) else: return DelayedTable.split(self, w, h) class MySpacer(Spacer): def wrap(self, aW, aH): w, h = Spacer.wrap(self, aW, aH) self.height = min(aH, h) return w, self.height class MyPageBreak(FrameActionFlowable): def __init__(self, templateName=None, breakTo='any'): """templateName switches the page template starting in the next page. breakTo can be 'any' 'even' or 'odd'. 'even' will break one page if the current page is odd or two pages if it's even. That way the next flowable will be in an even page. 'odd' is the opposite of 'even' 'any' is the default, and means it will always break only one page. """ self.templateName = templateName self.breakTo = breakTo self.forced = False self.extraContent = [] def frameAction(self, frame): frame._generated_content = [] if self.breakTo == 'any': # Break only once. None if at top of page if not frame._atTop: frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(PageBreak()) elif self.breakTo == 'odd': # Break once if on even page, twice # on odd page, none if on top of odd page if frame._pagenum % 2: # odd pageNum if not frame._atTop: # Blank pages get no heading or footer frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(SetNextTemplate('emptyPage')) frame._generated_content.append(PageBreak()) frame._generated_content.append(ResetNextTemplate()) frame._generated_content.append(PageBreak()) else: # even frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(PageBreak()) elif self.breakTo == 'even': # Break once if on odd page, twice # on even page, none if on top of even page if frame._pagenum % 2: # odd pageNum frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(PageBreak()) else: # even if not frame._atTop: # Blank pages get no heading or footer frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(SetNextTemplate('emptyPage')) frame._generated_content.append(PageBreak()) frame._generated_content.append(ResetNextTemplate()) frame._generated_content.append(PageBreak()) class SetNextTemplate(Flowable): """Set canv.templateName when drawing. rst2pdf uses that to switch page templates. """ def __init__(self, templateName=None): self.templateName = templateName Flowable.__init__(self) def draw(self): if self.templateName: try: self.canv.oldTemplateName = self.canv.templateName except Exception: self.canv.oldTemplateName = 'oneColumn' self.canv.templateName = self.templateName class ResetNextTemplate(Flowable): """Go back to the previous template. rst2pdf uses that to switch page templates back when temporarily it needed to switch to another template. For example, after a OddPageBreak, there can be a totally blank page. Those have to use coverPage as a template, because they must not have headers or footers. And then we need to switch back to whatever was used. """ def __init__(self): Flowable.__init__(self) def draw(self): self.canv.templateName, self.canv.oldTemplateName = ( self.canv.oldTemplateName, self.canv.templateName, ) def wrap(self, aW, aH): return 0, 0 class TextAnnotation(Flowable): """Add text annotation flowable""" def __init__(self, *args): self.annotationText = "" self.position = [-1, -1, -1, -1] if len(args) >= 1: self.annotationText = args[0].lstrip('"').rstrip('"') if len(args) >= 5: self.position = args[1:] def wrap(self, w, h): return 0, 0 def draw(self): # Format of Reportlab's textAnnotation(): # textAnnotation("Your content", Rect=[x_begin, y_begin, x_end, y_end], relative=1) self.canv.textAnnotation(self.annotationText, self.position, 1) class Transition(Flowable): """Wrap canvas.setPageTransition. Sets the transition effect from the current page to the next. """ PageTransitionEffects = dict( Split=['direction', 'motion'], Blinds=['dimension'], Box=['motion'], Wipe=['direction'], Dissolve=[], Glitter=['direction'], ) def __init__(self, *args): if len(args) < 1: args = [None, 1] # No transition # See if we got a valid transition effect name if args[0] not in self.PageTransitionEffects: log.error('Unknown transition effect name: %s' % args[0]) args[0] = None elif len(args) == 1: args.append(1) # FIXME: validate more self.args = args def wrap(self, aw, ah): return 0, 0 def draw(self): kwargs = dict( effectname=None, duration=1, direction=0, dimension='H', motion='I' ) ceff = ['effectname', 'duration'] + self.PageTransitionEffects[self.args[0]] for argname, argvalue in zip(ceff, self.args): kwargs[argname] = argvalue kwargs['duration'] = int(kwargs['duration']) kwargs['direction'] = int(kwargs['direction']) self.canv.setPageTransition(**kwargs) class SmartFrame(Frame): """A (Hopefully) smarter frame object. This frame object knows how to handle a two-pass layout procedure (someday). """ def __init__( self, container, x1, y1, width, height, leftPadding=6, bottomPadding=6, rightPadding=6, topPadding=6, id=None, showBoundary=0, overlapAttachedSpace=None, _debug=None, ): self.container = container self.onSidebar = False self.__s = '[%s, %s, %s, %s, %s, %s, %s, %s,]' % ( x1, y1, width, height, leftPadding, bottomPadding, rightPadding, topPadding, ) Frame.__init__( self, x1, y1, width, height, leftPadding, bottomPadding, rightPadding, topPadding, id, showBoundary, overlapAttachedSpace, _debug, ) def add(self, flowable, canv, trySplit=0): flowable._atTop = self._atTop return Frame.add(self, flowable, canv, trySplit) def __repr__(self): return self.__s def __deepcopy__(self, *whatever): return copy(self) class FrameCutter(FrameActionFlowable): def __init__(self, dx, width, flowable, padding, lpad, floatLeft=True): self.width = width self.dx = dx self.f = flowable self.padding = padding self.lpad = lpad self.floatLeft = floatLeft def frameAction(self, frame): idx = frame.container.frames.index(frame) if self.floatLeft: # Don't bother inserting a silly thin frame if self.width - self.padding > 30: f1 = SmartFrame( frame.container, frame._x1 + self.dx - 2 * self.padding, frame._y2 - self.f.height - 3 * self.padding, self.width + 2 * self.padding, self.f.height + 3 * self.padding, bottomPadding=0, topPadding=0, leftPadding=self.lpad, ) f1._atTop = frame._atTop # This is a frame next to a sidebar. f1.onSidebar = True frame.container.frames.insert(idx + 1, f1) # Don't add silly thin frame if frame._height - self.f.height - 2 * self.padding > 30: frame.container.frames.insert( idx + 2, SmartFrame( frame.container, frame._x1, frame._y1p, self.width + self.dx, frame._height - self.f.height - 3 * self.padding, topPadding=0, ), ) else: # Don't bother inserting a silly thin frame if self.width - self.padding > 30: f1 = SmartFrame( frame.container, frame._x1 - self.width, frame._y2 - self.f.height - 2 * self.padding, self.width, self.f.height + 2 * self.padding, bottomPadding=0, topPadding=0, rightPadding=self.lpad, ) f1._atTop = frame._atTop # This is a frame next to a sidebar. f1.onSidebar = True frame.container.frames.insert(idx + 1, f1) if frame._height - self.f.height - 2 * self.padding > 30: frame.container.frames.insert( idx + 2, SmartFrame( frame.container, frame._x1 - self.width, frame._y1p, self.width + self.dx, frame._height - self.f.height - 2 * self.padding, topPadding=0, ), ) class Sidebar(FrameActionFlowable): def __init__(self, flowables, style): self.style = style self.width = self.style.width self.flowables = flowables def frameAction(self, frame): if self.style.float not in ('left', 'right'): return if frame.onSidebar: # We are still on the frame next to a sidebar! frame._generated_content = [FrameBreak(), self] else: w = frame.container.styles.adjustUnits(self.width, frame.width) idx = frame.container.frames.index(frame) padding = self.style.borderPadding width = self.style.width self.style.padding = frame.container.styles.adjustUnits( str(padding), frame.width ) self.style.width = frame.container.styles.adjustUnits( str(width), frame.width ) self.kif = BoxedContainer(self.flowables, self.style) if self.style.float == 'left': self.style.lpad = frame.leftPadding f1 = SmartFrame( frame.container, frame._x1, frame._y1p, w - 2 * self.style.padding, frame._y - frame._y1p, leftPadding=self.style.lpad, rightPadding=0, bottomPadding=0, topPadding=0, ) f1._atTop = frame._atTop frame.container.frames.insert(idx + 1, f1) frame._generated_content = [ FrameBreak(), self.kif, FrameCutter( w, frame.width - w, self.kif, padding, self.style.lpad, True, ), FrameBreak(), ] elif self.style.float == 'right': self.style.lpad = frame.rightPadding frame.container.frames.insert( idx + 1, SmartFrame( frame.container, frame._x1 + frame.width - self.style.width, frame._y1p, w, frame._y - frame._y1p, rightPadding=self.style.lpad, leftPadding=0, bottomPadding=0, topPadding=0, ), ) frame._generated_content = [ FrameBreak(), self.kif, FrameCutter( w, frame.width - w, self.kif, padding, self.style.lpad, False, ), FrameBreak(), ] class BoundByWidth(Flowable): """Limit a list of flowables by width. This still lets the flowables break over pages and frames. """ def __init__(self, maxWidth, content=[], style=None, mode=None, scale=None): self.maxWidth = maxWidth self.content = content self.style = style self.mode = mode self.pad = None self.scale = scale Flowable.__init__(self) def border_padding(self, useWidth, additional): sdict = self.style sdict = sdict.__dict__ or {} bp = sdict.get("borderPadding", 0) if useWidth: additional += sdict.get("borderWidth", 0) if not isinstance(bp, list): bp = [bp] * 4 return [x + additional for x in bp] def identity(self, maxLen=None): return "<%s at %s%s%s> containing: %s" % ( self.__class__.__name__, hex(id(self)), self._frameName(), getattr(self, 'name', '') and (' name="%s"' % getattr(self, 'name', '')) or '', repr([c.identity() for c in self.content])[:80], ) def wrap(self, availWidth, availHeight): """If we need more width than we have, complain, keep a scale""" self.pad = self.border_padding(True, 0.1) maxWidth = float( min( styles.adjustUnits(self.maxWidth, availWidth) or availWidth, availWidth, ) ) self.maxWidth = maxWidth maxWidth -= self.pad[1] + self.pad[3] self.width, self.height = _listWrapOn( self.content, maxWidth, None, fakeWidth=False ) if self.width > maxWidth: if self.mode != 'shrink': self.scale = 1.0 log.warning( "BoundByWidth too wide to fit in frame (%s > %s): %s", self.width, maxWidth, self.identity(), ) if self.mode == 'shrink' and not self.scale: self.scale = (maxWidth + self.pad[1] + self.pad[3]) / ( self.width + self.pad[1] + self.pad[3] ) else: self.scale = 1.0 self.height *= self.scale self.width *= self.scale return ( self.width, self.height + (self.pad[0] + self.pad[2]) * self.scale, ) def split(self, availWidth, availHeight): if not self.pad: self.wrap(availWidth, availHeight) content = self.content if len(self.content) == 1: # We need to split the only element we have content = content[0].split( availWidth - (self.pad[1] + self.pad[3]), availHeight - (self.pad[0] + self.pad[2]), ) result = [ BoundByWidth(self.maxWidth, [f], self.style, self.mode, self.scale) for f in content ] return result def draw(self): """we simulate being added to a frame""" canv = self.canv canv.saveState() x = canv._x y = canv._y _sW = 0 scale = self.scale content = None # , canv, x, y, _sW=0, scale=1.0, content=None, aW=None): pS = 0 aW = self.width aW = scale * (aW + _sW) if content is None: content = self.content y += (self.height + self.pad[2]) / scale x += self.pad[3] for c in content: w, h = c.wrapOn(canv, aW, 0xFFFFFFF) if (w < _FUZZ or h < _FUZZ) and not getattr(c, '_ZEROSIZE', None): continue if c is not content[0]: h += max(c.getSpaceBefore() - pS, 0) y -= h canv.saveState() if self.mode == 'shrink': canv.scale(scale, scale) elif self.mode == 'truncate': p = canv.beginPath() p.rect( x - self.pad[3], y - self.pad[2], self.maxWidth, self.height + self.pad[0] + self.pad[2], ) canv.clipPath(p, stroke=0) c.drawOn(canv, x, y, _sW=aW - w) canv.restoreState() if c is not content[-1]: pS = c.getSpaceAfter() y -= pS canv.restoreState() class BoxedContainer(BoundByWidth): def __init__(self, content, style, mode='shrink'): try: w = style.width except AttributeError: w = '100%' BoundByWidth.__init__(self, w, content, mode=mode, style=None) self.style = style self.mode = mode def identity(self, maxLen=None): return repr( ['BoxedContainer containing: ', [c.identity() for c in self.content]] )[:80] def draw(self): canv = self.canv canv.saveState() x = canv._x y = canv._y lw = 0 if self.style and self.style.borderWidth > 0: lw = self.style.borderWidth canv.setLineWidth(self.style.borderWidth) if self.style.borderColor: # This could be None :-( canv.setStrokeColor(self.style.borderColor) stroke = 1 else: stroke = 0 else: stroke = 0 if self.style and self.style.backColor: canv.setFillColor(self.style.backColor) fill = 1 else: fill = 0 padding = self.border_padding(False, lw) xpadding = padding[1] + padding[3] ypadding = padding[0] + padding[2] p = canv.beginPath() p.rect(x, y, self.width + xpadding, self.height + ypadding) canv.drawPath(p, stroke=stroke, fill=fill) canv.restoreState() BoundByWidth.draw(self) def split(self, availWidth, availHeight): self.wrap(availWidth, availHeight) padding = (self.pad[1] + self.pad[3]) * self.scale if self.height + padding <= availHeight: return [self] else: # Try to figure out how many elements # we can put in the available space candidate = None remainder = None for p in range(1, len(self.content)): b = BoxedContainer(self.content[:p], self.style, self.mode) w, h = b.wrap(availWidth, availHeight) if h < availHeight: candidate = b if self.content[p:]: remainder = BoxedContainer( self.content[p:], self.style, self.mode ) else: break if not candidate or not remainder: # Nothing fits, break page return [] if not remainder: # Everything fits? return [self] return [candidate, remainder] class MyTableOfContents(TableOfContents): """ Subclass of reportlab.platypus.tableofcontents.TableOfContents which supports hyperlinks to corresponding sections. """ def __init__(self, *args, **kwargs): # The parent argument is to define the locality of # the TOC. If it's none, it's a global TOC and # any heading it's notified about is accepted. # If it's a node, then the heading needs to be "inside" # that node. This can be figured out because # the heading flowable keeps a reference to the title # node it was creatd from. # # Yes, this is gross. self.parent = kwargs.pop('parent') TableOfContents.__init__(self, *args, **kwargs) # reference ids for which this TOC should be notified self.refids = [] # revese lookup table from (level, text) to refid self.refid_lut = {} self.linkColor = "#0000ff" def notify(self, kind, stuff): # stuff includes (level, text, pagenum, label) level, text, pageNum, label, node = stuff rlabel = '-'.join(label.split('-')[:-1]) def islocal(_node): """See if this node is "local enough" for this TOC. This is for Issue 196""" if self.parent is None: return True while _node.parent: if _node.parent == self.parent: return True _node = _node.parent return False if rlabel in self.refids and islocal(node): self.addEntry(level, text, pageNum) self.refid_lut[(level, text, pageNum)] = label def wrap(self, availWidth, availHeight): """Adds hyperlink to toc entry.""" widths = (availWidth - self.rightColumnWidth, self.rightColumnWidth) # makes an internal table which does all the work. # we draw the LAST RUN's entries! If there are # none, we make some dummy data to keep the table # from complaining if len(self._lastEntries) == 0: _tempEntries = [(0, 'Placeholder for table of contents', 0, None)] else: _tempEntries = self._lastEntries if _tempEntries: base_level = _tempEntries[0][0] else: base_level = 0 tableData = [] for entry in _tempEntries: level, text, pageNum = entry[:3] left_col_level = level - base_level leftColStyle = self.getLevelStyle(left_col_level) label = self.refid_lut.get((level, text, pageNum), None) if label: pre = u'' % (label, self.linkColor) post = u'' if isinstance(text, bytes): text = text.decode('utf-8') text = pre + text + post else: pre = '' post = '' # right col style is right aligned rightColStyle = ParagraphStyle( name='leftColLevel%d' % left_col_level, parent=leftColStyle, leftIndent=0, alignment=TA_RIGHT, ) leftPara = Paragraph(text, leftColStyle) rightPara = Paragraph(pre + str(pageNum) + post, rightColStyle) tableData.append([leftPara, rightPara]) self._table = Table(tableData, colWidths=widths, style=self.tableStyle) self.width, self.height = self._table.wrapOn(self.canv, availWidth, availHeight) return self.width, self.height def split(self, aW, aH): # Make sure _table exists before splitting. # This was only triggered in rare cases using sphinx. if not self._table: self.wrap(aW, aH) return TableOfContents.split(self, aW, aH) def isSatisfied(self): if self._entries == self._lastEntries: log.debug('Table Of Contents is stable') return True else: if len(self._entries) != len(self._lastEntries): log.info( 'Number of items in TOC changed ' 'from %d to %d, not satisfied' % (len(self._lastEntries), len(self._entries)) ) return False log.info('TOC entries that moved in this pass:') for i in range(len(self._entries)): if self._entries[i] != self._lastEntries[i]: log.info(str(self._entries[i])) log.info(str(self._lastEntries[i])) return False rst2pdf-0.102/doc/assets/manual.css000066400000000000000000000035631463013543400171500ustar00rootroot00000000000000/* Stylesheet for Docutils, based on voidspace.css. Based on ``blue_box.css`` by Ian Bicking and ``html4css1.css`` revision 1.46. */ body { font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif; } a.target { color: darkblue; } a.toc-backref { text-decoration: none; color: black; } a.toc-backref:hover { background-color: inherit; } a:hover { background-color: #cccccc; } div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning { background-color: #cccccc; padding: 3px; width: 80%; } div.admonition p.admonition-title, div.hint p.admonition-title, div.important p.admonition-title, div.note p.admonition-title, div.tip p.admonition-title { text-align: center; color: white; font-size: 120%; font-weight: bold; background-color: #999999; display: block; margin: 0; } div.attention p.admonition-title, div.caution p.admonition-title, div.danger p.admonition-title, div.error p.admonition-title, div.warning p.admonition-title { color: #cc0000; font-family: sans-serif; text-align: center; background-color: #999999; display: block; margin: 0; } h1, h2, h3, h4, h5, h6 { font-family: 'Lucida Grande', 'Calibri', Helvetica, Arial, sans-serif; padding: 4px; } h3 a.toc-backref, h4 a.toc-backref, h5 a.toc-backref, h6 a.toc-backref { color: #000000; } h1.title { text-align: center; } table.footnote { padding-left: 0.5ex; } table.citation { padding-left: 0.5ex } pre.literal-block, pre.doctest-block { border: thin black solid; background-color: #ffffdf; padding: 5px; } .image img { border-style : solid; border-width : 2px; } h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { font-size: 100%; } code, tt { color: #000066; } kbd { color: #101010; } .auto-toc { list-style-type: none; list-style: none; } .toc-root > ul { padding-left: 10px; } rst2pdf-0.102/doc/assets/manual.yaml000066400000000000000000000011431463013543400173120ustar00rootroot00000000000000pageSetup: {firstTemplate: coverPage} pageTemplates: coverPage: frames: - [0cm, 0cm, 100%, 100%] showFooter: false showHeader: false styles: centered: {alignment: center, parent: bodytext} headertable: colWidths: [20%, 60%, 20%] commands: [] parent: table logoimage: {alignment: TA_CENTER} right: {alignment: right, parent: bodytext} subtitle: {fontName: White Rabbit, fontSize: 38} thin: {alignment: TA_JUSTIFY, hyphenation: true, language: es_ES, parent: bodytext, width: 65%} title: {fontName: White Rabbit, fontSize: 96} mathformula: {alignment: TA_CENTER} rst2pdf-0.102/doc/assets/rst2pdf-logo.jpg000066400000000000000000001346121463013543400202050ustar00rootroot00000000000000ÿØÿáExifII*ÿìDuckydÿá.http://ns.adobe.com/xap/1.0/ ÿîAdobedÀÿÛ„ÿÀ©©ÿÄæ       !Ö9 ´uµw—×X1"56¶7W·x˜A2#”•vYQt¸aB²34qRScÓ$%U–Õ!1AQaq"2²Ò³t6V ¡±’¢s4TÔ5•Õv8áB#ƒ´uð‘Rb“ÁUµ7Ñr3cÓ”‚CS$ÿÚ ?ŸÀž<ê®l´ê-ù³.q<íxåVVš¨:ó=ÉØ:;§çǯ•øOÇ­+‰o;Xñ~/ˆŽïj’DeÛgnüó±ì¹óÛ²ûg“Z 5KŠ*IjÚס§ÑÑÓçÔÚ>è<x€ï×”Ÿs¹kÍ“÷‹Û«GÆÉÜ?Ú›oéCëöé}ûrÉ~F¶ç¡¡óË^lŸ¼^Ø}Z>0>NáþÔÛJ_·KïÛ–Kò5·= œîZódýâöÃêÑñòwö¦ÛúPúýº_~ܲ_‘­¹èh|çr×›'ï¶VŒ“¸µ6ßÒ‡×íÒûöå’ümÏCCç;–¼Ù?x½°ú´|`|Ãý©¶þ”>¿n—ß·,—äknz9ܵæÉûÅí‡Õ£ãäîíM·ô¡õût¾ý¹d¿#[sÐÐùÎå¯6OÞ/l>­'pÿjm¿¥¯Û¥÷íË%ùÛž†‡Îw-y²~ñ{aõhøÀù;‡ûSmý(}~Ý/¿nY/ÈÖÜô4>s¹kÍ“÷‹Û«GÆÉÜ?Ú›oéCëöé}ûrÉ~F¶ç¡¡óË^lŸ¼^Ø}Z>0>NáþÔÛJ_·KïÛ–Kò5·= œîZódýâöÃêÑñòwö¦ÛúPúýº_~ܲ_‘­¹èh|çr×›'ï¶VŒ“¸µ6ßÒ‡×íÒûöå’ümÏCCç;–¼Ù?x½°ú´|`|Ãý©¶þ”>¿n—ß·,—äknz9ܵæÉûÅí‡Õ£ãäîíM·ô¡õût¾ý¹d¿#[sÐÐùÎå¯6OÞ/l>­'pÿjm¿¥íÅžeqÇš}¾oÇ] :¨Ç­¿d1]md43ÖÙ½­ñ¬† eä¶L%K‹!ly$…“kR›p‘rì<Í´s,–ÙcvÒÒœ$¸g.˜ÉÅõÆZ>Ÿ·G^(I-jnõ{‚ßhåÞôö«6ììª;Zd§]Ô] t—e}²©ÊEdøënDYy 5 Œy´øgt”^°¶UÙBM(ðgœÚkžºj¿jj»ƒo¢×l]uc)‡2s”8Á¸íM³M“g2®a¶·+¬[BcÏŽ“2$:‡™ge¹Wš°¹§ ÛRì· ´WRÞ²®O]z.:§£uØ’âÑÆJBp‡,þ"¼:óï†Þ}·“9Î®Ó Î)àçB-cçc§¢²¶õá²:¥} ¹Ó7£â„«²{ .“€¿hóÖ!âYü3›iïãv_÷^ãYÒoÑOü­Ïø›?ܱ‹0úTmy}¹xO¹h÷>˜¼86Mr\jrßsÏqwmÛW*®iÆÊetÂl”Û‰4ȇ!(}…¡Ô%EUŸ›µf×¹m¶vYÕk£ÓX¸½8¡8ê¸ëž‹Ž®¨Ê2…„ã‡;óî3¼ArG óö?i‰f³ÇÈ‚K#!&¡‘6Ÿ ã®’‹ÖÁÊ»#(I¢Å. ó“MóÓLWí}W;ÌmayµfÄ×–2Ys&×YRãø¯TZ¶Ù7畲û‹rºÅ´%‰ñÈÔD‡Pó,ì·*sV4໩]–}Z+©oW\žº4ô\uOFë±%Å£Œ”,…‡,þ"¼;sç†Þ~·’¹Î¾ÓÎ+0³a±ó±Ô´VÖÞ¼3Do¦MΙô>(J»'¹âé0@¯Ú<õˆEø€Ö æãZ{ÁøÝ—ý׸Öt›ôSÿ+sþ&Ï÷,CâÌ>•ÖNAÕœàäF×Ðûa¹ñêløÕž^ãYC¦ÝÎšÕæúÊ=[T…-1¥¿\›Ûv3ä¦eE}Ö•Ýï’ÓpòÆÅO1nom¶ÉU'Tå ǧ†q^¥Ê:¥8ù%Ö©¾Bj3Ž”øëïËœ¼<÷[²÷‘ÉN¹fÓ͸tßE«Z²ñ,ÄÏwcY§ªŒgÁ FpÒuÙMkãÕ>hð»sðcsÛiíÃSØeãXá9µs/þJl\SÇSQ2Ln[©ò‘ù."ÏÎ`IíiÒþª—ù›žÙ³çOmÜ¡Ùå×ÓÑÓEëÃerÑqW- ´OU(N1²3„s?p=ÿrˆ¾A£ž¹ÿ42ñ&×¾prtÖT_ö]V¥ÙÝ^“ƒõÑŽ£Š7›QÃÞannîjMͦnÎ$ø†Ü §žãîbÙþ,ãí»?Ê`4â<æ žçy—“Ý‘ BPû Cˆ#xù»Nm{–ÛgeVº=5Œ¢ôâ®Èê¸ëž‹Š:§ªŒ£(YN8g¿nây Ä/!dr>ãñãÏYãäA%‘…“PÈÇ›O†Q×IÁë `Ýv'X£ÁÞqižyiší±©ìJ-”R[°µí”–ÊuÎRããÔ×,¶Hó˜{‹r¾Á´&=„t÷“Üq2ÖËr¯5asFº•ÙgÕ¢º–õ•rzèÓÑqÕ=®Ä’’N2P²WYüCøxçß Üûo%s­\x³âžl"Ö>v:z+jo^ÇT®¥·:føe¬\'=ËA€ûGž±¿ÏáœÜkOx?²ÿº÷Γ~ŠånÄÙþåˆp÷ß÷?xtçê9ë‘oóC/mûÛ;]eEñ_eÕj]¥6i8?]WYÍn~ n{m=¸j{ ¼k'6®eÿÉM‹Šxêj&IËu>R?"%ÄYùÌ =­:_ÕRõ£sÛ3¶|éí»”;<ºúz:c(½xl®Z.*å£á–‰ê¥ Æ6FpS=À÷ýÈ>"ùŽzä[üÐËÄ›^ùÁÉÓYQ|WÙuZ—guzN×F:Ž(LÞmGy…¹¸G¹©76™»8“âp2œZ{¹‹gø³¶ìü[)€Óˆó˜2{æ^OvD) Cì- ŒUàgæí9µî[m–uZèôÖ2‹ÓŠ»#ªã®z.(Ɦ2Œ¡d!8ážý»‰ä/¼…‘È\ûÇ=g‘–FBMC#m>G]'¬-ƒuØœYbyŦyå¦k¶Æ§±(¶QJ5nÂ×¶RXs)×9KŒS\²Ù#Î`Iî-ÊûИöÓÞOqÄ<Ë[-ʼՅÍNêWeŸVŠê[ÖUÉë£OEÇTôn»JI8ÉBÈY\9gñáãŸ|7sí¼•ÎµqâÏŠxY°‹XùØéè­©½xgRº–Üé›á–±pœ÷,]_´yë‹ñ¬þÍÆ´÷ƒñ»/û¯q¬é7è§þVçüMŸîX‡Ř}* .þñf»uíŒ?Ü¡Fרq±|¢I­ÅâËs2¹4UÚ,‰n¿Š>êÌÈÈ”ºå¨Ö‚6ÆÆnÞù;×/áï÷ÈþÏ.½]V¥¬«“Ó^WrÑ++m)$šq²5Ù ßÜÜýáÓŸ¨ç®E¿Í ¼I·ïlìmu•Å}—U©v”Ù¤àýte]G3¸e¹x7º.tæá¨48Ù½a†fpò[bbg!lÁÉñ©n‘’špˆ‘**Õç$’™x‰DF­gܶìí£:Í·r‡g™_Z댢õá²¹h¸ëž†Z'ª”'Ù Â=Nwßç!x‰ä 9ï‘oÖ/Hebͯ|`äð§<{⼫®»ຽ,ƒÑ´µ,Q°ÚžsrðsÑîm5vqgÄ6àeX¬ç^/Ÿâ«}·l1\¦KIIƒ(‘ÞeäöH…!(}…!Äм üݧ:½Ëm³²Î«]šÆQzqWdu\uÏEÅSÕFQ”,„'3ß·q<…âr9 Ÿ1øñç¬ñ²`—¾0²jókÔÊ:é8?Ql5®Äâ˸EÍÝ3Îý3[¶µ-—16­Ïð ),/*×9RØñ_£¼a®çþâÜ=´{åßGuiu¦¶_•¹§š0]ô.Ï:½Ô·¬«“×Fž‹Ž¹èÝv$”’q’…²¸rÉâÃß>øpçÛ¹'©â¢\SÃÌ„_½ó±õÒ7S'Õ%Ю¥¾:gêe¬\'=Å9‚@_´yë‹ñ¬þÍÆ´÷ƒñ»/û¯q¬é7è§þVçüMŸîX‡Ř}*ro׎æø×ØŸ¥÷o¹{õÀé÷8œYówƽÏýG'ݦeݼY®fŸÎîP£²6/”I5¸¼Yn,Ív‹"[¯âº³22%.¹j5 £q±csß"GzŒ·ž*;ÔW«‡BŽDRÑ&ÞŠ7E-!7¢’J»Š„êÞ¯^7wŸÛÌ9#ç~os9·ë8-l·l¶Çê²±cÒåL›âÊů麕ÛqÂýÅ‘è¯-‡ÑÜqÓò)!hq q§Zuµ-§Ø}¥¥m¸…)!D¤™¤ÈÏ^Ú”dá4ã8¶ši©FIèã$ôq”ZjQi4ÓM&Ž“v=ófæm›˜y{*ŒÝ6ˆ]EôÍYUµX”¡8N-©FIêšû§Àx~¨H;Ù«õ€fŸÃÄýàjQ÷kñ¢‰³î#æÒÍü²ààÿ‚Ü‰Û Š9Ä @æÇ ôÇ;4Ŧ¡ÛÕ~ÍùÅ– ÖÇaYV¹Ê”Áµ ÇäºIñsº–çAqEÂ1xnv(›q»gš9_š0}ï‘ýžezºnKYW'¦©­WsÑ++m)$šp²Ù åáûÄ?xrçêyã‘îÖ†¼Ì;$ý﮲¢ø®¦º]V¥ÇLý\5NQ•u¼ÌážçàÞç¸Ó›ŽŸÃy¿Ç Ì«š}X®ÃÅTúÚ…“c3]AxŒ¹ØH•fR`É%2òIDF­iÜvìí£:{nåÏ2½5ZëEëÃerÑq×= ´OU(N0²„z™î¿¾AñÈ4sß"_¬ÊÅ›^øÂÈÓYcäEu5×]‹Ô] 'Óij`¢3aµ¼8æ>æáæ¥ÜšnëÀ–LJ_–âV>¼W`â«}ÎÅòˆ-->|Çâ¦ZÏ& {ã #F¡‘6º$º§ê-†µØœ_EŠ\"æî™ç~™­ÛZ–ËÀ˜Ç›Vçø”–•kœ©lx¯ÑÞ0×sLjÿqn@žÚ =„r´ºÓ[/ÊÜÓƒÍ.úg^Šê[ÖUÉë£OEÇ\ôn»JI8ÉBÈY\9fñ áïŸ|8síÜ“ÎÔñQ.)áæB/ÞùØúé©“ê’èWRß3õ2Ö.žâ‹œÁ ¿hóÖ!âYü3›iïãv_÷^ãYÒoÑOü­Ïø›?ܱ‹0úTä߯Íñ¯±?Kîßr÷ê Óîq8³æï{ŸúŽO»LÅ#õËtÛm¼™‚Ä ŸÏîR´EÊe)K˜çf˜´Ô;z¯Ãy¿8²Á3ºØì+*×9R˜6£dü—I>#.wRÜè.(£XF/ ÎÅn7lóG+àóF½ò?³Ì¯WMÉk*äôÕ5ªã®z%em¥$“NB»!œ¼?xçï\ýO"yŽ{äKõƒÒX³kßYk,|ˆ®¦ºë±z‹¡¤àÚm-LFl6·‡ÇÜÜ ÜÔ»“MÝxØðëòÜJÁÇ׊ìUo¡ÙؾQ¥§ÇŠÿw¿B;$AIy•%iòÕíû†vÓ^å¶ÙÙæ×®Mc(½8«²:®:ç¢âŽ©ê£8JBŽïã¸~BñÈY‡Ï˜üTËYãdÁ/|adhÔ21æ×D—TàýE°Ö»‹è±K„\ÝÓ<ïÓ5»oRÙx#ùµn€YIayV¹Ê–ÇŠýë wrw¨ËxÙ⣽Ez¸t%’Ñ&Þ‰\’Òz)$«±¤¡:¾ˆø ñ¿»øxÝëäN{²üÎæs/õQõV[µÛd½VN4ze*%'Å•‹]Ó} ¶ã†FáHŽôW—B<7[ìí.Ô­&•¤–Û¸ƒSn²ëj%!i3BÐd¤™‘‘{jQ“„ÓŒâÚi¦šièã$ôjI¦ši4ÓM&Ž’vMïhæM£Ø2hÌÙ3(…Ô_LãeVÕdT¡es‹q”ešiŸáú€öjý`§ðű?x”_ýÚüh‡âlûˆù‡ô³,¸Åø?à·"vÃbŽq4÷›œ%Ó|îÒÖš‡mWxZ7ìð,öº3 ÊuÎVlQ¯¨Ÿw»ãF{±-Ï‚µ”{ßÙ¯º´´ëVÏ4ò¾4`ûÞ÷Ùæ×«¦äµ•rzjšÕq×=²¶Ò’I§ !]ΞüAs燧žy&Þ*ž•æaÎMcçck¬©¹.©.™Sr\tÙ꣪s„ëªæG ÷7÷5ΛܔÞ¶üoîþwŠùžì»3¹ŒÛýT}U–ívÙ/U•™KR|YX±õÝ7лn:ò7Dw¢¼äy ›o6}‹AöÝ"RT•$Í mh2RT“4©&FFddc_”dã$ã8¶ši¦šz4ÓѦši¦“M4Òhé/gÞ6®aÚ±·Ý‹&œÍ—2˜]EôÎ6UmVEJW8·BQiÆI´Ó>#Ãô€w³WëÍ?†-‰ûÀÔ¢ÿî×ãD?gÜGÌ?¥›ùeÀþ/Áÿ¹¶sˆi×7xE¦yߦlõ&Û¬ð&1ç6X[…åZç*[´O»Üñâ?ÜCsà8²a»‹î­-:Õ±Í<­ƒÍ*‹ßg›^®›’ÖUÉéªkUÇ\ôJÊÛJI&œ,…vC;x{ñ Ͼ9öžw䋸¨— 30ç'ï|ì}u•7EuItºnKŽ™ú¨ë8NºÞdpßsps\é½ÉMàKcİÄrêöß^+°qU¾¶ å¼çPŸ+ýÞäˆëì‘A)—’•§Ë­;ŽÝ´gY¶îUöyµéª×XÊ/^+–‹Ž¹èøe¢z©Bq…œ#ÔÇpÝüòˆ~BÇçÎCÈâ¦ZC'm{ã #Dç‘ú$ºá5ê-†–VÜ_F© 34›eÃ>fn~nz}ǧ.<7›ð«³:Å×ÕŠìÏ2½tzkEéÅ]‘Õq×=uOUÂP²œp§}ÂrˆžA¿‘9î`õž.T÷ÆFšC#o©®«+~¢èk ¦šjÅ.ócLs³LUíÝEiá¾ß›Öçx%”†•kœ©L²qü‚3FŸ—;ªr æÒQ¬#ˆßb‰ÆÛÙnWæŒhÁ÷Æ?öyµè®¥½e\žº4ô\uÏFë±$¤“MBÈY\9fñá÷Ÿ¼8óõÜÏë[âžd"ýﮑº™>¦ºµ7ÇLýLµN2–à ˜Á€@¯Ú<õˆEø€Ö æãZ{ÁøÝ—ý׸Öt›ôSÿ+sþ&Ï÷,CâÌ>•97ÇëÇs|kìOÒû·Ü½úƒàtûœN,ù»ã^çþ£“îÓ1HýrÝÛ¼YˆÌ ?žMÔ¶H‰ŠerÖgù=Ú}ŒÒ]¼}«^0µŸc/j«TÓÌ™ÅÜùÈqÞc-ãgŠŽóêáЕé-<º%jKHM褒„Þœ¯è¿ß[¯‡½Ö¾@çû.Ìîc2ïù¬·j¶Ék,œh­e,iI¹ebÅ7«–F<{nÒ¼¾‘è¯9CfÛÍŸbÐ}‡÷H”•%I3BÛZ ”•$Í*I‘‘™ׯ¥8É8Î-¦ši¦ž4ôi¦ši¤ÓM4š:EÙ÷«˜v¬m÷bɧ3e̦Q}3•[U‘R…•Î-ÆP”Zq’m4ψðý w³WëÍ?†-‰ûÀÔ¢ÿî×ãD?gÜGÌ?¥›ùeÀþ/Áÿ¹¶sˆuÍÞižwé›=I¶ë< ŒyÍ–ŸÖÆayV¹Ê–Ç„Åíî÷ma±ÖúèFËòÇ3àó>¾1ÿ³Ì¯EuMë*äõÓ§EÅ\´n»JI4Ôl•Ö>ÿû€çß|ý"óÍ=3ÄË‚~÷ÎÆâÒ7Ñ'öµ7ÇMšÂkÖÊ[v.S€ ý£ÏX„_ˆ gðÎn5§¼ÙÝ{gI¿E?ò·?âlÿrÄ8,ÃéPs“|~¼w7ƾÄý/¸}Ëߨ0~O¹ÄâÏ›¾5îê9>í3×-Ówºrpí|üæ.«âD|É:þÃnTí¶é2ç«ÎÒNI„ém‰±ñŸÂ°P´>õ$üƒq²~:!¼êš#q)#òO…jy'µ1(8¿»xq»s^>r ƒl¬yư¯’Fõm½sÆ¥ÔåŲP˜·ø®A‰ø3˜3mæÏ°û®%hI4Ö«¨&¤µF¿O@ntvñf#00 þy7RÙ"&)•ËYŸä÷iö3Ivñö­xÂÖ}Œ¼}ª­QÿLc2gsç!ÇyŒ·ž*;ÌW«‡BW¤´òè•©-!7¢’JzpN¿¢þ|qn¾÷ZùŸì»3¹ŒË¿æ²ÝªÛ%¬²q¢µ”±¥&å•‹Þ®Yñí»JòvúDw¢¼äy ›o6}‹AöÝ"RT•$Í mh2RT“4©&FFddc_”dã$ã8¶ši¦šz4ÓѦši¦“M4ÒhégÞ6®aÚ±·Ý‹&œÍ—2˜]EôÎ6UmVEJW8·BQiÆI´Ó>#Ãô€ {5~° ÓøbØŸ¼ J/þí~4Cñ6}Ä|ÃúY¿–\âüð[‘;a±G8€i¯8x=¦yå¦lu>Ø®(¶1JM–½ØU±˜^S®r•°M³uJó†9'¸†ì+ÜZcØGOu]ÇËÍZüÕʸ<Ñ‚©¹öYõjé¹-e\žš¦µ\uOD¬­´¤’”\,…vC<øxñϾ¹ö®uä«xñgà Ü)ɬ|ìtõuZ–¼3Ž­Ór\tÏÕGX¹ÂuÖ󇛛„{šïLîjC‹>)¹?Ê 6úñlÿ[î5)ŧºÚ<æ žçuæUÝ‘ BVÃèCˆ2Ó¸mùÛNu›nå_eVš­uŒ¢õá²¹h¸ëž†Z'ª”'Y Â=Lwß·!x…ä,~}ä,ŽºFú$þ¶¦øéž°šõ²–Ý Áà ý£ÏX„_ˆ gðÎn5§¼ÙÝ{gI¿E?ò·?âlÿrÄ8,ÃéPs“|~¼w7ƾÄý/¸}Ëߨ0~O¹ÄâÏ›¾5îê9>í3×-Ó¸^Íﮓ…Ÿï{ïþ—wh‚ÏXÈlõ¿íç,êåÒ7JuOÒ‡A~Uø'!0JùïiÜÌvv?9ÒT•aù‚c$¥ßë{ùd^uµOBy^w±ÒZ“ ¸¿@’›‹Õ\òoŒ›¯‡Û¯6ã÷ p› f`–Ò®a°làºj]^IÚ!%ÿ¿ˆE" èæ¦_e_ТRSPškUÔOMIjŒ== »Ñ»ÁˆÌA×ÙüôµX߇Êæ¹÷´S&¨/W—òi娊<…þ _‘_ýªŒãâî|äHï*[ÎÏâ+ÕÁh•é.A[´ŒžŠKHMè¡(}ð5ã‡sðû»WÝ÷xVß—ÜÎeßóYfÓu’ÖY8ñZÊx³“rÊņ¯Vò1âîí*ÉÛÉÞŠó‘ä6¦žiF‡YyRwú;HÒd}¤eÚFGÚ^A¯J2pšqœ[M4ÓM=iô¦ž©¦“MhúN‘6Ûkß¶¼}ïdȧ/g˦Q}3•[U‘R®Êì‹qœ'¥E´ÓM3â„8ƒ!­;†ß´çY¶îUöYÕiª×XÊ/^+–‹Ž¹èøe¢z©Bq…œ#ÔÇq=ûrˆ^BÇçÞBÈãÇžÉÆ›K# !$ç‘ß £®°šõÃK+n,ÕqHfcmø]ÍÏÁÏS¸tõ·a—ƒ]šáV/?ù+±1_.ËÆòH+ÊGå\Ih/9'±ÖúÉ]vÛ¹glùÐܶÙöyuõ>¸Ê/N*ìŽ«Š¹h¸£ªz¨Î‘„ã„{þî|Eò ü‹ÏTy牗½ñƒ‘¦‘¾‰?÷[SõCXMzÙFÅ>óSLs§LTíýAmØ¢ð+³ŒÅö?*µÖUಱ܊+Gå#ò®Ä›OØëGýt#eùc™ðyŸßÿÙå×¢¶¦õ•rzéÓ¢â®Z7]‰%$šj6FÊáË7ýÀs÷‡>~¿‘yꎎ™âeÁ?{çcë¤o¢Oì+joŽ™ë ¯[)mй ÁN¸½bó~’UÜi†éWsù›·"X·“eÖø¡cÅ­XÖÏD\%UT[ã´<éÂpœ$x~nžÎÞñöG©k©cÄô#õöËwÐsU|°eÞ‡ ”}.Íùþ×ô¶[»þƒš«åƒ.ô8;(ú#³~µý#í–îÿ æªù`˽Ê>ˆìߟíHûe»¿è9ª¾X2ïCƒ²¢;7çû_Ò>Ùnïúj¯– »Ðàì£èŽÍùþ×ô¶[»þƒš«åƒ.ô8;(ú#³~µý#í–îÿ æªù`˽Ê>ˆìߟíHûe»¿è9ª¾X2ïCƒ²¢;7çû_Ò>Ùnïúj¯– »Ðàì£èŽÍùþ×ô¶[»þƒš«åƒ.ô8;(ú#³~µý#í–îÿ æªù`˽Ê>ˆìߟíIÆŽvõ‡_=·‹{×`qÝ8Uóx^?„¦›ÛFºƒƒJ¶•aªëZXLó·×p²_öÎħ°‹ËÛù‡»zwíÚÍÕeÊ©Z£¬{5=b¡ÐøãÐÔWFzôù·ÓÞð¼5÷vû¹å—fÜ6׸]—Úå<•oñ®2öWB)T´õ:êÞ¯¨Ó/ù³Â¿d™GʽOÍ0ü_™úÿó Ñ_þS>}o=ò|—åŸ÷ç~’?æÏ ý’e*õ?4Áó?_þa/ú+ÿÊ>·žù>KòÏûó¿I59É×›fÙ†fä4×9–å9Nºô>rQwÖÒíU 2TÓ!1N_p–hA¬“ÛÝ.ÞÁ—pqcƒ…N”)ªMõµ¨¦ý¡ò‹sΞé¹dnvÅF̋쵥ԓsikÓ¢oE©ü°ª(Ná{7¾ºN½ï¿ú]Ý¢ =c!³Öÿ·œµÌSFuré¥:§éC ¿*ü˜%|÷´Žîf;;œé*J°üÁ1’Rïõ½ü²/:‹Ú§¡<¯;‰Øé-Ç ¸¿@õ7ª*¹äß7_·^mÇî@á6&ÌÁ,¥\Â7`ÙÁtÔº¼“´BJ%þ-ŠDÑÍL¾Ê¿¡D¤¦¡4Ö«¨žš’Õ zzw£·‹,3Ï祪æ’ÜŽøñɺx~Ý*îó¼;nËîc.î‡ê¬·i¶Ék,Œx­e#Ãôw³WëÍ?†-‰ûÀÔ¢ÿî×ãD?gÜGÌ?¥›ùeÀþ/Áÿ¹¶sˆiŸ98;¦ùå¥ìµ>Õ¯L;H¥&Ë]ì:øŒ;“댩llÜÓºâš9Uò´7c^·Â9wThq ¼Õ¯Í\«…Í*›ŸeŸV®›’ÖUÉéªkUÇTôJÊÛJI)EÆÈWd3ׇüùở©ç^LµÏ|5æáNMcçc§«ªÔµáœur¦äœéŸª\Qs„ë«å÷w7 ÷5æ˜Üôg ήv3“ACîbùî.ãî5_•â–¶ÙL®˜Mš\mD™ä%l>„:…$kF~nÕ›fÛ¹WÙgU¦«]bâõáœ%¢ã®z>hº¥FBpS]ÆwçÈ^ ù Ÿ¹#´Ä³HdcÍ¥‘‡’sÇÈ‚o†q×XÉk `ãer”$™«b”ÌfÞp«š›—‚»¢§pê2ZL™¬Îp{'Ÿ,[bâg!/KÇ2íšFFä)­§Î`Iìu³2ï¶å~×¹çlÙÐܶéðeCUÓÓEéÅ ÇUÅ h¸£ªz¨Ê.3Œ'âÃÿ!xä ¹žiÒK[12ëKß9<:Fúdú×õmªO‚êõ„´|2Š|0æ~˜ç.˜¨ÜZvß¾ÚüìÏ ±y‚ÊõÞVL%Ù˜ÖK ¥qÄvšâÊAiñ/2£#RS²ü³ÌØ<̓ïœoQ• µ7¬«“×N%£uØ’RI¦£8Îå—¿Îàùûï?_Èœ÷F“ZÏ* ûÛ;]#‘'ÖŸU•¿í)³XM&“{j.3 €ßl÷ó§o¿¨÷„꼤ÊúÈ& ÄÐá{7¾ºN½ï¿ú]Ý¢ =c!³Öÿ·œµÌS‘}]:Fé^©ÚMt7©®Áy ‚WX?¤7kP|I´’䞘dyÝö¶È&¸¿~ôUçq;%¶üp›‹ôSqz¢«^Kq§tqtfÚá6XÍÀ¬•Þ¢r|H³¢¹ÚåfCY¶^g}Œ_CîÈ>:–Ä–JIöö‘T&šÕuÓRZ£O@nôvñe†``üôµ\Ò[‡‰å“òQõcÐ_ÈWiž6fd˜ÒTfu†d…Ÿšvl]Ï|‰â2Þ6x¨ï^® ^’ÿrµ.ˆÉ褒„Þœ2‡Ñß~97OÛ¥]Þw‡mÙ}ÌeÝÐýU–í6Ù-e‘¬§‰97,¬X¦ÓrÉÆmÚÕ•·’#½ç#ÈmM<Ò6²ò¤þïôv‘¤ÈûHË´Œ´¼ƒ_”dá4ã8¶ši¦šz4ÓéM=SM&šÑô í;¶×¿mxûÞÉ‘N^Ï—L.¢úg*¶«"¥]•Ùã8N-J2‹i¦šgÄx~€tó¤Ï85×y5»vv+šæí¶¡ÊuãX4oÝ7i{“a7q¦ºŒ‚æŠàö£ã/!fO÷؃.ñ•ÃÊûä9{vŽã:ݱP”xSá~©uë£5 Æ¿‡žiñ1Ý7w¼¡›·àî”o˜ù®ÌÇr©×N>]R‚tÕtøÜ²"Ö±áÑKY'¢r:ûNœ>ý„rSü;Wüä ™ó³‰ù•Ÿõµ>T}P½ùü¤å?¿Ü?AiӇ߰ŽJ‡jÿœ€ùÙÄüÊÏú‹Úª¿?”œ§÷û‡è#í:pûöÉOðí_ó;8Ÿ™YÿQ{QõB÷çò“”þÿpý}§N~Â9)þ«þrçgó+?ê/j>¨^üþRrŸßî ´éÃïØG%?õÎ@|ìâ~egýEíGÕ ßŸÊNSûýÃôö8}ûä§øv¯ùÈœO̬ÿ¨½¨ú¡{óùIʸ~‚>Ó§¿a”ÿÕÿ9ó³‰ù•ŸõµT/~)9Oï÷ÐGÚtá÷ì#’ŸáÚ¿ç >vq?2³þ¢ö£ê…ïÏå')ýþáúûNœ>ý„rSü;WüäÎÎ'æVÔ^Ô}P½ùü¤å?¿Ü?AiӇ߰ŽJ‡jÿœ€ùÙÄüÊÏú‹Úª¿?”œ§÷û‡è&—ó›¬wMžzi› UµxñÉ8VðŠU–ºØµÔš¡Ì£\å.0MµmRë›%³—Y0ÛCv5Î-1çÇI%F‡PËÌÚÜÕÍû?4á*nò¬úµtܧ*äôÕ5¸꞉Y[k‹E(¸YNó÷€ÿyö®säÎiå;0¬á†v íÜV>v:zº­KðÙ\¨½':fõ\P••Î+®“Dë„ÂÜq’qdËŽ¶–][D£&Öã(uô4â‘Øf’ZÉ'ä%ÝêÃqUáoÛGù¾Ý.ªc'Óëg¹W5ÑÅ èµ] 4¥ÆŽñÜ/ ø„îß/“ùægUs».´½ó…“>¨›]OEjÙÝ_©šÕFQ³ðmñÈ}öÏ7úvûñÊqqèN«ÊL¯¬‚`œMî³{ë¤ágûÞûÿ¥ÝÚ ³Ö2=oûyË\Å1 Aõxé¥ú§és¨·*Ü ‘xlç4–ín‰*šSùJ³TÅGž_k{éŸúˆÿ~ýsëó¸ŸÚx­HŽq~ên/TU{Én4îŽ"nŒÛ@oü&ËÙ¸’ ÛÔNO‰tW;\¬Èqë6ËÌﱋè}Ù'ÇRØ’ÂÉI>ÞÒ*„ÓZ®¢zjKT`éèmæÞ ´Ì >ž†`²†¡byd×I(§BH›d2\?&?÷bÏÿÆytü˺¨x»žù;Äe»íQÝ¢µœ‰\’ÿrµ/['Ñ%êeýYGé'ŸÛ—p[•]Û÷‘mÙ}ÌåÝêeꬷh¶Ék+èŠÖSÜ›žV,”då“sºœ­º}‡£<äy ­—™Z›u§iZ“ì4¨î |”e 8M8Î-¦ši¦ž4úSO¡§ÒŸC:<Ú÷M·{Ûq÷›"œ½£.˜]MÔÎ6UmVEN»+² ÆpœZ”eã(´ÓiŸ!á\¯þ>¤÷޷ݬŠlßÈíüT½‹(7_Õy?³Ø2ÚѺGàA÷Û=üßéÛïÇ*=ÅÇ¡:¯)2¾² ‚q4-èûÓg§ÖØé“ó¸UÆ Ÿåúf¢ß*Ìó '¯ò›"µvÊÕ·lnn¬è¤ØXÍq¶’Fã®)fI"íò yÊJM&SñKWÒúßÝ:KõKt¿ÿOžÿ/ZÃѱ¼ã‰ùØú¥º_ÿ§Ïÿ—­aèØqËÎ8Ÿª[¥ÿú|ðïùzÖ‡¼ã‰ùØú¥º_ÿ§Ïÿ—­aèØqËÎ8Ÿª[¥ÿú|ðïùzÖ‡¼ã‰ùØú¥º_ÿ§Ïÿ—­aèØqËÎ8Ÿª[¥ÿú|ðïùzÖ‡¼ã‰ùØú¥º_ÿ§Ïÿ—­aèØqËÎ8Ÿª[¥ÿú|ðïùzÖ‡¼ã‰ùØú¥º_ÿ§Ïÿ—­aèØqËÎ8Ÿª[¥ÿú|ðïùzÖ‡¼ã‰ùØú¥º_ÿ§Ïÿ—­aèØqËÎ8Ÿª[¥ÿú|ðïùzÖ‡¼ã‰ùÙugNîèìò‡ii¾ñ¯VìœYVJÆ³Ì Màx®[B«Š‹ ~ÕU7ÔÔ‘, ¬˜øN'Ä!ÆÕÚ•¨Œå'ÐØÕ¾³rD'€ƒêñÒKõOÒçQnU¸"ð*ÙÎi-ÚÜU4§;ò•…f©Š<¾Ö÷Ó?õþýúç×çq?´ñZ‘&âýÔÜ^¨ª÷’ÜiÝDݶ€ßøM–³p+%A·¨œŸ,è®v¹YãÖm—™ßcÐû² OŽ¥±%…’’}½¤U ¦µ]DôÔ–¨ÁÓÐÛͼi˜}= Áe BÄòÉ®’QN„‘7Èd¸~L|¼ˆ‡1gÿã<:~eÝT<]Ï|‰â2Ýöˆ¨îÑZÎ D®I¹Z—Ddú$½L¿«(ý$ð3ã›rî r«»~ò-»/¹œ»½L½U–íÙ-e}ZÊxs“sÊÅ‚rŒœ²q¢îwS•·O°ôgœ!µ²ó+Sn´âM+BÒ}†•ýÃ!¯’Œ¡' §Å´ÓM4ÓѦŸJiô4úSègG›^é¶ï{n>ó³dS—´eÓ ©º™ÆÊ­ªÈ©×evA¸Î‹RŒ¢Üešm3ä<+€×ÇÿR{ï[îÖE6oävþ*^Å”¯ê¼ŸƒÙìmhÝ#‰p ûížþoôí÷ã•âãÐW”™_YÁ8šïô<õJð?â"“á[K?\Êo+ôßÝ:¬!q÷“½wºfð÷yç|qß[»"ÅvÖ·vŒ¾‚»Pí|¦s¹6+EšT!«Üo´¥œ§±üŽ#«ðsÂZ͵ö- IF«“Z£Õ>”º Êá8øÝÔT[n¾.fv9Ö»¤ÎmµÍÅž%”á’Ëhéq̂ʽ5Y}M5£¬³W•ÂY>–•›¦”¨Ô…y(¸½ãMt>³n 8ùÕû¤.œê¡¥Š®Äëp.GëêÛt–éL#[Õ’ïJsγ™y®/æxÍ.Ed…ùÜB5øìIŽq~ên/TUÉ7în%nlÛAoÜ&ÏÙØ šë®é,PKbK /ºöŠÅ¾Øw¸Õì3L˜ã)qåGZV…}Ò*„ÓZ®¢zjKT`ÑéèmæÝí4Ì =ž†¡²†ábY\ç’Ú*R’&âã™ ·””'?#pæ8¢*ÃìmÕy—up±w=ò$wˆËxÚ"£»Ez¸.…r_rÔºŸõÒá—õ\~’øñ˹w ºSÝ·y[•ÜÎ]þ¦oŠËv{l–²¾˜¥)ÏrnyX°NQnY8ÑwvÔåmË­:î0ûn2ó.-§Zu mÆœmF•¶âD¤- ###.Ò1¯²Œ¡' ¦¦ž>†šëMy:=Û·¿xÛèݶ›éÊÚ²©…´ÝTãeVÕdTë¶« Ü'\àÔ¡8·E©E´Ó>b°õñÿÇÔžûÖûµ‘M›ù¿Š—±eëú¯'àö{[Z7Hâ\>ûg¿›ý;}øåG¸¸ô'Uå&WÖA0N&€»ý=R¼øˆ¤øVàRÏ×2›Êý7÷N«@uâÉ *êñΛ2_ˆQvìlo½ÛÛØxn‰âŽßþQÑ÷{?£°UCÖ¯H_¬ÿÝ&Sì‡z±vñ´¿tZI·×}‚ úâS‚YzêûÒ LõOÓ'_`U˜$°ÉËÒ›­Mo×>³rQà¹ÑElæ^ë{Ù†fëDK‘W!g.!wüv$Ç ¸¿@õ7ª*Áä‡÷7·6m ·îg€ììÍu×t–(%±%…—‰]{Ebßl;Üjö¦L ñ”¸ò£­+B¾éBi­WQ=5%ª0hôô6ïHîæÔ <žÛ1™m˜8¦W9ä¶Ýkm¥-DÇ29n¨’Š4$‰¸3œ>ÊÒî°ú¼ÃÃr¿s×"ÇwŒ·m¦)n©k8.…j_rÅäÖê}:3égo;‡pû…=Ùw›uÙ]Íe]ýžªËv{l–²º˜­g<͹åbÁ9BNYX±v»©ËÛ§Zu‡\aöÜeæ\[N´êÛ8Ú+mÄ(‰HZFFF]¤c_eBNMM=} 5Öšò4tm·n;~ñ·Ñ»m7Ó•µeS iº©ÆÊ­ªÈ©×mVA¸N¹Á©Bqn2‹R‹i¦|Ä%`¯þ>¤÷޷ݬŠlßÈíüT½‹(7_Õy?³Ø2ÚѺGàA÷Û=üßéÛïÇ*=ÅÇ¡:¯)2¾² ‚q4-ßèyê•àÄE'·–~¹”ÞW鿺uXB&öú¥¶Érkšœs ®™q{{c¢––¢º;’ì--­lºº V”ëϼâi´š”¢"3`ÜÎáìÉ D‰Êþ5J—)æ£E‹zêçäIúÒÓ,0ËYJœyçœQ%)I”£""íðËÌÏ5FÊMAå?>øiÂZȶ\¥äN·ÓîØÄv}N={lí–sy•›ëÌn5Öw —K¸·a×>ÚVd“2Q‘ª-õÓÐŽrc>Ò—FÜšùŠù[2Ér ,[\›IïjJ\Q‘!oÛI×®:ûófù³H"ûõ'ÉÛg"./!Úì;Ãv~‹l]w“Òf¸&oCY”bn7aÖƒ#Ç®¢5:ªæ¢Ê"Ü6øo%ÆÜBŒ”•Ó¡ŸÕ€0îëä6‡ãv(¼çYéŒD–¦ZÈ6fiá•Ó$§»ÙµÛÙðŽÒÅÃZI£¯¸¥%fD=I¾ r?1ö’ú7a¶²)—Ëriq6¤½‡içU!eÙÿ§¼c\·KdÙ‘öø‘$>ßôw»|‚%\™ ŸÈZ›Úé¸ìY§Ç¹§ão8–ɱì=;^Ú”dI72]ˆbØšP}¿wÏÌ“ÿ{°r^CÇ/#:édøÖgE[”aù WŒÜÆDÊ|‹¶{Em ÎÒDºÛz¹«çFY‘ö8Ó‹Iö}ÑWYáî?ºÛ ¸óÎ!–ZBœu×V–Ûi´$Ô·ZÌ’„!$fffDDÅ™÷Ñø™,ò˪q¢o·Ä<ƒbbÄßgÝïÄbGgý£Ý™žjŠ}z’gp¶oP®rgÕV°oirž[rÓ¸«—²ËskeMãs+§Äqè³ ?DÜu2óKSn¶d´™‘ªŠÒ)zL}j&Ãì¦ò+ºŸ¦þÈÆ¶–õÓš×#“ËÝ—qƒ?ÙØNvýL­S£"Æ´f«"»®œít‰P_m¥³in2´’ŒÐ¢)6&åÑæ$Ùë‰2ο >–ÜdùzÕ~•‰|2ó2 Q”õÖäÔ;}‹IZ—jë}£رîäk¬ç͘§~rr6cV–m×»1¸Î)¤¼h7 µHÉ'Øi®³ÝL<Ç®¯½ ´ÏTý2uöY€òK¬œ½)ºÑÖýsë7% VÎeî·½˜fn´D¹rrâÇbLp›‹ôSqz¢«ÞFqÏqñ?rç}aVxÎ×ÖÎÕ^ÑØ¶fÓíÿæWÝÒOAy­Þ7{ H•|u.<¸Î!Ä(ÈÅBi­Q=4Ö¨Â#ÓÐÛ½#»šCP0<ò{lÆe¶`â™\ç’Ûu­¶”µÈ庢J(Ð’&àÎpû+KºÃêó Êü]Ï\‹Þ2ݶ˜¥º¥¬àº©}Ë‘ÿ[©ôèÏ¥ž¼tîÃî÷eÞm×ew5•wövz«-Ùí²ZÊêbµœðg6ç•‹å 9ebÅÚî§/niÖq‡Ûq—™qm:Ó¨Sn4ãj4­·¢%!hQv‘}”e 8M54ôiô4×ZkÈÑѶݸíûÆßFí´ßNVÕ•L-¦ê§*¶«"§]µYá:ç¥ ŸÊ-J-¦™ó•€zøÿãêO}ë}ÚȦÍüŽßÅKزƒuýW“ð{=ƒ-­¤q.}³ßÍþ¾ür£Ü\zªò“+ë ˜'@Ýþ‡ž©^üDR|+p)gë™Må~›û§U„ Ы~¬^¡?Á%tpŠ¹Ç­ze;4ö³hmê¯+\&li¬ ÚÀtÈÌš›])©‘\2#I™!öRt¾àª*ÕhYé×/® N½/‹`:1êL‹—›ß ’àЧ¢=­N ÀmÚ[ í\¦©ÎóV3¥ÉCÑñê÷ËÍæLŽô‰äh‹&žÕôõ#/H­_*Ê·‡(öÕÆY•Úl]뺶E¼‹+[)%ygy]³©5¯Ãa†ì-&y¼vûŒ°Ê<(ñÛKm¡ ¡)*Ž¢w©Šó#ú{Ž&r¶Åé³>=îœ Vg’QbXÛ¹ö°Íð¨6™Ic¦–¶<ü–޶*äOŸ)¶ÛI(ÍF¯!£Š>t\Ťµ…6‘Ó:“Lc²Ö?©5–¬éa²i”Ôà˜µV/\M6D]Äy¥Z; ³È)ÕêSú}g"úâu|£éa¡)Ó…×Sæ¡Ý ¸«ÓÁ­úcIY¶§bÑ!´¸IJ³[-­$²JÈû;{{ ¿ÚTºÏôþNäþŠãü2oÿ@5^r{ÆÔ Ð4÷::¨kseiE!ã½KIbùñ—ƒRHü¤$Ûä%O¦]oþ$ÑD’8áÖ£æœêŸ§<ÚO༓\ÓÒÛ¤¡®2ÌÜ–x|QTÛ½sw5FjI’jd¸râ™È*8MÅú±“‹Õcr+Ž»Š7Лï´À6~hºËê4¡Ô°.i§´j…wŽÝÂR$ÀŸnF—ĸڌŒT&šÕÓMjŒ$== ½Ñûµ”µÏ,Äv[f%•Ï} ±\Ûi&¢ãY,Ç)j‘)$·ÁÅk;ă(µØ·žùnÑ–ï´E-Î+YÁtv©yWÿq~èëÓ_¥þc¬=|ñõ'¾õ¾ídSfþGoâ¥ìYAºþ«Éø=žÁ–ÖÒ8—¾ÙïæÿNß~9Qî.= ÕyI•õL‰ nÿCÏT¯þ")>¸³õ̦ò¿MýÓªÂhU¿V/PŸà¿’¿º ¸E\cÖ½2œTT€áÇyS×[žeO’åÓ™6¦‚ëuíùu«‘EªµYK†ÓD«­CE\ôT×Ä© ª'P©r´udÓs$· š‚Ôé\tE›!éÝľžºÚºã>«¦ÅT6ʶ›®6–šÙ%OYæù̈鶴7¤’nFÅ\#Y¢$Xíö ©å'.²Km½_Y»°Ä–”Ì–ZÊû¦¶Ÿm´®â’´w›p”…wV’2í/!‘„PUþÒ–ìÈ·WNDTÛLqê'Y®tÖ jY¦²Ž“¦ÊnÙBT£AÜ÷/¸—Ú’OÞ¾’>ÓOiÔÁiN­zN‘û#œ(Ö;›yïÎZlÊ Ì¦Ïõö;§ê­ã3a›?ØE–O´ÏІÔÒo±:LU¦*ÞWx˜vÑ×ÐI}†D6½žr°´H%ŸðÈ”F•v‘‘ù ŒÈddã¦ÚèGÓ“mrÓVóf–®Äsý–ži”a¸S5ÔšŸq_DjTª+-“¯Û€å4«:l•ÆlÜ‘0Unó&Ý¡Mif’ŽZh{«ÓO!ØÁàƒm?ÖvÆÿ>eÿ¤"­uõ«Ò,]öC½X»?øÎÚ_º-$[ë¾Á*~¸”à–@pëÑóNuOÓžm'ð^ÉŒ®iémÒPŒ×fnK<>(ªmÞ¹»š£5$‰É52\9qÌäG•&âýØÉÅꊱ¹Ç]ÇÅ Ç›èM÷„Z`?´]eõ šÐê ‰Ø4ÓÚ5B»Çná)`OŒ·#KŒâ\mFF*Mj‰é¦µFž€ßi ÞÑ5_g¶ °Ã ±Ëg¾–Ú¯i´¥˜xÎM1å% Ò6„¥ºûEXD˜òø?Âv·sß"GuŒ·}¢)nik8.…j^UÿÜö}O§¯é_YýÅgÓ݇y÷]“ÜÞMÚUkâ²ÝšÛ%¬­ª+YÙƒdÛ–N4S•rrÉÆ‹±ÝNVۼ˱Ýu‡Úq‡Øql¼ËÈSn²ëj48Ó­¬’¶Ümi2RLˆÈ˰ƿJ2„œ&ššz4úk­4te·î¶®Õ}9;fM0¶›ªœlªÚ¬ŠvWd…•Ù¥ ŸÊ-J-¦™ó`¯þ>¤÷޷ݬŠlßÈíüT½‹(7_Õy?³Ø2ÚѺGàA÷Û=üßéÛïÇ*=ÅÇ¡:¯)2¾² ‚q4-ßèyê•àÄE'·–~¹”ÞW鿺uXB ê·êÅêüòW÷A—¡ë‘ìzצS*Š‚Ñ_f_†ø—újký°Ë0fìÞ\<½Éd 7Þ}¼m™V4šË nRšiÕ×cØÛ+š¦ÔFMZ[Î$©h4(SØõ–žbDž²dˆ²+ö¡ø¡™h~¦ùÆè•W/þò»Åö>~L+ði䘾+Žà›9¦…ÜÕ\Ò3fë}„h‡wü½¦b¦·¬}M­ôiåFèiÕÒOJ®@eS3lvÓ3ã–ô…ÐîZ*iyN?'•jî%±1(Òß ÊÓNA=™5î:Âg˜²'óL'%èžÎ<]+¬³s‹ÜÈã40»'Œ[§Û˜ËÑã==¼nÙ²Èñ—¥6—[­Í0ùÅ+Ã. *.Ø–â¿Ødd“I‘;‹Y'«¡õ›2< ÛOõ±¿Ï™éˆ«]ED}jô‹}ïV.Ïþ3¶—î‹A úï°JŸ®%8%ÆÎ±5Tí2qÖU'5õ\Åim̨J52£7%«_gÇ µM¸×W³f¢$»"¢S‡2"Tg"4¸á7èÆN/TU‹È^=n+nßCïŒ"Û_lý}låNC[6_ì'`ÛTÎh× ëº„´I>2Ü‹2+ˆu¥© # ¦µDôÓZ£ O@o´†ïhš¯À³ÛØa†Ø‰e³ßKmW´ÚŖÓ×ôÇÀ¯Ž¬þâ³éîüû®Éîo&í*µñYnÍm’ÖVÕ¬ìÁ²mË')ʹ9dãEØî§+neèÏ;CN1!‡eömM<ËÍ(ÐëN´²JÛqµ¤ÉI2##.Ãý(¸·&¤ž?!Ñ–~ëƒNéµÝVNÙ“T-¦ê§*¶«"§]•Ùá:ç¥ ŸÊ-J-¦™ò`¾?øú“ßzßv²)³#·ñRö, ÝUäüÏ`ËkFéK€ßl÷ó§o¿¨÷„꼤ÊúÈ& Äз¡çªWÿŸ Ü YúæSy_¦þéÕa4ªß«¨Oð_É_Ý\"‡®G±ë^™N@ª* {:&z§xü=b_øç iúöS¾·é¿ºu$@x–óÓ\~ê-Çûþ>rù”Ó+¬;1¥8Ñs]gšÅ"5^k…ZI)¨–°Ú”ãO2ënÄ×#ÈmÆœRDQ“‹ÕÚz®²¶.¢}yçÀK‹ü‚.kÈ®?ÂzDŠ½Ý§¨loNß}Ä¿²0H'e”kÉQc‘—ÞDªT,É-Xº}¤Sã8ËÓ'FÄúúÇ-s³¶NŸË+sÝM°3]cœS¨×S˜kü¢ïÉëMJB—æW¸ôêû8ÉZ›Oxé» ·´FFÒ}d”8]íYsÛ@V3É:|O˜ú!´ÃÓòbg^î(Ò´%)‡°±š·èîM†Mf£¸£Ÿ6Jû½éˆ.Ó9n¸¾®‚[­y ¢tèëIÁþ¥‘Û¡ÓÙ¼Ì#tǯr}¾‚ÚmÀÇ6;qâ¶kŸ?(óçÐçÔÑI*Zߨ—%øÌwW-ˆ¦²H•(8úD¶šë:Ð <m§úÎØßçÌ¿ô‚ÄU®¢¢>µzE‹¾Èw«gÿÛK÷E „‹}wØ%OלÈÔîjsSAðAå|†ä6VÞ?ˆãíœ:jhfÄœ³?Ë$°û´Ø6 Lëñ×u“].:»ˆï!ˆÌ!É2\f+/<ß©9=ôYT?SN£w©Ç&n¹´`UãP«ËÕšö™ »_k˜§Ôãï[”hÓrK—¥X=*ÂÆA¤L}~qã%ˆÌÔÆ*+B|c½žb" ÎzkMKØÒ×ut¹uX T¿7³³á·ay`ÛmHV3ŒªCO°»50ûk—-m»ª3¨uÔ:ó±"K³9Ü1y_‚6îöÇû:ü‰uv–iÒ žº-T¬’q‹INpÚO þùÛÄÿ;-›fSÃä¼)Â[–å(k^5o¥URz+ríIªiOÏeŽ5FR:µ6iŠÄxìǾ¶¢¶ syQëêi«ãTÔW2䧤Ëy¨še.>미Hï:âÜ5,õ“+*üÜ›32¤ç“lÜ¥'¢ÖRz·¢Ñ.ž¤’K©$º¤û·î÷–;¨äm·»¾L¦trÖÕŽ©¦3œ¬›\Rœç9˦V[dçdÚJõ=‘©É¦×Q Î¥ËG%¸­ŽäÛ‹‰d¾Vj z4뛼%Tˆ§ß¸•6‰÷¥1V.M6Ò„8§Ü¨(vgä𪖂[ˆ›è} ™?â"õ‡f9n»Ë1ìçÉ/0Ü׸ƒŒe8ÕœÊ\ƒ¼«‰Uöµ°bm}„)-¥m¸ÚÒ´¨¾è˜Li5£ê-^èAÔæwS.ÇÊ6Ûä>“¸‰¬·Š!1|’ÀëQ?ٰ뢥«¢çÕpä2Úe«x3ÐËhŽ–HSN¥Ðæ× tÒR†ÐxZðµÎþ'¹Ýl{–'áÊÜ·)AʬZ¤ú!Э˵&¨¡5®ŽË*„æºÓQ"CY[-M=DDWSS×¥ÄWÕW¶ë¯¦$D¼ëòâIãÏ<óŽÉ—%×dHqÙºêõ—;;/rËžvtÝ™VKYIùðI-I%’I$‘ÔWu]ÕrGrü‘‡Ý÷wøqÃåì8ú¶ëd—i‘‘f‰Û‘kZÙcK©B…p„#ÿE)‘_ü}Iï½o»YÙ¿‘Ûø©{Pn¿ªò~g°eµ£tŽ%Àƒï¶{ù¿Ó·ßŽT{‹Bu^Re}dâh[¿ÐóÕ+ÀÿˆŠO…n,ýs)¼¯Ótê°„ÕoÕ‹Ô'ø/ä¯îƒ.C×#Øõ¯L§ U½=S¼ þ±/üs…4ý{)ß[ôßÝ:’ <ðN6n)¢Z Ô¡)²Qx‰mÃZPµ#·¼HZ›QýÃ4Ÿû ûQžÑfŽÖš«?#qÝW]]Cf1° «gŒÔ³5v=˜lL2¦ÿ0b,XéB""òýç® ®Ä¥µY ‰²AL±é'VýNžc°~Æ•Ã[ÜU )ßÉùÚ§PYY¤»ÞÜUeÙ„Z%9Ø]Ï0®l{§ÛØjìþžÈmê^™ kìÿàOÀH%€#;ºªMèÛ´sP¦æSlüúª[kOuh“]•ÛC} O—º¤ºÉ‘—ô¬]ED}jô‹ }ü‚ îœ;·mÄ2³¹Rã’ûË(zkE.ºZ“Ø]ÄÈ‘_)´——·À3íòö‹}wØ%Yë‰\‰Dªs;™Úš,ä?!òƱ¼7kÍjêâør¬ï*’ÃîS`ø=3Ç]ÞQv¸ê&š%!–C’d¸ÌV^y¿Rrz!×кʨ:Ÿõ?ß]P·Ô½§´å»ëÌmÛ Í1¦+,“ŠëVKè3B Ñy•Ú#´åÅÃ!é¯!(BYˆÌhÌTÆ*(Ÿðúg5D@œ4Þ›™±æ.âárêp*™eÖÖ96Üû™í¶Ì…c¤2üuÛ.;í®T¥¶ìj˜Î¡çë®Ã‡2ÎæþoÄåŒM ›­‘þοµÇ=:Tê]mpÇM%(m…¯ \ïâ{ÖDZ©aò~¡-Ër”ªÅªO¢] Ü»RjŠZèì±Â¨NkÙf8pk+ Ä©§©ˆŠúzzô8Ü ¨ ¸ëÉ‹/:ü…šä>ãÏ<óŽÉ—%×$Hq×ÝuÕë6vv^å—<ìéÊÌ«%¬¤ü¿ø$–‰$’ŠI$’Hê'º®ê¹#¹~HÃîû»ì8áòþ} [u²K´ÈȳDíȵ¤ì±¥ÕB0®„BÈ ëãÿ©=÷­÷k"›7ò;/bÊ ×õ^OÁìö ¶´n‘ĸ}öÏ7úvûñÊqqèN«ÊL¯¬‚`œM wúz¥xñIð­À¥Ÿ®e7•úoîVƒ@z­ú±z„ÿü•ýÐeÂ(zä{µé”ä ¢ ·³¢gªwÃÖ%ÿŽp¦Ÿ¯e;ë~›û§RD€ŽvþÏÇô¦ªØÛ+…‘Xã:Ç É3«êüG²Ê²‰µX½L«‰±(1Úv$XÛÚÈb"Ë-§ï–eÞRRJQz–¯@UQ¹ºæó§9ê“sãYmíU­ÆñL[Ä–W8 &“©²zU§Éñ‰©U]S(\»G^a.H¸’üèÇïØ©P„åZÓGÖKW~Ö÷=->)Íš.,mD7$üÊš« δfI5EáØ2©bÜg8)Ê|»UÆØQ¢5Ú8D£L©T×WI„—¢Žñb½NºqfÕ鳯¹åÄ ñÔÙ:¶žäV§¬°Žƒ$¨ŽmM¶WÖ ö(¼2Ù‘ù>è–ã%ä Ñ®³G¹™í ôÍân ymïÜ'“{-¨R‹ÕÜzÉ+váë„6¤Åfë`㪵À1tIR<êD™Ë”†{ÊS‰ðŽ%\Ÿ¤z£'ÔŠÅy_É}‘Ì^FmîMí¹Qdgû‡/—”\³ n²¢)1¯ÆiÐêÜ}˜–5]®:·(‘ñµ÷”u h´'¥¢Ð°“ÙYàvSÅþæ\‹ÙtRqìû˜w˜ÖOÔØ°¸öp4žÚ>¸›.;ÝŽÃw0±Éíí›IIú¹>Ó2$ȲZ½“7Å.Ž¢Q¢YTW׌WœRê…ËL"¶T,{=Ù—»×^Ju¢D;LtÙLÎá*¥dEãÀÇ®­'Ò)]¥&©Ô™¤Ìê õŠdø=cémìúu|Äzbn݇‰ovoäqŸñÆslz ›Ë]i›bNY#ÏccÑrí¨Þ®¼— æ<&×=Ö|ÙöPúâ&3ÞNÃaP òWÞ÷;ÞA'‚~bVÌÿÜ{Â^§ü8ê’nŒw‰ÛÏb§E9†#0»™ˆäx…Löó¥e-ÓKÆË`S^ÛÁmì>co¾¨L´•]Å-.%CǰÓ]gA'€ªœÎæv…àf…Ë9È|±¬o ÆÚóZº¸¾œ«;ʤ°û”Ø>Lãñ×w”]®:‰¦‰He†Pä™.3—žoÔœžˆuô.²ª§ýO÷×T-õ/ií9nãzóv³LiŠËäâºÇ’ú Ѓ4GEÞevˆí9qpãHzkÈJ–b331ŠŠ'Æ<>™ÍAg 7§%ìyŽ\\9.§©•æö¶±É´X]Om¶d1Œ*C/Ç]³Œ>ÚåJ[nÆ©Œêyºì8s,þnæì^XÃèá³t±g_Úãž* úNmpůU(ì÷…¿ ¼íâ{ž£°ljxœ£‡(OrÜ¥*±*“zBè­Ê¹),zÖMJɸS]“Žÿ²Ì8pàÖVA‰SOSôôõèq¸Pqד*^uù 5È}Çžyç“.K®H㯺ë«Ö\ìì½Ë.yÙÓ•™VKYIùðI-I%’I$‘Ô_u]ÕrGrü‘‡Ý÷wØqÃåü8ú¶ëd—i‘‘f‰Û‘kIÙcKª0„a\!þ…!‘@õñÿÇÔžûÖûµ‘M›ù¿Š—±eëú¯'àö{[Z7Hâ\>ûg¿›ý;}øåG¸¸ô'Uå&WÖA0N&€»ý=R¼øˆ¤øVàRÏ×2›Êý7÷N«A¨@5^s¼ø1Ì=/¬iÑìm±ÆmÝ®°J,ªé›¹Ë³-s‘cøõc–×s+©«:Ö{M›ò¤3¢WyÅ¥$f^Åé$Ùêèz•µ}™Þ³¿Eæß;"£´‡œ›ÚD±w¥ö“Ù\oéõĽ¸±öñ]Ÿ«´ö=‰æøëW·íÔ^À\£• 8å…µŠPN$ÉØ²^i]¾E‘6œ›]DŸ+ôÍó€#—Ô§Ù¯á—9¬ïö¦¦tøÈ;§$XYå8Kcœ[¾·~~u«[•O öj~ΚUd—]qOËD×<‡265ÐúQdãÕÔC“žÍ¿Už8ÙX.ŸEÇäfä.&eǛ虪æ0Û†L¥X ’h6{sœcº¥6Ý3ì¥FiCÎvvœÕdY1Y/AÌK~ sz‚b«ïxoʪK9á. ¿¶ålÄ»ÿÃTi˜ƒ/%Ïû =¢-Q|èÏg£÷SÝùg·]ðs‘™.4ÛwY濵Ԙ¯ö¿qg—ídaxÁ¡ ò¨Ó,Í%ÙÚ^RíñÊ+­ž9ÅyIfô·öShõ^Wo¢ù&%³¯(eE¹Ç¸Õ„.M¾¹iã~û[-Ÿ³–c,›S”pbµTã­÷dKŸkŽ©r³É\¦ßBèDÐXaˆ¬33-G¦Ø†ÐË 0Ê ¶™e¦É-´ÓM¤’”¤ˆ’EØ^A$€ú€0õèåªú­jŠFÕwXr?WƱÿ„;qUëP¬Rl5öÁƒ»6Û·šÚ^mÆLæSÌ3“œC’âLŽqôSqz¢¼KtGê…Ŭ†ÆŸ7â&×Î)aÊu˜™öŽÆ­wV m¾ùµjÕ®¿…saGJ5!1+%§´‰ÆP£$‰êQ}Lœ§è¿Œp™¥£4ا ùWY¾úc¢%_6Ä¥¡ÃQ$üámâfÔF›íí[Ž©m$jQ‘˜õ´ºÏxãçDÇ=š˜I8KÉ-‹¹9 §ÓÚ/hi‹"Ö‡/ÌñeæöY4\É0Ëè¸V;c}k^u)…c ÄÚsˆnÁÅ%µ™$J²QkEÖJœ”´Ð›’@j×1ù¡¸%¡²îCò.gÂq†|ðdäù¶O%—Ü¥Â0ŠWaËܪõÆ–YJÓ-!Éf+/<ß©9=ëè]eTQº¡on¨›òVÑÙ¯»ŒkŒavZ[LÖØ=+Ö˜¬—Ò¥”ha»ÌÖù 4íźÚC³Bm,Äb4vjc¡>1á^‰Ìáfý9§&ly‹··\ºœ¦YGµµŽM·>æ{mµ ñœdä4üuÛ.;í®T¥¶ìj˜Î¡çë®Ã‡2ÐæînÄåŒO%›‹û:þ×ôéPOÒsk†?Ö”vsÂï…Þxñ=Ï `ر9OPžå¹NUbU&ôŒV©[•jRXøêIɧ9¸S ,@f8pk+ Ä©§©ˆŠúŠŠô8Ü ¸ ¸ëÉ‹/:ü…šä>ãÏ<óŽÉ•%×$Hq×ÝuÕë.~~^ç—<ìé»2¬zÊOí$º’K¡%¢I$–‡Q}Ó÷OÈýÊr>wÝßaÇ—ñ#¯N’¶ûd—i““f‰Û‘kIÎm$’uÆBºáúfGõñÿÇÔžûÖûµ‘M›ù¿Š—±eëú¯'àö{[Z7Hâ\>ûg¿›ý;}øåG¸¸ô'Uå&WÖA0N&€»ý=R¼øˆ¤øVàRÏ×2›Êý7÷N«@µÌ~cèn hl»ü‡Ë™Æ0œaŸ<9>m“Ée÷)pŒ"•ÇØr÷*½q…%–R¤4ËHrD‡ŠËÏ7êNOD:úYUTn¨Ûçª&ù“³vl—±iŒ=a[¥´µmƒÒqkŒIyå­]ƽͯ[a§-íÜiËu m´³˜ñÙ©ŒTQ>1áôÎeˆˆ€7éÍ93cÌ]½ºåÔàu2Ê=­¬rm¹÷3Ûm©Œã'!§ã®Ùqßmr¥-·cTÆu<‡]v9–‡7sv',by,Üì_Ù×ö¸ç§J‚~“›\1þ´£³ž|.óljîx[À¥‰Êx’„÷-Êpr«©7¤bµJÜ«R’ÇÇRNM9͘YdzË0áÃYY%M=LDWÔTW¡ÆàUÀmÇ^LX©y×ä,×!÷yçœvL©.¹"CŽ¾ë®¯Ysóò÷<¹çgMÙ•cÖRi%Ô’] -I$´:‹îŸº~GîS‘ðû¾îû8œ¿‰zt•·Û$»Lœ›4NÜ‹ZNsi$”k®0ª×У28ëãÿ©=÷­÷k"›7ò;/bÊ ×õ^OÁìö ¶´n‘ĸ}öÏ7úvûñÊqqèN«ÊL¯¬‚`œM wúz¥xñIð­À¥Ÿ®e7•úoîV€ÕÞbóDðWBæ<‰ä.XÎ3ƒâ‘ü(p˜6$d¹¦M)§•K„a4î¿w¹]óÌ),0•!¶›C’$8Ìf^y¿Rrz!×кʨ:£uFß=Q7Ì›³d½ŒkLaë Ý-¥«l“Œk\bKÈï-jî0ÝîmzÛ 9onãHv[¨Km¥˜ŒÇŽÍLb¢‰ñ¦s,DD»NéÙ›bí­—*«ª”Qímc“ho9 µ ñ¬hä4ó[8ÃÍ®L•¶ìj¨Î¡çë®Ä‰2ÒæÎlÃåŒ>)ifãb}zõÿÍ/*‚fO¡yZÙ þùçÄï<®]åÔñ9[Â{–å89S‡L›Ñ%¬UÙW(Écc)'cRœå]Ûm}e˜áÀ¬¬ƒª¢¦"+ê* !mÀ«€ÛŽ<˜Ñ’ë>³rCî<óÏ8ì™R]rD‡}×]^±î†^é™f~tÝ™6KVßÚIy] .„’Hê;ºnéù¹>FÃî÷»ìE‰°aÇ¥½%vEÒK´Éɱ(ö¹4“i$”k®5Õ ë‡èQ™ =|ñõ'¾õ¾ídSfþGoâ¥ìYAºþ«Éø=žÁ–ÖÒ8—¾ÙïæÿNß~9Qî.= ÕyI•õL‰ j?FžiðãéuÂ|3;åŸð¬ÃÒ”õÙ)–ï[ä´V ÙÛ-È7W9T+JɈJÒfÓí!dF]¥åÓO‰”Ï­úoî3úÀøôÜâ'ó'¦½3èü̬MÎ"2zkÓ0Ñù˜Xþ›œDþdôצa£ó0>°>ý78‰üÉé¯LÃGæ`}`| únqù“Ó^™†ÌÀúÀøôÜâ'ó'¦½3 ™õð/é¹ÄOæOMzf?3ëà_ÓsˆŸÌžšôÌ4~fÖÀ¿¦ç?™=5é˜hü̬MÎ"2zkÓ0Ñù˜Xþ›œDþdôצa£ó0>°>ý78‰üÉé¯LÃGæ`}`| únqù“Ó^™†ÌÁýv ÌN#mª«Ö|¦ã–ÅÍïŽbhðÜwë,»*¹Uu|»{ªÇ±üžÂÞÄàÕ@~SÞ +ð£²ãŠìBdуcG€ `æ0tGôF_È~Cåìb¸.*Ç…+^œ“2É$´òé°œ&™o0íöW|ë LxéR[m´¸ûî3—žoÔœžˆuô.²ª^©S7¿Tmï#cìy⺷~Æ»JiJëdãzç’êIRd¨’ÃWÙÍóL4å½»%É%-4–b2à TÆ*(Ÿðúg0ÄD@›´î™±æ.ÚÙrª°J©EÖÖ96‰ÖóÛRÆŽCO0峌<ÚäÉ[nƪŒêyºìH“-.læÌ>XÃâ––n6'Ùׯ_üÒò¨'ödú•­˜ð¿áž|NóÊåÞ]O•±'¹nSƒ•8tɽZÅ]•rŒ–62’v5)ÎUÑ]¶×Ї ÊÈ1jª*¢¢ED8ˆ5Pã&4d¼ãï¸n>û<óÎ;&T—\}÷}×^²n;Žfë™<üù»2lz¶þÒK©$º] F÷KÝ/#w#ÈØ}Þ÷{†±6 E«oI]‘t’VääÚ”]Ù8§9´’J5U鮺áûFI×ÇÿR{ï[îÖE6oävþ*^Å”¯ê¼ŸƒÙìmhÝ#‰p ûížþoôí÷ã•âãÐW”™_YÁ8šÜ/f÷×IÂÏ÷½÷ÿK»´Ag¬d6zßö󖹊b@k0yƒ¢8/¢2þCò/cÁqV<(±Zð¤ä™–I%§—M„á4Ëy‡o²»çXRcÇJ’Ûm¥Çßq˜Ì¼ó~¤äôC¯¡u•RõL꙽ú£oycÈÕ¸«ö5ÚSJWX»'×8Ü—RJ“%D–¾Îoša§-íÜi.Hq)i¤³–j¦1QDøÇ‡Ó9†"" Û§tô½5Ë[g%U`µ2‰‹[Hþ'ÛÍBxÖ4r}…Û8ÃÈ\™KmØÕqÜKÏ!×\‰e§Íœ×‰Ë\rÒÍÂÄû:üÿóKÊ ¼¾Y>…åkeü/ø`矼ô¹o—Äå|G î[”àåN2oD–±Vå\£(ãc©'d£)ÎUÑ]¶×Ї ÊÈ1jª*¢¢ED8ˆ5Pã&4d¼ãï¸n>û<óÎ;&T—\}÷}×^±î;Žfë™<üù»2lz¶þÒK©$º] GwKÝ/#w#ÈØ}Þ÷{†±6 E«oI]‘t’VääÚ”]Ù8§9´’J5U鮺áûFIõñÿÇÔžûÖûµ‘M›ù¿Š—±eëú¯'àö{[Z7Hâ\>ûg¿›ý;}øåG¸¸ô'Uå&WÖA0N&€w Ù½õÒp³ýï}ÿÒîíYë ž·ý¼å®b˜k7.ùw¢x;¢sCò0‰`8”~ãM#“åÙ –žU6…Ó)æ^¿Ë/ÞeH JR”­÷ÖÌf^y¿Rrz!×кʨº¨uLÞ}Q·Ô­°¤JÅ5N)"»IiXV.JǵÖ5!ÔåKR‹Üë m†Ü¶µ[iqõ¥,´MDe†[©ŒTQ>1áôÎ`ˆ€5éý?7cÍ]¥¢åU`õR‰‹[V ´Mµš†Úxæ8ry‡-\aä.L•¡Èõ‘ÜKÏ%Ç\‹]©Í|ׇË}¥šO>iöuëÒßüRóAy_—©tõl¯† <õâwž£Ë\µ‹Ë8®Ü·)ÁÊŒ*$Þ‰-b®Ê¹FQÆÆŒ£+eNr®Šîº¾€Æ (5upbÕTUELª¨)q«¡!Ç(ñÉ×}Å8ûËuç[’$ÈqÇßqÇœqÅkå¹fnù“ÏÏ›žLßKò%äIy"º’]GQÝÑ÷GȽÇò.'wÞb,]‡k)=%~MòI[••jQwd\â¸ç¤cÆU 讪¡õ&K;[Ð_DéîCsc Á7~ºÅ¶~BçYæ]ZÝ¥SW•ù^½‡ Ñœ2ILÊB¯èKª/éW&mX;Ï0U…¸ÁÙŠã6â¥8jÔ0”_Ø×Cç÷ÒKÞ7=w_á÷™;½Ýs6}ú|ˇC¿Ç]Ž™ãæÊu¹/êÊUÁµçŠóÚÛ]0z|Sj­™oWÄ=!Ϋ_fvUÓ£añ‘|rÊT9l8JíCÑä4•¤ÿ¡DC)s"r¶/çeãcJaÝ8I]~±”k”¢Ö¶éÐÒgÄ~Jñâ{?œ¶ŒÎyæ0îÜñkœ%•'Bw×E¯*”[OÐeo\Ÿhñß–ûb°ô™R^nÅ| Ãö\ó‡˜Säªâ"s°ÔG…»ÈÛvM¯vÅÅÙè§Õ9[ ×8g4©j¸éZz×~­AIôtµ©ö÷è¢æ®÷9çšw^uæ ßtäíº8˜¸”fdÛ“dZíºéU+œçʨUÍCKõáÕ&EÄcãìQëãÿ©=÷­÷k"›7ò;/bÊ ×õ^OÁìö ¶´n‘ĸòëËÑ÷rud­âôI´õž²V‰¸åß¹±™Ê^MÊvCÁšÄS–3MldpoøÞþs}Î÷ßwc„”uÔŠ2áz‘ÖûÜËúVq“ûŽÔô8Lícè‘vÍöÿ }Žneý+8ÉýÇjz¬}Ú?7Ûþö9¹—ô¬ã'÷©èpv±ôGhüßoúØææ_Ò³ŒŸÜv§¡ÁÚÇÑ£ó}¿èc›™JÎ2qÚž‡kDvÍöÿ }Žneý+8ÉýÇjz¬}Ú?7Ûþö9¹—ô¬ã'÷©èpv±ôGhüßoúØææ_Ò³ŒŸÜv§¡ÁÚÇÑ£ó}¿èc›™JÎ2qÚž‡kDvÍöÿ }Žneý+8ÉýÇjz¬}Ú?7Ûþö9¹—ô¬ã'÷©èpv±ôGhüßoúCss¤oÀíÒÞŒÚû§Éò—0ê,Õ6z÷·± *Ì‚M¬X‘ŽFIi‹ØùûNT8n'ͼ2%'ºµ™…½÷‹µì{›]ô_;ªáÕǃOU5¦²×ªKȺuôÍãðõà/½Ÿ<€ûÅä½Ï—pöuŸv'g›vd.í)r”¸hÁȇVÇ…öœZ§¬WFºƒÿ*u´yÿÿ Óqù?;{7æ¹?íŒçõGx†ÿϹ3ÿÙÜ¿uùS«ý£Ïÿøhþ›‡ÎÞÍù®Oà{aõGx†ÿϹ3ÿÙÜ¿u»šc/áyŽY‡J’ÌÙ8žM}ŒÈ™ m‰oÐÚJ«zK-¹ý¢}Ȧ´’¼¤F]¾Q“𲡇Vmiªîª3Iõ¥8©$ôÕk£éѳåÞåƒnٸ߶Þã+ñîRqׅʹ87Rz6º5IéÖ‘üÈ©(Žá{7¾ºN½ï¿ú]Ý¢ =c!³Öÿ·œ³k—|»Ñ<Ñ9‡!ù˜GİJ?q¦‘áIÈrì†KO*› Âé”ó/_å—ï2¤FŒ…%)JVûëf3/<Ý:NODHëè]eTýTº©on©Ùýƒ°_‘‰j\JEŒ '¤àX»'רô—R•Ïž´¥†oóÛöXmv¶«m*uIK,¥˜¬²Ê*cOŒx}3—b" ÍzOÍØóWih¹UX=T¢bÖÕ‚mmf¡¶¤9ކžaËWy “%hr=dwóÉq×"Å—js_5áòÆif“Ïš}zô·ÿ¼Ð^Wåê]=[+á‡Ã=xç¨ò×-EâòÎ+„÷-Êpr£ ‰7¢KX«²®Q”q±£(ÊÙFSœ«¢»®¯ 1£B ]\µUQSªª \D*èHqÇJòÝyçVä‰2q÷ÜqçqZǹnY›¾dóóæç“7Òü‰y^H®¤—QÔwt}Ñò/qü‹‰Ýçw˜‹aÅZÊOI_“|’VåeZ”]Ù8®9éÆ1…UBº+ª¨}E ’À@¾Í—¬'þö7馯×w©ü]žÁŸ2~–/勸³ü.àMÇvþ¦vçÅŽ}ú+l3‡5üWܾ‘î39íîûãîÉþ¯‡þ"²¨‘ª§iAzSëš«ÔO‰8}ädL«-³[–ʆéw˜–ZæºÏb3C}¤—¢¿#B]m]©q³4¨ŒŒÈÿScÅy»Þ.‰Âytñ&“R‚².È´ú4”¢ý>Ž“X¼góVw&xZç}÷m›¯7ü’ÌhÉuÇßÖW„åä’ŽCq’錴i¦“,¿jrJWKÔ{¨ç)w?.÷RéwvÐÁuæ²òüZá86s‘â4Øæ{/¯´r=>­¹™ òj¼þd¹4‚}ói ´„j~û¾åïû™×Û9㻪 µW«ìøaÄãðpñÍhç%Äü‰u=áO¯sœƒÜ/¬þ^Ù÷.hܶŒl¼ü¼¼J2n¶üªc|ëS¾8SOiØÕ\8`á9EÙ9Éó¯moMɾm1ÛÍÓ³s]§yŠcpÊ ÌîþÃ%ºƒŒA±´¶‹RvöI±–Ë672\%¾ã®™»Øj4’H¿*ë²2,ír­¶ÛtÓŠÉÎÆ¢›j)Íɨ&ÛŒ‘ޝDµfÒòOw<‡Ý¶VÝÝþÑ·ìÛvnd²®§˜QTò' ë•j0‹pª¸éÆ>§Tµm¼R%—¡ëãÿ©=÷­÷k"›7ò;/bÊ ×õ^OÁìö ¶´n‘ĸ+ö=b~ 5ŸÃ9¸Öžð~7eÿuî5&ýÿÊÜÿ‰³ýËàx³¥@ÎMñúñÜßûô¾àm÷/~ Áø>ç‹>nø×¹ÿ¨äû´ÌR?\·N ôeäΩáÇR.>rcwZͧÖ:š³zÝärjëÞµ¶–õ‡¶æ=ÑÓ×2i󫜗&¹…].-¦<æR çZh–âa’Ö:"¦ã¢ë?}Tº©on©Ùýƒ°_‘‰j\JEŒ '¤àX»'רô—R•Ïž´¥†oóÛöXmv¶«m*uIK,¥˜¬²ÊŠŠ¦rìDD§Pj »r쬗*¯«”LÛZ°HDË9hCož=Ž›í<Öΰêü…¡Æ+Xq.º—r4iV·5sN,av¶é<é§ÙׯLŸù ¼¯ËÔºM’ðÉᓞ¼NsÜyc–bñysÂ{–å89Q…D›Ó£X«rnQ”qq£%+eJR®Šîº®Æ (5upbÕTUELª¨)q«¡!Ç(ñÉ×}Å8ûËuç[’$ÈqÇßqÇœqÅkå¹fnù“ÏÏ›žLßKò%äIy"º’]GR=Ñ÷GȽÇò.'wÞb,]‡k)=%~MòI[••jQwd\â¸ç¤cÆU 讪¡õ&K :Ñ{1ûÆò’ží®Pj–¸ª¯´m‡0̽N2Ý„Fe¡¥©2{ª[ixˆÌ¼†d/¬>í¹«3¬Êå·ªí®3IÝv©J*I=1ºúzO»ÒïÝæÝ¸_·Ï“÷™N‹§[k+Fá'שêzjr;é™ÊÝ¥ÊMµÅ}K‚Jβ=3±2l 4ÏI·(µ½+8õäÊ–2[̞ȼʞ ìH¾{ ”í”–dÌwV•$­\m§rÍÜ­Ú0*y…6λoXÆUÎu͹ÏFUÍFsàSkH§&¢÷w}ñuÜ·'w9²wËÎÛ”6í¯~Úñó1põWgZïª6JŠqáêí2“ªÛRšÖvÂ-7ÞÍUì¼Öy;»•SË%}¤*U6¬À£~¬xП–2L²Ôç]¶Nvö8ª¨eÙ÷ƒ"cwK»[Tg™MÝ:ÂNåè5c²‡ÕÖ».‡ýf|×ç?¦7üÆUw{É•”žwÉv¶-z£µ žšz•‘wOõŒeÈ?f7bcÔ6¼iä%FƵ‡O±¯ön0œÆÈÚï-q«3j«{ªWl$£±,·2|o¿´’„Ÿy4»u›î®ôæØµn/Miêc+-„¤ß[•E//GMß݇ÒñËžãVÛÞß,_µaÙ=nßòá^½R³ÊêµB/¦Rªë§Ãëi“ZJ2»'Zgúw9É5¦Ñį0\ó±r«#Ų(N@´¬šÚRâIÆ—Ú‡£IaÄ=ö”¶$°âikmiYã{!eVJ›c(]¤£$ã(µÖ¥“MySIŸ]9O›ygžùw›y;;qå¼ê•”dQ5:ìƒèèk¥J-8ÎJuÍJŒgü0„¸õÀ:Öt*º¸Rì¬ì¥Æ]]3Ó'O1äG‰ HèrD©r¤8–Ûm´©kZ‰)#3"JQ„\¤ÒŠZ¶ú’ó²FNN65™™–Bœ:a)Îs’Œ!§)Nr“QŒcܤÚI&ÛБ_½œnIîJ ¼×‘YåO(­Yfl<5T+Î6šáº‚u¿Ãt­[QPâÈiiìiùÒ§0®òdDiiîû²÷sÌ;½K##ƒQÖ.ØÊVõ&›¡85«MYevE§­}Zü±ï·éW7+¹ºÍ¶þlÜi“Œ²»e‰·©'£ì­uÝvJ‹×YBªêšÑ×tâøä˽—mlýéÀùeœVdˆk½ì»[ÐÞQ¾òLÂ~-6COˆÓÄ]ß/>mö÷»‹ìîŸîϺ<øÇŠ•3’OÔ¼iAIéиýñ>¯[à›ÓÈk¶ÇôÃsm{Œ_2rVÝvÒߪXÙ×Sr^u+i¾k¯…Æ*]\Q׉Ò“§Ç&:|u:j‡tcæá™¶‘Ú”8n×Ä\•m¯r·bØâ7ɀ͛Ñ"J¤È|Ò‘nª¶Á˜ÒͶÖãIu”ø§ù¼«´îÜ»Îø˜[­.¹Ø­Q’|UX•6Iºç¢Õ'˜ÉBÄ´s®*QÖæñ¡âºOÞ¥¹r\ëßöþaÛ®ÊÛ²TkÍÆR¯&ž7Z”£uV¨«é”ëâqŒÜ,’)­Ûú™ÛŸ9÷è­°Ì|×ñ_røG¸ÌøßÝ÷ÇÝ“ý_üEeQ#UNÒ ‰tÑè]È>1rkBò§`mí7kE…µuIÄðåfÖVÓYËõÎIŽDŽÄû¼_†Û±É[uÃR{ -(‹´Ì†Tå>Eæ }Óz¾X徦ßSmŽÞGX®DaÅÒ“]®‹§G-:~xµúF;²ï{º>eîg–v-úÃ>UQœ¯zB¸ïö.æxØ›æÏ…¸B©µ)Õ Üjòc\åS)B6(É®†Ók Åœ¼O_ü}Iï½o»YÙ¿‘Ûø©{Pn¿ªò~g°eµ£tŽ%À_´yë‹ñ¬þÍÆ´÷ƒñ»/û¯q¬é7è§þVçüMŸîX‡Ř}*ro׎æø×ØŸ¥÷o¹{õÀé÷8œYówƽÏýG'ݦb‘ú庚u ±ç.ÊÉrjðš¹$͵³$„L³˜„6ùãØñ¾Û¬9jã¡o¾´8Åk%×RãŽF*ÖæžiÂåŒ.ÖÝ'4û:õé“ó¿4•ý…Òl—†O œ÷âsžã˱‹Ë˜®Ü·)ÁÊŒ*$Þǵɷ†QÆÆŒ£+eJR®Šîº®E‹º ª¨1ªê*ã&]\$­ëá¡n:L²N¸ëî-ÇÝ[¯<êÜ~Kî-ç–ãÎ-jÖ-ÏsÍÞ3gŸŸ7<‰¿°—’1^H¯"ÿÇVuÝt‰Üo"bwyÝæ"ÅØñW¥-%~MòI[••jQír-á\sÒ1Œc ª…tWUPû 'l®¾üÂÂ?Ê×ÀІÚl_©0þ W¹Äâ“™þ2î?¿Ýfk%9GÅŽk듸/qÍs]•_YÜ3GŽÓÆw5Ù¹¤Ô0»7ê1Ê–š°É¯ä¥,”¹ï÷XŽß†©Rh’¢ü­ÛxåÞM¢w[W~M“·²ª1VßgCœôÖ)Éú•+l”b›„e4åò¯tÝÎ÷ÉâS™èå>EÆÊÝr°ñ«©Û}²X¸°ÕV­¾ÆáL}WgL5œåÄ©ªsm>Ìö¢u2£‡_ÄÝ‘+óŽéd36F1*8ó/ðæ1ë‚‘áù|/æžß'‰Ùåö}îä«Z¯l­ÓÅÐÞSRqó¸¬f”¿åâkþo)ôz¡çž¥³vù<ë´Ã˜8ú1ÁÈž?^úwBέïMtéáòâo-ô§4õ^éÑy ÷̹’)î*­b¦·(ÃòX-0õ†1•ÔòJºÞ#2št»Ž½Dw›y‡]eÄ8¬ŸËü÷ó&¿px£¤¸g ¤§ hž’ÑÊ/TÓN2”_Vº¦—̾úû‘ï¸y»;ÆÅ¼+µY\»L|ª&Ú†F5ºGŽ©8Ê/XÆpœe]…‘”W=¡N Ðnn8Èå–E¿ÇØÑʧAŒÚgfnTôǹd´›G%Ü u[ÅuÅ+Íà•‚•¨îØèrýVbG˜ñÖ™8Âí5õp›Q„šQmÎq޾¥vs“›j¸(ï‡Ñâ/sä.õ£Ü®ý“9r73ÎK“pÆÝ#*§ZéáY‡½¬ŒtãµãI´¡-`Ä0‘Ña0Ÿgƒ§N9G<¶Þ:ŦKucmMÇšÛhÉz>;KQ!úl‹f3CfŸÃ¶ÖìI®¬xÈ•,gÞo½çM-¼¯Ý§,U›cæLøñcÕcŽ<^Ž.È?WsëâìåýiéÁll“‹”jœ~ý(Þ)÷[wÇá»’2¥NÑUvïvU-%}¶E[F”_ÿFªÜ/ȇU–Y]rÓ±”e%÷¿5?5fQ¹·V] À1(ÈzÆÒZ]‘&\¹ &+©©k"¡Ù÷7¶Ò”ME‰ uÕŸÜ$’”œ»¼ï;~Ã-ÃqŸ )¤’é”äú¡ùdôoÈ£)ÉÆ”—É~í{´ç^÷yË»¿Á³?™³¦ÕuÇHÆ1ŠÖvÛdš…T×ee“j1^]ZN9wÞÔ6ž‹–¿â–ƺÁÛ”¦ÙÉm¶67A’¿+4”¯ÈèØåýsN-J&Žëú{ D1E½ïdö’ì6È:x½KžSŒœ|òŒq§ËþU9­¬úϪ;oÐ÷Ï—l‘ÉÝyÏiÇæÝàßu Zzß}JêfÒ}KÑHìçz’ñwŸT“¤i|žuvoA ¹ùN¨ÍâE¤Ø8ôE©¸ê´M|y¶×´E!ô´s«eKa¥¸„,sïÑ[a_Í÷/€d{ŒÌ1Ý÷ÇÝ“ý_üEeQ#UNÒ ñp£®yA·tǰíO»hs<ʹü~þMo‹+Á­r)ïLv¯5²µ&$ÄÆÞC=È«Q¸´w‰%Þ2Î\¯ÏôeO bxÓœ«5¬`–ºp§£kÓÓýÇ5^ ¾Žžõ{Ÿä}ÿ¾=÷zåü‡Õté¢Y"QÉË®ˆ(«1k¯XÊø¹kb\*Z6ôO¼C+Ÿ7Hëæ¾Ò_ð|Ç-¬´‡"¥Xáù5ö->TÑP¤ÍÇí%TÊ~ŸØl>¨¯?JlÖ„,ÐeÚ’? Äïs Ø++·³’Mk8§£éZ¥£óô¿MŸS9èžï¯˜¶`Äæ.V†.~9ŒçŸÇ]\lŒe¦\II)hÚ×]]$4¹5³©÷o$y¹ñèUXþÜÝû_gQÖ]&*.+©óìòÿ*¬lˆ2fBM”8VÈmòeçZ'R®âÔžÅ#ÜòÖ~呟¸Æûì±.½8ä妾]5ÐûÓÝ(gw}ÝG,rée7n{/mÛ}ÖUÄê²Ü<:q¬nqŒû9N·(qF2ákŠ)êŒ (L„zøÿãêO}ë}ÚȦÍüŽßÅKزƒuýW“ð{=ƒ-­¤q. ý£ÏX„_ˆ gðÎn5§¼ÙÝ{gI¿E?ò·?âlÿrÄ8,ÃéPs“|~¼w7ƾÄý/¸}Ëߨ0~O¹ÄâÏ›¾5îê9>í3×-Ð3N Ô¶<åÙY.M^W$™¶¶d‰–s†ß<{7Ûu‡-\aÔ-÷Ö‡­aĺê\qÈÑ¥ZÜÓÍ8\±…ÚÛ¤ó¦Ÿg^½2~wæ‚ò¿°ºM’ðÉᓞüNsÜyc–"ñysÂ{–å89Q…D›Ó£Xö¹6ðÊ8ØÑ”el£)JUÑ]×UÐ(±`×AƒUU5]E\d««„•¢|4-ÇI–I×}Ÿû«uç[É}żòÜyÅ­ZŹîy»Ælóóæç‘7öòF+Éä_øêΣ» îƒ‘;äLNï;¼ÄX»*┥¤¯É¾I+r²­J=®E¼+ŽzF1ŒaUP®Šêªa@dà eu÷æþPƾ„6ÓbýI‡ðZ½Î'œÏñ—qøuþë2 žÑÝ„ž¡q I2DÍ®J¶ò_v%yL±ÊäK(QÜZ™ˆRŸû÷<2O}~UvŸ”kßx Ëœsž®*˜­|‘T×%æ\R”´êÖR}mýø¸´ø_žMU×›¹;´šŠRŸ 1”xä–²á]Õ½Bè8,óéa%ïfSqÜãüŸÝz9Ùo-²tò³–á)÷Ãy~¸Éé @yˆ¦FÓNKÇs[yÄ÷T²ŒÒUÞ$§¹‘;°ÌxÜË,w-*ÉÇ”xt^ªuµd—^‡m¢ÿõy~Iý.œ‡¹÷AËýâÂÿ9Úwßy¹p®'læœºÚø´ðEê—i6´ÕñL›làu»OVl­es™UÌ0k8Ò•²ü ³°¡–Ó¨_jT…±=D}£9oX/sÙòöØ·dc[Zk¡§8J)§äi½Sò3à×%s&_'s–ÓÍØ”3v½Ë.¹EèãìŸêøâ+*‰ªvu[¢7­Š>ýìŸÜ¶É/'|hÂürûŒÓ/¤'ù;çOƒàÿê¸%ÃiUJ¦ù úýÞû/ôÒèinä•~.>Åž÷]ÿ¶|»þ…þ£Š’ú_ü}Iï½o»YÙ¿‘Ûø©{Pn¿ªò~g°eµ£tŽ%À_´yë‹ñ¬þÍÆ´÷ƒñ»/û¯q¬é7è§þVçüMŸîX‡Ř}*ro׎æø×ØŸ¥÷o¹{õÀé÷8œYówƽÏýG'ݦb‘ú座Oéùû&{–6.I©Â*d¥«›–’‚•:Q!–?“èq—îeÄ©×T•±^ÂÉç‰j[ Hµ¹«š°¹_ ¶»K3¬MURz95åðÂ?Ö—ØZɤö3ÃG†Ž{ñ5Ïpå^UƒÇرÜ'¸î3ƒ•4I¾—Ó×"ÞG2ŒîœdÜ«¢»®« qbW×BƒUQ_¦žª*aUÕÃJŠ4ˆ[ŽøiSŠqù<ûËuçÝRÞû‹uÅ)Å©G¬[žç¼fÏpÜ&ìɱôù^HÅV1] }–Ü›o©ç;ä^â¹»Îï±}ï²ãk)ÎZJü¬‰(«r²¬J=­öðÇŠZF0„aUP®šë®Q@eÙ]}ù…„”1¯¡ ´Ø¿Raü¯s‰Å'3üeÜ~ºÌ‚‡´kësâ+X{¯+÷Ïß3}:¿ÃÔtoôUÿ+ øpö8ÇEž}$;ëìßÒϳêaa*.;Çý“kf´%FÚ"ɼÁè™'T_zD¹÷ öýÓ/ûéÝî=—óv,ëê¦6Î_ü½”ë×Òâ²+Óhù¥ô­gãbx^«æ•Ù\Ï]iõ¹Fœ»žž”*–¤ñgM[ eŒÇRÌ8dM–òŒ‰-FŠÊß}Õ™%¶›3?ýƒd/º¼zg‘sÒ¨EÊOÌ¢µoì$swn^Ex¸ëŠûgEyå&’_e´UŠäâÖ9”Øxqkâ->A7ÆìKQàþRDZ“âŸ|ˆ›eŽ÷{ï¾á}ßéQ~<ëÙç‹UdqœžV¡§G¦ÎÑw­¯%r.^É‹¬òÿÊm¢uÊ~÷•qÓ£­ËM:>ÁkøÝËB>ÑEl¸=G®åHK„ÍÖ›Õ–P iìJ¢5âjhÿï7çÕ/Ÿþñ@Ö{ªuó–á9§Ãdé”}ïj#ÑöbΗ>‹<ºr<)ãÓVœtoûsÓþ'*­Zú<Gìhp¤Z‡Ñ²@¾Í—¬'þö7馯×w©ü]žÁŸ2~–/勸³ü.àMÇvþ¦vçÅŽ}ú+l3‡5üWܾ‘î39íîûãîÉþ¯‡þ"²¨‘ª§iUº#zѸ£ïÞÉýËl‘ròwÆŒ/Ç/¸Í2úB“¾tø>þ«‚XÜ6åTªoŸ¯Ýáñ¿²ÿM.†–áþIWâãìQÙïußûgË¿èXáj0ø©/ õñÿÇÔžûÖûµ‘M›ù¿Š—±eëú¯'àö{[Z7Hâ\ûGž±¿ÏáœÜkOx?²ÿº÷Γ~ŠånÄÙþåˆp·]uXõJûåQ¹JRiF1KW)7¢I%«o¡.–N« ?O\ãŠz›5߯›Šíñ’ &qâßaƕّ{ÂLŠ»ìÎÒRfI‚éx±cC†—RÛæû-çìùg#Y¿îà¾êû:bÓSU6¥9I=4í%iTkRÕ«4\åý%þ(9w¾ŽvÛû·îÿ*¼ÞJå¹Û;rª—9yö¨Ân™/Se8µÅÕ cêl²ËÜëUÎ[ïÕ’õ¼Zà~÷Í—`ˆYfaŠÏÔºá’q´Ì—›ìˆ31ør+Ðá’¨zmÊÒ}¥àV¯ÈgØ“¸ûÃÜëÛ¹["—£»1{Þ)êµíSV4×S*ÉE½Š×VjðWÝ&W|ž$9o—•NÍ—6–sÑðÇqºq›])_b«?øïJëU«m:Í-àÖø«äÇxýºë&³5ìËY㇑ø/!ÿ2Í©!§ΪÜZLÏÅ«Ëꦰ}âJŒFd]½ƒh¹7qÿ4åŒ,™IÊøÓìmhÝ•gcÓ­)J.QóÆQ—SG"{·Íþgîÿ2¹W ÞþÃTãljl»|K~K1¬ªkMWN‰½{DÜÏ7v-¯¹i¨1yÙnI¨±Û'kPQÁvÃ!“­NÆNCA“׊…ËŸ ¹±²óæÛK®¢5—œwRÌwÔXû½M!ξdÇŒ§ »;ôzªãJP·‡þW8Û=uŠU¶¸#9CèÑkâW–û¼Þw>å9ë2¼-§|ʆ^ÝuÓP¢9ü¦ìyÊMF˪vR“Œ]”vz¹ÛZ!V0ñÐ-/g_‚;ÿÚ916>-7_k[­[y¯°:ܦºÌ£;{$½Ån\Éê©å!‰Pñ(qÎësd! ž¹ 8Äãi[…“û±Ùw ·E¾¸pí0ªJ3ÿl¦´]’þ´[r³ÖñiqË´ìþ&ý)~$;³æNNÅî'•3+Ý9³x§72ÌyÆÌ|5E9,{-‹qžLå~²ª ºTµÆn0r¤Ý¿©¹ñcŸ~ŠÛ ·Í÷/€d{ŒÏ=ß|}Ù?ÕðÿÄVU5Tí ê·DoZ7}ûÙ?¹m’.^NøÑ…øå÷¦_HOòwΟÁÿÕpK†Òª•Mòõû¼>7ö_é¥ÐÒÜ?É*ü\}Š;=î»ÿlùwý ü-F%ô¾?øú“ßzßv²)³#·ñRö, ÝUäüÏ`ËkFéK€¿hóÖ!âYü3›iïãv_÷^ãYÒoÑOü­Ïø›?ܱ‹0úTä߯Íñ¯±?Kîßr÷ê Óîq8³æï{ŸúŽO»Lô´þ Ÿ²l°ž©UxED„7wtÊ[L™r;‰y>p•2ý̦”“[†—‚‰çR³6Yóy«š°y_ ¶»IçYªª¤úf×[ðÂ:®)iѪKYJ)æ >ùçÄÏ?C”¹V/d£†ÍÇpœ¨ÁÇmú©hãÚd[Ã(ãc)FWM6å]5Ýu]t#TÒÔÆ(uUPÉe RZœ4 ÜS>ûï8§_}Õ-ù­nºµ¸µ(õ‡sÜówŒÙî„Ý™V>—Ô’]QŠþ¬cä^›mɶú’îs¹ÎDî'‘1;½î÷clØËŠË%¤¯Ê¾I+r²­J=­öð®)iB…UBºk®¸} ”€¶W_~aaå kàhCm6/Ô˜«ÜâqIÌÿw‡_î³0asKäfKÄ‹üâ«Ý•t˜õå~–ª=KyåUY瑞ÂfLwÌ2Y1ÌbUzSÐm)~˜ìtÿ+þîØ§¾ßË9s쳫” »D•w;+„øk“m9idW¸e'¯šŒšÈ¿1½èGº¼Nû¶Íºì¾ï®È¾™åc)XðîÆ³†K.1\tF^¦uÜ×bø”{Ef°2%'t.3“žmŽiCæfò¤ž]I­°Ê¬œä,Ì× ïàR±jo(ÌÌ×â÷ý¢³•¹c&9˜»vY‘—²õFiùÔ”“ôSÔµwó{Èݶûuæ ó'aáá÷µ¹ÙVcð¯'c;]zz:½Ù¾4÷°+]›»ö5­ðš†Ö§î2;✹…-ºÊhñ,¯î¥w{… ™ßW‘¶Ôb§wÞö½‹ß{­Ñª§ªŠ}2›K^൜å¢o† ½o¡6;¿îßž»ÔæJyG»Ý¯/uæ ß©ªˆ9pÇËe³è…5G®vÛ(WÓ)"¿Ž¬]L/ú†nóÇbZbÜÖYÀÕx•ƒ„Ý´‰ëi»]–Ea×"§!½f+M±”ê+!$™BÔã’]{Zù›™2ù£r÷íñì±+N4Ôônm6ç%ªvXÔ]Š/‚*0„\ø;K:kðUá#mð½È¶ÿšÎœÎów…\÷˜-aT`›¯ M)v4¹JSž‘wÚøåUrt[æê’è—ÕvŸ† Ÿ·å„Ƹé±oÊê§*$I°=CœÌj4vÒ!0—¥»„dŒEd¬Q \9-&Sm™9+¿zrW6¾WËyjRÙoiØ£e\ÒQí¢¢µŸ©J6CG9B0uú¨vvüÉúA¼çwùµÓÞwv•VûÓÚ±»+q½L?Ìñ å8×½"²èr—`æÒ¶¹:e$ãN“¢ÅrÌ[:Çjrì+#£Ë±[èmXRd˜Õ¬º;x/kRëmk_“ luöyÚÔ]¥Ù÷FÆaæáîÑÌÀ¶»±f½Lá%(½F›] 4üÍ4úNtw“xåÍÒý“˜1r0wœk-¢úçUÕMuÆuØ£8Éy¤“1êøïÇ÷2“Î\Ñšuy©ÉóÓ̬°¥e>yßñ|ìòR·œø¿}âxÝî÷—·´~Cå>Vyû{fÞò¸¸¸ýïO_¼Zô뮥Ïô;ÌŽÏÿoG˜·Õ°pðûÙgå{߇M8{׳áÓ£N4è4jõ_ã Ê+Ä7!…´ö®ÑÙTØRþ'gV-« )ø‘SäÓ&¾Ç*•sàDEþ«‚XÜ6åTªoŸ¯Ýáñ¿²ÿM.†–áþIWâãìQÙïußûgË¿èXáj0ø©/ õñÿÇÔžûÖûµ‘M›ù¿Š—±eëú¯'àö{[Z7Hâ\ûGž±¿ÏáœÜkOx?²ÿº÷Γ~ŠånÄÙþåˆpÖš{e2¹«•ùO뿴γ¥UIèæÕqÕ·ÓÃ\u\sÓ£¡$äãÉ×s^9óÄÇ|û‡)r”; šÆë7 ÂÈ9càãÊû´qí/³†QÆÆŒ”îš“r®šîº­¯lÔÐ#ÔQÔGóJš˜ï7…¼n,Ínž“.KÊ7dHtÔô‡”¥­F£3ó¹nYÛÆt÷Æ}¦]o©$º¡ÓÃëêcé¶Üœ¤úoîc¹ŽCîñ{¾îû°Ú¨õVÛ-%‘—‘$•™YV%Òë8V¯EABª¡]5×\b„ÊÀÊëïÌ,#ü¡| m¦Åú“àµ{œN)9Ÿã.ãðëýÖd=¢ÞØG“kbAé-Y(žijmÔHjFLÛO6â ”‡Kì2224öxçøAó~|d“ŒZ§Ôÿÿž•Óöþ‹ /𨩹)Uÿpî1Ñ­S‹Ž;i§ÐÓÕꟜç¶ÔŸŸ88¾+Ë­ïŠ+E YýÍÑ@Ž’ìDjé¯ÙK®ŒÑyÛ6„õH…¹^áºSZ§7:ª#£ òo®K©F²1ŠÿåHÙíûÂg†ŽfÜå¼o<Ë–nSzÊqê®9ye8Ò«Œäü²œ[~VÍjÙ»‹mn«ÒÊ7Í϶–D”º†®¶]}—ÙGe哎G‰.ú|÷aÄ5¤»hÐÒI$D’""*{'e×<‹å+2d’”ç'9ÉG¡qNMÊZtôÉ·Òüæ[åDäžïößò~EÚ6Í›kzkV58ГŠÑJQ¦S–šú©k'«mêÙÄ%ÖtÓüä_ÝqÍ#¼¶®«nCÇ"\:Èñê‹”’I¹gK_`ÍEšŒ’_ú†û…þÂ(»#s³ Û¨ºi)J«'Tä—Rs®Q“KÍ®†9ç®è;«ï: árîͼÊ1áŒòñ(ºØ%Ó¥vÎÚÿþ[ó³*쎡¼äÛ”Oâû•›Ã Ææ4¶,(/nêj-#¸ƒmq®+èäVE·Œ´(û[”—Pgåìíò‰—æî9uK7+2üi­% oºØ?/L,œ£¯£¦¥—Ê~<:ò>åã•ù/—±·X=aw¼ê¶ÊÚz©U;•’ªIÿZ·ä×CP`ÎW:dÉUÖUңί°ƒ!蓠Έò$D™\u¶üYQ_m+mÄ)+BÒFFFDbšQŒâã$œZѧÔ×™™Ó'3Ì<Êán%°”' ÅJ„“Œ¡8É8Ê2‹jQi¦›MhdW·~èÓ±ämí û¶¶^eìÿ+u§šu&‡uµÛ)6âd¤™aŠOòüÐè§OþHÿð-8wuÝõSVW±lѲ-4Ö2i®”ÓUjš})£ŠÂò=Jk»œrÎ-Ö=ogCqN*µ4ùuvpÔó.GuQgÁu‰QÔìw–Ú .òi?!™,®»`ë¶1•o­4šèéê~IG¸mÛ~í‡=¿t¢œœ 4ãªØFÊå£R\Pšq–’I­SѤúÑ?ã¦îý±íO”,·ÿõÅ?ù~ÿáOÞGÿküÛ÷wÿl¿þŽ7ÿˆÆ2$H—!ùrßzL©/;"L™­é$<µ8óï¼â”ã¯:âJRŒÔ¥™Ÿh©Œc¨A%´It$—RKÈ‘xUUTU(ŒaL"£Å%Å-It$—BK¡.„|DDÀõñÿÇÔžûÖûµ‘M›ù¿Š—±eëú¯'àö{[Z7Hâ\ûGž±¿ÏáœÜkOx?²ÿº÷Γ~ŠånÄÙþåˆpËKãLU}œ±.zDz׋§‹©iÓÏ¿²Û˜ý3q¯ëOø5;¿ç8߇íMúã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ>ËncôÍÆ¾C­>tCæ§wüçðý¨úã6YŸµ«ýÞ²¿ÙwÌ`σ8ù•;æs#Jð¿à…¢_Ó °äâÛÿaåÇ´®Q×üÚ·§k]?ËÖºjKìg£á ÿÙrst2pdf-0.102/doc/gen_docs.sh000077500000000000000000000010171463013543400157670ustar00rootroot00000000000000#!/bin/sh rst2pdf manual.rst --custom-cover=assets/cover.tmpl -o output/pdf/manual.pdf -s assets/manual.yaml -b1 # Determine correct name for rst2man RST2MAN="rst2man" if [ -x "$(command -v rst2man.py)" ]; then RST2MAN="rst2man.py" fi $RST2MAN rst2pdf.rst output/rst2pdf.1 # set PYTHONPATH so we use the current contents of this repo, rather than our installed rst2pdf PYTHONPATH=../ python rst2html-manual.py --stylesheet=assets/manual.css manual.rst output/html/manual.html cp assets/biohazard.png output/html/assets/ rst2pdf-0.102/doc/manual.rst000066400000000000000000002026411463013543400156640ustar00rootroot00000000000000How to use rst2pdf ================== .. meta:: :authors: rst2pdf project ; Roberto Alsina and the contributors to the rst2pdf project. .. header:: .. oddeven:: .. class:: headertable +---+---------------------+----------------+ | |.. class:: centered |.. class:: right| | | | | | | ###Section###|Page ###Page### | +---+---------------------+----------------+ .. class:: headertable +---------------+---------------------+---+ | |.. class:: centered | | | | | | |Page ###Page###| ###Section###| | +---------------+---------------------+---+ .. contents:: :class: toc-root .. section-numbering:: .. raw:: pdf PageBreak oneColumn Introduction ------------ This document explains how to use rst2pdf. Here is the very short version:: rst2pdf.py mydocument.txt -o mydocument.pdf That will, as long as ``mydocument.txt`` is a valid reStructured Text (rST) document, produce a file called ``mydocument.pdf`` which is a PDF version of your document. Of course, that means you just used default styles and settings. If it looks good enough for you, then you may stop reading this document, because you are done with it. If you are reading this in a PDF, it was generated using those default settings. However, if you want to customize the output, or are just curious to see what can be done, let's continue. Related Reading ~~~~~~~~~~~~~~~ As well as the rst2pdf-specific features described in this manual, you many also find it useful to refer to the ReStructuredText manual and information about its directives: * A ReStructureText Primer: https://docutils.sourceforge.io/docs/user/rst/quickstart.html * Quick ReStructuredText: https://docutils.sourceforge.io/docs/user/rst/quickref.html * ReStructuredText Specification: https://docutils.sourceforge.io/docs/ref/rst/restructuredtext.html * ReStructuredText Directives: https://docutils.sourceforge.io/docs/ref/rst/directives.html Command line options -------------------- .. include:: rst2pdf.rst :start-line: 30 :end-before: EXAMPLES Configuration File ------------------- Since version 0.8, rst2pdf will read (if it is available) configuration files in ``/etc/rst2pdf.conf`` and ``~/.rst2pdf/config``. The user's file at ``~/.rst2pdf/config`` will have priority over the system's at ``/etc/rst2pdf.conf`` [#]_ .. [#] The ``/etc/rst2pdf.conf`` location makes sense for Linux and linux-like systems. if you are using rst2pdf in other systems, please contact me and tell me where the system-wide config file should be. Here's an example file showing some of the currently available options: .. code-block:: ini :include: assets/config.sample Pipe usage ---------- If no input nor output are provided, ``stdin`` and ``stdout`` will be used respectively. You may want to use rst2pdf in a linux pipe as such:: cat readme.txt | rst2pdf | gzip -c > readme.pdf.gz or:: curl http://docutils.sourceforge.net/docs/user/rst/quickstart.txt | rst2pdf > quickstart.pdf If no input argument is provided, ``stdin`` will be used:: cat readme.txt | rst2pdf -o readme.pdf If output is set to dash (``-``), output goes to ``stdout``:: rst2pdf -o - readme.txt > output.pdf Images ------ Inline ~~~~~~ You can insert images in the middle of your text like this:: This |biohazard| means you have to run. .. |biohazard| image:: assets/biohazard.png This |biohazard| means you have to run. .. |biohazard| image:: assets/biohazard.png Supported Image Types ~~~~~~~~~~~~~~~~~~~~~ For raster images, rst2pdf supports anything PIL (The Python Imaging Library) supports. The exact list of supported formats varies according to your PIL version and system. For SVG support, you need to install svglib_. Some features will not work when using these images. For example, gradients will not display, and text may cause problems depending on font availability. If you can choose between raster and vectorial images, for non-photographic images, vector files are usually smaller and look better, specially when printed. .. _svglib: https://pypi.org/project/svglib/ .. note:: Image URLs Attempting to be more compatible with rst2html, rst2pdf will try to handle images specified as HTTP or FTP URLs by downloading them to a temporary file and including them in the PDF. This is probably not a good idea unless you are **really** sure the image won't go away. Image Size ~~~~~~~~~~ PDFs are meant to reflect paper. A PDF has a specific size in centimeters or inches. Images usually are measured in pixels, which are meaningless in a PDF. To convert between pixels and inches or centimeters, we use a DPI (dots-per-inch) value. For example, 300 pixels, with a 300DPI, are exactly one inch. 300 pixels at 100DPI are 3 inches. For that reason, to achieve a nice layout of the page, it's usually a good idea to specify the size of your images in those units, or as a percentage of the available width and you can ignore all this DPI nonsense ;-) The rst2pdf default is 300DPI, but you can change it using the --default-dpi option or the default_dpi setting in the config file. Examples of images with specified sizes:: .. image:: home.png :width: 3in .. image:: home.png :width: 80% .. image:: home.png :width: 7cm The valid units you can use are: ``em``, ``ex``, ``px``, ``in``, ``cm``, ``mm``, ``pt``, ``pc``, ``%``, ``""``. * ``px``: Pixels. If you specify the size using this unit, rst2pdf will convert it to inches using the default DPI explained above. * No unit. If you just use a number, it will be considered as pixels. (**IMPORTANT:** this used to default to points. It was changed to be more compatible with rst2html) * ``em``: This is the same as your base style's font size. By default: 10 points. * ``ex``: rst2pdf will use the same broken definition as IE: em/2. In truth this should be the height of the lower-case x character in your base style. * ``in``: Inches (1 inch = 2.54 cm). * ``cm``: centimeters (1cm = 0.39 inches) * ``mm``: millimeters (10mm = 1cm) * ``pt``: 1/72 inch * ``pc``: 1/6 inch * ``%``: percentage of available width in the frame. Setting a percentage as a height does **not** work and probably never will. If you don't specify a size at all, rst2pdf will do its best to figure out what it should do: Since there is no specified size, rst2pdf will try to convert the image's pixel size to inches using the DPI information available in the image itself. You can set that value using most image editors. For example, using Gimp, it's in the Image -> Print Size menu. So, if your image is 6000 pixels wide, and is set to 1200DPI, it will be 5 inches wide. If your image doesn't have a DPI property set, and doesn't have it's desired size specified, rst2pdf will arbitrarily decide it should use 300DPI (or whatever you choose with the ``--default-dpi`` option). Styling ReStructuredText ------------------------ For well-formatted and consistent PDFs, the best starting point is well-formatted and consistent markup. There are some excellent references for ReStructuredText which we won't reproduce here but they are highly recommended as a starting point for working with rst2pdf. In general, applying a stylesheet to a structured document will output a decent PDF with minimum fuss. That said, there are plenty of customisation and styling options available so read on if that sounds interesting. Applying Styles ~~~~~~~~~~~~~~~ rst2pdf applies a default set of styles to the document. This default set can be viewed using ``rst2pdf --print-stylesheet`` which prints outh ``rst2pdf/styles/styles.yaml``. Each subsequent style within each style sheet file specified the ``--stylesheets`` CLI parameter is then registered in the the list of known styles known to rst2pdf. If the name of the style is already known, then the attributes specified in the style are applied "on top" of the already registered style. rst2pdf will then resolve the ``parent`` style, which is why the order of inclusion matters per-style-name, not globally. That is, if you set the color of ``bodytext`` first in a file and then set the color of ``normal`` in a subsequent file, then the color you have set for ``bodytext`` will be the color used for paragraphs (unless overridden by a ``class`` directive. Further information on cereating stylesheet files is available in `Creating Stylesheets`_. You can style paragraphs with a style using the class directive:: .. class:: special This paragraph is special. This one is not. Multiple styles can be listed and are applied in order where properties in the right hand styles override those to the left:: .. class:: special bluetext redtext This paragraph is special and is red. This one is not. Or inline styles using custom interpreted roles:: .. role:: redtext I like color :redtext:`red`. For more information about this, please check the rST docs, and for style information check the section in this manual on `inline styles`_. Headers and Footers ~~~~~~~~~~~~~~~~~~~ rST supports headers and footers, using the header and footer directive:: .. header:: This will be at the top of every page. Often, you may want to put a page number there, or a section name.The following magic tokens will be replaced (More may be added as rst2pdf evolves): ``###Page###`` Replaced by the current page number. ``###Title###`` Replaced by the document title ``###Section###`` Replaced by the current section title ``###SectNum###`` Replaced by the current section number. **Important:** You must use the sectnum directive for this to work. ``###Total###`` Replaced by the total number of pages in the document. Keep in mind that this is the **real** number of pages, not the displayed number, so if you play with `page counters`_ this number will probably be wrong. Headers and footers are visible by default but they can be disabled by specific `Page Templates`_ for example, cover pages. You can also set headers and footers via `command line options` or the `configuration file`_. If you want to do things like "put the page number on the *out* side of the page, check `The oddeven directive`_ Footnotes ~~~~~~~~~ Currently rst2pdf doesn't support real footnotes, and converts them to endnotes. There is a real complicated technical reason for this: I can't figure out a clean way to do it right. You can get the same behaviour as with rst2html by specifying ``--inline-footnotes``, and then the footnotes will appear where you put them (in other words, not footnotes, but "in-the-middle-of-text-notes" or just plain notes.) Customizing PDF Output ---------------------- Stylesheets are used to control many aspects of the PDF output. * General look and feel, colours, fonts, templates * Page size * Syntax highlighting for code The stylesheets use a YAML format (JSON is also supported). Older versions of this tool used an RSON format; this is also still supported but we recommend you check the section on `migrating to yaml stylesheets` and update them (it's painless!) Using Stylesheets ~~~~~~~~~~~~~~~~~ Specify a stylesheet to use with -s:: rst2pdf mydoc.rst -s mystyles Often it makes sense to specify multiple stylesheets, for example to set the page size, the main styles, and some syntax highlighting. In that case, use comma-separated values:: rst2pdf mydoc.rst -s a4,mystyles,murphy Order does matter: rst2pdf applies its own stylesheet first and then the list in given in order, so the last stylesheet in the list will take precedence over the ones that went before. Styles will always be searched in these places, in order: * What you specify using ``--stylesheet_path`` * The option ``stylesheet_path`` in the config file * The current folder * ``~/.rst2pdf/styles`` * The styles folder within rst2pdf's installation folder. Included StyleSheets ~~~~~~~~~~~~~~~~~~~~ To make some of the more common adjustments easier, rst2pdf includes a collection of stylesheets you can use: Font styles These stylesheets modify your font settings. * ``serif`` uses the PDF serif font (Times) instead of the default Sans Serif (Arial) * ``freetype-sans`` uses your system's default TrueType Sans Serif font * ``freetype-serif`` uses your system's default TrueType Serif font * ``twelvepoint`` makes the base font 12pt (default is 10pt) * ``tenpoint`` makes the base font 10pt * ``eightpoint`` makes the base font 8pt Page layout styles These stylesheets modify your page layout. * ``twocolumn`` uses the twoColumn layout as the initial page layout. * ``double-sided`` adds a gutter margin (margin at the "in side" of the pages) Page size styles Stylesheets that change the paper size. The usual standard paper sizes are supported: ``A0``, ``A1``, ``A2``, ``A3``, ``A4`` (default), ``A5``, ``A6``, ``B0``, ``B1``, ``B2``, ``B3``, ``B4``, ``B5``, ``B6``, ``Letter``, ``Legal``, ``11x17`` The name of the stylesheet is lowercase. Code block styles See `Syntax Highlighting`_ So, if you want to have a two-column, legal size, serif document with code in ``murphy`` style:: rst2pdf mydoc.txt -s twocolumn,serif,murphy,legal Default Stylesheet ~~~~~~~~~~~~~~~~~~ You can make rst2pdf print the default stylesheet:: rst2pdf --print-stylesheet This makes an excellent starting point for creating a stylesheet. The default one is always included by default, so only the values that should be changed need to be included in the new stylesheet. Migrating Stylesheet Format ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historically, (version 0.98 and earlier) rst2pdf had support for JSON and RSON stylesheets. Those stylesheets should still work if you are still using them but a warning will be produced:: [WARNING] styles.py:617 Stylesheet "./example.style" in outdated format, recommend converting to YAML To update your stylesheet, use the ``rst2pdf.style2yaml`` utility:: python3 -m rst2pdf.style2yaml example.style The command also accepts a list of paths, or wildcards, and by default will output the new stylesheet(s) to stdout. To write them to files instead, use the ``--save`` flag with the command above. Migrating to the New Default Stylesheet ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Historically (version 0.98 and earlier), rst2pdf used a different default style sheet. The updated default style file provide a more modern look to rst2pdf documents. To do this, it updates various spacing, margins and fonts. It also updates page template and font alias names and so you will need to make adjustments to derived style files. Until you make these adjustments, you can use the historical default style sheet using by adding the ``rst2pdf-0-9`` style using the ``-s`` command line switch. For example:: rst2pdf mydoc.rst -s rst2pdf-0-9,mystyle.yaml Updated Font Alias Names ************************ The font aliases used for the standard fonts have changed from those used in the historical default style sheeet. As such, you will need to update to the new names in any derivative style files. This table shows the old name and the equivalent new name: +-----------------------+-------------------------+ | Historical | Current | +=======================+=========================+ | ``stdFont`` | ``fontSerif`` | +-----------------------+-------------------------+ | ``stdSerif`` | ``fontSerif`` | +-----------------------+-------------------------+ | ``stdBold`` | ``fontSerifBold`` | +-----------------------+-------------------------+ | ``stdBoldItalic`` | ``fontSerifBoldItalic`` | +-----------------------+-------------------------+ | ``stdItalic`` | ``fontSerifItalic`` | +-----------------------+-------------------------+ | ``stdMono`` | ``fontMono`` | +-----------------------+-------------------------+ | ``stdMonoBold`` | ``fontMonoBold`` | +-----------------------+-------------------------+ | ``stdMonoBoldItalic`` | ``fontMonoBoldItalic`` | +-----------------------+-------------------------+ | ``stdMonoItalic`` | ``fontMonoItalic`` | +-----------------------+-------------------------+ | ``stdSans`` | ``fontSans`` | +-----------------------+-------------------------+ | ``stdSansBold`` | ``fontSansBold`` | +-----------------------+-------------------------+ | ``stdSansBoldItalic`` | ``fontSansBoldItalic`` | +-----------------------+-------------------------+ | ``stdSansItalic`` | ``fontSansItalic`` | +-----------------------+-------------------------+ Updated Pate Template Names *************************** The page template names used in the new default style sheet are different from the historical default style sheeet. As such, you will need to update to the new names in any derivative style files. This table shows the old name and the equivalent new name: +-----------------+----------------------------------------------+ | Historical | Current | +=================+==============================================+ | – | ``mainPage`` | +-----------------+----------------------------------------------+ | ``cutePage`` | ``decoratedPage`` | +-----------------+----------------------------------------------+ | ``emptyPage`` | ``emptyPage`` | +-----------------+----------------------------------------------+ | ``oneColumn`` | ``oneColumn`` | +-----------------+----------------------------------------------+ | ``twoColumn`` | Move to separate ``twocolumn`` template file | +-----------------+----------------------------------------------+ | ``threeColumn`` | – | +-----------------+----------------------------------------------+ Note that ``firstTemplate`` is now ``mainPage``. Historically, it was ``oneColumn``. Creating Stylesheets -------------------- The stylesheets are YAML-formatted and give control over many aspects of how the PDF is rendered. The main aspects are the styles of the elements, the page setup and templates, and the fonts to use . These are described in the following sections. Only the settings that you want to change need to be included so for example, this would be a valid stylesheet: .. code-block:: yaml pageSetup: size: A5 fontsAlias: fontSerif: Times-Roman styles: normal: fontSize: 14 Styles in Detail ~~~~~~~~~~~~~~~~ At the top level there is a bit of an outlier: ``linkColor``. You can specify any color name or a hex value:: linkColor: #330099 Most of the other elements for colours and formatting are in the `styles` section. There are particular styles which have great effect, they are ``base``, ``normal`` and ``bodytext``. Here's an example, the ``twelvepoint`` stylesheet: .. code-block:: yaml styles: base: fontSize: 12 Since all other styles inherit ``base``, changing the ``fontSize`` changes the ``fontSize`` for everything in your document. The ``normal`` style is meant for most elements, so usually it's the same as changing ``base``. The ``bodytext`` style is for elements that form paragraphs. So, for example, you can set your document to be left-aligned like this: .. code-block:: yaml styles: - bodytext: alignment: TA_LEFT There are elements, however, that don't inherit from ``bodytext``, for example headings and the styles used in the table of contents. Those are elements that are not real paragraphs, so they should not follow the indentation and spacing you use for your document's main content. The ``heading`` style is inherited by all sorts of titles: section titles, topic titles, admonition titles, etc. If your document requires a style that is not defined in your stylesheet, it will print a warning and use ``bodytext`` instead. Also, the order of the styles is important: if ``styleA`` is the parent of ``styleB``, ``styleA`` should be earlier in the stylesheet. Style Elements ~~~~~~~~~~~~~~ Within the ``styles`` element, it is possible to configure each element type. The following section lays out the known options and examples of how to use them. (This list is known to be incomplete, we're working on it and accept any additions you have). **parent** Each style property can inherit from another, for example the ``code`` style inherits from the ``literal`` style which sets the font used for fixed-width text throughout the document. Example: .. code-block:: yaml code: parent: literal **fontName** The name of the font to use for this type of element. It can be either the name of a font on your system, or one of the aliased fonts. The default is Helvetica as shown in the example here. Example: .. code-block:: yaml fontName: Helvetica See also: * `Font Alias`_ * `Fonts`_ **fontSize** Use either a number (meaning point size) or a percentage. The default size for bodytext is 10. Example: .. code-block:: yaml fontSize: 150% **leftIndent** and **rightIndent** Example: .. code-block:: yaml leftIndent: 0 rightIndent: 0 **firstLineIndent** Example: .. code-block:: yaml firstLineIndent: 0 **alignment** The paragraph justification of the text. The values ``TA_LEFT`` and ``TA_RIGHT`` can be used. Example: .. code-block:: yaml alignment: TA_LEFT **spaceBefore** and **spaceAfter** The amount of vertical space included before or after an element. Especially useful when working with ``bullet-list`` and ``bullet-list-item`` elements. Example: .. code-block:: yaml spaceBefore: 4 spaceAfter: 8 **bullet** -related styles The bullets can be complex to style, but there are some tricks that might help. The vertical space before and after the list and item elements are controlled by the ``spaceBefore`` and ``spaceAfter`` properties. Also these lists are *tables* so those styles also apply. Example: .. code-block:: yaml bulletFontName: Helvetica bulletFontSize: 10 bulletText: "\u2022" bulletIndent: 0 See also: * `Table Styles`_ **textColor** Use either a color name, or a hex value including the ``#`` character at the start. Example: .. code-block:: yaml textColor: black **backColor** Use either the value ``None``, a color name, or a hex value including the ``#`` character at the start. Sets the background color of the element. Example: .. code-block:: yaml backColor: beige **wordWrap** Can be set to ``None``. Example: .. code-block:: yaml wordWrap: None **border** -related styles Setting and styling the border for an element. The example is from the default code block style. Example: .. code-block:: yaml borderColor: darkgray borderPadding: 6 borderWidth: 0.5 borderRadius: None **allowWidows** and **allowOrphans** These directives are passed to ReportLab if they are present. Currently only implemented for paragraph styles. Example: .. code-block:: yaml allowWidows: 5 allowOrphans: 4 See also: * `Widows and Orphans`_ **margin** -related styles This sets the margins of the element. On the ``pageSetup`` itself, you can use ``margin-gutter``. That's the margin in the center of a two-page spread. This value is added to the left margin of odd pages and the right margin of even pages, adding (or removing, if it's negative) space "in the middle" of opposing pages. If you intend to bound a printed copy, you may need extra space there. OTOH, if you will display it on-screen on a two-page format (common in many PDF readers, nice for ebooks), a negative value may be pleasant. Example: .. code-block:: yaml margin-top: 2cm margin-bottom: 2cm margin-left: 2cm margin-right: 2cm margin-gutter: 0cm Inline Styles ************* The following are the only attributes that work on styles when used for interpreted roles (inline styles): * ``fontName`` * ``fontSize`` * ``textColor`` * ``backColor`` Lists ***** Styling lists is mostly a matter of spacing and indentation. The space before and after a list is taken from the ``item-list`` and ``bullet-list`` styles:: styles: item-list parent: bodytext spaceBefore: 0 commands: - - VALIGN: [[0, 0], [-1, -1]] - TOP - - RIGHTPADDING: [[0, 0], [1, -1], 0] colWidths: - 20pt - bullet-list parent: bodytext spaceBefore: 0 commands: - - VALIGN: [[0, 0], [-1, -1]] - TOP - - RIGHTPADDING: [[0, 0], [1, -1], 0] colWidths: - '20' Yes, these are table styles, because they are implemented as tables. The ``RIGHTPADDING`` command and the ``colWidths`` option can be used to adjust the position of the bullet/item number. To control the separation between items, you use the ``item-list-item`` and ``bullet-list-item`` styles' ``spaceBefore`` and ``spaceAfter`` options. For example:: bullet-list-item: parent: bodytext spaceBefore: 20 Remember that this is only used **between items** and not before the first or after the last items. Page Layout ~~~~~~~~~~~ There are some layouts available as standard stylesheets, but it is likely that you will also want to describe your own templates. Page Setup ********** In your stylesheet, the ``pageSetup`` element controls your page layout. Here's the default stylesheet's element:: pageSetup: size: A4 width: height: margin-top: 2cm margin-bottom: 2cm margin-left: 2cm margin-right: 2cm spacing-header: 5mm spacing-footer: 5mm margin-gutter: 0cm Size is one of the standard paper sizes, like ``A4`` or ``LETTER``. Here's a list: ``A0``, ``A1``, ``A2``, ``A3``, ``A4``, ``A5``, ``A6``, ``B0``, ``B1``, ``B2``, ``B3``, ``B4``, ``B5``, ``B6``, ``LETTER``, ``LEGAL``, ``ELEVENSEVENTEEN``. If you want a non-standard size, set size to null and use width and height. When specifying width, height or margins, you need to use units, like inch (inches) or cm (centimeters). For example, a slide deck in a 16:9 ratio can be created as a document with width 32cm and height 18cm:: pageSetup: size: null width: 32cm height: 18cm When both width/height and size are specified, size will be used, and width/height ignored. Page Templates ************** By default, your document will have a single column of text covering the space between the margins. You can change that, though, in fact you can do so even in the middle of your document! .. _page templates: To do it, you need to define *Page Templates* in your stylesheet. The default stylesheet already has three of them: .. code-block:: yaml pageTemplates: coverPage: frames: - [0cm, 0cm, 100%, 100%] showHeader: false showFooter: false oneColumn: frames: - [0cm, 0cm, 100%, 100%] twoColumn: frames: - [0cm, 0cm, 49%, 100%] - [51%, 0cm, 49%, 100%] A page template has a name (``oneColumn``, ``twoColumn``), some options, and a list of frames. A frame is a list containing this:: [ left position, bottom position, width, height, left padding, bottom padding, right padding, top padding] All the padding values are optional and default to 6 points. For example, this defines a frame "at the very left", "at the very bottom", "a bit less than half a page wide" and "as tall as possible":: ["0cm", "0cm", "49%", "100%"] And this means "the top third of the page":: ["0cm", "66.66%", "100%", "33.34%"] You can use all the usual units, ``cm``, ``mm``, ``inch``, and ``%``, which means "percentage of the page (excluding margins and headers or footers)". Using ``%`` is probably the smartest for columns and gives you a fluid layout, while the other units are better for more "fixed" elements. Since we can have more than one template, there is a way to specify which one we want to use, and a way to change from one to another. To specify the first template, do it in your stylesheet, in ``pageSetup`` (``oneColumn`` is the default):: pageSetup: firstTemplate: oneColumn Then, to change to another template, in your document use this syntax (will change soon, though): .. code-block:: rst .. raw:: pdf PageBreak twoColumn That will trigger a page break, and the new page will use the twoColumn template. You can see an example of this in the *Montecristo* folder in the source package. The supported page template options and their defaults are: * ``showHeader`` : True * ``defaultHeader`` : None Has the same effect as the header directive in the document. * ``showFooter`` : True * ``defaultFooter`` : None Has the same effect as the footer directive in the document. * ``background``: None The background should be an image, which will be centered in your page or stretched to match your page size, depending on the ``--fit-background-mode`` option, so use with caution. .. _fontconfig: http://www.freedesktop.org/fontconfig/ Font Alias ~~~~~~~~~~ This is the ``fontsAlias`` element. By default, it uses some of the standard PDF fonts:: fontsAlias: fontSerif: Helvetica fontSerifBold: Helvetica-Bold fontSerifItalic: Helvetica-Oblique fontSerifBoldItalic: Helvetica-BoldOblique fontMono: Courier This defines the fonts used in the styles. You can use, for example, Helvetica directly in a style, but if later you want to use another font all through your document, you will have to change it in each style. So, I suggest you use aliases. More information in the dedicated `Fonts`_ section. Widows and Orphans ~~~~~~~~~~~~~~~~~~ ``Widow`` A paragraph-ending line that falls at the beginning of the following page/column, thus separated from the remainder of the text. ``Orphan`` A paragraph-opening line that appears by itself at the bottom of a page/column. rst2pdf has *some* widow/orphan control. Specifically, here's what's currently implemented: On ordinary paragraphs, ``allowWidows`` and ``allowOrphans`` is passed to reportlab, which is supposed to do something about it if they are non-zero. In practice, it doesn't seem to have much effect. The plan is to change the semantics of those settings, so that they mean the minimum number of lines that can be left alone at the beginning of a page (widows) or at the end (orphans). Currently, these semantics only work for literal blocks and code blocks. .. code-block:: rst A literal block:: This is a literal block. A code block: .. code-block:: python def x(y): print y**2 In future versions this may extend to ordinary paragraphs. Table Styles ~~~~~~~~~~~~ These are a few extra options in styles that are only used when the style is applied to a table. This happens in two cases: 1) You are using the class directive on a table: .. code-block:: rst .. class:: thick +-------+---------+ | A | B | +-----------------+ 2) It's a style that automatically applies to something that is *drawn* using a table. Currently these include: * Footnotes / endnotes (endnote style) * Lists (item-list, bullet-list, option-list and field-list styles) The options are as follows: Commands For a full reference of these, please check the Reportlab User Guide specifically the TableStyle Commands section (section 7.4 in the manual for version 2.3) Here, however, is a list of the possible commands:: BOX (or OUTLINE) FONT FONTNAME (or FACE) FONTSIZE (or SIZE) GRID INNERGRID LEADING LINEBELOW LINEABOVE LINEBEFORE LINEAFTER TEXTCOLOR ALIGNMENT (or ALIGN) LEFTPADDING RIGHTPADDING BOTTOMPADDING TOPPADDING BACKGROUND ROWBACKGROUNDS COLBACKGROUNDS VALIGN Each takes as argument a couple of coordinates, where ``(0,0)`` is top-left, and ``(-1,-1)`` is bottom-right, and 0 or more extra arguments. For example, ``INNERGRID`` takes a line width and a color:: [ "INNERGRID", [ 0, 0 ], [ -1, -1 ], 0.25, "black" ], That would mean "draw all lines inside the table with .25pt black" ``colWidths`` A list of the column widths you want, in the unit you prefer (default unit is ``pt``). Example:: "colWidths": ["3cm",null] If your ``colWidths`` has fewer values than columns in your table, the rest are auto-calculated. A column width of null means "guess". If you don't specify column widths, the table will try to look proportional to the restructured text source. .. note:: The ``command`` option used for table styles is not kept across stylesheets. For example, the default stylesheet defines endnote with this command list:: "commands": [ [ "VALIGN", [ 0, 0 ], [ -1, -1 ], "TOP" ] ] If you redefine endnote in another stylesheet and use this to create a vertical line between the endnote's columns:: "commands": [ [ "LINEAFTER", [ 0, 0 ], [ 1, -1 ], .25, "black" ] ] Then the footnotes will **not** have VALIGN TOP! To do that, you **MUST** use all commands in your stylesheet:: "commands": [ [ "VALIGN", [ 0, 0 ], [ -1, -1 ], "TOP" ], [ "LINEAFTER", [ 0, 0 ], [ 1, -1 ], .25, "black" ] ] .. raw:: pdf PageBreak Syntax Highlighting ------------------- rst2pdf adds a non-standard directive, called ``code-block``, which produces syntax highlighted for many languages using Pygments_. For example, if you want to include a Python fragment:: .. code-block:: python def myFun(x,y): print x+y .. code-block:: python def myFun(x,y): print x+y Notice that you need to declare the language of the fragment. Here's a list of the currently supported_. You can use the ``linenos`` option to display line numbers: .. code-block:: python :linenos: def myFun(x,y): print x+y You can use the ``hl_lines`` option to emphasize certain lines by dimming the other lines. This parameter takes a space separated list of line numbers. The other lines are then styled with the class ``pygments_diml`` that defaults to gray. For example, to highlight ``print "line a"`` and ``print "line b"``: .. code-block:: python :hl_lines: 2 3 def myFun(x,y): print "line a" print "line b" print "line c" rst2pdf includes several stylesheets for highlighting code: * ``abap`` * ``algol_nu`` * ``algol`` * ``arduino`` * ``autumn`` * ``borland`` * ``bw`` * ``colorful`` * ``default`` * ``emacs`` * ``friendly`` * ``fruity`` * ``igor`` * ``lovelace`` * ``manni`` * ``monokai`` * ``murphy`` * ``native`` * ``paraiso-dark`` * ``paraiso-light`` * ``pastie`` * ``perldoc`` * ``rainbow_dash`` * ``rrt`` * ``sas`` * ``solarized-dark`` * ``solarized-light`` * ``sphinx`` * ``stata-dark`` * ``stata-light`` * ``stata`` * ``styles`` * ``tango`` * ``trac`` * ``vim`` * ``vs`` * ``xcode`` You can use any of them instead of the default by adding, for example, a ``-s murphy`` to the command line. If you already are using a custom stylesheet, use both:: rst2pdf mydoc.rst -o mydoc.pdf -s mystyle.json,murphy The default is the same as ``emacs``. There is an online demo of pygments showing these styles: http://pygments.org/demo/1817/ The overall look of a code box is controlled by the "code" style or by a class you apply to it using the ``.. class::`` directive. Additionally, if you want to change some properties when using different languages, you can define styles with the name of the language. For example, a ``python`` style will be applied to code blocks created with ``.. code-block:: python``. The look of the line numbers is controlled by the ``linenumbers`` style. As rst2pdf is written in Python, let's see some examples and variations around Python. Python in console .. code-block:: pycon >>> my_string="python is great" >>> my_string.find('great') 10 >>> my_string.startswith('py') True Python traceback .. code-block:: pytb Traceback (most recent call last): File "error.py", line 9, in ? main() File "error.py", line 6, in main print call_error() File "error.py", line 2, in call_error r = 1/0 ZeroDivisionError: integer division or modulo by zero Exit 1 The code-block directive supports many options, that mirror Pygments':: FIXME: fix this to really explain them all. This is a placeholder. 'stripnl' : string_bool, 'stripall': string_bool, 'ensurenl': string_bool, 'tabsize' : directives.positive_int, 'encoding': directives.encoding, # Lua 'func_name_hightlighting':string_bool, 'disabled_modules': string_list, # Python Console 'python3': string_bool, # Delphi 'turbopascal':string_bool, 'delphi' :string_bool, 'freepascal': string_bool, 'units': string_list, # Modula2 'pim' : string_bool, 'iso' : string_bool, 'objm2' : string_bool, 'gm2ext': string_bool, # CSharp 'unicodelevel' : csharp_unicodelevel, # Literate haskell 'litstyle' : lhs_litstyle, # Raw 'compress': raw_compress, # Rst 'handlecodeblocks': string_bool, # Php 'startinline': string_bool, 'funcnamehighlighting': string_bool, 'disabledmodules': string_list, You can find more information about them in the pygments manual. File inclusion ~~~~~~~~~~~~~~ You can use the ``code-block`` directive with an external file, using the ``:include:`` option:: .. code-block:: python :include: setup.py This will give a warning if ``setup.py`` doesn't exist or can't be opened. Include with Boundaries *********************** You can add selectors to limit the inclusion to a portion of the file. The options are: ``:start-at: string`` will include file beginning at the first occurrence of string, string **included** ``:start-after: string`` will include file beginning at the first occurrence of string, string **excluded** ``:end-before: string`` will include file up to the first occurrence of string, string **excluded** ``:end-at: string`` will include file up to the first occurrence of string, string **included** Let's display a class from rst2pdf:: .. code-block:: python :include: assets/flowables.py :start-at: class Separation(Flowable): :end-before: class Reference(Flowable): This command gives .. code-block:: python :include: assets/flowables.py :start-at: class Separation(Flowable): :end-before: class Reference(Flowable): .. _supported: http://pygments.org/docs/lexers/ .. _pygments: http://pygments.org/ Options ******* ``linenos`` Display line numbers along the code ``linenos_offset`` If you include a file and are skipping the beginning, using the ``linenos_offset`` makes the line count start from the real line number, instead of 1. Fonts ----- Working with fonts on many different platforms is a challenge. Here you will find the best information we have, but questions and updates are always welcome. Standard PDF Fonts ~~~~~~~~~~~~~~~~~~ The standard PDF fonts are always available, here is the list: - ``Times_Roman`` - ``Times-Bold`` - ``Times-Italic`` - ``Times-Bold-Italic`` - ``Helvetica`` - ``Helvetica_Bold`` - ``Helvetica-Oblique`` - ``Helvetica-Bold-Oblique`` - ``Courier`` - ``Courier-Bold`` - ``Courier-Oblique`` - ``Courier-Bold-Oblique`` - ``Symbol`` - ``Zapf-Dingbats`` Font Embedding ~~~~~~~~~~~~~~ There are thousands of excellent free True Type and Type 1 fonts available on the web, and you can use many of them in your documents by declaring them in your stylesheet. The Easy Way ************ Just use the font name in your style. For example, you can define this:: normal: fontName: fonty And then it *may* work. What would need to happen for this to work? Fonty is a True Type font: """""""""""""""""""""""""" 1. You need to have it installed in your system, and have the fc-match utility available (it's part of fontconfig_). You can test if it is so by running this command:: $ fc-match fonty fonty.ttf: "Fonty" "Normal" If you are in Windows, I need your help ;-) or you can use `The Harder Way (True Type)`_ 2. The folder where ``fonty.ttf`` is located needs to be in your font path. You can set it using the ``--font-path`` option. For example:: rst2pdf mydoc.txt -s mystyle.style --font-path /usr/share/fonts You don't need to put the *exact* folder, just something that is above it. In my own case, fonty is in ``/usr/share/fonts/TTF`` Whenever a font is embedded, you can refer to it in a style by its name, and to its variants by the aliases ``Name-Oblique``, ``Name-Bold``, ``Name-BoldOblique``. Fonty is a Type 1 font: """"""""""""""""""""""" You need it installed, and the folders where its font metric (``.afm``) and binary (``.pfb``) files are located need to be in your font fath. For example, the "URW Palladio L" font that came with my installation of TeX consists of the following files:: /usr/share/texmf-dist/fonts/type1/urw/palatino/uplb8a.pfb /usr/share/texmf-dist/fonts/type1/urw/palatino/uplbi8a.pfb /usr/share/texmf-dist/fonts/type1/urw/palatino/uplr8a.pfb /usr/share/texmf-dist/fonts/type1/urw/palatino/uplri8a.pfb /usr/share/texmf-dist/fonts/afm/urw/palatino/uplb8a.afm /usr/share/texmf-dist/fonts/afm/urw/palatino/uplbi8a.afm /usr/share/texmf-dist/fonts/afm/urw/palatino/uplr8a.afm /usr/share/texmf-dist/fonts/afm/urw/palatino/uplri8a.afm So, I can use it if I put ``/usr/share/texmf-dist/fonts`` in my font path:: rst2pdf mydoc.txt -s mystyle.style --font-path /usr/share/texmf-dist/fonts And putting this in my stylesheet, for example:: title: fontName: URWPalladioL-Bold There are some standard aliases defined so you can use other names:: 'ITC Bookman' : 'URW Bookman L', 'ITC Avant Garde Gothic' : 'URW Gothic L', 'Palatino' : 'URW Palladio L', 'New Century Schoolbook' : 'Century Schoolbook L', 'ITC Zapf Chancery' : 'URW Chancery L' So, for example, you can use ``Palatino`` or ``New Century SchoolBook-Oblique`` And it will mean ``URWPalladioL`` or ``CenturySchL-Ital``, respectively. Whenever a font is embedded, you can refer to it in a style by its name, and to its variants by the aliases Name-Oblique, Name-Bold, Name-BoldOblique. The Harder Way (True Type) ************************** The stylesheet has an element is ``embeddedFonts`` that handles embedding True Type fonts in your PDF. Usually, it's empty, because with the default styles you are not using any font beyond the standard PDF fonts:: embeddedFonts: [] The `embeddedFonts` element is a list of the font files that you want to embed into your PDF document. For each font, you provide the filenames of the four variants of the file (normal, bold, italic, bold italic). For example, suppose you want to use the nice public domain `Tuffy font`_, then you need to give the filenames of all variants:: embeddedFonts: - [Tuffy.ttf, Tuffy_Bold.ttf, Tuffy_Italic.ttf, Tuffy_Bold_Italic.ttf] This will provide your styles with fonts called ``Tuffy``, ``Tuffy_Bold`` and so on. They will be available with the names based on the filenames (``Tuffy_Bold``) and also by standard aliases similar to those of the standard PDF fonts (``Tuffy-Bold``, ``Tuffy-Oblique``, ``Tuffy-BoldOblique``, etc..) Now, if you use *italics* in a paragraph whose style uses the Tuffy font, it will use ``Tuffy_Italic``. That's why it's better if you use fonts that provide the four variants, and that you list them in the correct order. If your font lacks a variant, use the "normal" variant instead. For example, if you only had ``Tuffy.ttf``:: embeddedFonts: - [Tuffy.ttf, Tuffy.ttf, Tuffy.ttf, Tuffy.ttf] However, that means that italics and bold in styles using Tuffy will not work correctly (they will display as regular text). If you want to use this as the base font for your document, you should change the ``fontsAlias`` section accordingly. For example:: fontsAlias: fontSans: Tuffy fontSansBoldfontSansBold: Tuffy_Bold fontSansItalic: Tuffy_Italic fontSansBoldItalic: Tuffy_Bold_Italic fontMono: Courier If, on the other hand, you only want a specific style to use the Tuffy font, don't change the ``fontAlias`` but rather set the ``fontName`` properties for that style. For example:: heading1: parent: normal fontName: Tuffy_Bold fontSize: 18 keepWithNext: true spaceAfter: 6 .. _tuffy font: http://tulrich.com/fonts/ By default, rst2pdf will search for the fonts in its fonts folder and in the current folder. You can make it search another folder by passing the ``--font-folder`` option, or you can use absolute paths in your stylesheet. Raw Directive ------------- Raw PDF ~~~~~~~ rst2pdf has a very limited mechanism to pass commands to reportlab, the PDF generation library. You can use the raw directive to insert pagebreaks and spacers (other reportlab flowables may be added if there's interest), and set page transitions. The syntax is shell-like, here's an example:: One page .. raw:: pdf PageBreak background=images/background.jpg fit-background-mode=scale Another page. Now some space: .. raw:: pdf Spacer 0,200 Spacer 0 200 And another paragraph. The unit used by the spacer by default is points, and using a space or a comma is the same thing in all cases. Page Counters ~~~~~~~~~~~~~ In some documents, you may not want your page counter to start in the first page. For example, if the first pages are a coverpage and a table of contents, you want page 1 to be where your first section starts. To do that, you have to use the ``SetPageCounter`` command. Here is a syntax example:: .. raw:: pdf SetPageCounter 0 lowerroman This sets the counter to 0, and makes it display in lower roman characters (i, ii, iii, etc) which is a style often used for the pages before the document proper (for example, TOCs and abstracts). It can take zero or two arguments. ``SetPageCounter`` When used with no arguments, it sets the counter to 0, and the style to arabic numerals. ``SetPageCounter number style`` When used with two arguments, the first argument must be a number, it sets the page counter to that number. The second number is a style of counter. Valid values are: * lowerroman: i, ii, iii, iv, v ... * roman: I, II, III, IV, V ... * arabic: 1, 2, 3, 4, 5 ... * loweralpha: a, b, c, d, e ... [Don't use for numbers above 26] * alpha: A, B, C, D, E ... [Don't use for numbers above 26] .. note:: Page counter changes take effect on the **current** page. Page Breaks ~~~~~~~~~~~ There are three kinds of page breaks: ``PageBreak`` Break to the next page ``EvenPageBreak`` Break to the next **even** numbered page ``OddPageBreak`` Break to the next **odd** numbered page Each of them can take an optional argument which is the name of the next page template. For example:: PageBreak twoColumn In addition, two additional attributes are supported: ``background`` and ``fit-background-mode``. These allow setting the background image for this page and how to fit it (One of scale, scale_width or center). For example:: PageBreak mainPage background="images/background.jpg" or:: PageBreak background=images/background.jpg fit-background-mode=scale Frame Breaks ~~~~~~~~~~~~ If you want to jump to the next frame in the page (or the next page if the current frame is the last), you can use the ``FrameBreak`` command. It takes an optional height in points, and then it only breaks the frame if there is less than that vertical space available. For example, if you don't want a paragraph to begin if it's less than 50 points from the bottom of the frame:: .. raw:: pdf FrameBreak 50 This paragraph is so important that I don't want it at the very bottom of the page... Page Transitions ~~~~~~~~~~~~~~~~ Page transitions are effects used when you change pages in *Presentation* or *Full Screen* mode (depends on the viewer). You can use it when creating a presentation using PDF files. The syntax is this:: .. raw:: pdf Transition effect duration [optional arguments] The optional arguments are: ``direction`` Can be 0,90,180 or 270 (top,right,bottom,left) ``dimension`` Can be H or V ``motion`` Can be I or O (Inside or Outside) The effects with their arguments are: * Split duration direction motion * Blinds duration dimension * Box duration motion * Wipe duration direction * Dissolve duration * Glitter duration direction For example:: .. raw:: pdf Transition Glitter 3 90 Uses the Glitter effect, for 3 seconds, at direction 90 degrees (from the right?) Keep in mind that ``Transition`` sets the transition *from this page to the next* so the natural thing is to use it before a ``PageBreak``:: .. raw:: pdf Transition Dissolve 1 PageBreak Text Annotations ~~~~~~~~~~~~~~~~ Text annotations are meta notes added to a page. The syntax is this:: .. raw:: pdf TextAnnotation "text to add" [optional position] The optional position is a set of 4 numbers for ``x_begin``, ``y_begin`, ``x_end`` and ``y_end`` Raw HTML ~~~~~~~~ If you have a document that contains raw HTML, and have ``xhtml2pdf`` installed, ``rst2pdf`` will try to render that HTML inside your document. To enable this, use the ``--raw-html`` command line option. The counter role ---------------- .. note:: The counter role only works in PDF, if you're reading the HTML version of the manual then this section is broken. Sorry :/ This is a nonstandard interpreted text role, which means it will only work with ``rst2pdf``. It implements an unlimited number of counters you can use in your text. For example, you could use it to have numbered figures, or numbered tables. The syntax is this: .. code-block:: rst Start a counter called seq1 that starts from 1: :counter:`seq1` Now this should print 2: :counter:`seq1` You can start counters from any number (this prints 12): :counter:`seq2:12` And have any number of counters with any name: :counter:`figures` So ``#seq1-2`` should link to `the number 2 above <#seq1-2>`_ The output is: Start a counter called seq1 that starts from 1: :counter:`seq1` Now this should print 2: :counter:`seq1` You can start counters from any number (this prints 12): :counter:`seq2:12` And have any number of counters with any name: :counter:`figures` Also, the counters create targets for links with this scheme: ``#countername-number``. So ``#seq1-2`` should link to `the number 2 above <#seq1-2>`_ The version, revision roles --------------------------- .. note:: These are non-standard roles, which means they will only work with rst2pdf and not with rst2html or any other docutils tools. The ``version`` and ``revision`` roles can be used to get the version and revision of an installed Python package. For example: .. code-block:: rst Welcome to rst2pdf :version:`rst2pdf` (:revision:`rst2pdf`)! .. important:: The package in question must be installed in the same environment that you are running rst2pdf in. The oddeven directive --------------------- This is a nonstandard directive, which means it will only work with rst2pdf, and not with rst2html or any other docutils tool. The contents of oddeven should consist of **exactly** two things (in this case, two paragraphs). The first will be used on odd pages, and the second one on even pages. If you want to use more complex content, you should wrap it with containers, like in this example: .. code-block:: rst .. oddeven:: .. container:: This will appear on odd pages. Both paragraphs in the container are for odd pages. This will appear on even pages. It's a single paragraph, so no need for containers. This directive has several limitations. * I intentionally have disabled splitting into pages for this, because I have no idea how that could make sense. That means that if its content is larger than a frame, you **will** make rst2pdf barf with one of those ugly errors. * It will reserve the space of the larger of the two sets of contents. So if one is small and the other large, it **will** look wrong. I may be able to fix this though. * If you try to generate HTML (or anything other than a PDF via rst2pdf) from a file containing this, it will not do what you want. Mathematics ----------- If you have Matplotlib_ installed, rst2pdf supports a math role and a math directive. You can use them to insert formulae and mathematical notation in your documents using a subset of LaTeX syntax, but doesn't require you have LaTeX installed. For example, here's how you use the math directive:: .. math:: \frac{2 \pm \sqrt{7}}{3} And here's the result: .. class:: mathformula .. math:: \frac{2 \pm \sqrt{7}}{3} If you want to insert mathematical notation in your text like this: :math:`\pi` that is the job of the math *role*:: This is :math:`\pi` Produces: This is :math:`\pi` Note that while the math directive embeds fonts and draws your formula as text, the math role embeds an image. That means: * You can't copy the text of inline math * Inline math will look worse when printed, or make your file larger. So, use it only in emergencies ;-) You don't need to worry about fonts, the correct math fonts will be used and embedded in your PDF automatically (they are included with ``matplotlib``). .. _matplotlib: http://matplotlib.sf.net For an introduction to LaTeX syntax, see the "Typesetting Mathematical Formulae" chapter in "The Not So Short Introduction to LaTeX 2e" at https://tobi.oetiker.ch/lshort/lshort.pdf Basically, the inline form ``$a^2$`` is similar to the math role, and the display form is similar to the math directive. Hyphenation ----------- If you want good looking documents, you want to enable hyphenation. To do it, you first need to install the ``pyphen`` python module. Then, you need to specify the language in each style that you want hyphenation to work. To have hyphenation in the whole document, you can do it in the ``base`` style. For example, for an English document, hyphenation can be turned on for the whole document with:: base: hyphenationLang: en-US embeddedHyphenation: 1 Notice the ``embeddedHyphenation`` option. It is optional, but it makes so that hyphenations will give preference to splitting words at embedded hyphens in the text. If you are creating a multilingual document, you can declare styles with specific languages. For example, you could inherit ``bodytext`` for Spanish:: bodytext_es: parent: bodytext hyphenationLang: es-ES embeddedHyphenation: 1 And all paragraphs declared using the ``bodytext_es`` style would have Spanish hyphenation:: .. class:: bodytext_es Debo a la conjunción de un espejo y de una enciclopedia el descubrimiento de Uqbar. El espejo inquietaba el fondo de un corredor en una quinta de la calle Gaona, en Ramos Mejía; la enciclopedia falazmente se llama *The Anglo-American Cyclopaedía* (New York, 1917) y es una reimpresión literal, pero también morosa, de la *Encyclopaedia Britannica* de 1902. If you want to disable hyphenation in a style that inherits ``hyphenationLang`` from its parent, you can do so by setting ``hyphenationLang`` to ``0``. Smart Quotes ------------ Quoted from the smartypants_ documentation: This feature can perform the following transformations: Straight quotes ( ``"`` and ``'`` ) into "curly" quote HTML entities Backticks-style quotes (\`\`like this'') into "curly" quote HTML entities Dashes (``--`` and ``---``) into en- and em-dash entities Three consecutive dots (``...`` or ``. . .``) into an ellipsis entity This means you can write, edit, and save your posts using plain old ASCII straight quotes, plain dashes, and plain dots, but your published posts (and final PDF output) will appear with smart quotes, em-dashes, and proper ellipses. You can enable this by passing the ``--smart-quotes`` option in the command line. By default, it's disabled. Here are the different values you can use (again, from the smartypants docs): 0 Suppress all transformations. (Do nothing.) 1 Performs these transformations: quotes (including \`\`backticks'' -style), em-dashes, and ellipses. "--" (dash dash) is used to signify an em-dash; there is no support for en-dashes. 2 Same as smarty_pants="1", except that it uses the old-school typewriter shorthand for dashes: "--" (dash dash) for en-dashes, "---" (dash dash dash) for em-dashes. 3 Same as smarty_pants="2", but inverts the shorthand for dashes: "--" (dash dash) for em-dashes, and "---" (dash dash dash) for en-dashes. Currently, even if you enable it, this transformation will only take place in regular paragraphs, titles, headers, footers and block quotes. .. _smartypants: http://web.chad.org/projects/smartypants.py/ Sphinx ------ Sphinx_ is a very popular tool. This is the description from its website: Sphinx is a tool that makes it easy to create intelligent and beautiful documentation, written by Georg Brandl and licensed under the BSD license. It was originally created to translate the new Python documentation, and it has excellent support for the documentation of Python projects, but other documents can be written with it too. rst2pdf includes an experimental PDF extension for Sphinx. To use it in your existing Sphinx project you need to do the following: 1. Add ``rst2pdf.pdfbuilder`` to ``extensions`` in your ``conf.py``. For example:: extensions = ['sphinx.ext.autodoc','rst2pdf.pdfbuilder'] 2. Add the PDF options at the end of ``conf.py``, adapted to your project:: # -- Options for PDF output -------------------------------------------------- # Grouping the document tree into PDF files. List of tuples # (source start file, target name, title, author, options). # # If there is more than one author, separate them with \\. # For example: r'Guido van Rossum\\Fred L. Drake, Jr., editor' # # The options element is a dictionary that lets you override # this config per-document. For example: # # ('index', 'MyProject', 'My Project', 'Author Name', {'pdf_compressed': True}) # # would mean that specific document would be compressed # regardless of the global 'pdf_compressed' setting. pdf_documents = [ ('index', 'MyProject', 'My Project', 'Author Name'), ] # A comma-separated list of custom stylesheets. Example: pdf_stylesheets = ['sphinx', 'a4'] # A list of folders to search for stylesheets. Example: pdf_style_path = ['.', '_styles'] # Create a compressed PDF # Use True/False or 1/0 # Example: compressed=True # pdf_compressed = False # A colon-separated list of folders to search for fonts. Example: # pdf_font_path = ['/usr/share/fonts', '/usr/share/texmf-dist/fonts/'] # Language to be used for hyphenation support # pdf_language = "en_US" # Mode for literal blocks wider than the frame. Can be # overflow, shrink or truncate # pdf_fit_mode = "shrink" # Section level that forces a break page. # For example: 1 means top-level sections start in a new page # 0 means disabled # pdf_break_level = 0 # When a section starts in a new page, force it to be 'even', 'odd', # or just use 'any' # pdf_breakside = 'any' # Insert footnotes where they are defined instead of # at the end. # pdf_inline_footnotes = True # verbosity level. 0 1 or 2 # pdf_verbosity = 0 # If false, no index is generated. # pdf_use_index = True # If false, no modindex is generated. # pdf_use_modindex = True # If false, no coverpage is generated. # pdf_use_coverpage = True # Name of the cover page template to use # pdf_cover_template = 'sphinxcover.tmpl' # Label to use as a prefix for the subtitle on the cover page # subtitle_prefix = 'version' # Documents to append as an appendix to all manuals. # pdf_appendices = [] # Enable experimental feature to split table cells. Use it # if you get "DelayedTable too big" errors # pdf_splittables = False # Set the default DPI for images # pdf_default_dpi = 72 # Enable rst2pdf extension modules # pdf_extensions = [] # Page template name for "regular" pages # pdf_page_template = 'cutePage' # Show Table Of Contents at the beginning? # pdf_use_toc = True # How many levels deep should the table of contents be? pdf_toc_depth = 9999 # Add section number to section references pdf_use_numbered_links = False # Background images fitting mode pdf_fit_background_mode = 'scale' # Repeat table header on tables that cross a page boundary? pdf_repeat_table_rows = True # Enable smart quotes (1, 2 or 3) or disable by setting to 0 pdf_smartquotes = 0 3. (Optional) Modify your ``Makefile`` or ``make.bat`` file For ``Makefile`` (on \*nix systems) .. code-block:: makefile pdf: $(SPHINXBUILD) -b pdf $(ALLSPHINXOPTS) _build/pdf @echo @echo "Build finished. The PDF files are in _build/pdf." For ``make.bat`` (on Windows): .. code-block:: bat if "%1" == "pdf" ( %SPHINXBUILD% -b pdf %ALLSPHINXOPTS% %BUILDDIR%/pdf echo. echo.Build finished. The PDF files are in %BUILDDIR%/pdf goto end ) Then you can run ``make pdf`` or ``sphinx-build -b pdf ...`` similar to how you did it before. .. _sphinx: http://sphinx.pocoo.org Extensions ---------- rst2pdf can get new features from *extensions*. Extensions are python modules that can be enabled with the ``-e`` option. Several are included with rst2pdf. Preprocess (``-e preprocess``) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. include:: ../rst2pdf/extensions/preprocess_r2p.py :start-after: ''' :end-before: ''' Dotted_TOC (``-e dotted_toc``) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. include:: ../rst2pdf/extensions/dotted_toc.py :start-after: ''' :end-before: ''' Developers ---------- .. include:: DEVELOPERS.rst :start-line: 4 Licenses -------- This is the license for rst2pdf:: Copyright (c) 2007-2020 Roberto Alsina and the contributors to the rst2pdf project Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Some fragments of rstpdf are copied from ReportLab under the following license:: Copyright (c) 2000-2008, ReportLab Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the company nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OFFICERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. rst2pdf-0.102/doc/montecristo/000077500000000000000000000000001463013543400162165ustar00rootroot00000000000000rst2pdf-0.102/doc/montecristo/README.txt000066400000000000000000000002631463013543400177150ustar00rootroot00000000000000This is an example of fancier typography. To build it, get the scriptina font from http://www.dafont.com/scriptina.font and run:: rst2pdf montecristo.rst -s montecristo.sheet rst2pdf-0.102/doc/montecristo/if.jpg000066400000000000000000005514241463013543400173310ustar00rootroot00000000000000ÿØÿàJFIFHHÿá^ExifII* z€˜ (2¨i‡¼BCanonCanon DIGITAL IXUS 400HH2008:08:27 23:36:32š‚6‚>0220FZ‘‘n’ v’~’ †’Ž’ ’ ’–|’Nž†’ì 0100     ¢ô¢ü¢¢£¤¤¤¤¤€- 2005:03:27 12:40:312005:03:27 12:40:31* ‹ ‹ K .L¨°"¸üH Pp\B  ˆ' "¨\@ÿÿÇí ‹ÛÿÿààÿK×D€E‹*.‹+ú àÔ™&fþšfþšfþš×ÿ×ÿ×ÿ)))ŒIMG:DIGITAL IXUS 400 JPEGFirmware Version 1.00D ßÜááßÝæáß@f  ¶ñÿ ¸ ÒààR980100˜( ¶ ´´ÿØÿàJFIFÿÛC    $.' ",#(7),01444'9=82<.342ÿÀ “ÄÿÄ ÿĵ}!1AQa"q2‘¡#B±ÁRÑð$3br‚ %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖרÙÚáâãäåæçèéêñòóôõö÷øùúÿÚ?÷ú(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(¢Š(£4fŠ(¢Š(¢Š(¢Š(¢Š(¢Š(¤Å-QEQEQEQEQEQEQEU9îÝdháPv »‚«5ìçøñôšRÁŒ‘Óšž;éWïãò5r …œ—sÒ¡š÷drjÓ>8ÉÇJ¯öÔ‚¤c­KÄRªÜúº¯SŠEulí9Å:Š(¢Š(¢Š(¢ŠÉûT¬pݹvç¥WîÁéQ€ÿjc“åíç½Mœ0§kÿ«øÿ:ŠxŸy'éH“lç ÇÄÕÌ[ÉÍDÃ0ê=*Ä4ƒsHã5&J’êpO½FneÇúT°^ 3烎Õ$—h„c §¸5,r,«¹NE>Š(¢Š(¢ŠÃß<>qìi0‡ÿ Ïñœý?úô›ãÛ¸J2;sS+*®å›kê5*Ýî\©ÿhñ£†ý)¸ÆTð÷ÍJà@[Œ¹1Ö­ÄÆOÎzšI¡\¶@«s’jœÒ…ÔµLsRÀqJô©Öv œçÔTHÒ6[ð¦Òô§Çzš9YrzŽõ(œ0<÷ÍH¯ˆÆONµ(¤Tòêo47‰~aÔsÅeO•V„b£K)d`¿(ç,[›JŽÔ½ÈfcÝŒYóD±1\–ô51R"´ÇhÇçCA"ðTƒî*0H¤ïOôõ«1ÃÀéëO{u£8 3Ö¢0œü¼Œã‘SÇ!~^AÎA«‘†$‡AƒïLk$l¼ðE4XÈ1§Ê}N*Ai*ŒQøf²nx rjhT×5,J,95ÎÛ€è)ÿòÈ^´eµLª `àgãð¦$`:•)áT÷5Yì3UÙæù†xþµÊ𣶿ññûⶤ8—Ò³¯€3.ETE (pM:DPصEœŽÕ³¤"Ü;,£p HÏj¬8n?¼jìH¾dChù€ÍiÙÆ’Y.õ¯ó¤òÑNBôéùTr‚{â©–;'­ÿÙÿÛCÿÀ !ÿÄ ÿÄG !1A"Qaq2‘#B¡±ðRÁÑá$3ñCb4r‚%’¢SsÂDc“ÿÚ?ÿ¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¯\ÿ-?ý‘^>žòûƾ},ÿlsòk"F‘‚vƒÛ&½Ò”¥)JR”¥)JR”¯¾7é²V_èkÀ4Ù÷2õ¬Ô¥)JR”¥)JVm}û®7gv Ô¸ý3ŠÏJR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥|*¤ä¨$t$t¯´¥)JR”¥)JR”¥)_U†Cr â¾€v¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)J ÷þF”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¯„ãýy¬lì?Ê~3^ZGð¯^?Ú¼yïÜ/èkïœüŒ/x4óŸÙGÜ \ö\{€M<çämëÍ|óßÙzûóõ ’©×f½yïØ'èi翲þ††iÁ úûç>q…ÏL`×£#Ž¡qœg÷Ì<௸ʞkÐfÎ÷ÀéY)JR”¥{uù¨ï,ŠO¤cœu¬~|¹ä&;û×£<˜áTœ{žv'ÔqœúF*bgç®9¯t¥+Á,3Àã¾:ן0ŽY=ךú%CŽy=°k%)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥+Ë Ž€óКù·ƒ×žx8ü« ã«VíÈÏL×Ü)'$õÀ¯9äà2M}=ðpy'¶iŽ€gœÈæ¾’@ÉÇð©GNz×´MÄdpN=+)Œ/n ÁÿzɱqÈïžFkÀAê$r:p9¯¥HÁÏè:W­ƒÜõȯX ïšûJR”¥)_ƒÞ±˜¿¶E<¥îsž?¥zTUé^éJR˜Õð€zŒûV?/¯N~:ÖZR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR•³’{sïýšñ’3œdäWZǵ‰8ÉÆ;uÏÛƒ’@ïß^°¹ÇC“Žsùó޾ˎ¼{ñM§Ÿ|åp+îÜóÎsÊžÿÞk:.ÑÐWªR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)_6÷ù¯8$q÷æ¼€;œr{×ÓŒ‚;Šö®p3Ðc¥{ÇqÇJ~kí)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)_1׿˜¸¯´¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥|'“œ“€Mrõý«x~×UmXKÍ6å %–ÒB l¨Êàvãù®•oumyÏiqÌ,2²ÛÊ®óVzR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JTI¯ìmÁiïm Uášk„]¿©ªYücá›u‘›Z°s–)±lsóñZ„ÿµï ¡+k©vFAo¥ŒûzÈ?ʵ=Oö½{+Ë›¦G´€"I<½FyS…9ÎþµÏ¼Kâ‹¿ !y¬3Z»¼³ÛÆ\PÇ«m pOùtO ~Ó-´­*ÓLÔìã²O).­HÐtÊGLçŸnõÔôøg[xá²Õm¾ªL³¸q’N6€ßˆü.kj¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥|$(,Ä*¨Ë18À÷­[Qñ·…´¸ž[jÅÊ.á½ÂHÒ|5¨ŸÛ/ƒÎD_âr°ã d9þu[uûkÒbm¶º&§pOáidŽ!sœŸåTŸ¶}^X¤K- ÒÖVbškÖ“Ë=Ž6€~Ù­p~ÓülËæÜ_Ú"€I†ÞÆ4Ï2rkQ¼×5M^g¹¼¿¼‘§õ˜Ìå@?þ#ûïPij2wis²G-ü‰"„°ã œÛû5å‹(䌃Žzú  äsÐñ_IÁèGR:üÖD*yÚG¸¨v°´‚0Ʋ‚pÝŽ=ÿÚ·7Åþ-ÒVÓ[º—ËHoš —kdÒº&‡ûdž6ò|O¥m@ƒmö” G]Ñ·¿\ƒÿè×SÑ|ká}„Zn«—éfÌo“ü8ln?lÖÓJR”¥)B@’$žÕ¦Ýøóö²´ÜM|èÅÙDðÌ@oº’*v›âÝS*‘j[Ü>vÚ^È‘;Ô€O¨cÛ5²R•ð$€ROJûJR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥~|ý¯þÒ-ll¯|-¥8šú|Zê’+céãtWO!‹nþcíùSlp8›Ë_+À ¸týÞ7×=«p±ŽäÃÜÄay\+¦zàÔöÝ‘ƒêÈ'޵ž<É$’HÏW·á ÷ÎZø¡NIÆ?­dã¹Æ í_vcŽ1Û|WÆEì±Àý(A g·?ßZù³~zÖU}±žß¥{êsÛÜšù×9ÀçŒv¯GoÏ^>k“ ¸v‡”“!™É®¾Õ³YøËÅ:2'ÑkwoHn˜\"òáóÈ×Hð÷íŠIŒvúö›#"]CN—p|¦÷#œ7~jè:?íÂZÓˆmõhmnI Zê_¸f9ÆoK줟ŠÝ•”2ÊÃr²œ†õö”¥ygT™‚Ü×ñïÆ£tÚ&{ÑÛ¡mH®TÞ>Gî¹Ú>:ŸÏ?幎D)³‘ëRü½»|Öx­BÌâè3ìÂÇ·{df»¯ìùÛè/aÞÍ3¦ÀÌH\¯8ÏNƒŠè¬+K#KµšF9ÜîÍ·àgðQo®§·Ì1+²‘ÆìœyÇÜ~|Öž5ÛˆíÚv½™&xŒK7™ÐÊðWž™ëÏCV:w‹l/ mÌ÷á•É9ã®8Ço׊™´g¾Ž+k>æÝՔĒþ÷pÜ9èF ¿cÄ.ƒBÓÆ¢šf¥«Ãõ&ÚHô´I" +œ~qÔr3Rì¼U¢ÞéÐj‹rÖöó›.b*б8ÚÊ3·Œôù«øæ†_ûRÇ&NÇ¥d¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR¿?~Õ?ki M{á em^À½¼FèØ„tTÁË1RA㎜œãòÔ†æB÷­$·Lª>_ÈM 9Ï8㎘­ïÁþ¸Ô%[ëµubÖÝA<äa±ÜõûÖßã=´-]l™™”ÙÃ*1ÎW‘ù0#ò­8¦ go™àgpÉûñýk!äç€1Ñ»PØÈ®1ùÖ˜ :§Ÿô¬Ñº¸È 9ã§÷ŠÊªàöè9¯,1úöмç=00@çûâ½™¡4‘Žœò=©Û=}ížOŽêUGŒéñªä†?0àƒ'9$ðqš§2Gk¾œ¥ç”Iô¢f +L21¸ ô)à°8É9é\“[¹¹Ðõ[«uŽÞ‚f+å’|Óî=E@ÏéUqëzôŠ“Û\µ¦Ç'ϳ»ttí·§ÏOë[â‹*õµK³.§t±³Õe‹J¥‰R8þøÈ­ÛÄ7Ï¡w*}Ò±’X"™Ôå¹=F`õ§µBO¥«¨—(QL‘?_+ àŽ{dñß¡í}ŽnÖ-ð_Z™C±\»0•sŒôʶÜÕõŸí",vÚ¦—uÏn.Ö}=’dhÉ#y £ü—=øÇó÷ãßÝa’æÞ$2K4Hƒ«3€oê A]GOB]n7o8 Î[žNäžý‡p;`LŽá\>€ñ‰qÉè{ðxøªË¯é±¬Ò^Û´[D’4r1)Ǩ¨ç¿ßŽ•q‘ÍrÄë$R ’7SêFAq^éJR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥+\ñ=ψmôâ<5¦¦¡¨ÌŤ¸Š1j:ï;È íÖ¿ ëšN§¢êº“ëhë­ýcˆ%HQŸe%IêÆF=+dð‡…çÕn ¼¾Š)ͼEO<6q“žz×ë/ xb:8î.#FxŒ„áH‚F;Wý«å¼W $¶çðŒ7ûšåø‚ `ðH‘•P;H8ÎE3Î3ž0y×™·•Ê’8íÍVÊ’yÜ1ÎMK³f$ŒycÕ`¡cÀý+á “ðqÀÆ~kê©È;Y Ž¿÷Œƒ8þõŒãäó_@ `ç#⽨‚Ü‚pzWÜ9 žOçYÁ ’Fw œíÎ8À¡œ“Ó°5„Œ@ûäg9íUú„/üsâK]2Ï ifÉ.«p6fÊ)7(”) ± ½¿8¯Ø¾Ðô¯è¶zfŸ춆+k«‹[2ZþeUFöd–8É'8÷«;›«­±Ik­”¬¢åÔÐ1’ñÍ@»Ô&ˆªÈ—+pÑÉr¶ ™mv“ëÐÉ,ÓÞßIt Áˆ –@Î2=@gÓŠùuk,77—â<ÈU…¥ª³8眒Ä7`‘ž1Ö°Ý,vÊna‚ê‹ÐÅ-äû ƒ“ûNHãwAøx®ûC¶x5xîMÝÁŠ6»çÂÃhà–zfµ}>;‡žŠ4k,¡+’Ä ¡¹ƒgÈÇÏ«ííÅÓîNјPÇmp@ÝÏOøéúÓKÖõÍH|™a¸ƒ-#Jò1d~¤á²6“Øt®÷àWT‡EºYÖ[³Z3L2¢–h³ÝJ«{mÇB1ØkÄÊ8ˆ¢ÊPˆÚE$+v$ dgäWÉ$DÚ¶î GÍh>+ñ"hú>£zi"ù¾B ›‰1psÈP<GqÔÖ«¡®êÐiúžöñXéè’Ïe-’Ho‹ÛI<¨^=ˆÏ² Ø™$iâId½DðùÊc`጑ƒžÁqÆj»\ÖéšÊÂê=:ækvÕmׯF1Ò´ÝNÛQÕ™’ËHÓJ˜Ç•<ÄÂÒ0%C8\ç‘ÜWBýœëæÂmãjÝi§|jâ‰>ÿ…ò:ÿ®“JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JÐüGà/ êçTÕ®ô¥›UžÜÊnþ¦`ZDŒ*6ÐÛx£§j×4É4_ _èö7«»WÕ¯’ÓN±R2‘‘.O²‚Åyêr:ƒŽ¿_˜¿k9*r0?ý_ ëŒþ!\´4›Ž}+ØŸlVdg“0y›ö±Êà޵ m*r9ÇŽŸʰ…IÆqž=ë*"Â01דïC8PÜ3dãœÖ—?Žô«[«‹YË$–ó4.qÀ"®4Xk/"Ù;H f?åÝœsóƒ[ ðHþu˜#m`[Aþ>õ›p8ÎÜõû×¥*q’rIÁdPȉëpy{פ”;0@Æ*úÛ›€XÜ}ÿ¿šú„ Û”7§$½=\|gŠý û(Óà¶ðì·h€O{'&ÑûÅC…Æp2{ž§í]äd€Ø®{ øˆhÚÝ”ìÒ‡µ¸UºUeÌÑ’VA‚qøIÀÎ2Õñ¤D*Ñ ¶Ä Ào>ÃÞ…À˜d´g³^Zx”¦çQæ1D'¹³ï_ZTQ¹‰QÙ*yÿ~«âÏHbV>`Pì¥HÚô¬´¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR•ù¶Ïöû3`]xz I^Eµó§=ú«U×ÿÇK}χ®ÐŸà‡PøùÈ_Ò¸®™­Ýø›ö¹¥k¸žï|Eoˆ&›•u zp£ õûŠ¿0þ×^%ñRªÈ’3i°™Sö[/éÿöpý!\²GÁ‚0^ÚQ“ŸQë· ÈéŠð“‚KTõ$g69±Ø õ5s‚\b…Cn‘ŒrSQäW nÀ$ zü?â;Ɉ5§IdU:œÄ.ò1‚sž}ë´~Å^Y]‘ÙœïC9'÷+¸O$б•ß•nNN{|ö¤Ò¿¨óÇQøjȦpW•ñYÑ…î è{ö÷ªëÉ£ä‡#ÛŽ§ÿ?Ò¾Y<²N»s…’?³V2È"Ç^[i9ë÷¯/"¤eÛ$‘Þ¿QxEÿÑš@L 4dúŒ­ž2;ŸzÛ%ŒÏí–8å%’9”gË\ŒŒ‚Hà‚3ØŠÅ$¾DhP¼VÑešB¹“#êä’ÄsÔüç5âº3ÀLBarT&Ó!þ @ô€wÎHéTØÂnfÓc†çStã‚Ö/ÜÅaÛ 0_.àñŽ@¡ñô‚ÏCÔPª¬l±!@.O|qžù?ϵ~f¼ŒI&4G‰O<~b³Ù­äþ‚K3ŽOÛíWÖ ¢e™¶(áÚ3‘ñü½êá4x‰Ye ÛQ’Ûˆ÷5%´k4mÂId“p±ànøéþ•gá»ë‹Q-­½Ô°1R§ qÀÉÎpG·Ï xKRÓo-ïå¸Ñ)À·ÃaŽTŒ`;“ÿ="khn6•X´YòÙ$e)ž¼ŒÔkXH¦hÁ–å‚ gŒ÷žÁ¿iâ'†EGláb“C¸9õü šÕì#µRHmc*Nâ"]¾`ëϿ󩒩>a"3)ÇNœ~xªãp%»’Q!ßµ×!ˆÎÁëžÕ‰“ÎI0SæÅõ0fÛÎ éÈ8çµS\£#»x¡•A”m8vÉìpðãçï*8§–;“„ž „G”\‚K”mÝÛœþ½OˆÖ’é²™"c"]FÉäN†@Tð@ ñ‚Gj£¹³t ½‡“,‡Í‘PzT`ûã8Î?*–ª·(REÂíÀm½1Î?<?ʯ4jzÂÜi¯åºÇ°¡–eë´©àŒ‚;y®ˆÞ-í­Œï4»ZöV–ÝÊ–Œ¨C‚Ë…êH‘Àjt:ðkÅè–±µÃ)úòNKtnÞ8#ó«+[ËA‡hî¦ú‹‰,ЩÀÖÌ»pÚÙ$þ!íR-nîîâµ· -§S{s-à •Ç¨r?'SZo‘ÞæhÞ)$»h#Tc‚ kÆâ `‘Á浉´ õ/§2$1Äñ¶ÊÂYá$388Ù9ã¯Q\î/O-õä’êúm¼RH$׬ÓFŸÂžTjNâ9àb·=ÀZ]«Ûêk)n×’YbqéÂ ÇÆ2Ù8éÆkg‡MÒ-¼È%Ð$®‘Ý®©6§tUU—p»Hü Î=j–§¡è)Þ›¤ÆÈï$­ysw,Ò;ÿ Ï$ž€c99ªôñŸŠ%mÒÞ5¤FVØðÚC"ʸaÙîr ð@Ã6MTxä] Ú‚EnPºÆtÈ&lË¡1ŒŠÊþ0ñ£8I58L RG¥ÂÞb“éü#‘ÿ5)¢ #f»èý±x^Aû…ºv'*®7.ÝÉÿ1#â¸/‹uqâr]SÈò’õVhã»=+œwk_‡ UàõãÓŠÅ,{ÕÏ>–àdçû⨮uËK+û2\™ïÙ„ ( í<öéü«cGSƒ‘Œ`{ãÛõ©ÑäŽKdœŽžõœ€qÈluÆZrG‘œõlWàýiüÍ_SbÀnÔ'n}f»÷ìIiÚÛòK_B§¯RÖ»®Å•vc#ˆçŠŽéÄ™R9/ò"¼Evንb¤çûö¬ò\“ŽžØÿš¯t!‰p}LHÏcRí7$ªYˆÛ‘ÊöãÒ¬d pHÉ ê9éXæ `$Ç9ž:|Wê?ÇuaáZA-u6˜.Ugv©Ãg¸þ5ã#©­½EàGÉoæ;mGŠ=‰²sð{÷¯ ‚Uš#4(RP»Žq‚9'IpÖ°Ýæ¸PÓ!sV%÷²`•b2úrqð9¬irÀ³E ¤±ÝLÎß^Òz|³–Bà»”âÉ ¨Ôtød°Ks…Ä¢H#½:á>xUËI·ÔTtÂcßÓÈÅ$ÚX‡É6š~ŒÛ±ÿs@Fò÷µ(õ “’:v5¬d‚åïn´Ý7i‘3q¦,BÖ>„˜â*I=BòxüêÉ‘dÔ^;mªK½œ][ïØWÎ\)ø#¸¯I«•Õ4øîl4´Ù#ÿ¯ú ŸôÜ`mÎà–Ç8ÂŽÖWóÚYßiÓ·…4+Kª6Ÿ¨]M¥+ù8}  €ŒãÕÆq´Œ÷­Ý|QáûE– imí½ÓÛI@b— °tãñt¿ãi­VÜèbÒäEä·ðL¡GH®s‘öÍkmûCñ%Qì´‰‰;KAkrx$ Ìßàq‘Q—ö§­–•KÒâh˜(Y?z1Ë`@Ͻk·þ!:Þ©%åüQÀÆ%‰ÒÄgn $äç§öb'”©$¬¨›¿xÊ„“ÀëÛ'ùW›åÙÒª?š¤>G#óªç„\ô¬¥eŒNZRÃh#óÆ+%ÊÜÞX[ÂÑ„]ê±É„ž ðHcþüÕL猪å%·-9Bó¡R±döÎ[œüVh™?&†9T²ù9&àòª08ÚO9ê:f¢1˜kÆ!ѶÀ«&6)9o¹ÉïŽÜö­UcýÔw\”ÊG¡x,Ãߦ;Þù—4É$T<¼¨aÐc½A†8&!‰b˜ôª1¿Ïß³øwPN¢c‰!"ü¬ ÷a¶p®s’úv®˜ÖºÍ–—Á{$ßLoŸk=Ó}J3Î +))$g‚yk¶±gżÒÍqj-{©j #“³jÇ´Å<L‚À»ã &ÞYnÖoß•úæ² ;Ü_Qm$‡Ã#Õ.HéÐŒäÕ5™wX­£-Ýãïó-­ü¸ÒÙ7,Œ e9áœãžùªV×-î¯î£Ó ‚{Û»)`EsróÈèùQ·Ð •ä‚ THõ GGúÝNöæÞ(àm2[ òçiv®íÇ9ÛF dÒÓÄ:¥´ÙÞCgil».<ø` m?¢5 –—`ÁA?5I©C­íìu‹ë‹9a†æ_ñy`c(sˆˆÙÁ&>qÆ:|ÕF¡gw kÞÇçA+Ä÷Ö·,ÜŒþèÈÁ\Ž:š¥ <¨%­,RM³ËúÇ8=Îìö?Ò¤B†6Š9/ubU’[™X¢€NñÓœãùÉ+˜ÄCÖƒ2†tïÏ'¶zÔx‘|ÖvŠG¦âc¸r[¯<s‘È¢â/.p£D“çÌÀå€'ã8ÀéÒ©¯È½h„O*Â$2œ÷#?Ò¬?f·BhŸ¸%¥’xÑ"e%Á†AžHè9ûg¿õÈ•2Àî]Ÿ‰ž6Qúž zWG‘•צU¯T¨÷WPÙÄf™c‚Ò´«5¤*ýuÒ‚ ð.Ðî«×vÈÏàUÕ¯ˆ#šhmäDK“åyªŽ˜Çå¾ëù ØÁÈÏ¿<ŠR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)_€­ãú©mÄ¢;TlŒ·cíþàÔÛKhäcp±JclG#Œ`‘ÃÆHíU­é’`ÒDeÛŒXäã9sÆy©¶V2 §›ykxÿ¹X‰ÃÁÇ¿qŸŠØ­c;¤iò ORÐàVO+ÖÇÜsÇâX€çÜu®c¬ÛÈþ0ðÔª¥’5ŸÌ$~©ïö5ÑRÀcÂõÁ?5mîwOµd•Š ¶:àc±þûÔ9dz’¸"¿ jÁ¿Åu·jý|¹ÿó5ú+ö&tMVB /©…îqˆÇ?Mvà Ã…Î {|ש-ħq!ˆíšÆm“+†9ÜAã¯Zϱ#ݨ°PØéŽ£š¤Ôu‹ )-!¾™c–îo"Ø89•½‡üÔ´‘<ÀÀã¸øά]£#jàŒ` ô÷¬d e{÷øâ¿[èzh>}ÈŠ4{UºóŸ…Rôà÷çÛíwš<Àë"¢‘,¬¬X7dg¯^y÷ÇJŽ÷koj·W.Õ¦’ Ò.sÊ*¯-ì03ÇÍAYL#­íIy(øWÉü<°e%z;â°µôñG¨Þ#Ü\ÛJV=9‹ Ëéb:c-žÝ5ÞòâÄ4w0ú@+õ‡(ÁØ?ï‚ü8éî;Æ5ãs-¢F¯}"w»»Qs!Èô–99ÉÛ[•-¤™˜ÜJâ „™îÅÄ*«"ž‹B@9Ë7aóŠ"ÓÍt-„Ên^)Ãùû|Æ'€x9Ç·ST—¯©Í¨*Ú‚¶¨ÖÜÎêpÙÁ',Fðõ÷Å{¹mQ¶Âe[–Wk»5<䓃‚ÊFIÀÁì ë^!»¿XZ(  1NQ¹´±~x¬¶É,£o)Ì>\žd¤SÜÏnߦk›™Ú H!PA‹Õ“Ó?§_š×.¾™7g4’¥Ì&Mцܙ-ŒðJó·šÅ6Ã-½Ôv±˜Äa”¾ö$m#ßãŒóòXÈ®v>âÒD„”)Ð 6ûñíX'7 é.cCS&Á äs8ì=¿:ñgkê‘„äa•_y F£ŒØcûïRT¬¯(E“Å'Î1¹Ç~õ_¶0L’˼ÀÌð©ÜT“€G=~ÜuéY œ$ÑÊgÌË,{“hãÊs‘Æ?!UW67ˆ*³È›™ I‡+žI眜cóÍS´‚éÌ2FÁ¶à‡Æ>~j©{Ó°Tb£r‚YF+ÎŒÛÆåaå‚?<{Ôٮē´JL8ÆÂ2;ô®ÇªjÚ~Ÿ¨]j¶«JÖ }hŸSo2ù¨@Rõ“ÆAà0.î#·Ò¦{MIµ]'ÈÑ,u®¯å‡1î,0%,ÎÌ d<A2,í.$iá3H"Ôow[E©j(Ϧ[íÏ–¸åÙÜŽFÎ É5óP´³›R–ÒêëL‚ò ÿÃ㊨/$‘«<Ø6Ú›B¨;Îwb¢é×¶_õ+w7ˆfÔ,d’í—GÒ¼…˜8+ÈU.Šr}LÀrqŽ•eynš¦œú[J%¹¿º“P’}VöÒ´“*vú7>@  ž}ÍcKKIe–ÖI´Ë =Qä°Hì.®'wh÷ ´²;ÀïÎqZ|“¥®¹"éØÞYتA$ É9…üd®ý àƒ»œÔnÓN´…#Žx/n|¿"áîjI(;Y×8ÆÐ9ÏÎ9­}RÊ0Föî–Ѭ2Ü[•S32ò[ç¿Þ½5½Œ-Ç$ç[–¸Ädá³Â÷8Æ{õ¯l (•UT†Ù ÀxÈÇn¸ÈÆO5èˆâ2̦$xáä¡aç‘Î9ÏûÔe‹Î gÝ&éÖS·©(~ëÖ©n´÷ºHÖ9ka²F`÷8œš¯ðÞµ/‡¼K§ê_B·Âg+O·Ï îÁÁÃgŸjý¦þÖt[Í«s¦ê¶’ÄQ#™Wó7ÿ»[•—‰|9¬0Ž ëidˆn¢hÎ}€ þY«ï%™JŒÞrÿÑ'oò¯‚9•@Y÷¶r^xãÛ ¶£]Ü´È­ sÈÌŽ"øŒœ‘éÁ#ߨ¯ÏÊ0šêîêæHHvÆ5HÔ(,pIÜ@Û}ëBÖb´Û,W¦æHÆé J§CÔƒÉç$ÖÍ¢øãÄZŽ;{Ù/,Ô…ºƒ¼Á°cÈüˆ®¿¢þÔ4{éã³ÕPé7`Gpï¾) ÷àûŸOÿ*éŠÊꮌ®Ž¡‘Ôä0={תR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¯Â s%°Š{ˆEË«e'–Ùˆ›'  qúãŸz°k[­D‹†‹é­æ*'¬yèÑÏ¿Æk$z6•Æ/çvRíŸ."Y0qЀy>ý*ïXÓ4›D–’"Á#%¿œNüÏä{ô­~ÈDð•ž3·§§žýùü«$¦3#4h8Ú'VO(,vƒ•ôŸœv¨ª±³+2 ©ÆIÉ‘œà–Œ€Aê*D<äöïù׋‰ŽåmÇð>:ù$èĸlvªÉô­"mÏq¦é÷›9–Ê&ÝÏ|аÓáÓì—Ȳ±´´‰ß{%­ºÄ€êBàgÒ§‰âÂí,YNc½NM„¨,Ná‘‘_YÌB]B„xÿNk4¡Ú2ªqׯšäž:U“Ä^ ‡$#_ÌÄx!¢ä~µÒRÞXî˜wÐÜÖ§ØÄ–v sƒü?ñ÷˜ßaUb§haÒ¿^xv#þ¤¤×·eì 4lYT"àc'$yû ´¹¸ŠÖFúrÒÊ‘D%”(‘³Ç8íÉïÒª´¦ m B[) µ¶Vˆ[*­¸àn9‚3œ‘Ué÷2êzŒ·¶Ð¦žNmÚáUÄ€Î6>y'øŠƒ„Áö¥•½Ñ‚öÏȶ¶±$’Æcëdظ ³†ÁãwQœg¥{k›û;ˆ­?Ä-.#.¸R€J²‚9<Ž™þ\T¨%Ô·—˜Y)º‰ýÀ'ã¹ã¯jt·60*Þ)ÚI*\G…èOÎ?3XÒu{É ]¼ 9^3Ž8têO*µÞ¨&M9”HùŠH¢ Î?Œ`ž>õ0[Û¤I$ &’l´—1³GðrCu½}’&¸F¸úˆ•×͆(Ùwcü¤ž3œc5æ6MÅá ‚޾fí§¦rTüt¨°5ÌrÛt‰°$J@$‚¸*2I\“ßµ`P]iI˜2¨`©É9,pǾO|WÅœ»$ñ’ª«ä¨…ÁÞÙíŸïž+7ÔgsLÅŠ±i$(FÕÇ^3ÓÒ«ýŒá‚v,G‚I~ÄwÍiZMäK4¦8ç„eã1’xç<çŒð UEqƒå†pØ,G🗥Xʑ˙¹˜í8U™—8íýšîž’?Ú_›q$Ïw ´—XKn¦Ù|²±+HÇ!±¹¼° ‘Ò±ÿůk:Ž¢ÆÝôØí!ŠÌ<ÆCâ@#"B°*IP23ÉÍ_y1žïK0Á +\ D†õ†F#‘ç–ÉVôà2qŠòÚä]éc'‡­\‰^m:ÉæhQ£hÜ2n;öÆìçà§ââ¦ÄÑÚÍ}j—>P¸Šý[üTÛ 2¤„HÂàç§«8Îrd[]é[RXõk¸lôëxíåK“M³’žª3Ù˜œsPc¿ÿ¸µ°µYᱚåZYE“EHØŒfRqœ nù㌟Ž+í½Ì/Àˆñ0ÁáñÙã󯡢¹¶ŠH‚Èl’Hå„€€tŒà{ô¸øOƺ¯†§‚Öõ¥½Ñ¤;M›8-h0èON9ÙOCÍ~‘²¼µÔ-`½³™'¶¹Ì†Tþ!ýA ƒÈ ƒÍI¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)_Ša±†y #£DªÑ¤…°ª0Éäçè:öé[£¨êd ªËæ,öÌW8ä öíZÜÚÕ µnl&¶ºAåùÒ€ßPÎ žAý}ÅE½žÃP²6ÓZÄ2žfé0…0«<“ÏZ˜´”D*“î2y÷Ï_·ê'˜6î àNŠª¦Ú%²ê(²,Æl”çõíX%`˜ÚÜgœŽœÿµ|Šá€ô1Ü{Ѥy3€v©=y÷ÿšôr*)Lmç®9ö¯&Q»h 麒x½@š7rr{cò¬‘ÈŠÉäõçƒYcº;Õ†v‚1‘ÇÚ®â’9£\1Êœ2ã‚{i‘s¾EßÚ©otÝ/R»³ºcšæÅÚKY æ2qþÃ?añW(–$€ ñÚ²±SÎî{v¬&"“hì;qÜöþu¯XKâí6é®ü?wz‘B­0´ˆ—NAû¦NAÇOֺ׆ÿn·‚H­¼M [J"8š2ÚÆùR îpËߊîÚ/‹4ÁÚ^«§^©\¼"P’Âùf&Ë.NqŸŒf¯IC2(*ûŸh'ùc?Ÿ~ªmäs­Ô](ܺ|š# Œ±êAÆG‘ÆsòîHàyò¢_|±†PÙ†ìssÐçz¡¸„Ë"<д6––ñÆzýC>ÏIg‚rAºuª›í=Þæîê©ÙVÐFÑØîU/ǧ+î ¯Z×ux¥¬Ò§+i$Á®™ÚèW¢à{gó­jöh`žÞE·ºI^é™~¶&O6M§jú‡¿œVIö’©¨_ÞB×6ÒZ[°Û‰Q„Òc.[ÖY"hî$ŽhUs¹S…‘xÇN ŸçñÍeu‰‚¼1Ç$±’ÊǸ?Ÿôª‹ÓsFgÇÊ#;_%wqÁè0=Æ*܈%ß ˆÑ¼jYå…XÈù`G§8Æqœ}ª#˜ H¢X ó£Gê¸úV àò…>ÜýêdÒ\L›¬[“$± |ÏŽƒ##>àœ“ñœácI¥š$·Žy?s4¢@¬N‚¼Ž˜ïÇZ÷<ƒ 6w1<“úDR³Œõ<çÜã€j8Žñ&@¶òÚ,̆UcsÆCq‘Ž'íPåšâDÊ]\œaѤ$€26¯g#ãîÖ;&ŒÇA)ýÑ0 7SÆ@€1ïY¢‘ nÑ™Ú(ÛÌ(»LŠr}ùÀâªâŠÖ$f†ÜGœ©ó `ž‡žp:p+ÜO,„»ÊBpª§‚2;|Œÿf¡^i·JM³‹¥Fxî­™BÊ99dÀÝíÁúš [v…¤†hInAÔŸÄ=Ç~UÙ¼-ªÍ¦é66°ëP©†Ç͵YÙ—éå”ÊBãyB ú«wµLµÓ줉ÚïQ:eÝ•ÄïpN$ï~\+™É8U äOLf®moôùá»’Î95¤gŒÓYþ–"Ëê å—,w6GùEG½Ôtønc¶’ËPŠÎTß—P$GiÚ¡¶*¨a€Äã®yÜ~ïw]¼Ÿ~µ•h¢2ËÓÌÈá²UVLcø°NI<çíQ$r6¢ ­˜C,hѨG=ÎHþµæ$8·œÈÄ2LîNÕÇ=¸9ëÇ^õémÒg‚T3n4ŽÑ°_3'ºdŒpyɨþdrNòÊ—2m”-¹ä«g÷Ïr{s^w,É${&w8.¥°XsÇ9Î*:Ïw¹$7!â`R·ñÈ#Ïæq_ö´r‰!eº?¼‹Ë #<ŒûŽ{ñÓ¥bžŠ-üÆBG¯wÁ鎟ù£Û¤q†8”ùžXX×ËaÇAÇŠŒRdi(Ä¿õÝHˆg†çœüŸ¶*3ªNîó³Í¾LîD ¼àŸ–¬ŠÑ"º…pÀ·¡ÎA#§qYÝe¹¸‰Ü´æI‰$¹G8Ï$€?Ú³C‘”.Òe•O88ëÆ0N=Èæ¾¼Â4UHDm£÷h!<žŸ?ØÅ}IZ1º0ÞfíáÊpsžÃ§Óf¾ šËX]*gxôýX†äâ€2}·Œ®S·í_ éJR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JWâé4Ù&PZýa\~é¡Iàýøʢܛ•–(nÄ`…vŸ0Ž.;`qýKoðô™¦”G4œ¤‡\Ž<°mQdŠi,âhåsì ²ŒpóéV¶ö"K,Å1TXÊìa×ð=»þµBTGAÓx¨³*(8õ1ã8äÏúT1¸ÆŒüÔyâäÐ{Íxž½AÿLVdt,Åç(éóýšÏjªÑ1Èb8< }ÿZ41}DIŸ ´ž1É?ʳÆ?¡¶ÀÏQÛµd Œ²äœ@íþ•…#fŒ€;ûÔ¨e ˸©;G#úýé2NåcŒùïÚª3$wY.»OŸZÙ 2ªAÀ^Ç’OߥM)^X½Éê}«,{ž&'ƒ»¯÷š¾±µXÒ6¶3[ÝD¥¦ŽÏigSÕ}^“Øò=ê—ZÒ­æœ^êS:|[ÆÍd7¹+ýÃÈÉ}sˆc½Òæµ»†ò[k¤>l7Ò4mnÙ#† ¶9íֺ߇?k¾!Ó-Œ:ìRkPï0ý[Ä6«Hvc!ÆO>®MwëþÕí–=î»1*][°e¹G³Ï ç8$UÜò• ´²«m‰g;õ6 íIã'Üðg¸ŠÊ;y$0£3!¶2ÀÆO¯È`8ù'š«»6†S·Š·7NÏ•“’OqÀÉö?¬)™$o(ù© !\y¼`qÐd`V´Á-ò±£0‡%£Q´|v'žs×Þ¼I$€0ÞHU%|µÉñŠð¬Žó™¼Ü•'U#ÏŽ¿ëP…yо á'¯¡èj<ûnã– "kˆÍ¶ðD_Ç‘ÐïŸÎµé-æyVUIḈ–I Ç‚§ƒÓ$þ|šËs”*†Df“26[ޤôƒ“œqQv4.d}>mÒ3GæB@ ìJ©þ]=ûVi¬a•gÞ¢%|sIÈànŒñ Éà矊ˆ,•í-¡Sº‚A"ÄM½Ë³þìp1•ûw¬ðÜêÌĪN±·”C3’Š/–䃎¾y¯vmjítÓF`¸–s4i±•¶•*ÝHÎãÁÅxPÛªN³mI vóÌ¡÷Dulõ¨Îì.#,‘$¦kI|—^­ÀgÌ!ˆ`1íž½8¨3¼éždȳ±Pñ7ÿ»ý±^-ZÖ[(Ù\ QöËl´œãö9øëY`¹X. ™#0°†ù£Ž8ã£gß4՗ϵX ˆ%y7säž¡‡ÁÎ~+wÑ®-`Ñôyn¡\Imom*yd Ê …ãqnI$à ô­Öy4ø¬ã…›[‹Í!’ÊÞÂ6 ÊÌ%ÜÎÇÔ¥ÙˆÂýÏz«´¾Ò/m-,Í©ú דNæ0YrˆÎXî%Ê…ÎãŒj¤A'ˆõãuieumñ Úñ.X¢³í5œ2 ÇS[´BÂÞKÛ‹{Æk©Ý¥Ô"ùŒçÌE¦ v•äwé_lÍlÞušÆ—Ó¥’D—ÅÛ$ '1R~Ý«Íî‹t–‹ WÌÉoiv×s ¤=9ÎOq…\Š×µ ¹õ #7²¬Ùööð@À],¥˜Ë´•8$KuíZ­£ÅǘYYÔÝ ˆe%ÐqÇÀVt 1å¶õo³ý ý+fÐå?ãZ3ù-.¡l©.ÞI/Û·zýcJR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR¿ØX«Ë;Hçé¡d‹0ÝÏLœvÏÅIE¹Ô£[„»;•Ìf#÷c¶xïñúÕmä `±–u!!f=zõ÷=?Z¾{‰V(†o.È÷É=Î20:m9‘Ç<~uOgw4qº!qœÌ¡›;sÆ2z×ÉITgÇn‡µUÍ)ÙŒë뎽ûý«ÄM¸9\:W‰A#ŽcšŠKÉ’p½EDXŒò3áA$Óç¥f†fÛäîeö>æ§Ûi—I+K½EÎÖäöÉûgý:TÇ·0ô‚Ãq¾—çPb$.6 àsìV@]ÄC :oÏ"¬ ‰¶´ð8çŠöņB¨>¦$pVŸÞÜ!NFs» LIXÌ¨Ä ¾’Aêxÿç^®f;ž1¸²·â9çæ¬,ÚHâW#é ɈÅYÔ®w!ŽF9ªM¢Þ9/RQ\yKôáÕÒN£*=iÓƒŒpyâºO…ÿiº—‡§ŠÏQ «é˸KŸÊfÞÉ“ÿs‘Ñý1’þÒ&Úíe4‰òö³çƒÀàñ_`±ý“5£]&¥ªjpäK4Óˆ6c¶ÖXÝ‚x¬Ø”VóJ­%Ç’T÷¹“p‚ž}¹Nž&ý…G$ëŸ;í% 7DL}†dÁÏ=85&ÛÄÿ°ÕIíd³òÁTß6þ9cltÇ#žkÃxÇöˆwA¨Ddo,©Q,~@޾ø©¶sþÉoÖîK-+Ä¥…¡¼½º¶ŽõÖÔ¬²‡©qÉëUÐøÏö“5´zmá*Šé!ŠâMäñ³;ËÃùÔ;­sö5w¨‹("×,6ÅçÉrÏäDÀuæà—'Uç<{Ö *ûöO{¨Á¦'ˆµh¦œ‚àA†É .ôBÎHÇ=AÎ:4¿²xÝí5Û¡Ã17•¾^zWl}ëX—ö-©'˜Úˆ¬/l„žÞH±ù©~zW<×ü%âm O6ûLž8Sê¢Q$x÷&@û¡IÄò x+Êž™ÿN•Ñt?júý›ÜÇYXGc¨êyqªŽXƒÔàÈäVãáï~Ïl}Nã^´Ô.å(·w0\ˆ•ƒ·w%”õ9%Aö­æßGýŸMôÐÃ-”Ïmõ6ÑfR×QL¡wä¯È¯xgÂ÷vÒi–z´q$ÊaKt¿Š]£#*;Ž “žk]Ôÿg7-kw Œ–zŠÊ E»còð8ÆÜÐW)?²ÝHÓõ[o¢Õkù¼äº·ÜùRuXÁ`0 óÓQë¾¾ÑàڽĚœ1FeŽù¬Ú9|ü¨ÚàdÇ-Ïnµ§<.U¤7ŒÒLˆ›ñ†T6ìÔ“Œãã¡è~>Ôô¨í­¤TÓ"‘m¥·–ùZKpO¤Œà=$ôÝ] BËW[ûÛI"¿wŠ-¶7Æ#§±É-éÈÁ%@8#ަ°\"é«ß[ý<·¸hÚ+‚D à)ÎFrN1ÓŠû îŸS ´aqæ¦í’!=9$t ž@'âáahbò®ñq9#)aГÀã9ût¬ªû³TòG(ÒuQíÇß5 åÂKÙ4c"7€¯N¬6ç'gŒàµ…n#32™—ÌURÃŽ¸=ð ¯%æ’faòŠn2±–ôüf¥*®öV%Ð(¸=`zW›€ 3’ò®ò6ÎqúT{wI$s¿Öoõ/èsŸÖ“oÄr~&í׸ëö¬)9’$Þ`yÄŒã‚^žÕå™`·+åæO/*Ñ€Lƒ8àg'ìÔv˜Ä—r;(B¯Ï:uïU±Am=°v‰S{*Üp¿÷¨*“YÝ\_¢[Î:ÆÁJ’0G«°9ü«"·™1&[4Ï cÒn$£q•èEa åÏ.V5D\G<ܸ=9žÂ».„“Í¡[ݘ–Ò¬ÖCp.“å)]à˜±±È8æªb°Ïw%ùŽòæho2îïÔÊò?¨(›j㌞I9T‚v¾µšõ¯¡ÄÖ°¯šÈncs”89ãoE998«yµ+« ;»hm¯ŒVóGf5 ¶*¹@8ÆX{ô¦“{ 0Ìémª^]ÝÞ•–kkt °+¸³ëÁ ŽBäVcce¤¢5쯩Ïqrë ±ºdŠ%`Ä3 8QùÕ©kZÖ;‰¤Ót5€˜íä–éU¦læ îÿä Km>Êñ¥»e7M0›Ç†TYwEbëæ—#’J×.-áŽÚI Å6ì#š(á Èø%Ù”¾xÆxàU<ȳ¤ÓˆŠeÉÔ.ÑÐvÈç¯çQ¥Ë;Ú=»T(ö9Ž{ý»ÔV·%Ë8l°$© åàóÏÆ>x&¡ù/ªUœ¼Î¤ ¶Ÿ#€zw¬²ÛNÒdª1uò÷„çñǹûV ^d‡ÊETRrìÄJèà‘ƒîjÍœñH3”lSû›€÷>s×¥|yœJ0Ò‰<¬1s»=OlñÖ¢¬Ò2¤O• ÄH¥½e‰À,O8Îr}ðMí z+ÊÆç·nçÎ eh„‡ˆãqÄ„G$ð9'þ•ðÆÎ¥”.Uv³)*qß'¸À=Ç^=ª å&é ¼ä{óÀ¯ˆ‘F¤ UŒç!ÔH#‚3žA<ÿZÍçf£“° "$õÎïåÞ¾§—6ö;­ÙÙA¶ñÀÿšõ’5a ÛÀ,¹qü¸ÿj›dñ¥ý”ŠBÉõ° ǧÆpsù5û”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥8í¯5+kK»x ôQ;Kâ rbZoÖw2Åõ÷^KH8ä´ã9ø?51¯æq£~ív¼Ûb8b7sœƒŸšÝí4¼Ñ Äç©,p2k˜ZØYéò‡€wYTKäÈ[ùø<òkv³ñ7ˆt¨ÖÚ=jî#§Æûì ¥5€äwȳtÏOã¯]ÚÏ<ž$ÕÌŽ‰¬5 "¸Ob#+5—Œuíõoíµ«Ò^Õ$Vžä‘Æ2CÈrÅ”á‡;O¶j<8ñ6›{i©Au¥j {p^DÕ´‹k¿ òÛ•ˆûôo`1]zÃöѪx¦Û_ÐÊÅå:¾õª4Ù@XG!’œ±b]Ü\zqšä“\‰ãη`VS1,yß RûNAÇ¥[㎽êï@š+9îæšçéa[[Gýâ›TÚTÄ9iØsXLw6S»èWwIæ’‘ì¹r2Ä dŸ|r~3TCÆzõ«6·f9g¸wf¸gê0sëÆž Á"¯´ÏÚ/‰íŸXÚ¾ ·Š×L†H’M`í´Ùø¤ RrõÉÅ]·í_ÄQ"õ Yìµ Ó†»i$r®Òá·R¹9<óÔŽ*ÒçǬËsÿ£t+ˆà²#Q¶Ó#X¤gÃp®­“´‡pâéUQÙ½åÜwé—Z9‚×sÛêó @¬ˆ‰¢pÎI.£~0ÝÓ6ZM¯‡VHïôÿÜè‘[B×6óê\F4ÆÊó!|–~À&»!M*þ1êžÿrÊÿz\ »‰ØTÏ á™»äÖ¢úUì—¤YØ®¥knÎñÍ¥^AsÄä+,åyÃÇ=z˜1jÖbX[N{&iËæhÊ$“» ޠއìMeiÄi²âFóØLäžØ÷¨JØó&’Ý…ÃLD߈ árzdsÏâ¢E$¶ùo4ÓÉT+ƒŒwÏ<“íÐàÒ9£•®EÔÃnÃc¬e¹¯fàgqV^gÖå¶<~²ÍŒž§¯LÔ‘ä•uv‡È–ÒÍÃoRq¸gzûÿµ{ŽIà‚6–=×.¥§.D’`ƒÇ\ž•î)Þ‰æIBïæ!äž™Ï_ËŠÅ.ƤrÆ’ Žs埊ƈÄ*ŒXp¿Ûýª“s<-º%<¨è—Áç§AØýê*Ü›9¢uÄÖ÷ùB@T£0xžõ[z*7–3å‘åSÆFG\oçXn£ITÀÈ]‹(‹ƒ 䆌tüªž$žÔ˜eA)VfO0P‡žØ ~|×_ðòGq ‚#[¥¥¥¼_âC#Ê’Qš^ª§‚cr}G¶1©Âó^›A X¥¼{eK¶Apav,ìHv¼×ÀÀÈAÏjó,Z]î–'ŠòãP׋,6úfŸ$¦$Üê¹õ.¶$ä@\q_5 Fê'Ò¤ÓÖÍbhîÌW’/3Œl•Q³·…ÀQìNpje¦±¨ÚA6±©Ã{Žž ÛFbÂÈÒ©‹,³‚ΠmÃ8æ‚k‹»û„›E_6+(ÒiX?ö@à@=ú ôÝtí>ynšMbímtø¢¹[kÛp>¢W'–ä`븜àñŒÖR°Ï)åªJdóËE(ç’Å€' Ï·çZž¡j°E"KqÒË3 I9üÏOôª·„a†Üà)=G·ØÔÅ iKJWÒ¬ý¡Ï<Œÿ·å(0n‰J`J úˆã¹=O5LC! æ!b… lè?æ°˜^'ݽˆ<´f`=psÆJ‰;¼»ÑŒjÁ7ùX dnNÞ?­`_©–It’1´*³Á³vzŒ~XíE7 ² ƒœ¶]†}꽅–ŠDfF`‘(ä)ÉŽxÇÇÞ°“,m$e%ÛœI²áÈ?>ÙÇ·õ¬¹R#pJ&༌óÆTcŒãô¬‚+f%¹D 6ÓÈãŒ{þ~ýkË©…ÜÅ#\$€0À#ŽOéœ|b¼7”’)•kƲ„ŸW¹þ¿ø©;¥%¡RA8éÜœqÍA“Îa&GURÛ†xÀü°Gò©"I%†HІbÉç7ðíÈaŸÏ¡÷÷©¶SÆ÷¶Ë*D›/#F\yþÍ~Ã¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)_Ìi®ã¬d܇\ÅrÝÜÈ©ËmBÍ ­ëÞ0­+7=0?¨üªv›nm5!ws/™l[ˆrÁS;†6ŽÈ9ïñÞ¬fÕb·½f´†WÌm­D¾XÀ“’xüýê3ÝEô­Éây¦i0‘¡Xºz±œäŸqŽ;×Ö{ðÒÜCæ^ù–ŸMÔ”cUÚ‚{r3^kM[-ÂUöà‚1“רäçíRÔ‰S`Ÿ÷Ò¹k”Ÿ/äqþõw!·ó`Ž4 ,Îer¤z< m]¬_5ŒÑÇ ˜“9ÎÜõã=ê†ÚÍuD¹€¥¬‘Û£>7È¡Iã$ œŽHöéSaÓ$eµ²¹Ô­­`X®Ñ[du`6åÛ§CœŽÜæ³] ÔdÔa¿Õ/-ä± ÖÓXéÆE‘@ÏlàüqÇsWÖ §êUªßx•ì®r—O>h%XTpkÒ\[Ïo¬duëŒm6÷BIçš *çÍŠ@…T€ üœà‘ÜóŒUÌ B#–îÌXù»¶N(laOçãäT«ílÍ,ivò›–¸Ýq$ÊT¶ÿ¾qÜ}‡m?V:›Ü Ó£Y#&I. ÇÙ+¼“»w<~Um§ÜiÑè—V–ö2Áwp†Ý–å¢d¹nFàAàrN ªš{¡§Ãw1ÉÜsnÊ£ÜÀ1Êò@$ŸŽOz›<óÙjŸR’”Ž+h줋L10Bw2“¿ÉãÇ›yæ¶ŽÞ™¯DW—‡Q»[‹q ‰£nË Ë=F*%ì¢âH.Ä“Z äMc L‘Ë 9ãk gœž~Æ¥ÍyŸ(°7ÖÖÓX‹9bž&µ çªàñÓðG£>¡ÍåÖ£©\YÚo´¼&B-š2J©Ý•~Iá½»Öçe㯽½¤pk^'·œ^ãQˆ¼d' ”e*ª2=}ó[¥¯íSTµ¶Õ­µcm{3,°>±h×v€<±· 9>¢œx×NžHá>ioÑfxêKo-‹H;ˆ+ŒžW+ÇZšúχFƒi«½Ž§%ýЛÍÓtÝN6ûeò×Ñw–_VÒA|ŒÉººð…ÛZ¿ˆf¶»m'üP[Ýi¬vrC[—FoÞ ôÍÍeµ²ƒS†Ê[;»Yþ¶Ý®áŠhg‰åˆ—У’HcŒv¨áýB6Žá­ƒÇ:îÞXÆñŽ_ŸW¤ç'žõUq¦Om>ØåF–(¦b¤7võ×’x¯,í9L’.ÓC>z÷üˆûV6Y$,›óŒ(BìaêÈ ç¦{~UñnR"ÅƒÆ ‡–)2D|žxã$õîkÔ!n.\Gs !wì$w_‘÷éϽT]MPòùdª©@NH=7 pFbIec ²åå|¬½sÝxãýy©¢@7hä1—‘ÜÔãž*µcv’;†v™´Q«žQNB®öq÷®•¥ÛYÇo§3EWEšw2)‰X¡-ÁÉÚA éò*f¡¥è–ò\j÷éyf.¥···Š Í’#Aå6pÜ}½9üY©v²4vQÚøeu+v€2^·™¾YK¸É©8ë»5©[êZ>“,éyg=æ¡0²H̪¯¸†ŽÖÀïÏ­l:u›ø‚oñ ZúÓHÑü© ¼w°Å•ÚòÝêàõ‡ÜÚXé·qÛZÆ¢âʘïçhõ€ln^:±Sê œ£©« ˨$žÒ+Tƒè§*ÖÐ[Ä$Ù Bc;WqÎI‘âõŽgKasp%v ºÊT©n}*ÄHŸéVñØffŠC4HñášàŒ?=sÔæ¼Éû›€æ&krQä•ÌdÀŒŸsœŸÎ¾Ø]Îu©jÉv…ã•Tþ"pûäs‘VúÑ“Q‚ÓOúYœH·fy¤Ð¦êzf¡ÍÏqe¶Ë µÆØü«Ÿ-T‘€w Œ×‰áƒHÝ£e§jwwSÐŒÉån辬•qH51>™b`na3ÜåÚÕ$ Iè§àãÉûU½Ìf/¦K-GQ·‘§Œ]›}=dòUˆ,J==Üf¾Á«}!ò¬ngÖ£I$yær‚®¼„b€¢xBžzw¬_^b3Îu )¼ùŒ­löS!^?çä×Ó6MâÝj{o!ck§(!]ŠƒhÞø5¶<—v !˜¼RÄQÇ•œ€I>æ¾i“-´^tnÒD÷&æå$FýÚ6Inó¤Ks-%Å«[Écphê@Zƒ×ÇØ>ÜRj~]ô2‰í^Í*¦OVy9s“óדQü5׈ ÷¶°í~1D óßÛŸjÛ¡Ðìžþ_-¤´ÌŸ¼Kfd$wPz.üB®åÑÞçEq¨K’ÞMÍÜ~ïŒõÏJŸm;ý[ªÊ­õ@‡o$zFâ3Ÿb?Þ¦Æ×PÌ£ÊAæ¢Ä÷FÎÑÀrzôíóU¶:q¾k«8˜…µ{™\ßK»v—zs€F?.¹`Ž9àÖˆµ`ùRFûA1œp;ç’xëíUwvvv÷pùvÉdXˆàO¥ŽpÇüÝ9Á$3 õ÷©é¢9dˤ›ß½¤ z¸õcœc§½JecŠ(Ìs@ 2 !Fz“ÅBx™‚£´$Ê„ ô6oO}ªÎÒõ­ež(-CA*§Õ}C©2°.3ØàqÌÖ ›È!»k¯.xÐÙ›™à¶•T;ðªýq…sß«Ÿ{s ÓZ«Ú‹]Mžâsy ’~ó< Û½ˆê8Æ2*ïGŨKotn¤³·6­çÉ‘u!ÚÄ)Ï äzÕz_  øá´³¸ó®ææGŠVòر-Ê ã'=T]Cuÿ¨,//­“É»S½¼º“\s’Û‰cÇAö«ß«¶Šº’îä ä ·¶ºEˆ>1·÷ÈÇOνÛxŸÄúQ˜èº„±ÜN¥&»k¢ßOFm€aÀ?ŸÅBÓ¼Oâm[›[M^ê;Xd6ÒéRÜyñÅé\2«n ÃÓßï[ÖŸã%0Û_CÒ®˜²I1·–;½€Ä˜ÝpxvÇÉ$ž:íQë~ýì×v!ÒàxšXž;˜o¼”VÆJ¯©F9ÉcŸ·5ÛQѯµ(¬í'ÖmZ[†Xî5]ùS„ s¾r=,§•«4ºštµºÒ5 ˆ]£‚þ8¤P1ÀY|·ëÀéÜ÷‡uá}Z2˧jH‰ R £º¡¡+×Óž§úV¼ÎÐÊcx¦d¹w 9< wûæ°\B¯n­n>¡žRÒÄH  Œ®Üþ€9¯P¤Ðµ±˜0óc2²þóäã#Úº”£g.•õúl6¦鼕vÜÌÄæ2w/?8ñSîdÕ5´Û{Í.q¦Ç~’ªA¬ra›¹÷1ËSÈà/"e¹´òu+Ì}3CmtÖ‘$p €"» $bÄãvÓ€Z¥èÈn'Ô®KKc{6ðé6Ñ,–ñ«…è¸E$€0Ië““R.´;[ûØìà³ZèñË5Ìš•Ñ‘îî?ÒêJƪvŸ|žÊ+†Ò8%»¸ð¡Šòî57ÓoR°ÇU±ÎF bA« ê9$I­V&x<¹DO…Fãg?¦~õÜ„‘ˆÌÁɸ—%›o©Ž8zàsï÷­SRy%xŠÉ4Àܲ,ÁväŸHÙ‘ÁŽ1·⪤˜C‚é¡Y]‹°YK ÷àôzñšòÇ ¢BÌŠ^En$u?<çƒýyªºÔ¥K˜,òádd€–˜I¹—¸éŽ™ÏëWRHD-!\¢`C˜È8äcž¹þóPĪªZ2 *HÎOÍbie*£ÌEy’‰òÇ8ûÔb1:ÆeÞV=îçÌÉì3ÏbåH”±éƒí‘Ü!XâOBHË)È>¼‘Ü9ãïùVdV2—XËÆÒ¤áÇQÎ:óÇ+¹b†Pà*”İ‚ŒàcçôȬn†8AelLª|¿ö¾3Ûõ¯ «#zrÞi2H»ØnÇ«}üÔ“™#Y<Ô- ,"C׾߶þ@ÔÛ–\*"+ ±åàwíÈÅFKEÙ°VE1ŒpÄ çƒßŽ™>õûz#ÿ™C~µê”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¯ç-òéÑKN-P4[TÛÚl Ï&ÄêIOÂyäûñPm.,NÝ6Ò2æ $™RívNÞã磨í^‹²Ü@·š•ŵ±&=‘-›'±$äd‚y¯—z=›Ÿ55K¯¦¾§Êšê9Wv.¤’2{ŸéSíôÝóeÉ7M òEt\…”rH Þ‡¹Î@¼\D¡©Â+ˆK6ì1üýúãj—fÁ'“aÛû°¬;v«ÍZåÚÚÎQ5Ç›Ãk.æP¾VòHŒt8Ϫ¢:MØ¿{…”[ ¢övÓÞ³Ž„*öëÏ~3Îj‘tï0áÃpG¸¥½½Ä—iv÷†Ê%B‘G=¸O©c“ƒ‚~:gìzÕÍ›ë+‰§²EEÊFâD3ìpI98Ï<3.?­·i¦KuhoàV.FÊ”Ü28öb1ýfÆ7vimÙ¢º;dW9ò¤P0}úÜÒ¢[[Ú#Éiqa‚[•’Þf „t O\Žpy<ÔØ,8”¥ÓÅ&äaQ;¾ÑöÍy¼Žá2FËìÞ! lê~j«NF{õŸÉv1#s#`7OáàòEM¸Ùuq~Ø$²Ä<€ÊÃÊ>ø÷é×Û½U]éÍ Ê6HY¼r%ï·ž¼t'ã½dX¼™/¥f¸_$¬P‹«Rí· z‡·æâ£,P†K¡qd|-ô1Þ[; HêŒà·Ø?§Å{›ÊŠxïd7qE&Ÿ¨Y_Ì@íéÃ…ãŽpjÆÉu)mWL¼—Oš-êÚE̦@P C>9!TîQñŽ2%[ê:­¥¼ ½ýΣ³j‡ÊZŶcñ éz™¡x÷Y‚ÓGhìqhwì^ù®’5·•Á_3iì::}ÎÃ{ãÛø´Ù. »šYdo Š.y&ÜË•ä€Iíê r"¡Úø»N¾šHn´ÛÝDÈ–‹2ެ׷;™mÝN„)'°Yj~ÖVÈI¦êÚH“1jÑÝ»ÌT¸+‘“éqÒu Çut4ýnX­¬`òÙäÓmåòøÎYã$oʶ}'Üõ«)ZãZ‘`²×tù¤eŽÖÖ!#Äì¬, Wsšû7ƒ5ËàZÔonl­d-¶cr¾g«vØÁ;Ž 8êsÓgé–—u¬ƒÄ moÒGi{¥,+$ŒT`+!Þ,øsŒŽ­“Q̲Å-ÍÅýÕ¯Ñí¡´´)>fI`²fÀôŸòàg 9nû«?¦¶hlY[nfÌÁ@*v€U²ÿ‘#°[;‹Ç¶ÕX¾ß*k˜bÙ$͆bprÈéÆr½a°”F%“þž3ë#g;˜–@Håº÷ÍQ¤×Ò4r¼•¹ºšØ\ΑGÁ ¨#hCޤñÎj®æo5H‡ÔÅöÆÑ&VP3}óŸaÐT+,m10™96–2€ü/SÏšÎH0}^.¢¤¦0 2äƒÇÀî?–j4·&E’+yeH6ááp¸[¡œÈ×»Kæ·–Cjò^ˆ×yxÕÇ–3ø}@tøø¢j*·åšVo1ó‘°öéÅyº»úË…Í­¾Ø¹i¼0ÉÏùNsŠòözYÜ-½2†2¸¸Dˆ?|Œ|c5ÎÓèï’îH¿q¾jÚŠXuèO¹©2Èoî&µuÔs65¦3@â_ÇÎOBkÉ{gy±#´ž2Áe‚åeÜÌ20 ß·#ô¥åÓ»G$ÐÜG§]IåG¼ ½†rŠ À$äaºâ¾Î¢ÆàJÐËg3ä\<[Šã¡Î öÏJ«ê)¨[˜ ¶+"¢Ë$÷„Q™ÓR5‰ûñŽ£µWEmei¦Ã ²2\ÝHw™¥–µ[r Ÿ|ñ‘Áâ¯m§H­ÒS)žMÃ~åã‘ÉÇ`1V‘JʦRcH1㓟pÛƒ_%dØ}@4ÎYÄRp«Œ?•yŠ$†tG`ƒÊmØ;ÆÏÇ\dÔ¥yaì…”I˜dew$çoµEÞ°<±©Ì2]ðyùíúÕv¡$nª¨‘¦JyŒŠÃÔŸnدVÅ œysÀVgR Xü¿*²Ì/:"“"ù¥Ãuàú`u¨X¹{ÒçË–cT°õ#ßçï_Î7–Yc\‡á ·<~!÷Ç÷Öªuú-MâCw>^Ö9 …×Éß…N’Ä0ÀÇRWÍaº¸¸+eowg$CC[ǹÐàz𼓷>ç'îk寱kf.š)ï-BD_ÛL¢îXò§Ö@ž1ž3X ¾™EÝæ$æ40Zmx*IÏûw"­¬î®nlÖ×è-e’Ö-¦àLxÉñ‚A wÏçYaI­ºÜßK`Ýî›É"Œ˜8%³íÁã­WÎÑÅ%ÜnÌò€òÏ‘<Ýä‘&HãÓ´cÃP®-a’ùDŸO=¿Ñ¤+$qì0I¹™¸†8àñR&Ó¦µ•5ݾç3[42†)a¸zï“לç­|‚é"LWAi}>ö”ÈË^vþwtý*ú;rÍm·PFöÊï± % {ä8ïÓ½CÓ/f·ñ8-Váݾ”*†cê’GáÀÇQVúÌi¨\ÛÞ>›Ê‹ôòE)¬ÜçiÆT“ZûÝÌzsI¤›¶0µ®‘o°¨€RCF8c’ ç¥d7†Ê& =ÄÉ?•õw3 ðŒvíàÅl‡UÔô³¦]ØxƒRy¦ÔYY!½)ä(²y*¡c²ÑÞç7šŒ #X›nÓ™9ÆÙø~N8¨½s·ï%†ÞÚÞŠ&œàdzUˆœ1'8ïš×î&Iw%ª?–ŠY£Ï˜©Ëcðž20:ŸzÏH𲙢#~À  ÙÉ#çý«Æ&i£»nyÚpãt'ûTd8fõÌd"=¾oÎzq‚?ZóôÆ6óPí–Õ|ÕrW ƒœs^·4’I:¢a£>ÀT¨`A_žsÅGš+uIÙT²GÁ팜vì?•G–ádxcŽ !×lNU—Ï*¡ç'œõ¯’4‘¥½½Ñºß¸‘ëô¯L€yãöäóì3E$M…µÀ$yJ»ÁÜð~äûw©FdÄ_O‚d$˜) ÄãöÎïß½Ak{¹üõ‚G†8_ËÞîˆõÎ3ó׿°¯¶éãuy2lõ€ŽÿÙëSÚêEH™¢f`›‡BÀu9ê`*4kù r+î@Ç{œœcw§¹Éã‘Yù ²ÆÄä0QzFAàýÅ|b®ã( K¼p€gøº’?ŠóètÜw$˜Üã§°qŸ½~½ÑÛv“¥·>­:çÿÁjÆ”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¯ÀU¥ÆŸõWguÝÃàWÚT)#qÜôØ5 íõ[K‹˜šì¥¡Œ¬&áAÈÁÀ‡EŠòæ ¡·…$f}ó\Ì=1ÀíöþµU¨Ù<·¦ —Èh0É4Žyã¡ö©Kx¶^xi_`\'sÆ;T{›ó=º9“fÒÁ-z‚ÿpûgØŒóRîÕìOø…¥ÕÒNƒÍº«ƒŒV1Á8æ³éú|wò^%£Éc‹…#Ä€ò:cìk©a$@ÍÙn‚0É:Ž·þ¬†b{ŸÓÞÊÂKŒ["Ý牽ÍÍÃ.wÓž}«ÊZÇk&øläÔ.ÙÚméƒå®x1Çîr{äÔ+› õ´^ëšV— £VžÚ»[™?û€r ÷¿9ª ü2Ýâ±Ô­[Ì™š]÷£×27àpsÓhR=³ÐTDÑN™zú}ºÆMñ;úòÀäI<õÍhvŠ,íd²º ’º3Z¼£;‰ÉÛ÷«?jz”ú'ÒGo¶ év71ÄY÷O (¬Çœ+6àc„óZ–£q °ã)¼„´!²ÊA#+¸`ŒqZMôâÒ{Q$r̪ò‡_7ǧ#¨9ÏåŠàMdÔ¥ŠÎá•ܲ³DÇhðåAÍozüw¶’[Ie<N FÒF#`qêOB3ׯJªƒé¡X-£ºßtP ˆI¹ëœäI«$”Ú\2Ü4óFà³dw™ÂƒÏoj¼yo%DH´Ø­RæQ4W!˜Ž¥vôŸç[2ÝHxÝUB¨BËǹäg¯¿ü׉äh“lJ%™dÉCŽíŽÿÐûÖKK©.Fmñ°“”#n1ž;üßzÁw%ÚA*Ú\yWdÇœIÊîºwÁãçÏ•¦pMÒœFÜ/LçßãŠÀ;O$L†4š2ªÎß÷”ŒûüÕ‚XLå6"Ä€‡SŒc¶;síE³h/VÙn'{o=¼‚à'¸éÀíÅ}’&YB žÑ›l’ÏÏæ>õƒêfE»’Úl$ËI(™GQß§±Ò²Ï Oa$­¾èHÉv–’M€$Pvžz7<ß•OžòÖ{†¾Ùs4MlÐÍ LzNîw`{ qšÉa§Iq¥ÛÚ½Õ«ið\†#¦®ädcÆâH#pìF‰ne“Q· êÍæÜMwä†B0Y ¶ã¸ öÇòª™¯u+ Ãaokq$·*~¦snNÃŽ$@?ZÁs©JT9¸¸€KDZÜo¨Sœä1Šºúˆ<»G¶úé®fÊ%³xÑÖ6õ»žôûûåcš[‰@°¹.ŠX•¶¶3ÀÎ 7aÛŠ°kL1‘n„>j¨pWÆÞ3Ðwâ¡Ëú¾ØmnÀk'7½à…ÀÏnAªfŸi6æžhcžx‘¼»}ã,YT.c%²èj¾ê9NK‹ÛMÄúgêÏ~^™â³Þj÷(ÖÏ ½±µòÅËOwjÊ@pNH$ýǶsXÒåïnûÌ0ÊÍôr5µ³Ä'#ø½GÕ‘üCÖ¤]²]ÅE D·cmƒÃòvà{ò}«Ìégo§Ç<–°HÂYb‘>œÆNáê“räçƒÝsÀëPí!¹Ž+o«½¾}8L² «!ôª«`r@Éþ*Ëc9McI’âidÓ×^¶¼¹ŒÄ¬r+0ò3_£î.—V»ºZݘ5µ“D#U‚+¿(wüD|qT³Áô—:\FÖÖÖÖ+¨î.ÜêB@È1ÃúX(qÙÇñQÍÝë]\%Òÿ…ÂþTmsq+yQËôÝ·Ÿá^{UWPÉ6!òb) ÎæBìÍÎà­ËlvÎ8è)¤¸Ž9d` hÈ>a9ãß¿N{~YÄn¬ĤˆŽÑ¸Œ¦Þ9ÁȬ’<»·)]¿ wý*8‘ÂĤBÈb¿Â9éŽ8÷¬«J̨P¢±r Œ7Ç8¬–_5Xyo敲}dƒŽ{cíPd¸‘v È W G¹À¬Gt²#«íbác”íǸ㞿מk8g‘„nì1°00yëðj\ˆØ©iX,m—²•=±ÐcŒ’~ÕŒHB®¢A´à“Óý{WØ&{fF‚Xcžm×—m.üŒg¹àμH"ž@žr/˜þVe_À£$ôÏû×ÉÙ¡§,²JÊ6J_9`N8ù¯ ˆÐ³Ý0É$~gÓ‘ ¢²«!3•ã#žsîOOÓŠI´îVQêRÈ™ “×8àwíR¯¬míî-¯’Ú§¤Ãqaas< 0ll(± ÁOp L¶Õ…æ –vº¯§µ§¢î Û¹0Û9³;8Æq÷ëS®¦½:y·¹ÓãŠЙ/íäŽGiN070S´À~U§êsµ”–RØ6¨Ñ©ÎÏÌr©?ƒ°÷õòõ›R‰VÖ|Cm$†Q°¡ìsÁRî*ÇÓˆ­V+{»KØa-u*Ì$[¦ Ë#+ŽNrGV·K…–C´³¥·P€n¬îã°?zÐõ›‚q —a²á\p;úŒóRÿg×Z¼V²líZÞGݺK£H}ðŽžüÖëâ[T’ÖݤÓíâ1^Ûù3EzÎC—©Uá‰Û׌׻⺖O¢Ó YX² ®ÙZAž2QXgô©²\ÞÜÝH²[‹kˆ@IV; ˜ œŒ`Œ‚x v5u¦=ËH¼#B\:ªõLqïמ¢¶d`2‚6mÄã§SŸÎ°]Ê Tv†GO4)h”’£ì¼‘ýšölÁâ—Î%‡š¯Â€t«K¡oJe ^FÄ`w÷ì*iÈ‘½Á•¡úßiÎÁñ×ô¨Ð4Ñ\ˆâF_ËŒÊx'®~8þµ:áïcWidbæ#Õì;|αFìysÛˆ”ÌmåÇAïìxë½{“TžàĄ̊0KHV%ö#?μ4²n¬÷C"Þ¦ÒòÓŒûppzךÁslÖ« W1¤ÓmWób”·˜ƒ€}Y(r½ˆÎ:šÏºxfh” B±y¤’1ÎAéùf°»Ä¶ìÞà v¸¶â<XtÁÆOU}Ç}uw§êš´I&Ô•¥ŽI…©à2’߇Ô3Æ~øª)_Z´Õoµ[K˜ã·Ag<êw”-‚Lq€0 ä’9Ï¥É>¯bl¥·Ó"Õ.^S{setª%f*»Ù[Ÿ`;ñðjâ(/ÚCy}µºšP‰om:•bÄn‡Bp:c§°¬Ù–)ÇœSr7@ùÚzc9ÏÍ]‚H^9!xç/)P gägŽ£±¯±,ƒ$²nóÎæ1õŒœ{â³Ce ®ë¸$¹šIˆT÷.Ý{(è¿—çX/\¨Ü,òC‰ã`eã8=rF:1I>¢wU¹•çm§jî;"cŽÝ=…U"Ê%¸ ªJÈFòÇ*F:Èøçš¾gh$ˆn[K‰U¤0 _`ãß{ö¨¡ ×Ѽk$ü±K’WÉ“¶‚99çŽÞù¬÷PÝÌ· Ó”ž5GE> AÈÝÆqïZÜÛãŽ[‚Ó¶hÌæUg;‰Ïàüµwó>n,ä·±±NEÆ«ú„£ W(¾zŒžFÞ1ŽõϦYÞÌ|¿[‹…7^bƼmŒ)¶<0<“žzâšãMù0\XßÎòyÖRÞbÝ-~"ÊÁ•¹èU]Ç•‡xì·Í˜`+V>TÇ> 0OBÝj´ÝCìëo‹Ì".ا wsì1Ž+4os<È"D`Ò*É £¸É^äd+$Y»ŽfGHSÊù e¹çúHø÷¨’Kº&é€ÄE—Ë"BxÎî_õâ¤Æ²yrýPO:#¹Ãr $Œ}±X¤†Wþëy+ ð}C9÷¬rÛ¿¡Ý„34…‚ÊzœÃöÆjh±Áÿ{&o˜v'-ƒÓ=ˆ«8¦’$ó „Lc¨$cíŽøÎS‚wË%_PÚ2½Nzwæ½AéÌxËωŠJ¦sÐô9ùÖG•âŽto žYB<¡3‘ÓŒœö}óšÀ-ÜGùd….[Ÿ»ž20ÏÏÍz,ù ´ ©üxà7n¤wÅK7+#©%•6ìU>­ s»€_¿æ+/âw¼r")`Åmø÷ÓÞ²B…¤9•;œn-¸ø±Øð9Ïå_ªü6ż=¡1êt‹lÿÿ5«ªR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR¿—öv…§-’½Åº^Ü•3ýgïÏ—n¸¶ù´õ‚o¦˜iÒò+ÿ§Áys€ uÆ3н Ž=6âÐK¥^I/Ó4Þ]Ú¤aØíõÀäðFk_Â×÷V÷zv—,—aQm.x,l¤ãí^$բіK#¦&Ÿ‡˜\Íw Ålœà3“Áb0øæ«tëh/ì ûÞų<Áá°€X1SŸp:qšM­jcNòSJvúøŒpÞ A‡ ú@ÜqÐŒ{Š­ŸZñ)‚Ý.¬!·ËÚ_®çHˆa‡#·zÿ>µóÂ×––öÏ^Çop£lq³Œ©à~ý¿¦û~–÷v2)º-êOC6ÌÀŒ÷8#"Þ9lPʺÜò¢•ŒÃ(ˆC»’=ÏjÇco(Ie–'»™Ôá=‡=ñØÖÕor©ä­ªeƒMQ™ƒŒ7N¼þU±$b(’HÁŒ™I,sïÞ±+–˜‰IIÌY^&ש:îqä‡Îã#Ï ÇÆ?Ò«'‘<Ãþ2áÄGAÐ àg&(îæWŠ2ž\CjÊÍ/¸Æx¨“H¯ ùé0Ê0Gßý«åÞ⑬jYWÕ0cœ:þ_ÐVM’ÃŽ¢HÔJ3 g€ ãÿ|ÖG¼óâ€b³dÉtÖêKÆ2rãÇ¿zñÊê<ÕfXÙöH‘ŒóÆqúóÛò¬a`ÌâYz¨ò`q(Èôç#Ö³5”­¹³)8òÍ´R1*=ùÏn{Ök_3Ék*á™fU\ò1Ûçæ¬DJˆÑÉ•9ؤ`œØT  †Úå'U³W˾UU$áÞyëØçíUvÚK ‹»±,–ó]K½Åëí#÷eOÜ éÕj¹W¸‚kwc+®ZB®PŒôÏ9÷üºÖg»ŽæðK:G ¬c†'˜“'³”=@ŸòñÖ½\JeÔã¶ÁudLR ’!;‡æ¥1ס¨í‡‘÷'œ»L10=:€@¯å÷!g·ŠÝUT–9KI*±ì wèx¬W”Ä÷tnû­äòT޽ÀÜ·©±Í12ìà‚r³mÎ>ÃãàÔo¨’2Ël\áFâsêÏǪÒée™žFUrì„=Çê ç?zM¦WH#S‰”˜À›'¿#§Qü»Ô­1bk8Ñ“éåHð«“œgÜ·½C½±’Íág7™è2nÀCÉÉ?Gó_ V©´Ÿdˆ–B°Z•!UAós¼¹¹à‚=ÍGž2a¹ºÿ _)c†ÒÖ{e,PÈíÄäžK’H_jóu~¶9ÿ¨´•ö4 fÏoZ‡Æž}k³ß[¿ÖI3+¼q¥´;ÐÇ‚\cg ïúV±5Ü34Q… µã”K&å#(ã®Hç'{Vk›è®haˆØ4Àà ˆÆ2¿óþu9üÖf>NßS(ʾ; ñÇóAÄÌ%0B »HªŽæçÑ×Óýš’ ºC…w•[cŒúGá8ãœô¬¢ y@ò!$ÌÌ~¥Pq‚: Ž™ÍFx„r:ÊU@Ì#{çgnªGÏl}ë¹Xã–6¸–VÛ±B"²„?Ðb1ÞŽÑIJ B¿¦{Öc ŒàÈXoÌyrBŽ£‚\çô© µãá]ÁævÚs×-ÉéÀý3XÚ\)h“Ë]„9Y?ÁÇcçÛ­xD–Q†Ë¡BUƒO9Áø{}é.Á74ˆ­ûÙIã±l¯4e•Ë0T”V,8+Ç<¹=ëÄa|ÅQ„ð7äÉÇ~þõ4<‘;î(K÷@H^x$©Î1ƒÈïóY#vFg³g‡3Ôñ‘ñÔq_©¼+!—ÃZ’ :\ ‘ð Uý)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)_Ì+„…"¼Ö®¯îf†@mç‚5e´ŒtE8íŠÏyão4ÕOzöÉs¾Ø¬f6‘à’9éŒU”Z•µÌË ¬ÁïçQlí}#}&?zÉf$òyÚ¬®,ôõîíÞK«¸½[\íÚ9àÇç5Tb³½°[ÍGL·¿·‘„‘«¶&Ï–Sž{óȯCHÒ®[UÓ!–k™T[Ho@X0§açœãï[”éŒÖÒè6:’ÛÚF²y;UaëÉ “ž1“ýkXÕ^Ãë­e›BÔ¬l£¼so%øžƒ,0£'ÀÚ'¾+¥©Øj0ê]´‚XØÇ刚 àv`wéÚ£iáïîMÛHwG!ŒYI8›{±Œm Ƕr*N³et ™¤µÿ ±ù“ÆþaÈôá ?ýø¬²4‹åG,ӪĪ–B±öÇûÖ;ëÇk˜æyãÈ›@9W#¡9à}¹jdYŠ+•+½ra“Ûõ¬V²ÌF7‘^f˜Í ‚¬y=Æ8ø¯«y:¬Íæ0[ÊÀ;xéž§œûԸ(Äß̃&W ÜgØï^- íG§hfü¹ëPu'˜"Æà$B^¡rP´u''ï_¡-B=ŽšÛ(fÒUã´Šbá[Ê;]˜“˜ÏÉ=Glwsùv«$ö0*\\YK »pÃñ’NOœp3ZåÃ_ˆšæG…à¡·Š_{~!’ÜGj§–+’J¬ç¸&pçI'ÒX¶޼üþUÍjwy‘»Û¶QŸrs'Lq‘“׎~Ï()É,^tŽY£òøNfà:Žyù#¾)§g±v>˜¢wçËþS_¤»ô1A,n7¬ÌUÂŽv Ùã#uæ½38d˜´…es «í‘‚óž'¨Æ@ùø¬ñ¼’²Cv€ÄTç€v©ÞzV5‚‘ÎÈcS!Ú[j{ž¼ÔDŠ&r»ÆíìnI”g $YÌÞJÛ»„ç‚ ŽÜXnbHØ »j„qœÏ#½G·YȬÇs’ ‚@s×ßó«hÊB†1±Ne~9$žÞØç§Z+#¤œ¢°BûŠm'§¤c·¥fpÍ÷ó#Š8Ì{㸠ìý85XÆÌ¥ÂÈÀ…Î:tû1R¤(ìèb˜Hˆ ¸ã‚=8#ŽØê0kØß 0C…™•†t#¶GÒ¥Ù#»Ž §ñ ž„rzô=ëõƒ]_ÂÚ!A…*€{m$Q[5)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)_ËNù´Óio5ˆ6Ïå¼2]¿¢hÈÓÔc?™ªýAô¦…ÓE¹K©nËÏuc0ÏNЀç`Æ:õÏaŠß,oæ¶Ó­ôØRÚ'¾Ø÷Ü–PH sžV_Ãs Êéé*Ê¢Ü1žL0qøN9÷ç¥[h6W·f×R¼²—N´‰dKkXB¸Bç9Ǿ;õ³xŠÚÓOXõ, >â,U>™#êr=€ÉÈÿzÒßT¹µ¹ŒÉ}¨[Í|þy nLwx‰Võã TÔ5 IžÕæ h¡Qü‹sçü¥°AðÎy T‘§µ¬v— gŸS+›:©-`Ì|;½G®*4×i£\CåDÖrn’2§<ËÄ?ˆq×äT»Mu£ŽÚöæxž`«kyq4< ¸ Œœe‡aÉ&¯´ûF¾‹RÑmtèfÔíâú™îïÇ”l)V]ÙÃoÿãUÖ°^éÍ}ÿ@××vB(’[äcÏñF#Aæ€T9z¹³MâÞ増êâIn-5‰@#;LcüsÞ¾x‡[¶¶Ónâ±XãI 6ÉDǹHÚ@#§§= kqêú}î§þ%þc¦«G‹Xcfvñ#»gsñÓ5³Í®yÖÆÝäVØ ïZ%ÿÕF#»º8b’(g€mhØÚOÿ•çääU¶›0ŠÖCwk‘H—ð²–2.Õ*AF Î3ùb¨<»Q§µìpIoôò9{ÙÛ“ÉÈÏ~Ã¥išÕ¼70Ï Ä†ve_$¶TÌ#ŒóáÝK»"Çé E7ý?˜%\¯'ŽöÍ[^hw˜7Ï'ËÌ7R«ñüD{ñÐTÖòFó.–Þ&³@€Å—äp:ÿJ½žm:œjLž­«ä·ùpNïËÜÔX!¶¹žâ$„06Ýç>¼Œçž?1KhiÑ™ ÛÈ‹¥²fLžqžéßïSJ•¢…ÁCœdc9ëöÁãæ¡¼òŸTR:~ð \Æ_µ&‚CæJ»aÄàì$±ãžÀÍ|Ž$Ýouß“RNs¾zUÅÑV‰$„º) £(c Ç>õŠ'È#p¤…ÎÒA9ïù×½b½½³cš<¸ØŸ69Cöé÷¯± >áÝ-Bɘë“Óv{àgýëÒ+A¿ÊU1<™È<|ûVXžÌ3Ÿ· µ¿ëïÅ}1ÛE9·¹„ú¡?L]‡ï:àqÆzVXÐyvò ¢&·%ü™‹¶8ä|ò.øŠ —¸[˘‚Ç…Ü‘ä1ÎAçýè¤,im-ÂM ¿ôÞ[ €3úmÎNõêÊVE…íZâhÉ(zÇ7td‡ü#d1œŒòÇ<|ûqYÔKåÅ1‡V$bpîAè8ÏLÖ)ØDÀ!(D†ã,¤ƒ’@ÚÝp:u5ðÍ E¹Ú±´NSÌŠëiä~r 9'uù¬&I”•Öâ \d4yœãqùõ°yŸjBYŒQ/›/–ƒ6àpG<Œ}ú õ !F (Œ°ØÌßå ç¯o½}VŽ#Õ2(&È8s’sì9f±ÊÐÊD;]—nМ÷ç+œ{Ö `r¡P̱´#vÂyˆçŒâ¤¶äl݉WvBÅ>qÈ'q×¥yq¿j¤Ìò±bqÀ‘À¸¯ ¡ä #\6á")Ë‚«ÇçÏâ¿TxŸý)¤ÁФ©¸¸•ÇúVÝJR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JWòûüÖK9ïµ ¦b¤´Ó®!À'‚Ä' =Æ—qdkdö’J̱Ǩ"®üà67’=DŒ¼žâÙ¦UÓ„Ò–„¹ŠHßvF¾ÇåšmFU[…³{‹‹Û·Œ‰"’I ·q·÷l»JÜqÀÆ9“6«suh[q…’Ö`±ªåYOxüT{«¸ì7WR,r6ÖÅH%Ö¼‘ïΫWSÓΡq,Gk4cÈ3ýœ\Œ‚ãÌaŒñÈçàæ¶mÚÂêÜÛkÚ†­9„¤°¤Cj…áØ¨99œ{pMFÖhÍq¡j–׳ÝÌÜÚ ½í'$‰QŸGÜt>Õb"Ó®mmí^2"–½„ì–fõ yíÓžsG%¼º…óZZ[ÄašÞ9®Ÿ8cŒ¶sêïÁã888Åd»Ò¡‡R´‡S0Çô–»~ª}Fg+øR à`œr8ÅK:^…{¬“’¬ %ÓÏÌx²qŒûT+8tÛ]5°¸µi„V±ˆ³éQ–>¢Xç9'çŽ*.¦ž‚ÔÝhI7*êgh&|$»N@àûu¬WÍs>“7A‘¥µW¡áƨ~|ã¯Þ¦éñ+%œÀádÆÜ‘óùõöªý^{Hä–9Ým.f·„ù8RAø÷ît­cX´ŠítÖ–+GwW·™å?»rˆÜÃÝ9ííšóáÛõ³´k[‰ÿêã¸0þåùé·rŽzkp]Q#÷É$lªÄB»¸Æyíö¨–/iis}šÛ`HäV]¨H ’I‹ïúÖ;{¨ÚHciÒ76±ÊÒ$™ÞOPO¸ãŽz×—[3|–v¢h˜È$žh#%ô öÏ@qÓŽõ³ÛGcé·Ê‘©;Y¹#’pIçíVKv‹˜Á*A*d+Ô{}ÿZÄKh¥WØÛŽù,¸<ïýj\- ãI19e*£÷}9<ð:W׸”„ ¿Lዬ³@\…ëŽEc2¤ñ´¦)¦º„–Û'¨ ÷Àãöè}UÂùo^rî}ª@Ý×;ñQ%·xf’q¹U|ß0ƒžÇ9þµ2."”D¤Aæ‡ó àçœu8ã¸ÅfE{•)ZgÈÉ08è{ÿNkÌ3„ ¾iQ1åȹǨéÛ5:ßË’8r<2Så!= ÏLtíŸzÎŒs,S,Q³úƜ˜düÔh^fy¢gpÁ‰\¹'Žæ°2]tˆZàÌ4èICïÇÇçÏja•]å•­mœÛä¹o`}' øqòO”3=¼(Û)Àfd‘óýâ°N·3;#€¤Ê À÷¨2I)•df”ç%@ãõü½ª\wÆH^«–_ªœg¦\Žù5œBdÏnÄì»}¸ÈÜ ÷È÷¯Ú·Œ˜Aß(ËÊ„€G'î1ÏOÌÔà²Ás#Ãsm/›&Ï,9`ôÀ㟽6â9?z]Ò»6âÌþ¼çÿÒéžœvâÅbµò÷+)‘S$¼ã÷ªyRÙ Èa(\ùl¨B£“œvÏ<þub.yIM¼Rùjñȑ̊ö>“ž=?:¦Ô¤´ÔÒÚ-J9~E’²B–*Ü8à_½w_ $o èqÜÃXíÌfÚÙ²Ê[Œž ÀÉ<õéRÏÍŽy#·–{¦‘–ç駸‘´¸ÎFï-T!‘N9äÔa¥ÙiËj!3K|m’;Çú5S ìË íã7“îr+T»±·žÍçh!’H§Ú×RÊ2€€vˆò3·ŸPÏ=zWÛël¶ÙlŠ;¦*ï+]‚n‹(l0ÁÛµq‘Î{Õ,©äL`˜Í"& \Ä0àm1.åã $ßÞ£ØÜÂbtc©,¬]-”J®6¿PW¾xŒ{ÖIüÑ5¬bÖHšI’§ª+/@äî ‘Œ œóXÅ•¹»Yšæf·ù BTÆüàdðzóï^ã„þîv¾sÊE”cË\ã§ÀçýëÛJ²ÇådçÍ*&Fàã? ã ¬`ì )t‘„e2¯9äuÎ~ãߥ`‡ÎD­o+Â$±¬›—ßÔ:ñœ÷9¬ó,pRvy ™ ûº&OAŒc¶ zÝÉ “ho4,’ov$p6Œ‘ü׸còÎ\*¨llŸ9?„ƒÿ5é!M“åO¢)CžGà‘þŸ•c”MåoÁ…¡aøãm£Øg,ãðjD"òäH]Ä:¹Œ©Wã*9ÀÇ=Ï5b$`›·66yŸ¾-ørqŽÇÛŽ=³P¥Xî4¬ãÊ@ ‘ƒÔûŽüç¥e)lÈ#\ZôqìsÀ9èsÛ·Jý-àŸ éGŽMÇá?ÿºJÜ)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)Jþvßj ©4Ö×ÖðY[ÆG™Â³3À :cxëÒ \jV¶Cer×Ö¬â"Š6r¬Xs€OåóVQéñ%¤w³ê72ÜȬ|Æ,žû›'®xö¬–6ZY¾¦u¹›R¿LE·Vô)p«° Ä‘Øò;Ô KËmJU{ù¸‚Gw+jÑÈHòÉ8Àaœç±Ç¸ªÍGQÒâž ®…ÒùVp"ººñÆ0y9çœg5aayis"¼VÒj7P‚Œ‚ÑÕ"=xAßd’}«×e'šX­ÅœqÌ>¦5·Uã‚F:ý½ªãN¼ÔÝ®ZÒ=:8=îd·Bó)è3úÿÅMÑàºÕ.nõ4ÒÄŒ°5¦›§Bžlk’ —wÂ{æ¶ÆÒt‹+C#GKf?y{* Àv<ð8¡ÃfšµíĺdÚMµˆO(Ë}î3€]HÁô0÷ë[<~›NŠYôýQçœÃƒåÛFå¿ý Bóî+]ÑÍ­Åγ® .-§Ÿè¡º¿hP©cø^. ú²§^µŸR±Ó¯.`…-lš[¸¥@¥¡Û꤀x䃎‡¥IK [G °\‰n®åG.ÝÆ1×>تmzÛE¸·‘íôAhþö«‚Eä.1“œn$žÀÖ¹qev«ÛØâH2“Hª0w: ©#ØþR4vžïË1M ÑK(icåóÃãÓŒ|ç=ª‹ÄqýL——Siop-ü¶×hÃÒ9ëÉSñü«“ø—R¸°µ²·³šWK¹fkØ®!;`”mÆÓÐåXñÎ1ž•ºøJâ7Ó- †I|‚1œ /L‘×[„÷v¿O½¥! u?ù­gͲÔ-¾ Iï»kt¸`ò¸ÈÇ~Õ³EnòE 3-³[¡Ü‚Ù žÃƒ‚:ñÒ½Ù[ÙYÎÆ1¸DOš†V“Ðã?~y«uü.ò®\ñÿ8üÿ­`Tº’ycKŒà|f3ùƒÔZ‘ F9gùÒSöÇ>œ}ëaÇ»*ƒ¼…`ÿ/Åa™ä8 w82Æ*{qïX¤’8¶wDônBW¨<>=ëæËÂK Á‘³²EfP«Î:çù*Ån°Eu Vc‘å¢Ý·±­X&Óç¬æ,¥K19Æ1ÇÇõªéÚ„1[Èc(ÅdÇÇÛŠñq ‘#„mèêDªNóz[HR"Wb¨d<¸ØwÍX+ItÑ´8‰Ñ ’_°íüûÖŒ<ÄI½,ëÁßžÙÎ:ày¬Ö—±]æçl°Í ݰÓØœsÇcùÖY’Kˆ®,Ò`Ë2ƒÀäGN¸#§·¿ZóÍtæAŸù D¸à·#ŒûsR.ÝŸp*±ÎÜ'w=OåñP2(qëÚÎŽÍuëŒöø5öGi§ÊÈT …Jí$àƒØtö&¦Ê“É—6ÈÔŸ8q·ýª%¼¥  =Ò£¬§œþÌÖs+—ÈæI<½Ûó»gç¦;TûymyÂ,±ú`SĈ G~9©PÛù®WjÈ@/¼dzHíú~˜¯k2ñ.%B¦(ãÀÂrxîxª’–‚æ=ð(ºBdIb ¾<ðF1œ`.ÕW¹o: 2¬i?Ó´æÍÉè"ç€ rOP1]»ÁfÐtðÛÛˆ ˜A-źá³!Üêá#ätù«É –å.DÍ=ÄR¦ ³n$¶A@=¿™æ Þ[_[à%–éÜy« ºFP3g äôâ -„¾}½±·—é ¸inX¡ØPlzcŽN >×R3_ŠžS‚HØ_K+x c'ÿgÃ…I¸Im~³é€ŽvaqŽ 'Ž£°ã§=ëÃéÁÍïÑͲN¶I²Œgœ g azg¯Þ¡IföÑC9bã2Jdaæ1ïÓŒüÖ ÖEÛ¢Ü).Ó2yŠà/¸Ï9ƒö¯ªÛâUp¨¯ÂR<Â{?¿šÇ"˜ƒBÈŸk~ó;ˆï’Aï÷ù¯ªäð¸h•Iy^0q»q·8`@8ÿAY QæÆ.Âw¼3NÄ9ôò2Û¸#®3Ò¾Ù§f)¾q¹–3'“Œ…î¯RÃd’Kûï«d\Èc×~Hpr9Çüô¬MµYpY#ŽRËe¶ñÓçúÔ…P‚2Òå÷b`z1ÎAsœsЇ>á¶Uf\†f/+)û=½¸©PP ·±˜dŒ?¥˜õ1Àã¶ja¢í1"ˆÆTÜžqÔÓ¥| E;Û,ë'–±ÿÛ*3ƒßœT›”„3gP£s¡9óçn}Ï8ç5ú/öxÊÞÒÊ–üw$†êŸ)Ån´¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥)JR”¥=_B‚áF¡=õ¥ÅÜ€\,omæ,'êýû|×*ßT¹±’ 8ÙÙÃm#Ù\j,KµÃ¨Ã`“Ï\üqYì¡m‹oðÁpÏ‘æô±¸lX‡Žbxª[ÔÔà±kk];KAu<²#Aw!kMÄž¨.rO`žµ³[i׫a¦tØÙ Üù¤ qÈއ>Õ«Zˇ«Ouqk.«²˜(­#Aîr$>®3Œž2Mf¶º¼7"É­ ¶kë‰nmÄî¹'s)*1×éV’[iúwš÷º´³5ʃ ´D(þ H9ý1ýkRŽïζžÓM°Ón-ÅÙVÕîæ1ÊëÄùx;G`Aãµl¶O¤D©1ÔæÒî+p\ Ï}¤IÜã±Çnj’ûQm_ë,5_ˆ4íØ·³ŠŸ^ÈbHÍýkÖš-oJ\éöq¬–ÒÞˆ™Y8!›c~+gµ¿šó+}Ñ/¥®·ªîaÓ #ӋY`Çç²fV;J“œŽ'ùÕ»HûU‰& ­»ÌàÆxÆ>8=ÿZÏA'ÅÉy€cÍ'øsßŽÕæ,°}¢Gò—"0$©êÐuþu°D€+2dŒ’TŒñÈÏÚ¼˜ÕHÇpc” rŸ?×­|´Wž%ï Mê¸Lsóü«K &]©;Çû¤~qö¬Ò­²]˜†H¼ß4ô¸×È®A oå© 2u,8Çj¯&×qŸ1·úüÀ8ý1S-¡"A±Ç’í³tRÛ<’Çß ŸZÏ4 ,ªer~˜ Ò ”ã+íþôˆì¸ETb®1ê·÷ÇLÑü¢²4ˆï™Ü›¼zGé^cŽÆFYã¶X–J)UõŸp>*jƒå²$av“åcg_éÓ÷ª»a*ÛÛ%Ú@—1ÈßPÐ(yÉ䣯_ʬ"Yf¼£|Xü‰êqýŠùôé2L|Í’cˈê9\{“œýëÊÃÜôÍlvÖQÞ˜¯õÍ}&—fø­ìí˜Aìõ { |ÐØøoÌ]Âî'VUêº#~y<‚G'PÐô;su§…2ç+=ë8-ž88P~Þõ¥Ç5¬¦¬"t¸•±7Ÿ&.\?<í÷=*Æv±¼°¶@©2ÌNÈË(oÌvïÔÖ¹«Ü´,V±2Gm¤Ai!,opǾH&ÇþkkŠâ;™L­MÌ;Pù%‚ã''ù~½*]ÚIaä=Üðµ¸fh!%\`…ÈÆçs§jöºœæÖ8®!ˆ2É+¨ =ÀÉ<Œ~•³ÁVêm¹ŸwªÈ,Çœà?Ò¢ˆá’I#Éû؈e‰ŸÔuïS®.e† мž^àfø3‚G¿óâ²K)‘"XÐKâÌË qÓß ö¯‚ý¶å¢, @;³ñìj:”²ÇÞÈ\¹Í}ÚIJÜ[–%‚®$ »¯SƒYáW†æDÃ7˜ÅN9Ü;ŽéHã“Ïv‘6€LxŒŒ°ë“ï‘ïYØ“>bq  ey,üW¹¼Ñ‘ªKlVrO#©àtçŠû²A}çË9b ;-€Yq¼q•?ž++(ÔZ¬sþb´)P2r3ÇNÇ?éP’Ý#œE<¯½3"†sÓà}¿J±%ƒ0I!°±M‡.¾qý*‚D¸…Vf{q -"¨ ¬1ÆOQŽç'æ°¬e®Èóeuf.×'ŸluçŸö©o lÅ.æ>¢÷Ïéýæ¡Î—¤±EP¨§ŒJqœn<çãâ¦Åw$BT ,À!Gœ(äàóŸaù Ïlm-bQ"NÓùí!emÂ58~Üc Ýi‚YŽ£óÁª»íú 8É#ŒƒØW¢‰ƒXùrª¦qŸçŸœUÃï'ÊO$±Œ0x×>jõÁÈsýŽ•.mæåH‚V1Ä%„²¹  ¨$wëΫ­–)%–Ù¢»–1+ŽÞA…<®GçÔ‹…µk‹+;qo"¼z„£gÓ®FâÛP‘éã®>F*¨F÷ë»Ü»H†h⦸—; sžcŽ˜Åtí_¾ðæc{qa׆ÖìCwþ K‚‡m¾WÖ߈6Ç^+5¿í'CY,ñ¤ß< Åä:‘ÛÌN×}’DX.àO\œó[3ëÞÓ5 ‹Ä7,LËi ÈÓ–n¼—(¬`, “޾[›m6Ý¢»ƒ_ÓîíînÒÁ"E¹„É3B*9õcø¸ävã–¿OvÐÏ%ÝÅÅ©[tƒO¹Šã|ƒ-—±a€½ÔoŠ›»´D rŠìf¶Œ³©‘L†ÆpFz}Åj3ÝG’3¿Îæ-ŽÃáÀû ñá¼æ3I<±°ŽGe'a#;z`àÈþdf²Eq$Q4+&P± ²Ãœç&¼$“*þG—· ÑÂS ž‡œtç€+ tŽhv(ØHVò.7œ€2zóúñ^î>–îü/(äœçç¨ÏzŽÖûÀ\*+<Çhˆç†ã¶{ÿ.õ7ÊJƒÔ΃nõ}\2³N‰-”@9QìH$gäTo5 f[}1%xßdfkÃËó§°Øj··r„ŸH¹²Œƒ™%/ÁÁQýjì“‘€Ïâùª][^³Ñ~¯q ÷KjÓÆ™1Važç…'ŽjÖÞæÞš9áe%‰ Y©JR”¥)JR”¥)JR”¥)JR”¥)JWáÙ®t+ë3oØíŒZÏÙž‡ÓØqÚ´,£Šúý^Î F#UÉ•! <•ECÕ³ùf³JöR,W1ØEk½Ð’k†ÜUÊýŽž˜è*|—÷7¨Æ]gµ¶½Ôf0#~{žz{VÃa«Š[Æ,ÔH¦@d3)ç€A=±ÀªK[=R[û»2ä[ÜÉG+j(®-×' oKn‚¤ZÞjÚM³ØGmour÷,×7³\($·&L` ddœöäÕ-úêZUÅ®±raÔ¤[’ ±‚Ly%òFF2~9ÏQYµ7{Ù­æ¿‚é!+n–·nÌU¹ ø°GF¯NõAv’Oeq=ÔÖó½´smµ¹%Jœ1ÈïÔô­¦ËLðÓZÚMsgß—jå’þvÜBò0X¨è1Š¢i£SÕ}äXAŒm/”þ^âR>^£žµoªé+gg/øs]O§yØ›N¸Ôž¹<&üç=IÎA÷­ZýuÈ'½ 6öí§ÌcÃ,*F 9 pG_jÇvúw›z¿CrcTÓ´ÛX¦c ÿrGèƒ8às_.›A‚æÉ,õiïfvh綸W‰á`?–Ãp³ƒV7¸µYëPYF(ÊÄ#$sŽ­U…ݦ¬Å!Fe05¶öì¸<{ä÷amhÓâ) -‚K£ù…\¹e>üc¯QŽMjW7†òí´6òY€T©X”îÎyáG Ÿ·QªkA µºy<è~’u‘#œc¦~„~ƒ½aƒÃž½ÓÒá °4  ©«¹9ùöÅQéºu½ü*ño‰Ÿ’IéƒÓ#â·HZÚC¹¨I—oø©höè¶“ÃFäùŽkÛ@—/a¶|A æé Á$d9#ž˜=ºVí6Ñ%ˆ[ 0Y]#@WŽÝÿ OZ½X¥h¢»*…óc]œç±?¯Ú–ñAr²JÌH.Êwe½ùÏ·O¿Z“<û£hh•ÊOýÀqßç§NõšÒx‘˜Ô¸]ΤäœñÏ^õKŸÞ¡ü[Os÷¯±ßC¹{–É}.r)Bø8=ð$|÷ªíGYÿ Ž5M>òíæ,Æ(SvõÇNœgÜÖ¯±^Grb²¹yþ™`vbâ—' Oä`dô`ñX®,Ý,Íœ4{.  `ÌÒ=!ÀÜqƒö«ñIÒæÌnº†KT’[ÓwnÓylù&Bz䓜gk —:¥ùÓµmDAwgo»œBà}0ÈÄmÎA''¯j¶Õõè5Íi^èiú1µ\4ÿRìfŒ¡U¶VWb[~‚¾j:’É©évzÅ‘ÎÐ}LvÑnrÌäàãž3ÇZ”ÚíûéBoñ® n 00òïü°Øa‚Xpx'g¯zÍ}q$7S[ÚÚkO=ݦØ-®fHÖ4ÝÃn ÆOOΤëBÑÙEy¨3ÙÙΆ}>öRáü¾6å¹ Žý¾ XZÞP—“h÷zmƒÜÇ ®£¦êJÆs$›V_)Üç(ÃÒ»@5±®“¦MõOñF™u Ã4I ÷6­vàÊÔ #¦ý³Š…6•ª*Í;[j2Ai/‘sum‰Ù°Ã"‚:2÷èEEÛ"<ýûãØ¡ñéêqúŸëC(uX„cp%ÙÐF1Î;|õíYH·8F[X)ÆÜ’: ‘×kì—Hv“1ùª<–Œa˜qŒwÀþY¬å¸hŒ™üÁ){sÑr3À<`W‡¨n2€b(ÇPpr:÷ÏjͲoUC pŠK¶zž9öþÍX$‘-Á!‰@˜‘rC=ë&è¼³›fTŠOúƒäç¨$ ö=Ç~µPì±²¨òØù‡ËrB“ì:ŽùµwßÙKú›TŒõM`·ëCØwº)JR•R—Z‰Ô$¬—èѤÈ[,¤~<¶‚OK‰T1Dˆe$zÿÔTe{YînX#‹Í$ Û¦~>õîѬ¡-Ža; #9qížçvÏZ”°Àsä'–¨Æ@±–ôó’0=Ï<×À³Ïóm"’"Û••ÂùëƒúÖ(¤‘x%¶F>Rq¸MÆAø9ÏLýÍe‘ãWPò¡óv¢SÉ'¿^ÿoµFk£¹’æûƒ3¡³{O?z’3‚ä)êj]òa1E¸‰ßwâsÆìõ<ŸœÖ;:ºy“ma.y^ƒ9ì}½ëë‡ÞcV›Õ˜2¸'9Ý3ðj|ˆ-çúHåBÒBg1ÊAm¤õéÆ[==«-ŒRî'–8£HŽdV+Ç¢ñ×=sP®„QH’Ì£s$ïö|b¤†iÑbY<¹P„Ü+“ñÜŽ=«Û4Ò…˜2ÂÞÀzØx¯v‹r¶‚…¶ +”ýÈá'ë^ÒQ[¢°Ë)rÍå·LŒžŸcQ¯MÄ€^S3I³o˜@Nœá×5ãÎÔaC;ILËûµˆ81Æ·$u¯ÄÍôn­Ü4ñ£`©%Y –àzÎ@⪵<û¦i#·I¾”ÛÁvÈdú`sÊûò~;â©íò\^Ü '’å~–òшXÙx ë×¹8ç§OipyFíRñY¤êæ8iäÉoãÁ'ôÀªËŸ¬ÿ7°ykõЯ™ ¹?‡Œç9ü¿*Ás©ÚYÙH‰¦Íkq<ɼ¶‘²¤#–X ã î3ɪª¼÷s4ÈŽË`¹ø‚yÇ8«3lÚPµõh/+e FØ7“ $ä*œŸW±ýzU«-݉´´ÓåÔ¯mî i©Çq,Åq•ÓéÁÎ3Æ01ëVýÝ̳WK† ž/ñÐ m`_.ãÊ©çx¬öÍeZ&V†Ê#G4A0îFOpääš“}{¹D—Ö÷–v¢ñ$µŽÅWlå°½!Ž;ûdÔ‹¬’)!šæìØ¥ÓÝà [šU,Ä>N*Jã®~ÕŸMÖo –ÞGÕ5”†âáÖ ùáB†ffW §ñvõ´KâfŠ#=ÌÚn¿s¨,–ös\ØE# 6IæE´‘‘Õ²H¶eº ré?Ó¤nQ1Çœ¹ã¿jŒ’£#Ç–Ý#?˜Â`g €~ǯéYFYÆU.a ‹oñ³ÝHÈùÏåó_]Ü+´~S©9X¤q»ã9ô e,ˆTF¾µŒ²£ŒŒû|t© 2OUœÆpÿÂ3ŒíŸç^â”n ÇiBÊ‘ Ž0qSfA3É"ys0E-³q<ž£¦{g"«¥y!`f"³lÆ:õùôÿ*îÿ²YÃïD°IíåõòVÿmv R”¥+RinŸQ©¼Ôa´KÐÖöØd*T,qïtÉ–ÇNI«¼Ý~–ÏcGraƒÍ´(XVQŒ¨õãs`ì=FzÇknî[BdR$òmö¸-ƒŒ=ùª;è­g{%Ã6Þ7·ñÉƤîÜT“ê{‚* ´º]î§̓Z^Øh¶Mæ†`lŽÜ(VvØx IÝšô–šN• ÖÍ£½‚Ê‚AxS4Ó6"Ý— 9ÆpMpßÚåÌW~&ŠE–hÞÞÆ!<Fñãy‚ÌÜŒ;õ®IsÚ}Ôw$£€Â1Þ“ÏéÛÞ¿A(šf%‰eb3YiJR”¥)JR”¥)JR”¥)JR•𲂪Xlíþ*ûJR¿‚}6ÚÅ »¶ê­·HÞtt`z“þõ¬èz•´ÓÈ×Ö×ÈßJ–‰ l K~ðޏÓµnö1„¶7SêÖ6vÖŒq²4rJH' ’N8‚çN¾º³ŠælÌ`ùí¶ÁÿÈž¸øÇÞ«­,qœñ;Ä®ZçÈFʹûž;b³µ°7^[XêQ[ZÌ$I'†<‚FùIÿò¦¡r$•§o3éca;Û‹` Ów#<Ýý³Xõ Í?Pµò“NY^1q5¨]„Ž9<‘‘ñQí®5¨.,á´ÿæXíàe·!€#ð±øG|ž•·[h3"Ý»ê—ß]Þm61¸—É~J¦–âû£ÍM·öòÌ"•Rà« ÄFxcŸsîkã[Osi"ÜiP_ZTž&ž[nÎÐxÈ$dŸœö­‹Rðõ¾§²é· n+q ¶8#méíúñRl¼-áÙ"úËÁsqtaî®od>[c'o>žIÀ=3Z•î …Ì6:ŒVš}…Ô&Ó°oKæbAÉ' ÉëX-ÛZÔVSˆm!x×tqi¹—“•ÈÏo½|Ô4‹‰£\x’=Cl!ÞÚ /ôS ·ä£µk^jÝ›;«È eFýÑÜo®Ý¼ü‘úwëP§‚áüëuòâµ Ü`œ¡88R8SÎxYzÏþc*]IsmôòÛÿî•o0±=È_l~u¥^Þ*©Y“gÔ¹„J8±ôã9Æ1óRlt¶µ¹V†H„À%qñ0éì>Õxm¥PR9F@ÀÆç_v²µ*V/§¶w¹c'9R9ÏÛ¥`“S¸‚Eg%Äew1Cøùã󯒛˃ XFl§Îë—–O/ËŒH%rGJÞl.f†ù®`™Y–É"É7š8$óÀ99'9Ål1²Nw,é-Ãþ|*ƒÀÇÿ¯C^ãBÓ C¹‡rÎ:ÕîX&fTG ÞYBúñÆMyŠuvXr·Y·ªäã#?nøø4-*,±Áæ0.ò8ç•ïÖ¾Èꮫ‘¸†ÝçˆÛïßÅF@Œè¸eh}, RL˜êF>* «+–æ¾ zI €©,luâ²J@¤nw -êl0Py?­zhla•cUº ¸]Í3s‘€3‚:¹¨–On©ç#¼äÆërÈã®öüê§5ź; -+‰dÚXgÔsÐrG_ž8©FóËqb!‘—1´˜C(ÇpÉÏNµ=îfÜF)C$·ƒyü§޵’Ýtû×6ëÒÜ(î?x;6zõçó⢵”P›„S4w7Ý4YRÅI*Iˆ ß9&x¥V2 á×(U‡#9ä}ð>Õáͼ\mŒÈp»%…ËzN@éÔ‚øí^áŸêT—Ú²~ñH##Ò~sïÀùÌã,ñ>ØYÝKFÂa‚½Fw ôùÏÅyi%¸óU å$ ˆ gvxçŽsÖ²$r<;¢)#I!‰Õ£bÖã9 1×5’;ƒ˜¿w,Ò#”p°:ù¿eoaííŠÁpÏ%Á†8®Qf\&ÛRD«Á''€G9Î:WÈàK1 ¢íˆKÑå¦;ŠÅpRîIl'–O)äM‘ÜmÞyçžãŽÕG¨ÞC–‘F·"Yܺy‘­’>¼§Ž›Xó“ÅAŠÖÞïO’Üêo9’ `‘C"†Ü ©È$c¸í^b²ÖÆ£¦Ïõ´–òÆVHîyÆ@Üʱßé·"[Õút‰íîàxî3åõ6Þ@$öµm~ÚÜLgˆÝÆgÇ ½ñý~õ‡OD+s˼ì/…Œîf#ùÿJ™ijn‘fµ‚;Y-ÆÇp ñŸá=3÷«[{ÛˆOñBÑ—”\'ï˜õcœœüêTÞMúÄwwsi)Œ¥õÀãeHü î'Çâ³Á5Ý•Ü2jQÇcku ‘ÝÝÃ9o>B=' Æ1ß§{h±É6¶Vº¹ƒŒIѸqø"²K‘^â1§È$ÔKè0wn,H$ƒŒ`T¥‘â‰î.Ú¸'ôªñêÉõí€*³Ü˜qq§ÉgÑ ñO¿Í’‘འðsØòy¯_Uj·rB—vS_È9-¥»PdÆNР’»A'ð’s×½} 3M(¿“LhVmöv« ¬Xìvf'“†è£œûWæÿÛ<±·ŠíšVgƒÃðÄVrз›pH<õÁÖ¸»Ün…"2™[;ŒDݱŒóß#ƒÒ¿@ê´Ñ¤ê^}]p Ãm¨¢Ý`YHX¥”mä|Õ<ÿ¶Œ»n¬õK#ž¶—ìËŸlzI©pþÚb†Hj€){f7ÁeõÈ×Rðÿí#IÕL1^<Ï2Žò)sŸryóÈ÷"º:²º«£+£(ee9 CšûJR”¥)JR”¥)JR”¥)JÆb‰¤Yš8̨¥RRƒ(PQY)JWó†å˜^ˆä·±Ì¢5‚Úßli’Ä–É$õö«VÒ@ÒÍ1ùlÁ QƒÎÜÙüªšæi¥1Fª[ AX<¿1Éó»Ï'$b³He¸ó3mo 1$ŠI”•Çù;@ÏØ©úœ×šflêЄ’XÞâÖ)|àA‰Ç$Ž:ýég©ëæÛ…­ãMñÀ±nh{¼c?¥G“.’ ‚O;“¶?)û’v’¯^¼×ߪŽ1]Gs•";xí•”cã=G|gµA¹±Ó¤³[‹}VKmP v[{0O™Ž˜8ÀãŽq~÷¶’k“ióÍš?•%ÓüJg+þTÜ£ž0OßK Úüq_}N‰$¶ì·pZB²J.ß8‚­ïÇÏ\K½Ó¼Olñë^ ×ròã·ÓåhV1’TzrFS“œŒT›=&òàÚÝêBkÙ¯HKXæÕäu‹ØØç`À½¾jt“R–æY-n8Èd²»*†rzúóÇCÅaµð–…¨^Ü5ýìš}½“yFÌÜ mà’Y² Œ`Ö¢ëZ^Ÿ±ÙèVZ•È’f‡i±ùÞ‡ ú Vµ¬Ø§‡’ÐÜÜͽ–êÂæô™„¬ß» ðæ Ãqu-•”¬RMm"I®ÅKã±ùéÈïÏ&[¸nYíb ¦I‡šÉü².Ã&à@ûI÷Ú¨õD¸0Âë²Ú$¼®c”ƒ¼|ué†ëÖ´+›ehc{‚„}aS»,ƒ·ìIó¬Ñÿˆiq´cO–\6òÑȇþZ«›Æ6V³˜nÅݼ¨ÛYdð™ÿ¨ì.-X©¸“ÍCfÖ@$í·‘ÏµeÑõ d¶Oe4qË´nWRL °9çŸnù¼éÒËsqœ‰bˆ WK©ïÔqúýªÒí,MÈÃÆ/f2»ˆó¹°G@=ò:Tè|ØH¸Í¸T‚Eü?˃ÆyýjÝõ ‡•£búý#.\çý«"_“Z•R=¢07lÿôGù¬yq(Â8fy‰‰xÁÈ~uŠ B9‰ÎvS·$uïÛåSàY Ć9KÜpÃ…tì~M}uEß4J¤‰<Ñô䃞«×¯^µõd‰ÖsÏl®qÍcñ<ÿ3×½ešÝždšP»î‚ÇÒ 䌃zv©[Én±Èï—3gÒã$c éŒçßæ³Ix[pˆÁ6RXÝCnçØŒjšhÈâïí#4qª–g` <œã8Ç<þ°¡ŽŤ0ê–íwj÷°ËcŒêà`ààtçŽjè]\ÉæÅ Ô‰$"9,î~õW†müœg¿óÅ@½šK5škKdóHÚ±Á"€à‘ûΜó× U©»i-­|èJH«ºI˜®@ã¨8ö¬’yPá¥a`X¤‡N0F'¯#lo¹mÙ˜ù ¬ˆãÏN:b°²C],FÏ|ç'ôêOÀ5–;˜ÖáÙZä1ˆ™@È<€3ïΤ™ÔzVÝw3›x'¹ížÿΤE*0Œ®"f ¥ŽHø=°~jjű°—xa b6±Îc¦8¨ÿXJzâyfŽSçÍõ.=¦ä3ùׇêOþØíE'$Èûµõ gŸlR0H_Ô¦BCŸšÖµ{+›fº‘&l"q ‘à09ʃÀ±ž2:Õ>•,¯ ²ÝY´ Ãóhn2N}C Èâ«’ôÍJïT¸‡Q¶‚wÙ(¶ÞVLd‰vIüýÆ+ Œ]$×2J÷$H¬Ë22°úXÛ{“Zÿ‰O¤Í'‘&cŒç·èG²y REä]£Í©ÜŒûלŽç¿µNháH¥yY";@Ù#í'öcóXÆ¡TÞ‰:ŒchȪô’HÁ$ô?•MÓæófº»“ËxX"Kn·@ÈÈÍ‚Al`Êø Sžî{ibšòWÊ͵[˜•ÔÆÜ3ärxÎî¸ë-»Át³Y…·lCç¯ic´ÿ‘ÿ.01VÆèK·hJ_*Ê÷ ‚ÙˆÁÈŽzâ« ÀÚª³KkqrnmoŒ º"Usµ –ÎAÉù¤·A'¸…îÍÕºÞ5­³¬¨¦"ÄHÄ Â•%²HÎsÎ*eÝäm<–vÖðß#Ƽ¦á(aØs¥OéVéwþžöÖú]¥Œ‚ÙQ•eœdn,ı'ÿj¾ðÝÆ³¬^Ü[_ÝB;M=pj×v± €PI“$à/$ñÖ®"ñ°Ôom]LßG%¬Mc5Á6³nŒyD‚ ï@O¨tÒÚÂÛNo6j©;Ìß_qƒrû‰Del‘»tÏ?l:v©}¤Í{skj³m˜¥¬öwñ©·•FæüNjÏÿPAyrö÷–!êàE¼"¤–Š[Ì*· äãæ§Ma ²cÔcß¿ÇJ…p—v†ârg¶2Jc.ƒyö9aÉü±šÞì|=áßðÈuùç³—Q‰g–IõOÞ=9n3ÓÒ9íZ®­£i¶PÛ=¢Åy$s3€Þc8ÆsÇ g žù¯iqkv{|‚ÒAùwG…rI8Á<ã“Ó›HXæmQn¯må Ѹ¸ ä³pê;ÿâ¼^‹{u4\ÛÅ:F,R‘²ä3ryF:ç§ØìŒÈ«â OM¶¶{>T`{a~yäºÐàÕ–/«´Õ´˜á¿ºczÚ¬â&t\¨mÃ×ê¡®k¹øHÕ£K­vÅ´k„Ôˆ´Y!—‚©’\>ÃÁcƒŽ¤tà£~ÛüO=׆ít!ôW.¨—WV%ž8z’<²ŽH#•?È×åØnVæ-Ͷ7ˆ˜¥êßz4h÷pÎ÷ÉΊŽ˜T*€¹äú¹Áí^¯ïÝmã…¼¹gµySI98èH=2kGÔ¯ÃÅ#GÕž8F2߈Ÿ·${vâ§^ëpéªeºT‰ “†8'õøûV›ÒõÝlêl·‡ÈQÔ¿\ÀŸRƒŒàãŽ{f¶öñ&—y¦Ok<ÏæÅ(UJ¨Î£þzÔo4/I¶‚(çò’âÝî$h‡V;s‚Iè{öâ¶]>i¢1}LŽîÈÝe)%88䃌ŽOn:VãåÄH’(Ú6Âå$¹ó =7p[¸þ]êÊç‘Ë#1½¤,A-Ç¿|×Ë«€·‹¾..T²4žàrH^÷¦ AÖž[{6¾K‹m¶`1’ç ð½ñÓ·¿5?J¿žâÅ ³Â²M<®AÏcùqÍc·2\XÈ]â„Dò‚¦pÜÅxDaik4²îrÍ‹;v?—8n3žÕ ô˰ g3¨`ÂOϧž¸÷ç­ZÅq-·ãòÄó6èâw§Îþu•on£9ãYH%d+cœd ãûèër<L¤;ŒŒ‹´¦yÆ>9EXËr’Æ€9|Y+Áç¿Ç½Fc¨®?.gp@p{…¯*6‚ w4“ˆÈXUÛð.$gŸëQ‘`’çÏŒÂn"b‚XK)ÂIäý^8¬³ ‹:Lb–ß8‚xßÏLʳXF~•S+°-bIÃ`1Ü`ÔåÄ[Æëç°›¸n::ƒµGŽB±º[G«NVO(c/Ï·ÜÿZóõK¡>^p²}@Ÿ=kãNÁVìÄ'H íÕ7‹… Âãœãûâ¥*y±­`‚ !ßn"àïÛ˜¬¬ H°HãÕûà2ßqžµ%ga”ˆ"®ᇣóö5áC»8PYO©€í÷<AYU"— „f';ÿcžú{T{˜\Ä€ Y<ÜÅ€[×äšÒõ;MJòùîtûØì‚£Gr·EË'+ ^œsŒ½EÓ§×­ÄIºVY¥eÀ‘ Œ:)Ïß¿zçÜ$ÛM4sïPÙ…$V sƒŸ‚?SÅ}•"i£º»µÛ\O,Sµq§µÝGOŽîx£u#jˆlF2¹ëÁÿÍ`¶gµo%QVH˜ I›¢žsö àUn¹<ÆDR8É-ó¼œ`ãØ`š¬Ž5.brË’zàÏ¥m:Lr=©gŒÄ#™&C…ólçÓŒ@?${UôV˨™-în&†9Ûº8D¨C„$Œ•ÝóïÎj­¬/®Á#O¹šmGΙãP2TœŒ§ŽÙëÖ–òÝ‚Þ$°Z›Ÿ$Ûˆw‰öç+»± 1ÐqÔž´KÇš Y-àŒÊÑ‹;Èî<Χ/‘‚+Ý„S®Ü[¨Ž8ä³eiFç%\ñžw*Ž£¿JªenªÉ;\¯–ذ$g°ÏïÍ_Ú²@ò­Šnþh1ï-pP‚âpW<ñ’>3[(ÕfÕí‹i–º„²K ÷×_ÜH¦ 9f] a÷ž9n1ߥE–«¦ßZßO²ŠêôÓ¬mãva€‚3Á êF½_½òj¶w7–V­q;‹s¹,$foó6ãäÍFØÚ˜¯$†Þo«"&°•D• 0¥ˆ'Ž‚§‹(^ÞÂx¦Û›©+Íf=Y½¹üÇ5i¡Î÷mu,òl{”ši’Ù ê`…RœwÆ~Û‘\CˆäGÔFí£ÔG8ܼ7>Ä€qï_¡¿fð¿‡æm±çüỸ¬¨Œ¨?b3úéRME<Éb‹q'8]ÀqŸn+TÖ5›)®m´˜5HbšöU…ÂÉ +Åd†$”@åºû[Zèöš\w²B×rMt™žc.^L 1‘ÛŠçš7€¯¬|O&µus;YJd¸6Æä„ÄÑf`Äú‡\•Ñu –Úé­Y¢ž`&`ÄŸ1×ÏSÀšü}®O¬F[Ýj/>g joÖ]çj´Äijr:`ZÀܾýRŸ. ­Õ€ŒdîF_r9ÏÇj··¾Ôg% ñˆtËGO¥Ô´«¶Mòº•ʇ+,a—ðž™lu¯ÑŸ³½kÄ>'ðÖ™'‰ÅÜÚÔ¥·¾’+8cŠcnä«£Ò‘O8­tÉüè™ç-;3Û xíí·ï2Ná»Ò;rÜ{յƣdÂêöÑ®íôõbë4—Þ¸Œ@¹<Ð`‰]ó,Z=µ†—tö—qtÑ$ hWpf(3êfàõù³ö‹s9ñŽª×SÀd‰Rðe•Рʣ8ÓqR>^kžÁyJ±ß+êáe6ó¨¹<®zuÏ&±\ÙGooç5Ò©’ÕÕ¡UEÀãÿŒ|Öý¤ kÆ+ƒ+³YîuC"«"oÙ¹¤ýÞ9lÏ\äF‡«G˜ \ªm'ªÇ<{÷ª–…–) ›’ /«¨ÁÇ¿ÆGÍWÅ•ÌY]¥‚z.O^œc5mª[Ã-„Áâ_> ¡³…a‚qœæ®ôk>Kg»–åò<ËW·J€c$mü@gã¿©ý á?Ú徦cR1´e¶â@²GÛsÇžØgà×d‚ö+˜ÒX%ŠtŸ&Ýà Á€ÈéÏ¿õ¨ÞUÌ“@d½’ܤNe·VO߯¿q‚G?ï^noz¡”˜cA,ÓG*'ƒ€Fs“í·¿QŠå´_^iº>›¨hú›Ûݛ诡.¥ ñ$+¯*Uˆ–àäñÞ¬üûSÓµ¨ ¿ˆ>ŸCÕ¡!dgmÝgº³³Õ±óŽ­‘̉,R$±H¡’HØ0qîë^éJR”¥)JR”¥)JR”¯ç]Þ¥§A¦Ëem‚2ƒŽ3‘Û#I¸¼†Ê9t­@½†ÕŽA$*ùÒm^áX•àòAàâfšæežâåüÉ®]šY^(îµ Ê4èA àú™Aï<æ¿*ø‡übêÒ ®'°ÒÌ,)¹–,³*±ÉË àçߣ[*¹‰SÔ×7e†E †=ÁÛ¿Z•¨½Œ–?Sm%Ä­AžC#CߟcíTw 5°ŽK`³Ë?ž‰ d;¹Ï¾HöíÅjWÑ•UH@¹ò£\r%˜ŸÈt¯—“ÌÖþUÄËwlŠ^k[ˆ<ÍßaÈ~cßß­^Áh—,óÛÝFnQ<¨Ü€Ë ?ÃÇ#Ÿj¦Õ4kë÷M{kk=¤`µŽHÌéÁeà ¦1×ò©:m¥„J‘\\´AÁ]דäJ Ï|“ß½oÖ¢Þ8ÕmÀŽÁÌ*küaÈÇ={f®ígp­y (åŽGOáçßžB†/f¹’;‹wúa#·`NO\Ütÿ/Í|šÖ+›ˆRß$D@ )##¸ÇlŽŸJ„$AÁtŠI*.yãÇOoçZõÅý œ_ß·ŽåÑ#Mè[ŽFy÷{mlÝ ^æyMÞõ–YK P £¨ÇÛýqY!³†H{t¸5Z=GhÁéÓ ÇzÉ e·Œ¸uß#Ž7ÜÀs`1Šœ‚7iNß)$F‘±°c©çß5#éKÛ(!÷Ëx?bsþÕÿR[KY¥†{h ý+¢áU#¯,q‘þõ+é®Ö¦3"ohfq”àã·<ñЏK5k‘q½Ö4‡kÁ¼õ<ç~=ë éµÓ%3KpmP´xGÉ/Û~"IÁÆTa¯éî«äÊ$’V û‡£g<.2:þYÍWj:͵½âÛ¥ÓÏ&#Žy•9#•_xëÈ­†FúeiÀh% 1÷\ã¯R1×sRî–p3²¬›xÉÎU¿!ïÍKY¶’9pAÌUžÀ{â³·Ÿ*’@Nîz`µbŠXŽ(8åZ28ç§56%E“J¶$zàã¿4U”ä–ØÉ.V?ÃåÇŒuíÈ¢?—±¥”È^y<ð:ײ›%2FÛ)>Zœ€I<ýó’*Ã4ŒŠ\·¤!fe~A÷óÅRx‚æêkwj¶óXB«8C†›n9'¦3À³“Z…ްºª”]–·Qþ+V—q”¸ävÆ9â³›ë—F;#Üê`œ ÀSØäò3íÚ§F)-§ŽÚõ$‚w•ÆTc Ž2GÚ¼m+sAPG±~™[r–\t#ã±é×§žâÙnÕ㞌ڶ՗Ì;£oåÆ1ÁûäUMΞmÅÄWAn šLöáWìJ’q;qúÖ|X˜â]D»2¸…ÈçÜïÓ¥^iq\`"ºž1zY$Tl¿!W€6¯ñךÞ0¯nöÓ[̾T«²b2=899àÖ8`¶X®å°’;Te(P‡ÔSÏ¿ô¨Ka$fk“7˜°’ÊaSÿX{»È$ÀÇÍK»ÓÂY“s§É{-öï*8- 8c“Ðdú‹|ýªšê&²È‚xà¥Ü¶¬Hdˆ±ýæÐy àcAø:|éhupšuÝ™O0´—ÖáÕ+åùAŒ€wÁ_œÔ(-·J¹1v§{€Î}«a…Œ·—Q²\ÙR ìd ³oC‚FîIýzTëxb»ÓÉ’K£õk$¶ö—¬®ÝHøN;äÔUÃÍw Ú»AxÀÜ!GÕ1'Ó«7#äàt9=2Ozª’S*Å#%•Ü“ÎÒH-ÆÙ4ùÁˆ1 $uù銷:ŸËhÐMin±Æ÷1:ŒE& Om޽ë5››9$¼ÂÍÅ‚‹Yò&VÈQ‚xÁãŽk-œï§5ðµmZÊKë€Öki QÝ d0'9#“Öº/…?i¿†¤Ó-çÔf¿¶[§m^ÎâÍ"¡]ÊÁ ¥F3œž â»í¯íSÁ70Ç(¿‘nØn6ßáÓ¹GÆYw¨)£üÜÏJ­ÕômÇwZ6³¦j¦ÑÞF,ì^Ui¸DÀ;³œŠé¯%ÄS\Þ}LRéÐYô±Ä7 ±vßœ~.Üu‘^ »‚êÑ.¬Ü_"îò^&8‘†TŒŸœŒóÞµ+$Öu‰¦¼}\ xͲ,S¦¤ê¬®VDTo(€9$£gµqOÚ=¸ƒPÒ¬íc·¶³³VK›»K²æõÉb –·dd Î gŒitô“²´’—Â&7©ÀÝ‘ùðGÇ"[¿•0ò¡|*ÎÒA‰ñ“ßœt®àÿÚ½á};ü>C¶Ë"ÉZ”EÌe¿ B¼÷ûóúHñ§‡µ[ 9¤Ôm-¥¹Vˆ¤—60àüž ÷ãjÃüKÓšmJÊ8mo–×Ü]9ØŒA ³–$H=ªÊ¶a…¼{h„æi™]ˆ“v ôÀÇ`1_Ž|i çŠuv‚ÞÖÚ¾šVÚ@c¹HØÆŽ8”+œ Ä÷ÍrAuéqlŽÛv"”–*¼rlr3Ÿõª³×®$CirÀÄÑmY@æ&‘×®O¹ù®Óá­PF-õq„Kh#sä(ÎOaÈ÷Ü:ŒŠ£¹Y„§Ì‘‹ëVb3ñþœt¨ŽÄd0·•Ù¸°~‡ûqUVÆ&Ÿ'Ô Œl3•ÎÀëÅM¸X¥†šY~¢QlÎÁ¼mzm8ü«4èf˜8ú˜-ç3Û(lùHã{('°-Ó¯«÷·FúÚib¸‘Õ–{OJÈ€œFØäcž˜È¯Ò²¿Û‹©t«ÈåŽçPHÌ ]¼´eÈ#<à¶î§ü¾õÝü©¤»¸ú‰ü¡¸\/>®6úqžyéÞ°¦§ÚʦÞíƒ2픾 ŒsèVlžƒøqÁ®eûkŽ$ð|„›(¤úËhó%Lž<€8èkòšë3<9”'ÏSÿu¿ÍŽqžk¥ø3Ç:†ƒw¥¯×ÜG£›ÕmFÐæEh‰Ã½Ž <`ð+õÆ—«éºÕª^éw‘^[¸áã$9#NNAà€x«*R”¥)JR”¥)JR”¥=t?E¹ÓîÁ¸µ Ì–Êïµ™Wû~OóïYÂ]ã[_[ý:BaóDE¼aIŸ’Aà~¹Kc¥Ÿ5Ä_ý„¯‡fÏ(=YFF>süªÚÞÄÝÃk-ªYÙ,12LQK‰à’x'äÔË{ÝvĽ¥Å——nêÏŒÆÄp œóÈûÕlZ‹YjWw±yÍ)Âý92ú¿ÉŸsúã½|×ü¶pê.ml¡I@å·´Þa ³KœðÅlz:ê7ñ^jÑ[½”±,6zE¨%TãcŽsŒ…žj=ÒG§Ü[5¤Ös<…¾™beóAþ¿meî.šÖ wÓ¦·”ù÷ó‹)^FÒ¤ƒß§åPcÕ¦´Cf°Ë4ÄL6ćA_Þ)ècѽµf—^¿–9"’ÖdT„(˜ÄÃfïH8åGNç?zɉg´¶·±Ó´[iÁ]H›¼À;Ô“ÉÁ8õµé~-[ »µ± ¶öKn$#9;I8'Û8ÏzÚ¿gþmoÆ6Ú­ÜÓj°iüIüÌÄ,'Ôªá]‹ŒŒöVë]+öŸ*]ÙÃgs«ÙXÅ!¹›OÓR"Ú¶ßÀ ó±I÷¦Jœ ü½|šuú]Ý2[[7˜ÆH®äŪvR<ñÎOsZ­ÍÒ­ÄEaò0lÝ+œž1ÇV³,ñI)çIlÑ^2*Án$Ïrožµ&â;tš2×3½¯Òo‰¢‹¬¸* ûŸ¾}ëM¾•£fF\\©¶|çÁÉøÈÎ~Õ¦ßjS,eí¢A¶1¸0¼çŽ¾Ç‘PÓY½¶H’;Ï%–ÌäaÉ=95=|Q|Žï ³Ž6rbYŽ~8=rkb³ñÍÕºÉo5¬Wbò1Åþß_X ¶'¡ëüêU´osqe<;Cç´ª>âýñ]?L7M#,² ¶"lØ#ŒŒã¿^ƒ½_‰-ÂlÙûÐz©ãïþÕM«Ý²A)‰\<ЕEŽ@XpAÎsÆ=½ÿ:«Ð'½1…ºhæ †Râ9èA«£$‘Ïè™dfp61裒:ûb£ÜiVwPÇs(Oo*»@¬FÃÜþCõÅ[¡Í´R‰ Îņp[“µ¶ýºéU·ÐÝNÑF—""“,ŠéIÁûþ8«%I¢YY3Íœ¾üÆ öÖ¤ùkµÎä ¹çÆ3š‘7šÑĬKC؇ A7òöäñU÷±™$I¦d<¦a– 9 p~qXMÅ¥Š$÷“LÍØƒ`ÊgÛŸ_Ö¡è÷~o%{èÖAy#*ÄÜ´C…Êçž9¨Þ&Ònµ]4JíX,ÊŽWùvù­MQŽ U£•`†âH7Â,¤‚Ý:wöøÅYøcKiu1pÒ=¹Š'¸I >Þnù<κn›!˜ÍÒ4ŠŒ6‡V.AÁ`p:;uö­{W½ÔâÔá´±†Id"y·«yrg€ÄŒã¾{VÜu-­¡xv¤{Fœ´cûæ–~#Óï⺽°óïDQ‰., Äã#Æyçâ§éí$‘ËéÜê£g;Nqœt©[n/¹•bMæ% ýöäûÖÔåŠæç†ei­üÈÊ€vŒò ìG\b±jBi4ÂtéŒ7lUDÊz®A*~ïY'’kv† LІ@¨ŠÔ¤ã'9Ï_~‚³\™`KYg0,M¯É' €¹ÁÝüsU÷mÆñÝ\-µ© ÉpÌçnÜuqìI÷­nv™ä‚ïRšÞ{X€‰æ°¿rá´’Tíë@ê1šó,HC5»ÿÓ™vîG÷ˆGR:à~];ÖG±dkqup<Ž ´!Š‘Ç$ñÛŒàõã5]3Íyor-{•‚ÚP^Þáf¹Ãqnãæ CiªÛºO›”º¸†/* açùè?»#<®2GZ²ƒP’lÇõֱݵ£Hö÷V;^L…HÈ “ÆO9­cÄS–#¦(ƒS1 ¤¶Žeòåˆ1€Ø(ÜÜ8æÓN‚úÒæÒÎþ›C*'eÇ’B#ƒƒÈûw­É Gm4ï*ÊìÅÉ—i|€°r{ÖF‰Ò4IÚ&‰í‚@êÜ~xì:Áâ¾oxím•!’;p1 Ét Þ®óœãú•ku0¸Wú˜ï·îš›(uŒðF9Áé‘U:¬¦ îî-¤ŽI¢&»ÆÓ“œ¯°÷?A¼±ÛÅ4МM‘w°ò:“ÏÇÛ#¥D7B’DEŠ•#`ʯ´ää‘Î8';U¥ªB—™KØD†Tš4ÄOm«¸Ç^:ô¬w·Kª[‹fºŠ4Rò5È*b$È/ŒðO½[Ù]ÞjZ­»È%Q]Ë'Sé\džqßµ|½f¸k·žH€‚àÛFÍh?Ävá×Ô: sž{ñYPÊÖñ[¼bH̬âo¨~âUISÉùo“Y#„4s,6¬n VvB[(PJóŒñŸÌüÔ5ŽòOúˆVi/˜€K§ßÕï÷©†é [[¦¹Dôž;xðÊáXœäú°Ã“ÇåÅe½¹’6žîÒI­Ä;®È“cM”*¿»#o\z† Ïc£M¨[ÝÁ;Ç-‰6j ¤ª"áðàåzäþ.˜ù­Ûÿ^ø–ÎÏY³S[¸nV[y§]An¼´xÿç$zFX·JõáÏÚÿ‰,EžŽ’iÿNö}¤ö^_ГԫB’{ò{šë³ïès\Yilú•³\ÙæYu`ÛΙ ¡¶«)8ÀˆíÁëÉ¿h—¶ú¦¯ ÑŽm°\Ika£¸‹smw …g*s““ϵi©ä™UÕŒžle62êrÇÎGlœãyæQ[”w mÉÛêãÒA=OÞ¼È!rî€AêŠ X)m§ô¯×”¥)JR”¥)JR”¥)JþiÞ—Õ&óî!ÚùX–æ¡•U8#•8ÈÀ=êßRO²²!º•"ÆîÅy?Óš“jn,mÚâú s€ÇëÀÎÑ‘Æ}úýëÔÖê®!Óo. ò‰y–WFÀ#…‡9ïíUw‘CnÍu&§ü÷m®¡2˜„Y)àòA8ÏüרNœ‹ .Ò›;x|¹M­™ ç ƒƒÈûž¹'?>.mô»¢–²Á"ÈXK’dc‚ËÈ­ŽëQÓà¹K=òñÞÛ+Ë팎ˆ‡Ž~{{ÕzM6±{»)m%ª‘ ÈoRqʆ÷ã¶sXÒÝmîî®..nŒ0!Yo ŠqO¿ªKH_ß­½£%ŤRKöWvb¸;˜1*0IhÇ~ùÌ´–[û»ˆ¦yÁ.èÆ6ó…Ã`àu«Û{kÛx¬EÓ]Ý[Iˆí¯‚]Ç$ÔyýykaPñEŵÅÝÃy¯¸5‰TØàðxGl3ÜWéßÙÞu„æÝàµÔ5{‰/{ˆ ¾XÝ·»ˆ HçwÞ´Ox·Cѵï/YÐõ;¨ °2ÉmYÕåÚ<íÁ‘ì £Wçoñ2öëQ¸¿²·µ’æñ¦…ÛrE8XÁœ(8<œf´ÝVHìΨ,Yd¶x7[²66nRyùÙçìkP[›kƒ²Æß÷ɹJ¡$)UïŒÃ"½G{ q,âg–tá­ô¿ˆuø$ε;ÙÈmÆC#JVV.9GÉëù1ÿž+KÔ¡0;Ü ¬®FÉ2sêþ|‘Q4ûxïµ]> Šžl빩 Ï¿9w¸|#᫦I%Òl†ÞÅa¼ö8Ç?z·‹Á>Æ`²[dZ¾gÁëVúoƒô«<ùq3Ê¥®c>Ä1Vw,‘>û •½-os'ÿÝ‚kͶ˜“<ÎÚŠ$±I²H!Û'”p=õÏSÛ­bºð´·±#Wcî  M¿þÏ?ÔÔ O jZJzËÞ+mç<{g ïHâ¾¹–E™¢‚`¦9#rÙüÆ?.jͬ–;gáÖVRŽèÅwsø²G¾}«$@IÀ2¸.Hã‚¿Nß•A˜Ö?:EòQ"v—gÎ9ççíSd®‚«#nOÜþµÍP£ŠP‘­Ì‰4Ç÷’H£haÛ ž1ýæ«îàóšQÅ®fŽ0„–Û?ÅŽ•Xnb–E ÐÛO'š³_Js$Ùȱø§iÒÌDQJí,O>Û;™£9e;OBŽ<Óí‘×ýjUôÐØ´¨²3Èë-®Ðv5°e:ž§9éžÀT,_Z[$VfòkЛÚX®Æ-W#j.î6•ãeltÈžÛY¶öÐKlÒD ùÒ8aܞï^•'N¾‡PŸR¹ nƒ`…c# N c޼±û{ÖX‘ä[›)|ÝÆ!¸<ˆÃÉëŒö=G^ H¶²èÊZ £Â7ØÅ|Ô ‘ÎpGNµ™×Ζ8“l!T€v‘ÇCóïYMÊ´) ê&Gˆ†Ë¶y>ÝÏ\ý¹¯V÷Vi< %¨‘ð ç‚8ôð@ãã­|Ö'?J&X-m¢E !Ü Ž:`qìyç¯YjFÚ?"k(îá’!©$yWÀÉöäcã½eš×O{;‰’Xâ¶.VK9<ÆØ;·÷äïY­®ôû](a0K/ßNQþ ž6~ŸjÔ^J7—u™’äE“`BNÐØcŽ˜çŽjãOÛ%ͨRð€»ØKéÁ\ðO¼$)û´‹jBòoòŠ D{ž{Õ5ê1&{‹XÄóÞ–†åI!#^r€G'¯^õšô­£Ò\ÜÏ ³I˜4„2† c¹ÆCÅUÆöža–H®&µ‰8W“NˆžG|ðJŧˆç¹¼ˆÉp°—)b¤céËܽò}ÿÍÇ|ÚOšn­é>ž[xÃ$R9q#޽Hçò©Ï=¦·r-u9dµ‚Ť·I`yvÊËÿ`@ÉÀäÿÍzú5þœÍ~÷V—ɽ›Ï9"äÅ:møéÓ½RZÙ^*¾¦&ÌÓxÚ¶hÃ…!‰$m#ƒÆAç߃Wp_[Ia&©s<ˆ/PK`ñÈG‘1;Bàwôƒ“î}ªd×ú•âNnïlç‡O*ñ=š6é˜(õÄ€yǶEL[û{•ÛlŸ¾’Ù£½óÐ#‚¬Žq–ùä¨;ZS’­ãK¼ù1Ï+.O€üäc'â¦?“±[ÈY¡*ÈÒ6çvOår}»f¡Ú–e’9n2ˆÅ÷8\–Î^EF÷Ü bó[ÊÚ% ˜õ‚0¸èAÿÅnzoˆµÍ"6·’À²DÖïäFFäaÓiÈ<ŸQÀ ò1Åj°NJ4 èB¬³y*Cƒï^)áQØ!e‘d$2¨à¶IÇþjSA)³—•ÚUI¹‡ñ[“’–3ž•C.–eº†‹k~úB¸ “·#àî'¯|Ö³{á9-æ¸kGp#D1Ïï“¿$Q½zÒõû½"_¥»(7i‰;¾p{û½mÏ{ÚG4G#g-lö?zû}}$ ¥ùÐo¶·WƒÌiXf=±žsùÖH-¡…&0¤ qs6ðèúÀ-ÇBÀóŠ‘, ís"Àïm+“ç9¢9#ïŽ=«uýžCngך_8ËjÖÓi¶ñ)"LyždÌNq€Ts޵{®ëZ´L…nQ]ÔÈÛeÜHä öߞk@›Åšíª¼,WI¿t~taA>’BûqšÍ?Œí5xžÒx§·†xZ „.XñÆzŽ1ñÒ´?§Šþ tè¤ô™¸Û·f\sÎ1Ïz¢°µžÚþ[F ªåÈØã¿ÜƒÓæ»ìVþX?hÚe”£k)¹€î@àü~í¥)JR”¥)JR”¥)JWáK_éV)"ÝC嵩x¤Kû’§r’|¿Â0x>œä{Öš±YË­K€òiÖè@‰gm¾aί<ÖfŽÞâd†k«…1O¸8' ½±ì1Ç={qX$K‹ˆãÔ-!á㺸…ä÷À …?r:V'‚ÖúDµÜÏ óMtlAót#8ÀÁãŽÆ¡Ù݈¼øÎòK$´J«A’NÎ’Øö5s¤Z¬èúÉÚÆ$g´ŽX³qž™äÖ;m?Y½úËù&2¤m¤0,&%œm ùgãšÚ,´­ÍíñI!¡‘ A˜ÙrÏAQ/UtYâ·¶žÕÅä¥Y/™9ÁÕ&H.µã-­›È­*7%¶«– g·§²zÕ´¾ÖÅÌ7"4–{‡‰ÇÔsÁ½¹èGúVÉ¢xn÷ÄW–úeìwPjfo%ËHZBZMÜ–% WèýS]Ð|áùäy#ŠÏF…,-í½_¿—ŽÜçcŒà2Iù/Æ=Õ|_q \Ùiv–š-ȺLAƒ!m-Œœg¦GÚµ›Û[{Ý=ï¢Ñ„ q ’9!½‘”Þ€xä¸#ŒÕ¯ônß\³Ås¦ÏL¸‘á¶üÿZçÖ« ͵ÍÄIi%æí»Ž ÿ£Àã§~æ±^Fa˜CApë4m'T'“׃öã½TÉlÍs,N»Ìs´JÒ(¶:|ÔåÒl®mÌW6ñn9ʘÀ 0FsQ4ÿi±jÌ{3Ì%Wpõ?Åßæº=¤7Vh®©öáK0Œä{€zŸŠº±¾K‰Y‘¡ÔŒ6~z{~U°G6ÉB²’§ÀO5çSÔa°·’êvÂ)ÀdÈzrqP4»#mj;%¼¼¹7³;„öçØqÿ“RÚ Vê xŒ‘H$f’%;ºŒ0GQÆ{ñVêRIpêÖÒ˜b€‡“Ààt¨‹,ºx“m•ÕûËÞÂú}´’,Àð@+ÂAàãß'š²óüÅŽ[k{õFVD–Þ@_Œ»ùÈæ£G­ZÁ¥É:ÝLÓY(‰ÄѸ388ÆXuíVâÖå¢'72&ï)ѳ1œŽ«ß¯óÅGºÕ!ó9ãÝpé$óÁôƒ€:ÿ§zÍdö×—p[­Å´±\ .˸ÎÖÎ ÷?5›V7¶) Vv–Ú›ÌûU ôpyC¦þs»ÛX5+´a‚ÉpFmwHF$²ƒ³¯|ŒÔ›;˜e´$Aº°òå–6ư'©þÅYưM!i"•˜d€Whûüt©H‘•–ÄF&`*;üýêbÁ^Üt÷çûéS CB 1ñÇÿç¦k:!RgR?î–ôw#Н5µµÝÖ²“N'¹¶ ä¸ÁQ~G@?*³8¥DWXà¹Ú1œsùóíR‹ìGºoÁgœ7ßâªÑn.gX”/ÕGµ1½y×9öâ¦ýD$–·á•”¬°Ê„œŽ¡‡AÁªÿñ„ÒVêI£ÂD›-ÁP7ˆ÷ç¨Æx­fãV[û¥¸Tš, &™ °X)ë†S‚~Ýyªv»mVæXíîžvR`,êC\Œ¬v®þ`ÿJñm‘‰Mþ˜â[w)#Û[?ïQ“:2þjzÿ†Î¥¦Y³1 mq"Ÿ1l.^½3ñž¹¯P #¶k;i#¸¹šïl»ÑG*É8$a@çµG´†%ÓEËC=ÎÜZKkÆ6‹m27c“†Ï5e{¥Ç!Ž ._Pmf“`hBòrÍÎí¹#œ¸¨Ö÷‘éQȳÎñKqwä¼7±12å‚(yÇ?zùvf–5·A#Ä’,ï vœ†ÀÉÉÈ矷9ÖÕØ²&dhDEJHHy?æaíTÓ¢§”nc$³mFa–Ï >•[Áb÷J« ÞK·=7vªÃ›mn5¸žo$ÙùÐ4s!b€§ øˆñø°:õ«È¯ÇÐÊ#6—¤y„ V€FJœgžÕ™oR‚{{»8®uKX€³¸drH#Œ=êV¯5Å“¤JlÊ"ŸÊ@Hå#GáÏš×õ7Ñ´¸´˜í5Aov÷3†ýâÛ9!”0Û†nÝ;Zí‹VµÒ-ïßT²œ'—tÊÄÄËé·n¼cß&·X¤k}2ûdë x@(ÊÌBíÅËû~•W¢=Ýž‹§@ÒÏõÖ2F—QÏæÛ3î½O|/9±C"¬¢]†s¹%U‹ô°AÁàûûÔ!Å’e2FlPK‡d|‚ËÁù<ã¿Zñddk‘F†Xæ19•îsØñøNÕu,’ïXîc@ò;e.³±<qÑ¿³UÉ,B6†Y'‘°¤gÒ3Ç«§N3ŽÕ'ê&ó#.Ò«´`(9矜÷¬¶†i¡–ŸÍK¶ò$›—yLA:‘ÓŸzñ²‹ €Ë›•}‹…9²Füœ ŽÕWâ(¯®´©c´½úIã ž»?—ë \é««ÛC³«_Cˆ’õ‰Û#Ò@ëÀ<äõ={I†ÖúÎ(Är˜å‰¼nx%N2> I·Ö§‰ÇÕ3v§I׃xûb§Zêw í&èÙm÷ÜÂP4c?¹aÆÓ€ ‘î+e±Ô–ü‹•Qmp®WsI•ˆƒ¹“ÌWEð3Äšž«æ…¸š]9YcÝIa“·Üäcœp~Õó[RI Ç*ã=°äz{õÏu6&Üwoa£Ž9üÿ•TÞ S茎Ùùýj^—EÅßšÒvˆ¤+øp=ß튭h–ëU¹Sæ¡‚ãAÆã€<ç±­·ÁÆî/Ú?„g·™íæ}Ac•à³ó˜13‘·#§çµC)JR”¥)JR”¥)JR•øJmCJñ`ŽgIa`yO)ÂŽ^CêÊŸâ> qŠ÷‘áK6îîÃQ¿•¶[ªØ3 \•ÜN1ÁÁÏby­fêÚÏL–‹›‹d¶‘@5&P’BÂ> I§Í´;ýR{ù£»±·ˆ^Öó¼Ž~“ëQìü'ƒŽÕÕ#²6Ñ­¶Ÿ}rÄ©Û$â'lÉ8?מ½*¶ÆãHƒR¾·º¼ñ¢Â&™-Ïœçñ2¤yÇ'©ûUâØèZ}ÔQ>©w,* °Xöl`A\ƒÓ’xÁ©WSiQÉqßK4× 6¼w…ûªÏßóªÛ†¶}AOÔïÐ]Ç#Þ7§÷g×»n$ž0>Ô·ƒFËGwu{{?›åM%ÍÉ;—9ôã=†?Jƒ!Ñìõ'ß—¶Ì¤Û¼©Æß ÿÍIú[yní§¼š{(T(¤¤ù#gÀïÿ¼hZ‹¥Ã%Ö­¨ZÙÆâÞÛʉ¤SŒõwVUÇq×â»÷ìûE+q¨ëóÄ].¶Å¥]I8s¦í DÇsYR Ìv«æ”,‘²aòáè=þ?¥XéãÍ»yƒG•Æ}]{õÇú¹‡PKÙŒvÒZ²"3d~NqÎjÉbd•˜y{¤z‘ãòëµyŸP†Ù°ÈH…Ô²!läól*âk1m¡ <Àmø ñÏ?<:sR|7ze»4¯0gÉYe$ 䀿¯þ+iÔîEümä$‘&Ñ${¼µðò:1^¬îÐÙ¤Ð\-Ë–Q¹˜œsŒ9éÔãšµ´E…ǯÍfóeØp&'±Ïoø¯º½Ì¯¹C"¥´©+GÖg\á—çätåxëQ⹎X­D›âšê?8E/¥±ÆAùÇ?5¯øŸJ:‘‚7uœÌ« F$œu=±ý*4û½3e”iÌIåÉ8¼“†2L#¼{sÉQß5>Ñ&ÔlmoêI¾…¤1D.M!A\ð_ wuç®s†MJä[iwQµÖœ¬öΪѾYnH`ÜcŽ;VkùnÕ¬n#–Þ{#Ø¿·Œœ.ð¤g'#‚ ïî*»üR]D‹»yà6±˜ ÂÂÌ$;¹êµ%¶Ñ5›ƒ ó\@óH&¶nVt\– ÏSŽ8ÍXÃ¥i¶1<t-¥>én2Á‡`ÉÓëUᢆÞ6·Ôg”Dò,ù±ä›¹ä‚CŽ•qgse§Z[Ç*È·EA˜CÌgå‰Ü žOŠ·]J'"iá’̪«,l…N8'=?ñRc•‚y­"Äf%‘[ |çùj¨Üiš(Ž]X£Úê);7 €OÏz¬Ó%†ÞÕï‹ÂªÓÚ‰Zá‘ðƒÕŽã÷­’Æva*JÓŒe–â-¡Tð8ûwï^@ª#V v/nOúÖdµ‰¤ó]FNWq<süÿ±^çइќc oCÇAýj;p%håUO3(ì3å?^¹øéTÚ†™ªfÒ[}a”ÈÁVbˆ6€rÈx9Ê瓜méU…,ﮥ} 7—JÎZñ£Ê‘G)ç zýê¶ÆìKo'œ¦’à<ñZ!o1ÁØÄ3(‚qž:µ{¡ÜXÙ^ÜZ‡hÖHÞAŒ®Nž¸9àp3S|\Àé‹-ƒ/TÄËâS«(ÀïÓ'¦j‚ÞmFÚn ’ÞØ¬fIX“ÍŒm‚3Êç§>k˜öS_[É.¡êÂd¾ÊHRzs‘Ï^1V:–—h·’UH¾¢Ñ¯d2yy—r…Ïc» æ›yle’3:®$hÔ\ýþŸ5_¨JÃTÓîla¹ŽKmÊDm:—Êž\Ð󑌣´Í3TòZKYô{© ²4“4 6î Ãu¯=ÜñÙ‰,.Õí¢tµº{s‰ €Öãž8®{âï˧^HÃKȼlÁpþjo €NÐ@'q=~8Ç5­Ë® jÉ,®ÜÞüÌß» ê`A^§#œóÍn6z%†(Š-/¼biEÁÞÑ“ÝzdŽAÀÍmë%Ô¦Þ1cŒwcêuK»‡Ø01Œ2ç.<0zÔ ýVßK»Ò⺹!õ™D‘¾rxÆÜ̪r:`ö&³Š[¢^XÅ?›¨Em+¤P€w°\ª‚Ã'g¼×#Ó ‡ëbfó‘JF€lÈä yüúu¯±Ý‰˜[mÆöÁlÓqS†ëÛ¯jº¼xÜ´«#ˆö(› "ô—xuèpzÔY$eŽ—ÏÜsèpy1ýkÍË2¢¬–å¶vF•åÆû@ óÇn*}œÑÅ´Užé|°ü¤mõ’9ç8ëïÒ±›™ífH®P\§˜èJú^-ÊAýðj³R×!Òâ\Ï‹GPŒì´ “„ 窃êøÍQéZ|“^%ÜPÍk;,ñNI]ÄžF1Ôc=9÷«©gÌRNnˆ˜ï@Чi9ì:׊®Ô´Xc ˆFFfòÑËa9Ç99ûœV·=¬ÖDN“ˆåfâqë÷ä|Ž+>™­[}Áæ"E ésÓ‘÷þ½+´þÎ]¿:uçÒ$º;A0„Á+™Hàô¶¯úݴм—òÝÚA•z·@=— j„…eBÛÁ%À@Cçûÿš×íТF‘³irc~ý}ýê®ßQ¹Ó¯¤Y$_§¸Ÿiô3ó…xøëùÕâá¯^O0UIÒ.2ŠTvë×<÷«m>äXëZN±mu$WSy¶ïí;OpF=ù|×îxüO¢}t¦6šÞíìf’1)UV Ž€ã8ã9Æ:VãJR”¥)JR”¥)JR•ü”ðý½–a}G]K‹iUu K[$o92Ad;÷19Î6ŽZè÷ú;_Gu§¥õšØjL¾–e–Þ6+$fw»>®1[ìZuÅ„’½ýÊ\¯®4”Én&pÔòΜç#=ÎkœÈÚ¨µ‡Rm:ÚHo/Êå!Ô—}¤Ëêߗʤl1‚3‘Ÿ~áï ø‡PŽI›O»²¶6q}qw*ªØ È½ÀFÈÁàñžj.“¢Üé——wVvOª[Ââ9'Ó‘ôò;ÄO$ç ¨ÒË£©˜t鮯.²òÉ îb€íÆ[ÌÆƒŽ„šÃ›rºÅí¥å¥–•a=?]³Ì üD7 ¼uÝŽ½ù©úޣǧ‹:î yÄ 4 ÌÙ#×´ç'¶Õ'—§YÁnn§’ì;'ó’?)ñøp2qÀ=jæßSÓRÓÄGë {ä¶’þ__4ñŒ=@ûŽ*ÏDѧÔíZ{ÕÅ£+%¬—1œ®27xÆ1ùs[ƉqÌÖ~ʲκu½äD"6H¶zã?ßֿO[Ú[izuµ…¼d[ÚÀ––ñ,K ’G&¸'íMîµIt¿é6ÖRë:ܤݬ:LËd€«†°Á–\2 È9ÌüO¥ÚèÈ‹¢Ýh*cUîцéÿy}¹ÁÈã=ëJÚ†­s=ì·0D%I8óþrrNq×#ò« nšþÊKAi2¤`<«(#Û?ï\£_Sgs4¶¶ë)tÑ´ŠÀ´ÙUÏÉPsŽüšÓ.uXn6H@Äå ç%‰nr>1Ç~:VOñ4µš9­$I•QË·NIcÀ«û[ߪe¹˜”ÙQâ5í÷Éǽ@¿Ö&¶¶¹™..›<²v—'öÀÍiš~©qiy‘9)‰ó@?‡#é]ß@×â½Òå¼»”B3FÌ?öˆÇO¾Ny¬3xŽÎê6Ž+ˆÜG&÷•Ú1Æ 6AÇSÎjŽŽ5k››©B‘9i.Q‹‰²¨ãŸr}ÇÅ\iÜÆZ[X¤2$‚I$ºg¶G§ ƒ“Ín7„v«­$²m¯Ý‡=9ÇÛŠÅ&—Æ/Ì’ea1JèqßNq÷«™"žCÙÜJïâ¼bD€u‡ üóÖ¼[jQÉnæõÕÔ,™;ºÀõnO\U¸˜TÛ#È,FJ/z¤ño&Ò fe¸žõD99˜ÈV¸^ÒödÙ õ­ý‘xÖYG]ÀoŒ@ê®j“Qkn,nb¼·¹Óœ}3\G# ü@ø†:ö«±|-¬àš{˜…¹CªYG†±Î0’' ŽŸcŠ¥º×Ñín¯õKÛŸ.óâ·HÖdó¼À lsŒÖGñ›}z'·¶Õî&¶ž#v÷QDk‘ÊôÉçþG}ä ++»;«w•.æ”Ú˜Z>iÜU°G«qžŸ~*êóKÄV¿¦xBî  N¨E¼7&yb·óÔ¿@ÅX•øþumiuo=¹[†¾Èi# ‚1 R§nÍ×ç è&²Ú“Æ2Ë´©;‚µ®éÖÓéïqkw 4±o1‰rëœíÆ}¸æ¶²±bšÈ¬+ ó;¼ÇÍC¼ž[Û‹_¦_(¶ç¸¹ÄŠÂðÝÿ•J6Ò<©:J­"§–àKsŽ~ÝëÈóÊÉçÚj¢î¹ŸÒ¾‹–XÄ.‹ };r89ïÛ¥W>¡˜“ÍŠçxuQÝefàzºxÇ|W‹’ûÛ@Ò[3#°ä"c;òSŽzqÓ½PÃpÅh˨\j&k¶hodOèìFÜdd`ôÏ5—\·ž;?ñ+K˜u È£ÒÚí<ѸeA$…Éã­RY\º°“S·xæ„ÒX¬ªñÇàçŒÕ­Å¤7îô«mhôò—¶Y<°FDÛNW¯ýùéUJ‹ÝZy¹‘@m£$w&ªÂÊ¢Ÿ§"ÞT|ýA ØÈÉÆqȪyZhDª yƒË,¬¡L$CsðÀäÖyœ}$—ö6ÓÁ~ä[D^3ˆýY-¹}8Û“Á=kÊY»¹qwºãjÇ Trzä ääÞ«.LÃT•?j#YcÜN¾ùäð=;jÁB—iÀxÙËÇõP;Fã8õ 6 æ£Ëk$ÓÍ}l÷ëëxVØo¸—xòp£gð“Žõ®K6›â˜¤·ÿ™ÂsÓ¡‹`Œ:v鎕͵O ^Áq³LœÌñ>ój’.ðzƒ´ØÇ;°y¥lÚmÞ¯¬[«\ÜÅc¨è“ƨÒÄÞdÈr6“œÄ~œšéÜ´lÞs‹¦´X|ø28P7Èþ%o³vâµé)ª-µí”ñ†°‰î"‚3À€~èZ×u ÈDúåµÈž;[8f/¾‘¸ûð@ãÚ°ø¯[·º—L‚@dšK(d™ÎÆu†=qíó[î…£½¾Ÿnï,°z„ÇÈ>‘ùŽ >ÿoy,úZÜIo‚'V—ËYDžLy Cœã¨ã–¢ÞX-¤RUäÝ$ï»!Y²p9ãÚ¬¦‹éí-cÝ,W–žIX3Y²2yÆ1žÕà™P5ÒÃ$"s"¬jÇ~2Jñ߸>ÀŠõ¦:Ãq [)vÈžk, ‘9=g#w=ú}ê·ÄzTÅŒö·Œ³²í6þHÃ)9Ǩ`dc¿½dÑmá±·G‚h§ŸO¶]ʬ¥É<þzO9ÅL*Åb…q,ŽíйR¯OÏ¥-%Y'’ ‚Ñ$HØÆIÇqóÛÎ\ÐÛ8¸Q@Wnþ‡ç äsóZN±¥ g’hÚ6‰òßNñ…úD#‚6öàþy¨z.­s¢¹š7*‡ ëŒñßïî~+¦Ûø†ËV¶‰DQ‹…cæ3ÈyœóŽƒýkäŠÑS‚»Èv:>Ó†ÚÀí5ꔥ)JR”¥)JR”¥/´ÙìuéŸPÔQ,õaŠ=»và îIã·橯H êÉã­[Ák­Gsmu Þ[É’ÎÔl/žê9Œú&TÎ cŒŒŸŠñoc‰äì'ÓîÖæYõ;»¹Ø‚,b<)çìEtÿÙ^›¯éªÃ©xŽoxh úánÕ ÑmlÇ;K2¨äwã5Õ´ïxGXÔn|=áûk£Ô­²kñLòË~a`À†Í¥Ïº€ÙëÓ_ñÖŸâ ÞÎ×ÂÚ4“Épiõ{›˜¼½$¶ÐîíÆçÈ=I'‚qVÞ/ð¨xjámoä³ÓáS—:õãX-ãBH ¨Þ¥¹õ|ò~Ò´­sBŸO½úMíàÒt«x>”npB4üœä‘ÃŽs‘Á­Ï[Ð|I¦K%í׆廜Ç+ÁæÃ8‰F<òcVÏU`¼W5K O¥\Ý%§‹[]FõQ![EY ›È$ºqê+Ž7}«mhdI¬®n¤[4žÚãM³º1´nòå*wn1ø¾ÕÕ¿e~¸›^‡WÔlõ4·Ót£q§6¡ " $m¢EÝÔó#Øð+³ë’/ëfZZÚ£*\ϧIs/ î1ƽÑŒ•'8ÅWêWúWƒü+©êV®–B+cv 쀼ιUÁÊ’Oð¯ØWäÛx‹RÔZÕífñ&’B¶zª»À„ƒéÂUÚAñTZΣáýFÊW‚¬.@ð[ªç<®Oô­6ü$7 i Æ‘bv$8ùQßòëÍso]‹Mx!úhäC2Ž8*00x¿ŸÆn´Û«‰d¸);Lî€;zß?ò)j—H8)åíl•`Ømÿ\UŽ›~m.bú‰]a„3ùIžx8ôæ°^H.ebev™‡+íQÒÚ8òwÝcf9ãíÒ®"Õ.môÛ¸oÝÊŒžX‚ç<ã¹þûUZj¬K0Ža$‘–âlt$gœf¦Á4p›x/î 1DIEWàçÒsÓô"¶‹ëb%`Ö²Ãg*’v€[¶299ø­Â×ÄË«?ÏŒY»Ýƒ$fa‹‚¹À錑ƒŒæºµ­ê:$HJHo¡¸8ê>ã*ÎR‹²e±èîsœóX¯/R1ȱ< íÛ)9ûô8¬¶ú´ðƒl0°Š`[%0p3ùWÈmûVŽiAòl g€‚‘œü‚ýù­‚xÑ€ŽHEQÑ×¶1ǵsXOoÕڳɥ@ —v~R‚˜É2?’ã¿ZÕ%Õ´}WN0éšmåóH©/˜ Žt#9'œŽ+ÔñºMBîä\»X®ŸåÈ£¢à!îíךÙGµ†ßjJÝ=gVÛ‘Æj]¿·´{Xª'ºy6Ä{€qÏnJõ⢠£B%xÉ/Âol=7f½Ú´¶ñJ׊g¼ÈLgq:uÎ~?­`—RQ„6Âî!¹h¦ì‚Å$:szõl—sG¶šÆߺ‚KqÈîîqß«å/nˆó•fÔÛqŒ ƒÇÇÍA¼½Š%d”ÀE!ã—o˜Oðäõj?ÒÊŠÏ+Bd‰Ãàöö皮ԮŠYÊÆh6íuÛ4ÕØt®:¯²ÿM>È»ý:Ü]%$çkã9ïÓ­LOot·76–hÒ'“ç#o[åC) £iÆ¥j†ãI[Éþ§O¸·37ý/Ôéò•cÓÁôè+=ü i§P·Hd‰%@"”²ùŠÄÃŽƒ®;â¦ÙŠÉn×r=¾m<CLàõe|ätsÒ \M§X\E he[·wùøn:ã%³qÞ‹pd±á­ÍÕ±Šé%~á#ˆlõìMJqÝÒÇumôñi¡bh,FD²œ®1œÆAçµ+Öæá/Sd+4HœŒ úùÁÀ#ž‚¼Çhê^Á)m qmöø%Û<žý¸¯æé^c’8¤¸òæ,Ùò°\6H‘Ð÷ÅfxƒÙÜÀ‘Ûƒæ¨ÞBÆë ùaùˆîp8é_%½²_UÒ_Èî‘Fó܃¹°ÎqŽ©z}¤¬®òÆ#·ÃùG^0Üõ+ïÇq^äV…"ýè˜`£±Sº0H!HqƒÓô©6÷&²úƒÂÖå‘Ye@ÝO`ØþçÚ²˜¬-e’'L­wòÈVGLýªºXÙÅn.î ½žGšÒGq*H1¹—q8/ã¯z Óüß©yÃ1´WH׸V‘# žxcšÙmCÕm, ±ïŸÞÚÈ69n¬Äsœ:Ç‘’çH™¢½¸µ–ÞÍì”ùq”½¸QœoVÁÇ^µ-tÿ*+I//®um‘n¦¹`Æ@«tç$·ZÅovÑù¹ŠRVšyœ09œsÏ8¯-1Žx~ ÊVé÷ù‘²8u®K釱Óõ²³‚Þ{{‰¢èy5Äñ¸Ü¼HØóúñÞ«®UüⶦHR(šqˆŠ–ÁëÿËùu­z;›û}F[Å‘$}Â@î»Öc°úL`“îpqžÇe¶º¿Z›IMÒÈÿRmÂ@`ʀ󌞄‘ì{TEr~¢B×T¸ºÈ·ŠVn^Á¸Éè* µ£>û˜H¦¸Ÿ7WGåùÒô žsŸ~ÿs¿Á¨iwŸú•.cŽy]l&£W#8ÉÏÏô¬Ú}ºÏ¨Gu%Óß-¥º]]L³¶n\î$}‡¤ƒÆ{šèp,W;¾¤_¥a ØXÛNßO\…ÇåPµ]7N½UXŒŽ³Ë±A‘¢òIcÕÔdŽÛ²;× Ñ®¯~¿SÑÄ…á¹ßiŒñ&sn@éÇQÏZ‡qeq¤k–ëw]ÁÛL]Hl#´÷sÇJï’\ÛFÆH¤“Í™D@Ç~9Áàæ£ÍÔiÏa™m<ÖæãËòþ«‘µ@1€¸$ð3RÐM¥Ãª€¼+Ø<°r¥N0='?56Æ[Ûx‰K=ga*ÀèÉÚð?ƒžÙcíQí&°»™îÔ½¿”äF".DSz¶¶þ,‚?‹©ëW·Âå –ïg•gž ¸.1€1èçø³Æ*¤ki ‰YB$t…}Sû7ëŽs޵É|N—º7‰ÿħ–#bd‹É;D§+/ÿ,œ‘Ðã¦+bð†¥s«é7SÜ“/Ò\©bW³Ü`õÎr:VæÏºI^#!2FœÄU£ÊðqÉdõ¬í…K»7œWjl\nDZÒ&ÃH³ºXN¡%Æ“¦ÿ†M;Z¸Uó2³~ñÉá¹8çœdo³=kž(†{Û›Ö²“é¶‹¨€>d),N‚WpíVÚ…|=kv4ÛH&>$7­oú¼×Q³ŒàÀÑrÓÆKH' ý'Nñßìׯ°ëþ/7·ú]üÚ@¶š¶‰Ã½p j€)LdðIí_£¼=ãÝGeqeªÚIiw,v)iq©!š%€fRO¤r03’Ùö®ŽŸErñÞFðNÑ#,s¤¡„`ãv0p3ÏÅpßÛðĶ֖W¬«}r|üÚ8=¤5ŽãŒO¿>¿Œ®´ÿÁV––·ñK¨É-¾ªò¨Ë´°@±ŽÕDu K]*Kô¹d¼—1#¬j6N8þ‡òªø--Åâ[ë~m¼b46õÇ#ÒßË¿h6žvy˜Ï;Z_yÎbË ˆb$Ü:vÍq®ïnHIL²–BŽŽd^Ã>ÜYâxá‚]¶!’I6+Í# ¤`0pp1ÁçœÖKK¨‘$jòH‚$i"¡ÏPsÇzˆ—@3/ (èXüÿb¤F«¹¤2WÁ^œtþUŠÊ[giVs:‡E‹~çâ¢a)`­°PÛsÜóYÜÉ€"#.ÜÙï÷ëR-‘­dŒ¸YaÜ•Á 0?LÖëN’â{U[[X§óm¡3ú‘J&UG¸u$ûnû×3Ä–÷6qÃwuú É³rÙãî?–;×é¤Ôc¸xK• KµÎ:Þ„Œÿ|WFùÛ(Jï7– ° O qÔvïX®&KU¹b 2+I&ïã8n£óÃrHñ˜ÒgYbfšY fy$¼Ó#¦=«vI®BíàrÅW@ïÁ9éØW9ñ~®n¥L"¬± n‚2‡ )ïΜ|£Ó-­ü᳆‰7°^7ƒÇoζ…Š]‘ɆÆüry§åíVìM½”·qì ‘Ï¸BÁ\0àsÎüT‹}Næww»ò]ÐŒµ²îP>øæ­ã™rSŒ•#%³Ø~•qÒ@Pƒ‚†GÇZç>!“O_¢Ý^Ç!{T¸Š"1ô™f;u qÿ6>k-¾½§™£†Ýâ‘\y!”"‚Ié‚wwëŒtù­ÆÙ£ŠÌàÇ6í|Žs‚¹ã<þF°»­á§<»óÆ@ë÷ûÕg×ÄÒ¨–á#uÄf“;¹Ï<ùf¬‘¤Í¸Ì™W.W9Èü¾ÿzéÁ‚4XÝ çÏ|V»u©Úé2ÛBcv;R|ÁÁÉë’z{޵–akêÌ­oÍÈñÏýèÀcpàc‚:z“kqí£šUã7Vð[Ìç;O,7ç$ s×Õ둼™›x·’\[HÑFªÈ#'’Ùøüø¬ê²%ú9„>o7Ÿ·žGéžÕBfò-îüGqcõ±A©P>˜1fŒ0#§b+[¼E‚æhÍÌ·pHf ™œ›g\‚qÛ#€~Ãyey}=„±Zim´ÉĖ֓ȬY'“Ó=GOj‘w}õP’bŠ%Sçl9Ã!# ýˆÏ½Aþql Ť—Ø•f ¹q€Ü{óØý«Ú‰7W²j $sH º:ÌGŒ(‚ÊÜç#ÛÞ¤ ^ß˶3^E·%àòÝ”›p¹ã*xûœgß­d†ê1£S§I‡XDŽ ÂT“èéï¸ôéR’ÐÁÌU°7ÅcÉØ3’ªvž¸$gÝXÉÿO§}‰ßê$̈ðà…ö<÷¬1êÊ#1Æås¬«å³çØAþëÔºQ[›]R;›É‘c+sf’çÌ8Ècv’O$TË[†‘e{%hb1™E¦ ¹õ1‘ÀÉÿ<Ô¬­cµ’ÚúÕnd`· ,0äÎ ~NHÁ=øã'Š•¤iа[Í=^Ù-nä·I! É“»ñ)ã#€;sPÝ»2¥šK&~™$pò:ò>ßΧ¶e{‘äð8òåµ™£`FxܤdsÐä~•CgàË»Õ.­µ}BOªŸÎ{w'÷‰Ï¤}X_¶y© aªZ!žMFå­ØÂ–¶+¹pÄ)àØ½½éŠŸ«è1Ûêj!VY…©Q;"“î9Qí‘“ÿG2]™mf±œ[‘Œ±Ä2NGÿ?ŠÛ®n§µÓî54V«mfÒ\ÊÑðÝ|c$÷øª†½KÈm^ä Àg·LP¯l-üBb½‚`8öúFÓ3 …8ëž@à|öª»t»Óf’Õ!’x$Œ—I×!׸ùÅ_X˧Åú¹ŒÃ$ʘ³eU:`ƒÆqÏåPî$Œë©uY{PË"†Ær=øÆ;ô«8Κá”qÚO=^ÕѼrŒ¾"Þ‘Ío½´›e,8Ý às×<ð8ëUÚ³yO"ƒ&:ç#Ü~•§^A’[c1ˆÚN>ßë‘VúuÕ׆…ÖŸ%Ü"=“Û]YåZÜ“Ï9è{ö#ŒýŸû4ñÌž4ÓnÍÔQ­þ–ÑÇu4-ÐpÛdøIØr:{{•JR”¥)JR”¥)_Ç™¼Q¤§ž&IMÇ nXcø¤l`Ž+zÐuka¦"Ü,PÙ‰–?5eg’õ³ž@ü9<ã9ç‘ÔVõkco¯L¶³†—OÓg7r@F~¢VåW=®I>籬=ºÕõ;9´-3Zh¿ýXëu,÷ŽÂÀP¶Ýx `vÇ´oø¿Äº&‘yo¾¥­Ø.“mw…Vµ¤šE'–b ÏLõäŠýŸû:ð®­§µ†»âÍfþóS¼·$3Û[`fÚ±B3æmgs´p¤dûï_´MnóOML²†ÆáõK‡šæ í»L0m‘‰,@ÇAŽK"¿;xoMÕüP³x_RÖÍÆnnôø’oÓN·É䯏 éB£O8àŠ‘­þÎÛIî­w%¼±/I0Aÿ¿ó¨°] ÛóÜw ÖKrŸ÷T·q•Õoˆµ™äºŠj«uª»íÞ&QŸÏŸlT iäŽI®n¡Ž+9À[¨¢Œáב·Íp=SJL²’ýæÔÕZ%·  ¸¯«®p?CZü×3Íå%Ìr~Ä­L¡$“Ç,O¹ädÖ V6PžZC¶ç ŸÏõlà•2ÄÃ8!ÜFz÷ÇAÛÚ¥ÜéP´1ÛÌÒC8X8Nüžüë¢öðB––ìÍ"*—˜‚Üç·=¿J‡c"±Œwd®Þ¼üÔ—i‘ÂE&ÖÚ';A÷þúÕ—™p®#dˆúwÈÊçŽsQ®å{ÆXæp²‚mP7v=:þuq¥´:UÝíÂGùºo†cZ$ι’pÈ0wŽÄ~_Ö¶†sqw²œ"¶sîÆ¹gˆoä—XÓãXác=¼Æy‚ú—c^}«ŸÂj^š¢9@Ú­…’e9òò§µmËyþ˜º,vã8Ͼrâ Ë¬Y\_é°=êÚÛGv&¼Ù2©™@$ ^ gç‚9©‚îwzèȱItòÇåø‡vÀþÎjÚÃQ·‘äÁ„„!K3‚WòëúU›I  Š=¬»œÃ.GõìNZÒµ] µ«›‡‚HáH˜$X@Ä…Q…ø9'ŠÐⵂÎ;«I­Ökär6Ï)"Üž‘Æ2 p{q[nþ-¥Úˆ¥•³æ›&G•@È :g#±ëWÑê—7ÌÑ%»ÙÁ3™"ó¤¶âTèÃw.ÕWæ}=ìsβÀÞ`UysÎqÛ#ßE_Í}¤ÝȰÉ:Z³Ùi£e'Œ3ŠŠo'ú¨-Ö‹˜Læ1¡`@êǸüÇÚ—¶›‹¹ìg¸{)˜µbCÛ2·=r{üTy亼“OµV„K _4Ë =:¶[¨Ï^µêK'Oº[s"Ùj0±†âIm‹,)ÁÈÏrÈ8ïÚ¨õ}N΄:œ—rB¹—Ì´€”˜dq¸öÉÎßqÖ¶[“PBÑ]F!Éb­³»…ädp~jmÆ…4—O%Ü6ïfÁ­ÄÊçqM¤î)ÀÊ·9þ•ªêQ¥Œ—Òy{í/¡6öÒ*𮂘B3ïíZ-¼á‹oÙm¤Úû†Âp{“Àî9ÏéVöêbâÕü¨-æ•î@’I$Ðqì¥mv:U•¤º¬ð¦©waŠi·©€ÂôÜÏ#š¯ŽååvQ¹7W øâ®¬#o$*¸$7âßN§·ÞÛU•]–R:×íe–ëR¾º˜˜Ñ‚Ê0bQêcÉb Ïn>k7Š/žŸe,èòÇ%Ón‘$Þ•-‘žOüÖ¢÷ r¶Zž"½Ÿþ©Z"J°Alxäuýk|(×\vL†hï Y\19ò=$«ãÿË?z} ZGqDaR#»G‰•XžÙçóÅs»Kx`ÕÃp×î«Á78xŽBäê“ßžœÕ̶²@ñ-½åû²±šxµ8·7\cƒŒg?•`x¦g¾žëO‘l Ã }<’О (¹© <íl'–Ý~ªÜ®ëØn”$±ê`ÈF·|EY\Ý[…±[e½BòáîùhäÇÒ9øùøæ­®mQbY„wQÈŠb‹loÞ1ÿ¶3팯zÏÌÐÙA¾øãƒé™%R†5,޹ÇAÓ5{¦–ÜF¾u»"„³à9¯§ß߃YÚÙdŠ)â„Ü^ÆÞLÅW¬Xf݃Ü:{þ—Â9îŒ>LÑÇlB´mp¥¼¶ ÈàŒþΠ²‹F…çŽI1$k`©<È©× Œ€ È•Rým²^]ÁÞB«;.d£¨m½ƒà¿¶¹k…Τ/â»H¥¾RÈmÆ<×GË’2 çž¿¿BÒ,E<Õx’EŽ(ÆÌW™.mäŠ"Ì ÅàugfYU Œ¸ÏBHÚyÅbX8‚Éo‘‡,³¥€þ8üC··>õ eÙyøÄÐÚ®èÚÚà%_³‚A#çí^&I6ˆ”²áÎØ²%RFGNAÆ1X¡Ž(oo!´b6ãÎŒ c_áaž3Ûý e‘BV•äM»‹ ‚ÀõÏN{ŽŸ|V¼ösØéú½˜ýò¥ÁïER?äçÓŸ½`°– S܈§-˜ö¸&ÜÄg"¶õÕ4ëhËÊ…SئA1[&“yi2ÜÙìŠ+Ø”£ù$ƒ÷lœ|T{ë±"®Ô;åp¾TL8Çâéù{~•QxžP ÌHS‚0x¾Þ§ZDOÜ &$˜$W¨ŒàŒ î_ý;ÝïÔ|mj‚1 w(©üÎ¥GÅ~¡¥)JR”¥)JR”¯á-þ‘­[j/c"}MÈo.Xà;ü¶ö-ïÖº„-5­3ZW‚f‘!€$d2äã8ïÇJäœÜÚ驼žU¸I!ãcì>®㎤óïÂ5o¾£x`-ofÒ­-£“ÂúL¤qžÀÿäk`ðÃßMqe-ü¤XÚÜG•cHÉ9$sÒ¿¢·:ìV^ðv­©kvöºlßIso`#ŒyL‹‘+¸²äBª€XzÖ«ûY¼›W¶Ó4}2çIo_\Çs ÒÊ?ý]jÃ+?8S¹°s€¤d`×*Ÿö›¬ø~ú(¼3m¥ÚÍgf<)cs5–°Ûõá }#!srsÏzíÞËû-Ðt«O_¶£â/êëž'Ô-˜ î ¤€HUä îìkSý¤ZkzìšV·« m7êñ>‡áûä,öQ+eZFAèv}¹r§#+XÔĺê>9•`H‰<òI#ñXf¹’)ŒRYÃ-ìƒ|ÓõÀ Gj¾ºÐ5+ &ºŠæÈ<ˈ<¤€rqï\+Æ \#µš² »å¶Tg$*^ïƒÛæ´”H`ŽæY$HA#fFÐsÇæq^W˶œ ‰#»—vT`ÿ Ïü×··šf`ŽâbјÆ6ÏíþÕ଱¡†wd$q¶LŒdñÛ þuí£bœ…%“içߟö¯+r}5¼jA}Ìç=:Ÿl}«4Q¬©–@Í&¹Ç—œä ÿÅd’'ŽàLžl %¿ ñ©è>ÝxûUlr´wÓ³±‰jýúþ]ë4—3j1ÆØ ÑÿÚZ³€Ë†[…€° pq»'Øóß·j²¶×/MŽã¤fæòÖp˜.6œ|½y­Æ×TÑtè§»M.+ËíFëx†Yíä±$ãŒýù®§¢êJ¶ùöi@àJ§lY÷=:óî*ÚæöÞ+c¨C'³¼¶î`~üñÆyâ¹½›A%ÍÅíÁy¥™II‹t‹ö“Û½YÛ^%b"ÆÌc ÓÎÐ\g§Z·7rßÉ šÖ(’7.éçÓŒŸ±¬ú„6?ásÚy1B³mòð€y­œõëž¿<ÖfŠóO¶k[FŠ`ªYešP~6ê±ò©:Íõ´ví{ Qʱ¼’Hì2¬Lx÷î9÷­üWi>—tÖ“5½æV#n˱²NÐ@#‘žxàœœÕö•:iöPýYbó9;ó×ÿ–OßùW'Õ‚Gs%é’-²j;²ò]wdŽ ÁëÏojÚ,&¾¾žû­wü9VÔƒ~štÒÀxÎ_n*Ê7³7guh-Ì‘J$Û½ÎnFIÎ=_3=ô“BÑÍiòEÁ_V1ŸÌ÷ýOz‰aglg5 '‚æ0$1Z2¹xÛ;¤Ï<û¯ƒÒ®o¼M¨[ê‚k;ËK` sÚ¡ÎB$’Hn ŽŸn*f£#k‚ÚâÒØ'Ѩv‘6´ëûc#sÇJ®·š_¥i®ÙÝb”Ç$†"¦8*¾ýýºûÔ+­vÎ+f‚dk„`<ÆL2í?æ8Ïè}±Qïu¨uÁ,—M%š‡ónfR <`€$}€â¶{ ¤·úY‘Ä0®Y\0Â1ì{Öýkq—þá’ ¢L¸Çõéðk_ñvœí§Iq¥Ï O y·ùE†âqxãô®8€ÆI€»»ØÀ㉎}Gž£¯Ï?8é—vÒ D¸^2ñÌŒ–2 {g·¿Ål\ד¥ÅŠËÙˆÁuev/áÈÀç±ä¹­Å‘j–ºÞåÊC{%„ñÁ&|ä8`ÿ|‚ëÓ¯5{à½C¥Ø^j 3]³¼žTŒÙ¸…Sž¹Lg¿=±[Lq-½ôï+¼ËÌF!OÛžýêò^Mw4`H”"9b6‚xoŸç[ ¬©iiº3m‡k$I’@p@犪–Sz°Ì‘I¼Ýˆ¬n×wîÀ‹2 —Ç ‚qóT×··ÜÉ6¥ ­º\¸ApˆÉ¬T¸<ž§ڹψ-.ç×,-<ÅO¯q ©;¿œ3ËzÉãÜõ®ÖÚ,–iPXÂÞÕ"¾·Œ`´€7ïÇ\îÏ+ñš™v¯v‘¢1’!(²˜òÀäg¯_ô?5*Sms*B‹²æÒ-–ﻈÔãröøÏtù•dv#+»q)?=¾ÜÔkqZ˜¬"•„ÎÀÜ…ÆD@sƒÈŽÉ ’(b’&24°¡Þ±<ý¸?ß3_³SðÔöÏ! â\îU9 {ö$vü³Zï†Ò[$Ó4F1Çæ4Ø£Æñ&{ú¶ŒñšÛ,ÚãëdE\–eCŸ5À;[ÂûŸµsíÅs¿Šu¯ênmogg·*säH¹ÊŽœ8ø?_Ï`4ým™Û­ÄjÙ0H=çšË­\¬–7 +;2/ÚÕŽâÙ/#žŸk­u=GPxî¬Äw–÷S¤LLG*}\ðHüÍ{’Ö9IžòÂ[_:g’âÞÜIÕÏ1c¼VÎzæ­¯õQ£Am$–У{¸¤ ì¬AÀ'§\T&½{›‹‹¡t–êƒ|ÒÀ²4ìÓ¹Ô`;çñõ,â’òÞæ]žsÙ%´}y žr? ^=¿*ú<æ¼¶D|ÅnäÉ"±ÁÈÇCÎrx¹ª}mmá·½Ò"ÖïôîcÚ·` كߜŠäš%…å–¹j—Jb´ú³?å<ž?­whæŠ'œ˜Yì™c‘Y‹H;Iëß?O†öùâ)¤vë ¿›`Ùü,ç¯Aíüëì²Á{\Þi¯ ó˜Õ ‘‰ÞùòØàp à™ª¸mÙ 6hßT±§KÌ=Dço@v°#µY[GsjÅQƒI)l$UhÛ,H õÜŸjŸo¨E} ßÔÛ5´‘#ÍŒ†ÚêpFGCýæˆê‘\à ¸E †Ë»Œðp{öïïP!³c=Æ|»¹“,¢þŽTž½G?z­·³²°šE³E 5¼ ¤ÀØÀl7·=»ÕÔ­»«™ÚKuFí¡ æ}GãqŽþÕq4siñ5±‰ÞÐ{ÑÉç– Ǧ£CrÄÊ-£‘d!òšTS†bG<0ÚWô>Õâú8]ÜN ®°o“Ë\m  äªûäçè*ªtuúu3Ã(Ùßǃ®ƒßâ«5½VçKÓR‚Ñnf‘Ìd°D`y<‚9Éþx«ï–溊ˆ¢1ÆèíÀ@GFÆqÔøâ½FÆæY°ú)¡¿‘éŒ7|6zñjÕmb„6—R[NÖr5›…P¯R@@­Ò;M)­öËÉž‘»uþñ_4«Ý. ¤³,W- Q³1p9Áã‰åâ¶• ^ß1( Œ$ PÓ>ÿÞ*»R¶BRa½ ±Cu¿JÁjËäÛÅ™%‘J€TΧ¦ð··¹®ÃÿÓÜ«‰üQdŠ6ÜéIu’0c1ÌU—Ž̾å~²¥)JR”¥)JR”¯ã¦Ÿ Õ§ÕOh`‰†bK™ÛqÇù”ò}òOå[ƒìõš{ÙPHB$|;÷ïÓŠ…âÚSÛÚÝéze¨¼Ôd‰â™ÈÝäç#q㎿„~µÄ4=7T¾{¹â†äÅc ¸¹œ!Ä ž3í“‘[D„ÑÛ¤Ìå’ÝCyfL°ñÔçíŸÊ¶û/ÞÝM£Ü,úM¬ŠñÙÍ#5A?»Àè3Øìö~-‚MZ GÃóZÅ,¢;«·ˆˆ`£zˆ'Ô¤®3“Ø×hðÞž5y¿õB_h:}¥Ü0FþÕKk—[Á1–8Tz›nO=âZý¯†oµÝ?Äþ3ñe´z}Ô³Kc±1‘âGÄq¤k»ËFÜÄg“‚NâI­3ö›ûMÝLJšDÑtä_*kÙD_W6Hy•FIÂy=2k”ØøÆÆr_hR$z„:$vZ•ÕÃ1³îÚÎr"r~ø5—Xý§ÝëGứ`]#C‘îæ*¬†æRNÙåbrïµ¶¨ÇqY~±|G¥‡ŽãÌESlñ´a‹:ŒŸ¿ÍkbØê®~b6ðF#!lù¤6AÇLœ|þUc¤[Iu|tH.nB}1¸¼¶-‘lÙ#çõéÐ|Öésá{½.6Ÿ¨Kæ—H–??Ò´_N6Ò³–†+¦durqÝzñÎ9Ír ^êæÛSÄö¿K#ú¼³<Å9Ã{wíùVÕÿ§,µEÓ ˜K{Ë«o2àKpB§¨ç$¿Ò§xJÆÖ¥±Õ¬¤žÆš)¦·RB ¤y€°Æ?ù0j.­áÁl÷T2µœŽ=e¼Œ“…ܼdבßâµÙôö‰ŽÕv„´`ûôþ•Yqj»›Ç’7eA8SÓ9ÿ/÷ªÕ³—,„y¼uÎF~ý{Ô³o:ª8–2ª6´`ž;wûT'BC•ŒŸ5„M»¸È8üÈëS<‡†ÖYcUbœ‚?ëP O±q“»ÒwçhñV q_Y!ÎÒýIšîR6\KoK£ÃãòÇSšë¿³íb)ô»Øo/&r²yÊ.¤-…œ¹ÏÉíWš®¹ee¤êhËE,+mm hØ‹yÁrGË/ÛrkKÓõÝ9$x›ÿh…ŠQ"àÏ=0x­ªÆ$KpHy¥P¢wà¢ó…¥^ZÍhQTPX¼ñß'¯¿ŠhnõKyWÃ,jÆØ°,»1qÛó¬>EÏÕÀ£é¦E¶Ûxd%¼Ç÷ýsö©6¬mż300pœ {g‚:qÍyÖmã/ ô¸šF…mÍ#Éu$‘R¬4éõ„ÇW¸Š0«³:Ó“€2zÖ¹«ØÝèvW×°[Áuia+G½Š®õÎíÏCÆG\žõ¯øöƒ é÷¶¶fÙçÜ®##ðN:ãlã“]­…žžR ¨Ûüa¢[É m‰£ °Pļg‚y Õuf’þþkø­óaâ[[Ý2I´À' éa~k>Ÿf±]5Ó:Ÿ1HbˆNG³×µZO¤[Ï?šU–v*wÇíßGõ«Ë¿ªrÝG=¥´^b]zóƒÇ¿s[–¥ :tó[IÑRUcü~ä~Dûf¸çg—ü!H–îI¾¡\G(â,þ/ž{vã¿5Àí6»¬Ú]ÞÅæ…ÄV&< IyàmÆ?ŠêÚ–¡q1ÛE,2Ép¶ÃzŸÝH݃“Œàdûûb®ìn¢rÖâ2 Æ#’ã<€ž:ÿÎ3"ÁkpňÈÁíÇ|~uóQ1Àc¾‰·ÚIk˜÷C/$Ž«J†Ýc™ä™­o/5 áaŠ7c7%‚’£<;ƒ·M²#žIã§U±Häš5*&œH(yS“ŽO` \\ƒm¦˜§ƒê¾¦eŽxøÁ>ÇíZƉ욦©p³9Óm¯ÎÖ9ú™sØ%qÎã€3°iŠö’γ.òÓ •Hõ«mýxÆvÿú"¹þ—áÛÿˆ—ZÒ'“±i%†2‹+0ÆàyÆ3“ß?om4rkwKwqâñdºw 5Ð0§ ݺô« ŒŸSqb“­ÔZïo nK0l2®ò{·£j–&K»W¸–×̈˜ì™$ݺNztÇ\T_˨Çlo–ÑM´ñ¤€‰UUYK€sÁÈ«¸’íœäGq”ˆF aÐþg¯ü“ ¹šOûª÷+pqË'g鎾Ƶ«É/ïQÜ}@ƒÁûÿ:û%¾Ve“ɸ]›w˜ÆKtR|Ûýj$iti°«î‚H6 ^F=ú~\Ž)7’ÁÚ1 6‘‰9É=~ ÁûŽõYmfd°z‚‹™n^hL±d«m,Baxü$rzsùà²[w·Š8½3Å‘r#oLSìxaÆ}ù©­nÆå¢o!– ŒÊU-Ü gàîþ•­OgõPÈTš;…v’2ˆÎIÈà«dàöÇÅ@@¡ï¤ó§FŽ mVY˜íלäžS×­lzCÆëRè6ºŽ¤{œf¾Å­ê±j7 Ä2Eƒg„YÂú{ð>õ²‰[ê[rëÀ€"ÜOcÉèߨªkÉ…†¡§Ï,Æ( Žà¼ Ùi 3ù»Œôâ»ÇìÕ¢ñ†¹0Ÿ1Éáö"l– :lžN9ÿò¯Ö´¥)JR”¥)JR•ü˜±‚ÎÙ^ΗW‚B°C ÿ”(란*Ü­,õû»2·ª¾Ó Áw’ '¸_`£">1ò>üW/¾ðä÷_YEÒ¦2°»ƒv±’0H#$…ÕVñVžŸMÒÒ=>k«åšû`ÎèÕ0‰’I''°øæ´-+ÃZ–«©¦˜4ÍœëpŒ»ÝÏlsŸÒº‡û?1ëékªêPÜÚÛF¯¾)J‰Éù`Ÿeçý«©é> oj‰¥x_P6oÔ/™xV(„`ù·ÎÌp«îõrIÕÝžóšg††‡¬ÊñøoKŽ[‹4ˆlžâR2¬­Á¤`:Œaºv®o¡ñ ë!ŽV[7Û )ÿ²¤vï21Îq^uMSÃöÊ.,’î;;%i&Aú™vòFÞÅÉž9¯Ï‘ßß[jÚŽ¦-ŸÎÔ.$Wl±^¸äz@ü³ÏÇDð¼bòùu‹Ü£ d•Àýù<¯è00zc«`°UÒ!{X.-c—S°>Id$Ç—äà´9êëÃ&2ÿL"ŽâæIËÌw€°Fsµ¿0?t=.ÆËAI”MfYÍ̳à.ö<ä“ÉÇÎzToköÒésÛÚÜfBʲϴ¨‰3–9#ŸHãozÑmo-ίq#KqsbÓåÓ¡ 6ÔŒõ!·g=H>õ\:¬ú³Ï j-}5¨³]DŒ£’A+ÐtàV¶¶„YÞGz-´ûË"ÓÍq-Ø·#ÓÈ9ãŸõ¬¿LñÝéW"òÖòÞ7 ÿqŠ9Ë‘ÀÏÛÎuí üA¯/µ6ú{ÛY’ÞÊ0F"y.Øë‘ÈûŠ ž=B7·žkk„±»,¶’í1È‘¼.wc={WN¶ñž÷¶ÖÖ–Ú£ÜÛ[A4·¦c3 #bÌxÎ}€•XM§Ã|.ᱎX´ùmVMÔ\‡3ÎÇnã’I¥‰vÏzŽš GnÚíÅ¥¯ÐÛÛ­½Í…ü$éFcÛ‚wy˜'8åAÅi0x2IÒÊ8š_ªsôšº:¸Šs<±  Ók¬`ŽÃ®p@  Â7·š¤#üF)eMÊñ€NHìÇpsíŒvëÏⲿ»n#Óî.­]ʉ¡€"Ê@,È;u8öø¯3è÷‹p±‹imætß«Â݆õcw>ÙÅS][\E,Ö÷PMo(9’ ”*qµVñ9Þ¹Qé!À8ϵX5¢HÑÜF“HŠËÆTÿ”|vãâ³O’5Fp ,Àìø¯õ¯v7ri²‘ ßƒ¿g#ÜtéÍZj¼ú´a¤ŠÝIQzþ]úU4P)ís†ò‘ZNKäóÛƒ]+LÕ­£·¶‚æê8®Š…“s Õ´¥ÒÞ¬Q'–V2\!èß­OK¹âÊBãmì1Æ3îMx¸»ŽÖ ñGfò0g+ø‰ÏLÔ|Ö¢Ô]läŠä É¢Uq€ˆPIã·Ϋ"šæïWKk©ÑÞa·‚"Ä ðòòqÏ·Ö4ëk{8áˆÍåÈÇ ÕæÊÇZzLÎnlÌQ‰cFH;ƒnz¾~+›j>Ót¸ä·Žæ#wÃQy¤@^(ÆBÛŽäŒã¦c[f—rò«ZNg´´•–kxsƒ2 õ8Ó·Z¾¶¸”øsPX™’â;{†¶iJ†(IÆsÀÇn•§hÖÚå…µ£êj“Ax•£%ñÀÀ9|v­ÞÝcvÛæ.Ø”4­æw‹ÏëÖ¬¬¦’B\Úʰ^Xù³“ùÖÀ®VNY½+Î8ÈÏ_Ϋî­íoáö˜¼Ý«)€ífÆ}Yì:­—ÚtòÛM$’;Üï•™3œ6åÁÎ@éÁö©+áëxßbBÌ¢BD±LÙÛi$׸.ã´½“„FB+º(ÝÜæ¶«u‚H"1Ì›ÐxœŽGuÁùÿz¸K}TÙÝI¥jK3B^;Yâg œ+Nxïîj6‘¬i¬ Š¥ÛÆ%šC)Š@™’y³*þét袚é.!âPιڳH§‚ôÝŽ äþu¢ê÷s,ž\N‰jÒ½Ôr6 en¸äô«àÙ±o$)_-X–ßÚ·˜n"ÂtöÌmGG„úºzàw=:c[4²Ìºb3H’æA1ãnp cœŸõ=º×/×t=KénâyÈ2 бÁ<œzsÓ'‘Þ¤xfÄiZ|RÏE5¥›K:1¸’Í÷Æ@ãçíW7·×¯u=«ÇZˆ¯!–à0ú¤L;¨l`>ÿ5–Ï\ŠIžb…"_ߢ1PȾÇy`8þµwõ)(iS8–pîSŒsü¸<ù¨•ôVÚ-Ô¿™;ÂïjCe˜ñ†ÛqíŒÖ­¡ê­m¬-ÓiSÚYÝEåéæO$ó´cžüW]³œ7©•È%GýÁœg3ǵC×5mc=Ó•>BýB†ÚG=ONŸÞk‡µ;Kí5|±êuó§¯WbNãí“““þõ&w&å¡UhÀdYA æQ+Ž£žœ‚:àã<)I$²Dêäú¤nÆQǶ—úܲƲŬF™  ˜ŸnÀåO\g'8ÏZ¯}!™ ’$´³FÑêVȪ¥°¤îùBÉÍxYViãw´yƒˆËÙÛ¶Ÿ–ôïw$õÈgŠ×|Yq“K¦ »IIqs¼¹FPC…cÁ*ÝF2 }ðRÊVæMV9î.¤Š8`ó’€6ÝAݟζ«{2²Fk‹UŽYäºHzßp Ϙ1ƒœðOnjOÓ$¶w&òÄ’‘ÈÌ…6’¤vqÓ¶~*ŽÕå$m¯4I´@ÁTĤðA?ˆpsÏZÄîV}ð »,ÄTÛ=½ˆëóŽõöìAjåk‡A;DÑ€f ÁÎ=-ÛÚ¦eš6—zH­1!°Ñ16] ž¹#¥Tx‚ÆþîçÃóØ\<0Ûj ò UÝl?þg¤`¯åÆjÉ.á¹k‹hæ¸-SFۉϬãp{pyûfË÷ÐCn RC2lÙ:d¬‡Ôeû3Ò³¨g7V–ÑÅ4³4éuY«¹ñǸ>õ"Þf–¸Ræ4¸žÝf#•ÜÈWjŒž3ÏÜ\2¹v”Ûr s}YòóÁ …‹ÏéɨòÚ Y„†à±;mÖVÙJœ…ÞO<1Ïz“y+Ú~ü[™Ävì’r2;…ð99ûW„OÝà‰"H lp€I9O\ÐTä2¢ 720ŸžhÆ#‘ÓzÉõp:¬Ç=­Õ¤ ¡ñ¸Gê9LI$xϽ¼¶Í)çD&w—}Á#3ÆOc÷R>1U³©GwÄ“™Ø©ÆFtÁÈ=G5*ÖÞ4Žâ'ŠæÞåmÌÐ¥>€T’Tô'Áäg5«i–³Z]êÑ_Å,qIp²C,3`zˆ žàv=j†IàE”€ÈIówŸ9A$ŸPÀ8æÁøª¥Eu$Q¦á€îFN6íí×¥E¹úSwsm4¦d јã)±Ã-ŽŒu®zÕ¬) ÇÒó,Hñ!RÇbñ»¡ëŒoʦê|ñ$—öÒ"ÊÙÈuV ?Ê{Ž}½ª†Kyê2ŠÍ2ˆ ‚G>ý:|÷éX§/¨[­½ÌO ÆË¥4$äÏN:õÛÿ`7òé¾0µ·¸¹ŠXõM:ãMJø#”‘Ÿâ& ÁÉç½_Ó­¼?od–šlâÝîÈuhçÊŽ9'¿~¼ çzóë:žª¯q%ÕÅœs³Ã=ô ·oYËœtù«{Èt¸Í¼A„~^Zç#cœ“Óôý+ø‡ÅßêPi6ž“m1’vBšÃzö<àññSt;Yu‹ã)Bcޱ‰1œõ21“׎:t­–]>úÛU"T‹O¼Ž:ÖÞÙŸÖÿ¼%‰öÀÉÎz *Ú/Û‰.¯d¸'ÌS,±øFIÉÉÆy'½mþ¶x žF §lîb“ÛlÓ½x»¼¿Šâ‘¡’ê`eXP¢2˓ԫ“öÇJÓ|C¬O=œ‹b\Û¦ëbFPÄá0 rAÉçŽëq¦AÖÖÒGy4[Æ>ž@`@ÁrqÎy#Û=kÛj >¤wæ³Ç³Bv`ŸW¨ÉýjšæÊ-_Q¿ò¯aclÛí§¼…yì>ß5»Oq%¬ÃK°š8<ëoñ©` e,ÉŒ™eÆ>Åkº°µ³žÖJöd¹»få.dÏ ¸'ç)îೊ{Ë"$CË·ºž¬àŽH\e<{[V—16¶QɺI™_.ïÕH霚¨úö”Ë:²-ž4–ó[;í„ו`ð01ñHµ¹/£ŠÇNvs]™|Ë…Ž60Qµ? €xÎ+lÑå¶¶áæed— 3Hz‘ùçùUÕ¼ëq¹Ã‚)Éœ÷8éÈùâ¤¶× -ˆÆïÝûsüÎ?•x‡d·,K *ù·BÇõv$ÖYXÈ[n#hȱUzÀ‘íeš4†K»xñž¤qÔ«Èn½*®[H¦×Ró`º Äò!ŒÀ#Ä«ô‚سI ÊuSÉ^„ãäûW-d’\N·AŒÖ„AÑŒ†Á@áãõ«=*ålnšÞm ¦ !‡r;Üý¿rÍz[ëßÝO´pÙDëiç-ªð£'vOâ9çw8Ç\q[ý†¢U¬lõí§–Y¿u)C1PÌHÀAÈ?|Ô}R%i-"`u–åm#•aXóÉRÄt?< ‹w¥ÝÛ]…’8á…ÐȬ„•Žvþ½mú6’‚)-eibšH ›ùô à…nzdâ¦[\A  ï$qªÀÈËÌÎO\‘þ\üô­&úöòÎöYfœ\/ø‰‘$’s‰ÐÊ…ä.rüþvhcV‚4{|}zI5Çï ™ºò3‘ÇûTÑ\4‚Kf¶†};m¼N ›YÆ œ‚¡ooq$1À%Žþ•%Fõ~“†hÈŒŽzšÜml‘`Cqå\ßùfg’–\“·éñœtûÖ‘%ÕåÂÏq ¹KHmîR ÀÆêHÈ$îÆ#=yÕ®4ÝIæºYn­ï,/.°XªŒÔ@ÇáãŒVÁc¤ÛéÏmca¨àš=­w4À¼n=;z`ޤôçÔËVDCaw‘ßZ¯'8¸Ë櫜 c¾:M2·LʲBèéré¼2ô ûW¯ùOÙyí^dGeŒÔ@‘züú‘ùš¯Žñn䷚¹¶–G‚ù˜”uø6žàƒƒÎy­k]{ïªÓG•ne[—~^X£'»dÇOʶ¸L¶±Û´ ¹P$a3î°üCƒÁ ñz cˆíU(ÛÊ#í¿‹#®ëQßN·S¸Õ –;‡–À[KH™ tÈ\ ñÒ¦Á"JÌ—0ÌÓ¤bK$+º8Œ„猃Ï_j…k¬Ïe|öŠñEwFöÚÎôúÄÆ%õò%[“ŽpqVsµÔÖ×P%½¤1Þ(ŒùCÕ<’qø²01Ïz%›YC Ì‘ÛjVí7Ѻj(T™¶‚¸B§…cù.ZE´–ð¸Ü¬êÌÁÆCއ¯^y«+‹RÍ'‘’Jùꬒ/ùO®E(ˆNÞhØÜƒM${ÖE'Ò¹‚r9ÿz·µ†òÎ;k˜b‰bVxg™~ ·iàAÆGJõ3Ñ@C–‘‰1Ä0»yéðj¤ì²]Â$DÖ `‘ö¾ žç=}ªÆÑÕ–8e]òýÌr ›9É`{NÞ²¬r¤³‹‰¥©Úª=lc u#¹íœÖ¯¢ÏªËmÔÓÍ릈ýKÑ®}'# ó€rx«›¡uo+ÉäKk²1ùÁ–`½Iàc=0~*…¬®-î­§U*¦&ó¥óCƒ-ÛÁëQd[k-JÅVbÁÁÛ¸+úÈÎp{ñîµ]9<Õe%åòÙ#ˆ‚¤c“þÇ^òVh§H¼ÕC—+Ç mŽ0{}º`ŸÖ X$ÖÈñNñ»É)¤d(<•<ýþOJœ,šIʶèж蛉·BxïÏj xVÿÄ:þ› é³ÛÛ^_Nêד n^FlI ¼Œœt×ô6ÊÜÚYÚZ´Ò\5µ´víq1ËNU@Þ~N2~õ&”¥)JR”¥)JWñRñŒ:’É¢YZ[Úi³JQÙgÍÜôç°³~Î|/cy%­íµä–… ³É;òFçìÉÍ~°Ò¼=ûÑt§{Q§xƒ_hœAmÔD¢] ’@!=ËóÐ̾.ðÅ߉üG}%†–Ñ[[Ì‘Ü_„&ĘË"4§;K|ryû×%’Öêt"8|€ò DÝüJ¼·¸üXþuÛ|!à Å¥ÜkZîûÒ…]-·˜Ö0{–8-Ó'o³[%­Î‰ ìŸáŽ‘ᣠÀ°àžr3Ô{׫³²ÚfÔ-Ý#R\;¡3Žr9ÎOzàž=ñL±ÊºF—;³mi€Á ŽŸŸ_|cÞ´éW·×ȶÎël%šDÈ‹=Í~‰Ò¬#¶µ ²ùiÕ•Ïy=´ŒãÒïk".p1߯ÜU-ÄV2ÛÝÛÁ§I%È•¥–é™wD¹ç¶Ocû<³^Ód–ÚÝ^_>#ä 'Õ)ü#õæ²ø;B‘'6÷ ˜íã%Û®>p{TiæËÄ7 PW#þjY67ÌE†8>Ž?³^¦ˆÂ !ÊŽTÅ‘þþÕNô•C´EÔ“ȃÓûíSaJ#‰åÃ/"¸$mîGÈëíS£Š (îÚàK¬LP¸ÚqžA÷ÿŠ×oÜÌâU—,£Ëòwtâ° %dT9™Š+wlqŠé>ðÛjó]_ùLZ6·[y\©7 ûqÉûö°YèW¾ñØÌ–öó[ª0ywËÃt°O°­à_X[Ü\êŒ|ÖÇŒ[GîÀ÷剘žl@æÝÙÜTòWŽƒ€:Ž•ÝôÈDý µˆB„þì©$Ÿӟά>ž4dŽOï¯Oï¥k—ž †ÞîçN”>UD°Œ«ð§ØòE^Ø0•Äù$m ‡<·¹öëÐU“ÊFK;{c«îÝÝ"6«¸ã¦:ãrkñ][É{5¼ªò­ÌŽª|’ÈØ¥ÝŒ{dV½z+ëˆÐ·ÓÚK“H ÏæÇÅk“Þ˜®f¹G¬Ó±çÀ8P>Àqޥɨ]¤6×IÔ3G, ¸e’§uS»§#æ¡i×àÝ´ðÆÄ[–Ñ“¹;yûÿã‚Ê+xongv•®YÖ9© '… œàŸnœàÔZÞÏKÏš+o~ª9#‰G$Àœµ€nž¬1Œòk޹åí°ŠÚö%‹ÝYÊ®âr¹ÊôÈU»øŠöïQ¹²±¶PêJ‡‘ Qxà€?/µT^Îö9¤y] ÎIÂA${sÓŒôƒV¼ cE<SÊ«›€ ’8'‘Œó÷«­>æ5Ó‘a˜Ü¹‰bL(V9õl°${óÅnÖèQd½˜Ý­b…ñû„#='=óŽk˜Ü_]=ßø`ÊEí¸mßÂ_n~+`ŸTŠMCMÓíQ¼ñn¶×BĹ9îqž}mÚ¯‘b-ÌVhã.Ç–\ü÷ÆzWÄt€F™GFãp¾ß­A¹ÕMÌ‹dahnwÕm r™÷ÈÅUêÁÏÐ4By-ªJÇðþ^ão_llžt–Gdi&RŒ¸Ïä3ß+u±¼‘#Euàm÷­XÜ4iÒ9‡Ê<Ò8Žzôöë˜ÃâõvÀXXËw§Y]9¹º`ècëÇfÇ}¦·'»že—d‘‹]Aý%ö‰P(ÆG|ƒÓŒsÅK¸· Ì…ÜMgŸ9ŒíÚ:俚 Šâª·"6؈~¢$YÜ7Žù-ù“šÅ î]ÊJ$*î­åg8sÁ÷íÒ¦Ý^Üh…Ü-ûëñ΀8I0Uc>Ù^zO’Ýä®#ˆÚ2àžÕŒ]ÈÐËoÏ¢PÇ+¸«N6Œžny¯„L¤ÅréIÌ‘·¨eHÀÇÈ's×5.D{ˆ|—µA$N¿¿U »±’r9¡ÏÍbB†$O5P3¤“ ÇcïÁ~‚¼·ÒݧÔC$KmV3(Χ?‹ƒÐŽ£52)mÔ´ö—nòÀÄ+0d“#ÆOÛµUDe!¤ ]QHÒ8õ€~0$r9ìk;êq%i™M¤Lˆ¡íÐ… 8Á~z‰¦ D»¶²È-î.­Lw%Ž,7Œ÷ ÎEXopòÛ‹‰î ¢y<â^êØŒçÛ¼M—0°» çHCG4L ŸF{ó“Ç¿ÅSjê–×z|­„¤›œœNAÜ=úàÖÓ¥ÀÊ÷ ¹H¸¸kÆÛ×iÆûŸO\ž:{U¹uÙƒ: 1•$œrx?#Þ¾],Aá˜1\·˜ å@Ç^ýºšû¼Û«,~V%ê„eu÷ýqÒ®<;5Ûëšéìë¨&«jÖˆag2¢ÏL6í§<H“á¹®N™|õ8,”q'áPäuîH¨>Ч{Û'U{s©K‰í6‚¶Í’v“Éç8â»>§}¦XÇŠ#;¤ŠU…¹ÉeÎÕÉëŽÝ>µÛ]FÒÙ®¡–'Õ..EçÔÂ¥…ªàá gŒ÷®_ûKý£Û»Á£h¸šH—þ³qÁi‰ÀˆýQÇZÐô Ùuø^KåSww,¬à3`SÆ1€1ǧ"·û8íí´ã+æºÌ¶¾Òµhµá¶ŠxRY­Ã¾RR˜3œ¶sÈç=«¤ø;\–6ãR¿8›\¼kÀd”z…EÁêHÀ÷­ÆwM. ìÒ<—S2åÌFÄþÞñÎ9ª1¥ðÅÇøâ,2Þ4‚Kkw%ÖÏ‚ ó2E]Yë7–6×zη*«‚I ŠI8Üç*Bž%‰Ï'¯Ú²M¤ê  ^æÿP°·x¿Âtû+H·÷-Ÿ¨e8ô“–= ¨éZÍÖð©ðÜ1Ø\_½œÑêw!°\ùŒÃ%È}¸îzrkóT³Á ¹Œ‡Xä*§w¨ïñœWjðYˆ hLnîGQî§Üרô˜ˆüCy§A²ÓAIu191IÎyïÎ\ž+Mñ§eq¨@öÏÈ’Êd`’/•’H^1öÈ»T›k8®´/j׋$’ª´u•S,Xç+Én1€+ï€î-弓FÔôž¶¼¶c‰`fhFÀ; :溅ç‚<5vö°iböÜ\fÎá* EË6#’xÈø­GYý˜k`McÔ…Ê<é ¼2nŠ5ÛûÃ2ÃŽ¿zå²[±¸{Y"Ù*¹L+±‡jô¡-mÁnÉI•ˆS‘Œüðktðv”u§¸·60ÉFŽ38 <…NFzœc°¨:Ïìó_Òžc.‰<Èc,÷ö1K"F;´zN?ÌzVŸg©wmÐØp#]™Éžœ{o½uý6çÊ6é"„Øèd³†9ïƒÆ{õûÔ]fê)µ™õºò… ‘¢6ê@— œ0<’ÙÇñÍkzæ¹v,®£–®]ZØGÀHbA99$žžÂ¹ÜW{fË£c1ÆyÀÏï[–…«Ïm3NþAŒÆ|á$Ù,1ú“ì+¯i^ ]J5l3Ekå3#,pü3ñŠé6qf!TvÊå»ç߯øëTºm…½†½«^…ŽY.fóË¥ÈÁó+}«wˆ¢‡^SÅTräó×ùû{ÕÞƒ§É›Ù"2\ìÙ l·˜Ìzàsœž¹ûæ‚ytÕ…DjS`R„#ªç`{Õô/ÑG8#›•€ûõ?ü°‹jnô=øü«\–Ú>Ÿp󲈬£29'¶‚q÷'ùšÑlõ‹}N+ÝJ#æf,ê†ÇnHÁëÏ5O=üÐÛ™&‚2$„±Á#ÛŒ‘óz¿¹´t°"áa‰JÄ‘•ädç¿AÅUé‰{{{:Ã…íháN3ÓÛ©÷欴½>8>—P-,7JÚz<Íè‹~ѼƒÃ)]Ë÷Ç T^4´½¹Ží£{‘`Æå/RâF,œB­›[’öàƒ[†ˆ²¶·ú˜¼²êWxÖÇ ã¯\ þµy}¦‹#wª[2æó÷>³Ä{²p09€Ï·jÕ&K«xšîûO†rè!X¥‘y$½BûÓ¿QÒ“TÓl–òâßÏ«+1Š)â+ÃF:çÎ3®èÚŒ‰«¦œ^H-­[,vòg/žq“ó‚ uGQˆxzÌÙKɼ¸sìøÚ£ ž9à×¹¦^\ÛÛJÁ•ZâwŠI•2ÊFTŸp:÷=zVkkIí`ó!29dÿ6HÆ;â·arnâ²¾¹‘µ²9eyHõð|ô#Ÿzñgy&¥’ˆ<ƒWyYz“žÜ~¸¬0#Z›‹¸d€-ü®.‘2 kln!ƒd)Ï=+]ž mn[{k†ó$Ÿ+ûÞr29Çn¿jØ´û¥·ŠæêE'0€Å0v.'œÿúUa¤l‰Š±‘’g-ºgÉ$ž2CWÓIkpßDÌÜ*H ¸`’§Úµÿ øj O¼° ójèºéÁôãòâ¥Aõ{ˆˆ“+šÄÊfaJý_qÍ|·žñ^6¤ïõ-:Ñ0ÀCŽãùç5[¹Ô'rm?}m_ÛÇ"'—»£nnO ädp½AźÊÑâVeYn$XÊùo‘Áÿå×ã­H’IZX²MÐcß €\drF;c®*RÉä.PÁpà‡ºP0dnˆ3ð:u¬Î–ég=ÃH±K(“oÀ8ÚsÇ^ÕKSDËZÇuot¢$"Oûà§=H'=yÏÞ©¿Å-ZÊX¹òÚPtÜAPäã<}òxÍlð ±¹³Óâ䀽ºJÊg9äààüdõïZÚøŠ(u¶Ñ§m'ò„ðÈèJ±<·¤ž'œŸÒ¶µ1Å¥‚é ¡žM§’1å ~A#¯S^~—Î[c5¼W "ËJ0r à“ƒì:ô5åna!¸ú{I$(êñ!F¯«·ö+µþ6¬Ö0™$›éÃ]¬RH@|.éàŒ6p9OK¤o¥VTIÙdgˆ°S¹Àlòyè{{ÕdíªÄ.§–#²`˜1Ééí׎¹½o?!äU*‹p ‚ÑdöŸqï‘^ä’;c4²$×1y"ž6ÎͪÃÏØçïQì^Y”BóBþ\×!ä`g®}¸è;ÕÏ‘n±Ú´3¬+6ß:02±J àç¨aƒöãЂ' ¿u¹ˆ~qRì㱆G™£/€ØÇ 28 öç'ó±`× ’ÈÛã‰N\G† àï ð=¸¬’Ê…$š1Ê#H“‘ñÏ¿LVH]¾šÞ)S̲`€rFqÇÈïþµaoyôRÛêïA¦ÞÅ{‹Éå8aŒã g¿úCVñ~¯a<&©s5ä*"†Ï ÎÐ1¶Lâ$ÖŸ/í‡ÄÖÒæÚÊ«lR{õ6Õ,=;OâÈàŠ·³ý½´R(Õt8ç˜f}.à©AßÐù ~7½vŸx¿Ãþ+€Ë£_¤Ò"žÎPRKlû¡çó5³R”¥)JR”¥;?bú%†›a§ÈYÙ¦îeU–Ï(>}º×ôÊ;7³³–Þ0ñ­’Çm#( #Ú0¹íÆ=«óçŒü!oq®ø‹ÅZ®³¦]ô×0Z;Þ6ù^IfÊœ7~§¯É¶Z¬× %ÚÇ$-3Íik¼‘ÁlN7`;sïÍ[xfH\Ý^Íéîä-#ä ‘úV÷N–q˨^N~š ´1Ê€IãƒÎOAýšâšÇï ›PM ’JI3²ôìxvÏCÿŠæ7šeÂÛØJ!šîûQ2]É3äïb}LqÏ÷ÿŠÜt­FG…ãºú‰$³U²S¸q ÈaŽøà±««ë›Ëxá»6&7TH¬¡’`«3Ü#9''8Ë­l2%­ž€m®.EÅåä&-¦Lzˆå¶ƒ€ÿlÕN™unËA^YAmhv¤”ûwœöüûG†‘"±–g_úd‘šNH7Œ’zí~|ÔMwÅvPïž3¥­µ«E VL[–cñüû×å¯Å«øª{Fò  Q"*Å”·„p¨NNsüëð퇴•º¿¹‚Ò=Ã|ŒFelàŽp0yÐ¥y.ì`Ô#¶¾]ÑÜ2cÍÎ8ç·NGêÑ"·ŤYm ¶Dù‡jÈê=r`öfÏ'ïŒuõ jpÍ}ªy N¾Dms4Ú$ …ˆÀ‚ߘ÷­Ä>0‰µU‹N‰¤‘c6ÑE»ˆ³‘½‰éœž9t’É%ºn÷SŸsøpµsnÖÇÂ6ö²ê3êɨ,—v×È…D >$öÇ<ç­ij,ױ؇¸·žé¤Êå›MüóEŸÆÀ…ÈôíT:G‰æGfÖ¾kòÕ oêÓšÙt½D%´÷wJñ³\µ¸Üá—À޼ñŸÎ·Ök­%XÄÌÅÒ8Ëãb¹o¾@©žQdˆP”PÀa°9=3ýŠÖ5u[I®onâ1ÛE4Kk¥Vxåv 8 ¬nÕ-5ö»µK¦‘ C> ŸÝç#Œö犅£_\ʃO¼µi|»”`A…ÁüXíŽMt¨dYü˜bl¤0ùï!Ááz`ð QM:¥ãH‘FÊ…áeh]„­œÚ½‰-êÁèx¬2GlÒ㎵̭¼=¨¥Ö£"§ÔG:É&è|¼““ð{ñŠè^‚â[+[›âR¥˜íÊœúyàÿÍaÔ4ÕMVËT¶bóZ9¶f ¼ìÛ´ö>ÃùU>…âȼA{%¥ê,Ã#,‰ІuCµHîͶmO4¶ó[­´Ë ¼³˜b‚ç†n2O9nØsšÌ×]G4&åäy!í1,dz‡ü›Û?8©¶"Ú9&›#Þ9Ë^T4›ºnÚrr9ÿž*`–f¶H® ¶Eæ$w@ŒØqÆsŽã¹ûÕ†²æM.F†F•¥zð,yëÓ]§G ÕŒð¶Ùql^Æ×ëŒýÿ®=ê‹N½Vií!TŠhÓÊÀ$$n,:ç’~ÄcµYÆÖ’YÀvÇö÷>¼. ÄÛ3Û9 ¸à÷îÚ#¹ŠxßÉI „‚$;€Þ>ãñÔç­\aØÈÉhÈÙd_P#¸àƒþõ¬]E4Æe–à–DYIx1I9ŽçúÕœ¿w&OqóžhÈ*Ç= éŽ9ù¬w²Íų˜Ú7™áví| íý@8ûô©¨_kª;,F;cb›Hîo¸ãâ«/N‹w寳º6ºB@‘CȪ¬íIÀryÏÍ~œ×//´ØbÓ-õˆ´7N¶æVn56È>ØòÔœ€ÀäœòÉü¡ûMÕ¥¼¹š$5´r”‘%½3¼¨IÜÅÏ¿=äòfàÛYbHùq‚Ç÷xÿR¥VéÚìši¥“Ï%=(¸0;Ÿz×Lyü*z“šÜ4«;k xÖA†‰ÍÄÒ·ñHF uïUú® ÷—èˆ$š+B¤ãÿuˆÎ=0Hø¯³ø;Ä×EïÚòÕ^öP@BOÓÂG‚G`;u'5_&¢Þʹt«#ZÆÌÛÂ…<ŒŒq“üëÆ¡û[¹tOÒâÙ a.$õ*¸<œ(=2*Ž+Ýc\šæ{¹fnbY. ˆÔtÀ·¿žîæßüvöwSÝ)Ébo^}Y €?AÇÕÿ‹ïï[Hî‚3#MæM!&RO ã¹=»cò«m)VîCÓRq=ÌM ª3ºàç'8'8]®ø†mBi Ä²Ïij÷fá~ê5<žx'n2÷¯>´ž &ömJÖHîBë6Úœ²™ nP7¼·'œrʲÑ-ïõÛc%»™c°»+H»LÌ!ÉèI#§@+sðý¤š¥ôsê`aæˆ[#Ï|±*y铜}³ÒºªúíË[ØÅkDh¥“”M10îcœã‘î@ëUŽ%‡MÓ"Ã[Ù…ŠÔ¸«ð<Ì÷'ª½WJ£y.gqÿJåG™´8 sz®à1‘ÏqTsµ­»Æ7“¦éêf´Äòêlw$ñ×¹¬ãÃÖz´ºuýÜ1A1WŸSfLùÀÈà¤zwªox*ÚÓPÕìõAosáûÔy­V«.ÿô° ÆF ö®gâ ¬:½ì>ͤ ò”–$É"ZóÇÆäÖÅa£hv:6â6¼Õ5Èf’ %ÇÓ2A žO8ä[ä×KðKêí§Ö%d¾·vY¶DÇ…qʯ8¶;¹ã³Sq:•/pöö©ç´¯éSŽ  óc\óTÔïô}gW¼“ËNµÅ¯š¾‘ ¼¦ÜrN ïœ{Š‹c¬Úk÷°Ý-µÅ Óå–HÊEPQØŒžÀqŽ8ÎMoÖqË ãÝC¨%ôD«ox‹±ÀdXã€'5Ǽ}ãFóÄ/c­Å¬69WŠâ"xüMò1ÆGµoV¢ê:*éºýÔ¶–z¾œ™dh‡Ó09ß¼ç·ltçšâ‚ ø‚ïMÓ¯-ï­mnÐãQ œ¾:õ­Cñ°5»xüÆXn-Ý|ˆÕ°.ô“Óø@ÏÞµ&‡ÉÁœ2r6œì<üÕ¤BÊh rZ¹sž& Sï×pϾÍE†×È‘.€C (oÁÏ~ý»U´“ÞÞÈ!/,Â1åÛ…°8Cߎxø®‰àOÞZ·•z—P4 ,éê1=#Ì“òk¯Ëqm+­ðXc-—6K!\ƒœnÏojäc^³K¨ßQѯ÷1‘å†Êcà19¨Ç F3[$·®a´Óî4™,ôÝ*!k¥Û¥Á$ƒÉð:sÇÍlvÞ$°ÔT-•ì³6U…‹y$ƒúŠüéûQ ·§îmø·y ¹Î nãÛý«I´Ôb·œ—„rn\(Ã"AÁì@'¥o–Z–‘›Ú[ň]P€fÛôíÈ“ÔägîkkÓ¯æ{XtëÒO:#t+‰•s†À3ž3žMlñO5ÖÑhPúPàzÇ@ß?éZ§â]PÔãµÕ#½ÓîmïŒj6Rmyc‘ƒÇ9둌W@Ðt]6Íî^Îiæ´¸­¦»A—S†ÏOó ç¹—Š.ŸÃÞ&¹ÖS-ük+9bw€ƒÜõÍt? ê‡SÓ„›BD¿{rÃÚsßùuù©–ŠîÐA2”¼7²òJ©‰›i9;‚ääµ°"s#M™T–ô)e'9 õÉ<ûW›ëhiöÆØLU3olˆ£BH''Õ´qPw[¶¥vAvuT’ø0»Y†z|õÎkYšÞâBg±’)ÉH§nóÿä:‚;Tñ’É-­ü‚ÞâÚ]·…²Å‡nüw«;[ˆÎ¥$ñ˜â†éV¶‘xíŽ5°Ìm"kœ`ÛåE"°qÏ#¦Ga§A̶±@Ñ~êÈ“c(qÁ랃ïTÞ'¾–Õ…³.ù&"€“…|ŸÊµëXììâ_ñ ‡Œ·¡ÙˆPÌv>ü}LºH¥º¶±…Y%Ÿ•‚bBE†ŒÇœ‘Æ:ŒÖÄ"Óí¢K-¾^óîÁO_¿=kÕúG$“Α¥ Iàå—n¼`üU¡¥]_\ÚIiu5šÍ´¼2K¸Æ©¯ÚXu=:T71E-Ÿ”ÆvŒúW€BŽœc¯9ïW?â>h»´YÁ-ãÐ2¨+0Æ“ܑМc9÷­WJºÕ[[¿]NXí¾‚gŽhö.è9'/\g¶GÜWA l-gyçW„ÈbJŒ¡”ÛƒŽ;ƒÇ½W3Ã:ôëA4©#´0Ã,«lc;‘µˆÛƒß¨àŸéT³M}­dÖÖÂÜoÅÕ¡Ú<òßÄ$`üô5³išÅ‹é÷v®¶ñO¦ÊXA<¼¢¼ŽOp'àûT'¼’Nx³­ÂÍd‡-’²Œzžÿzá¶· kâ–¡x_õ‚QÑËÚH‘@‡ÍÀâ Ãcß ~¿5&Þî-¥´Y£¸„[ƒÄ,È[c<ÈëÛïŠ] ô³ž ÅqqÁÚîÙýÙè7dñÏž§ØÖË’2ÜK<ˆÑ™°b»lŒp~yÏQd”˜9¿™å6ä1=#“ÏÚ½y²DqmÈÌb<ã¨-ñϓڲH-®H•b]vHTGÃq_ |}q©~ÎôÛ`. »›K‹Èò0w–=É.8~µ¢êvÉo<ªÐH®¬C“¹Šþ§ùZ¥êưÊ\eIûÖsnË2‡ä ›#êà×öù¬V‘A"‹‡´·êå£;‘PT«r2y?‹ï_l.olîÔ7rÄmæßêYLmØ\}ºž:Šýû/ý¨øTñ•á}ZXu(/ä¸/gŒ‰`òá’P7 »#, ç­~œ¥)JR”¥~,ý‹AbÒ¯—E‡ë#µÈ@åÆx'ƒêéü=*ŸöÉã 5=Bþ÷M[hàòb¶µ¾uÁ“ja€ÉÇ.[òÛ_mÞkVKýFIå›&5ÞÜ&9éØùóœÖ›â_A;µ•ŒùA(S0õÉÈò*·I‡‰nÒVZd€r=÷÷­Ó[ðå„&8âG¸’%ù¬}{‡îOjÒï­u {ë=IÖܺÚ"Äc ñÔäÖð–¶ZU‡Ô]Ý‹w ¬ë]ÍŒãýr(Ö÷—RF®²Áh‘Á rNzqù×¹üˆb·’1#Çæ…%³Nzî8€3ŠÇ¨ø²}T -+6ñÆûÇ”ƒ†cÿˮؑïÊüMª$“\ièKlF%Ywo$’}\|gç½iÖ¡!vi#-‘„ HÀÎsŽÿcÅt{V’ãK»Ô¤rÿÙä/ŽÃ¹æ· h[cίl†b“1Ä+öéšž·1êsM¨Û[¢iVqy1ÎìÜØ$gçŒóϽlº/„®|Y¨Ç¬k¬SLµYi„•…èJñ…ûrqÍnšüÐì´ÓáhÒwE…cÛÎÐ?¼ V¤Ó«[êsÜ;ÛÂÈÌŠ¸õc©ÎýMivzŒP„Ô/#‘œl‚(­ãgØÇ8ãïí~Õ©ø¦âîh5MNñDko:Ái˜½EY•x‰ÏèûUèZpy!Õu¥ŽÔ¸Žt'r‚ ?‘5gâ´©&v[åV嘩Ž0A'?–*·ÂÚ’h)}¨78¶ OýÃÈ ð2q[v‡=ö» ÛÀf·‚;[Ug lp±HÏœdã¿"¤jŠX¶¤+›YcŸP*K$ô,†qØV×¥Ÿ+O‹ëlå±Õˆ7vâPÁbJäH㱪ïkm>ÎæâFŽpÉk¦Ú ‰väÔýýÅkž!Òï¼H,|;št3j-íåÄÒ6û5B¥¤ 89ÈyÝŽzŠ+-)t›sO²Ô Õ†”欮 »º¤á¹p{u«;[ƒO¶›Pšá–(ý’m>cí=ù湋å›VÕ¦½08´ʳdS(#{1n…²I#5I+^$í<óBdS IÒ3ϤüÖ-kL½ÓµMÁ)–ÑÏ¥Oïãe >3ƒÓùUSŒY×;Nvƒç^dlŠêC£pO^ÿóÌl¦ÜcÊS¿ xê9ïÐö«[;+»ÓVñ›‰§”APõv9!@ëÈ}«®iß²=y¢¶»»{=;÷«#-Čǧo¥nàtðuĺ·ÔJútr82+~É]£ƒÈüXù©¶^,úË¡a$O¸-<ÝÚ˜| pIWã zž‚¬¢ñn—&ªö÷útHT%›¢•óÐR³žœŒŽ™ëV­gàýH[¤ºfsi;4éæXÄKÆ ®Ån§/ÔŒžÙÍxÓ¼á;›=Ÿ‡`µKiD_Q ̰™xü ®Où­áô]:Ú&nUº* xEä¸çýø#½WÃwæÊ·«¼q¯Õ5ÊÝ·N:ñíúWä¿Ú=´–Þ'ºKØII£F³zM ÿ£ÓÜÐ.$>jÄ_rŒˆ²1ïü«ÂHÑ®w0PL{׫Ÿ÷­ÇCÖþ­ÖêR «äÜËȉ2A¿Lñ]^}~ÖÞÖ(Òg–KˆÄ°I¿g<·§l×3ºµ7:Ä+<­-(›zg,FIŒvÁãýë´hwíejÑ>Ƕ(vwbvöv#ÕSâ]Ë]œIqºU²€p¼ lœgßùÕ5¤¯áÛ3mdvG$©ïÉfôü~#Sâ¹}Ò©¼¸—RÓ-–âýJ²*æU ‘Œà€HöɼhÚÍ–³:ÜÙ_G/¼ví8ÌC ç’|[]”ËõWóÀ¥R37E>Lkb+Ã#gÕìAÕSïw«ÆÎÄ%Ú·“˜e#÷ Žs·,Em‘ˆ–Þæ(ãD«¼€[ã U¥=”¶vÍzóÖÉ*1BYNà¥Èô“Œ{œô9ªÛ–’6b$á½.°³wíÏ¥{²¸YžÆòÜEk­¨“œù…ùØÀõÆåÒ¶EÑÕÔ°Çnf™¼æ‘I'§qÀ*xï„QÈÂÂE³O0ÆÄ¦ä[=³ÓÝ*Šá¥¼ ”Â’2Io[iÛ‚?˜$ñQìš%Š+?1âúÓ!2:àC&ÐUy8õÌT˜¤d[Hì÷Çd£±F00O ’8ë“Zö²ú…¥Æ‹m¤Mç=ÜM Ü8T³s~;jØ£µQusÍ¥Ä÷¥èÅr‘„3cr ppzT˜&·‚+¤†),–ÓqU ³ î{òO­EKk4¼ºcm!”4“ˆ®þõòs&GÏAVús³E+KmpŸ@=&ó†3œ§gžõŽçS¶ó=—62#yrÞ$y2&ÒU” ä~.H?•IðÔ·7Wq]ÜM,1A¿@üüu_-Θ`H0ÛLÄ màüsÈô‘ZäW¨³[H’ ³¯%GV©*É·¯ñ}Çq[.–'NÓ!Hãˆ!dôÆ îsUš´bHí."1ÅrTÚ4y ¿¨?#óÍkž"»›MßyÚÉ sG ÖžIÙŸ˜äSÁÀ#íÇÞ©´¿ÚDï¨õ(¼˜â€ÛÅ*©?ç#ÜûÖ÷cxú…ËÊ—–wQ²y°Ü£²‘žPõ縩_Q*EmæC$K4Ê“7ùd–Û׎8ù⥴°È’H yˆ"x¶ øSž½qÅ}[ˆ­w·vŠYéaM­oŽy¨&°Dò\ÝîY¤*‘´«Æ£yÊž#õç#ŠÅ$Øš^©ܸ$XÏû©8ëèn[ë‘ó[])JR•ü§—Åš©½5ÜÚdLÖÎ,cÚ\pBœ¸dbµ½g[mNöÞçS”?Nb`ŠGØ åÈ9Á=1ÏëÀÑu}Jÿ^g†Xôý{—†Í†‘ ·¿;ONµ7Cðö“wÚZª]<³ Szà! žøœ¤ûWAÓl4¿ ‰(áYb@$™°<ÃÎqœœcúV‹'Œ%Õ|E=¤0±‚iQÔLucð{àöü«§ˆôè­íláQÕo ˆbô èOD±Áàýë5çìê+è#×nnoúÌ›ˆíËåQ‘NÙ#¯lU]ó¬ñ™Læ ùŒªgUÇ8ǶkXÄÖz›G"Û7øu’´6ä9º˜Œ1é§ÜüW˜¯Ä\ÃGŽ$Ú(ÿ9ûœþCó®A¨ZÅ=ÝÜJZFó‹¼± ŒÝø$có«Øü¨>—þ! ky×P†ÄA:Ü$!U뜰ãb¶»]6?¬±ÓmeŽxô|ýPYýTì®ü¿Jêpx_PÔå·ú»±g¦@7ËmhI7¯‘éf죦Z¿›ÃV—Hšm´)në*OA jªî0|ŒWAžÜZ[Gå.còÎãôíŽÿ•h76¾l’4¥e”@î8äŸÖ¨uý(Á ÜË æl¤q¼Ë»qÝÛ>Üœ ®Òì•´øp+\Ò+9–éÉçï|×(ºžOj2[DȰi¢áÌ®0—wJ¹ 7 çâ§ßkN°&™Ë.g# $Ì2Xqœ{k›_ËõR‚®í)!œãðŒžqì?žjE–sª_G .á9$( y8o׿zýáèbðý´WrÁ·ÏýĬه©ˆã8 ½»ÕÆ•-ö£¨_\ÞK WvhJǾv‹œc+ê$ç9ëÒ¶+m:ÒúöÒþ{h¢{UhôøÐœ"çˆîHøÐ<ý9 IcÊÒ´Ç‚~yíZˆµËM.Õi–H¼‘û’ðyýk—.«w’i®¢KýZYn.7‚²*–ÜqÑ@\¸íPnnYiå¹·šÚ :áVÆ#Äè¸>aûõ·¨-¬ú…ù¾·3IYb03.À$‘Ž3Žø­ÓJ¶R‹1«–yOýÌrIîI#¥ošZ,Ö’Ù¼Æ5šS0ݺ`tÇ?®2;VËo¥†‰{{{q<7š‰i e˜]¨§ñïX¬§ŽêéÖ(äŽÜR= .R~r§æ´¿øv]vXµ™Y¬ôéXĶlA9;yêXÇúZ·ƒ­u_Ä1Aâ(oÚßICi5ÊJË´ígDsœ°l·§#=+k×´È/µ‹­?F·úxím¢[@]É;xÈÏãÜðtmvÎÏWšÏÃÚ"‹‘bËy¬ÎÙ;òÝ Î:v©ºÞmÑÒÙgÕm­l+[-=¤QcxÀ1 n;ð‡©[¬ÞÑôË»•c¦\Ú,Cü9£’ݤ)>r¡ƒƒ·ŸÄpdw¾ñ,2^x6 ";Hnµ/NÖÖM¿ºØä4 ŸÁµ`ã­~l¿Óît=Bm7W·xnmXG*<™ÎyŽ|ò:Ô(ÛmÊ¥`¶å ·oéRg÷2yèYÓ&3—9Ï?×eúM•ö©f±5À¼¥šâtP¾B€6n½ çØw¯ÓÓKÌ[m7K.¢Y$$­Ë8è³þõS}}:=Á(³5æ¡çOñøÆYO …ÀçÛ¡®=ã)4sysr%‚Î+ke‚;%¶%$Ÿ,]€^œÿèð*§F½Ñ5tû»¿£iš32j7n®²Jê¢0øço¥Ž`’j³ñ—4ý6çI·¹–Ö]:Ñn´F´P¢ ÁÀQéP¥lׇƚýן¡r„Ì'>TÌ¢Fã' ŽN¯Ó>ñÔÞ/³‚öêhá¹²ÏÖ[DN!€<œŒ~.2xûU®·â—gtŽ9Öxö•Î}'žÝZç>!Š-s@–×PˆÌövój¶²Æû «'«ƒœþ†¿<=¼hÂBL‡%ÛrGV9YÞ"w«qÁÆÞÜf§%¬í —JD‘B«ÑîRyà6Þ¸ùÇçXÞêäIÝ&ä"}ü aGåšÙ4í]&»¶i›"ÛÙÜqüoµu=#T‚O.9$@Y„|œŒ‚sñŒñžµ¸Ã=¸ŠK¤rÖò˽Q”  @gç5Í|O$fòT¶¼DŠic!äެ§AÉíñŠ—iâ+=M:]Fìßù¤‹©™ä‘ QÃv:äó׊ÒüA ßh|G£Ìí¥^Þ<úkÙ\`A¨àç ’1ÈëWº ÷v0]_É(º»ùÓ$¹ÉLôüë|ÕgƒêÚ yqBùÉ<çðš¸kV‚M°1R ’ÎN{ô©ñMp÷ˈ¤[§š ã°üò•^AªLÊ``Uƒ œuª]kQ†ÒæÔÆX4……ÄQ¨Áa¤ÀÉ¥@þ¨­‹y“ÛÞ†íl¨6–kp둚Ñ<$u­cQÕ´ÍJè0´‘¢óâQ˜Ý©Ú÷ÆzÛ_I‡M’%¹v¸hoÌвÆB㢳g¦Ñž?¥^ǪOua4‰èãœÁÆ]̃y瀦*¶îææ@³$Mo?îÃÀNäœ2‘‚p*²æas[x¬ÄþHºQ6yÎÑÀ<œöÏÚ«ám’FHÁC*4ˆ¤ ~çhÆ=‡z“,WÖðIe-¢¹+ç‰Ë à#¹ä`kؼ³V¶GŠkq ôNñ>|ÌäãÛŽÕ‡I¼FÕ ‚xÕR0aUHV ‚Nyèz{õ« äp\ÿ‡\Á'š%†K‚Π9.Ð@÷éÇ5ĬõíKDº»¶žêáfIÚ9Wp“.<ž ÿ<×ið7Œ-µBlF;žLÅÎÐêyÝ÷É< ±×tÔ&æêâãÏ’Ö–Јý‰#u$1ïßãDO¦Š;\I*ˆå|~\Œc VËvÒÝé²ùÒ¥”HÊØ»€Ï=?¡÷ª¹¼ãvâ8÷HfARSrwS׌{ƒ×µ|QiãèD›<§+ÿ´½@ãØcò¨¯«E%ÃX`Ç$·ÿVÒ.Ò1ž½?â¨|AÀ»¼–/2f³c1ÄžH>[{a<瓊ִ ;^ÃKMZ !ušF·¾D+…#ð=\ãõÏÒ´›{I®o.-ͼTSÛ܉}6ì¼8øœã<ôÆjv»}$S%»ÜÛ+H·Mè ©G# }¸¨1]µÍÜ)©’(ìšm¬¸eÀ'ŒœütëW±mbv •GFd8Œñ– ñÈÅbýü2A{b¼ ^å®#Ê3óKJ<ÂÀã'§¿z–ŒbDŽONøÄÀ>Øö õ–0âØ3ÛåÌɆ¿„Ž8ê9çó¥ñŒ7i!› 2¿˜]ˆÂg<÷ÿNõ¤KÂTQÖ @\rrGoµJ±ñ6£i …–-ßöÊ~/nC[5¶ —4»ã0¹Ý·4 …ôŽytÁ'¯iN#roW/œ õížnsYZy三Ö³Û–)%°ç¦;ÿb¶_í%Ðf ™“TËÚCíÉÆsßžßκ/ŽMîá4’"¾^QB÷ýkÜ´Ås¹˜tÜÚ¢ÚÜM[†ß†TÂAÈ Ž‡ŽµÚ<%ûnñ™pë×ìTì2\>É¢ÿP_ÿ¦ ÿä+ô†|wá¯Æ¿á—Ê—de´ÛÀ#•:ÿpü å zÜiJR¿úÌö/¨êá´Òa¿?Iú÷ü¡G`9äWãcÄ:Þ¯pmµôÐþá8xñŸIîO÷ŠÙ4("¿žÌ܈îmá‹ÉK$˜®Ü(çŒÛ'¿Ú¶»SÔÿÂ,c’ÚÆÜ$7Wû×)’‹×€I÷t /XhLóÛÇôð3ܼ²ã÷ŽÛ’qœ ØÏú ãú¶»â/x¬,ZXím.Ùm"·Ê¬J¹ÄÄŽüuý+·h~ŠÂÆÞÞ8Ò6W {u;îGq¸ó“žO\WD¸¼‡O† ™$®¶öÖ©ÕcØ äž€Už‘kœ—7W/Ý^H$¼˜/,`{(àw÷ç5*]B ï,ɲ×÷c¦îÜÖ¯\GrÍqÿMè9hOaÜÖ“m~þ"»`’[?K‰—êeVârÀrp2 ?—j÷â=Xx[EÔ/g‘¼Å_&ÕT`I#J~A'Øk“øÆïXžÎ• Ó’o¨¹Á½rw`ügÿZÙkl`ÓÞÚI.&ò&ºQHˆ¸äð øÅq+&¸¾¼ÈÄ<ÄyŒñ®2G¹éÇ^{WlÐ4÷°²¸–Þ8å¼0m·IÁ$rr·aïV‰`Ó>}NEú¹íÓê I…؃’W¡ç·û[ÕªÄB‘˜¬c`FATGLàrzšÛ´Ð^]Ù; £8&¯uk»há·´‰$mÏŽBûççûÁ£¨Ås.Ñi¤Ü°…À“>œã¾Oÿ,Ô­'L·YMíàk‹Ë…`f'&4'>_ØcùU_Œ5f¼[?iÒl¹Ôåÿª™ÿ·„g=ÿˆ­l–--!´€3,cËÞì=^äþ¿ù­’ÓN\5ê2 ØèÁ9??súVYµ;h¬þ†ÙÞâtòa€ELõÆÎqñ[Mí›_èŽ5ŠÑ8x¡ˆŒ P¡c8'Üäö⪡‚ÖÑç2^È‚kex’v?» 7§Û9ÿôIÑ’d§œM ¢3$‰€”“/|Œt¸îjƒÃ+ÀÚ¼3*ÿŒ\4“DÐ À !W>ÀvíXõqªiWƒéö\Ûj— s¨M„’Ô~H' N1ÀüªQðí…½Þ.—Àœžã®ÝO¦øK]éíÖúr>±c¸r\W'±{˜í]A¾7wWS(Ë“2#1 )$¼™nìNO`:t®uªëee°úIàŠ{{g–Ü2o6p»3Ú:1EŒîã=óc¥¶“ƒ­k~#‚@Ü+\Ý ¸UÀô…EçØcèI#’kòÕ¢HòÈQv„;Ù 8Æqƒù‘÷« ”9ãÓüôû|üWé¯ÙÏ‚¥ðåí­Î£uŽi¾|P*¸6¤,Œ>ξØ#Û5Ô™ãQH-üÚ››ˆâ%±Çý»V½|n/šeµu\ºíUXg$«/aí\]ü¬Ë¿h÷âYíŽþ™Y†Á*Çœà€GPA­Â>ÿÓ¶êáÒk­OÊTENù>XÏ\ŒŒŽ3Æ*îOÙþƒ¬ÜêWï¡[˜-Ý#XÜ<.²W‘¶) BîÛÉê~5­_öOáˆ<3a,ZŒöãG4ÓËæ-ä®@l0 9_ò’sTOû=ñ NÈ›í6éMµÍΛ½Í¨8$ºc!F?#ƒÒ·ùü5&«¦=Íþ¶dÕƒÛG¬qÁ?ˆädnÝóŠÐµ™/bˆÎ.?~~jŠæÖY8/Ô;É!òÇ.9;9îWžTÙ6¡7NÉt'¶7Ö¬c‘ g÷d0íî äVi¨ø†Ó[’-·Ööò\È"¶¹|¬ä¯,lô8ï]N=Bò ).e‰dÛÅÍÕÌá@á[–ÉãÛ¯Jº±‘g²’ò&S+Ÿ0€¿‹hÇóŽ Sj7{`QùÇ›.ä#npÑ{zç½[Ãc íœé{ J“ò†)Þ2€gYyÏojåzGˆbðî¡}¤êFKw±™ä[¤ˆî¸L÷'n9©µè"Žêâúæ?6Ñ•QfŸ§m¸$ÓúñÞµ“46—Öѹ’æØÇ˜œ¨<H9Æ*ÒÆÊiía†Pó*]Ivä#Œø@aÈ=‡Ú±ZùWHɢ˦݇Œ$„ r SŽ Ü¸ç•냚º¶±ú_Y^Lìn.%²¡+»’ùn8‡Þª|Cm©iºFŒ–2>Ô¼D—ÊÎï/cäç<ú‚ð=ê}ÌÑG¤E"ÈMìhÑÝÝF› ¡ôyxÈêÇã?Q{â+½2}Ý̶wò›YDd Wo ŽF=êäjñù×6ÑÂÑIgp ‘mÚ »Œ Â7r{sùU…µÔr@¥<öi¶ˆ¤gI¥³†ÜyìãŒV6‚W‘„žZ²8ug$ž­¹IýsÐö¬Þ›{›„I¥,ûc8ÝÑrØ~gÛ5î –× n“Êéå—vs9ÏÈê2o·9Þe’ÝC |Ü0î:8ûVT}òBð‰KÛïR².8ÉÇnžøûõ¬bÞyç’æ)œ•Lñ;PmÙŽ;â¼jq4ö2E$h‹#yžc'©pyRéšÖ«ˆÍÄoq–Pª·©ã p¸ÃŒ‘Ï?zûmd†ãÎ’‚M™ m½qÓß¶9Viô»ws"’Ž_ƒä¡—X½±kk©bè’˜¹ŸIûcùÕ´: ºx›"˺T vþMoZ6îèF+œÆºå˜ cÌ«ƒó]{ö… ¶Ò±24aŽÖ21ß×'§\ŸÈšáw[‰>ZmV$.Õü#žj<+·2 ï°ÅH%½®ÿ2Aµ£œà:mäc¹Îy7¸³¦šðZ Ç zä;x®½áÏÛ‰ü<‰ku2k–@zcÔšH@ö“;ˆÇù·c°ûÖán­­îa.`K„ô Ö³Ò•üQ·Ñ/5çÔüBnúà‹æ°ŠØ…Û0XðN=kªÙGd¶ê² K37•K‚ÏŽ€ü9¯—:&í“ΚI~¦Q³¤Ú¶9ç ;ã‚x9®;âËmbâÿü"¥ž5„k-KgŸu¿øeÞ’­$¯©L¶óGn¹ùd\pÁ3Ôñ\®6eßo7˜<·«9ëß?¹xSókWó˺(,´x£¾½¸’ø—l`wf=»`šý€³ýT‘N$Ÿ÷‹uC(gž‡=1ùTE»ž >úä<É|Q¢• #ÛWnysZ·‚õ[|ÜäIZÊr³íb¹!qŒ`uÈíƒVºN”šu†¥ßÜ_¨¸–hd½ˆf%bނÖ'“ùÕ—©ý~²ú=ø†Þ}ôù~¬ ’ƒ†ï÷==ùä Ù`yô£¬^ZÌ%³1³}$ÊÛ´†epp;çô­>ÇÕ4­5Òòkc x®Yk™«,ya€˜bHp9â¶95™í¡¿•ne¼žÖÔ˜tû` ’B0¸\öb:ž€×<Ò¥y>£©qô¶ºl"’ÕZG ­ƒécŒŽ;ZŒ|3â(mYÕf±»óçò¬g-ôåÎÅŒ‚9.A\ôäŠã²HKƒµ” !9_÷©‘Þ\`”òÎ:ñÔû×1˜†EÀfÆX )Õeª^M ",Ã>©_hsŒà“Ðñ€:dzº]:ëËÏ•ª.\4€Ç¿·¸ïÖ  HÜ3­Â£˜ÙB,Ÿn>?×¥GŠÙåFvÞ­lÇž£àΑל~•/KÛ§Nh¦YIóT€' ŒüwïS®.-ïµcùF(¦ŽLáÁåxî3Ï5ö/¬ÚªXϽÆe8ïÓaùïÏLT¨%ºÜ«ÇnU”¾wôûRîõ'¼…H|EÓ8£çŽ:³³½Ô¾]¼ræ0&rбê>ÀoÌÖ ^ÚÊ@±ËÜïTµ»œ gÛ“Á÷ªÙ9tèàiâ¶‡Ì u©»AöÁø<šõ£¼1ßÝÚÛ;‡‘Ç1‘@Bª9ç©8<üŸÊÞ}%¦µ)†vžìùí&óôÊÌ?z£=r ŸŒýŽHn§²Û\ ¥€YÔHéÜV·&‡c©øŒÞÝÚ#Û_é¯mxò6 #+œŽœcÛ§ÅcµÐãÒìntûõQ$°K…&WǨ{qÛ’1U¶Ww)£M4QMon$·u!¿ŸAÈã~>Õžá®`‚k{¨®ÅÒ2ÄîË †IGß‘PíîÝ|Ó4#1Æþa ŽAÆGF‘Ó?jøfP`³FLXf µH¸8àç¨ЍÕçðlíE"7 Ö–u(O~$qŒ×$§3IRáY1 º•.½‰¸ù¯±ù,€Ä}ü†^ÏÍ|h§²eé°‘èù…d‘0­žþ¡œvÏé[V“­Ih²Å-»Ç&ç”àõÁázv®™wºÞgÔ~™ MbX¦Ýlż™ Øn³’@ÿjÝ/.¤¹‘-#œHê\2{”“üY9œàŒqZļé{e hær\9ÞZ\7¥x'€s’zâ¶ [QK­A#DYnlaFLAsÛää z —y ’[DÂK§Ž5I–¢CæŸäsñXµ8î\ߣ«ŠÌDG6dÃN@Æ0AÕ#M³[->ImcŒÝ¹i<Â?9 žýy¬Öööv¶6ÓÈg™PKåGÅ cœa‰ûgó­TêÚ¤:ö—a G&™tÓG+lϬðw{¾ÝLVçâ‹xãÑâOOÓ̾y¶ÄeÆx‹ÉiÌÁo|õ-ß·Åa][É4¶“<Çp"y§mþtC•à‘ÛÇcÖ¥›»B]6ém¼©liLH,_qȰkfáÌQÌŒdóQ•öŽq' +/(Ï´¡~J缃ü‡¿Å%Y£q4ž¸Þ_$€Œv 'à|üõ«?¦V·šæŒBçFNâO\g¨é÷æª ŒÒÉçˆñµØ°» tç©ÇSŠ«µiYgÈ&Þ``ía¼2pz qùÔ¤T>TqϘ DjÈÆ6äF29î3ÍHJ…RVTbヌÿZ¥Õá¹’4úr¦D¹YKuލ}»õæ°]hÒ]ÀîrGû³à±ïÇOïïXí.5m"æ°ÈñÈ$‰·gk/ ƒñ·8®‡7íQµÕº›*:ÃåyÁ9ã>تØRIá7H“(=˜eâ ñ:¦Ö}ýYŸ…5˜¸weɤ”óœs×§RqY®€–8ÁZB Úäžÿ~ƒÿѯ-hƒã*} œ޵ýÒ|Á ik±#L€‹·h¼œþ•ÎS]ßÌÓÞJNécÎ 8®±£i«o4D\HÒJŒÄàsÀý?¯åWLj4ß­q’FÄQ» ÌÝ”Éü«šxÎëWi<´Ξ"ëlŒ[é½Ï@qŸ~žõÃdðåͬîÒ.7¤e@;¤ qÀOßëâøKN˜Éô÷²ÈÍ’å¢L„}þ!]ÂÚi¶ó¼VÏ%ÄQ‘,â6%:á¾öøäÖó¥][iSA?’#¶G‘ÌŒ ÀädòI?ʾkÚåæ·q ¼MžúräfV?Ä}·Þ­´‰c·c‘ã°Ëº@ >ç==½êÆßX‹PÕßK¶’9,ì-^K÷Ü yIF9ÉÚ2XŽ™ÜUüÄÊâ1}  Ÿá|g(ÜDц‘¶gù­?Ä÷QiÚeÔÛcób„­ gçÍ9ØFsÈ'ç¥s‹ ZÝœ{óßÜšõei%ÜŽg¶X„r2ÆYˆÜ;œt&·­;e¶eÃŒaŽG\ûŸÍl0Ä/%á•D‚"? >ùö¦MPM¬E¬Iqk§È¯cjæ)®clùî§Ô£ÜÇÞ¢ClRàÀÿLÈ]Uú±@çÞ¶Ë;%–ÚÚ1 Ñ«(óÃzL×õS¼ŠÙžâå— ý:D£šOp^ɨþO§¸ŸSÿ¶Ï9›é9“ì20ZØüGq«ÚÛCuSr³}ˆ³ÉÀ¹ÆGác×=k^ÓÖ(ݼ“åÆ]Ї9'I¿÷ŠÔ5ßhV÷Ij³3Ln’8…»2Oàt®8­×Â7šv¡~­£És¨´'ÏŸ`%cncÓÒn$–âÏPš4í$/€íb%(vR8•~?ñ•åÕŒðC ±|»M($´Ìqê>Üvª{»ÂÐÜÆì·’ êÃw–Ì ÝƒŸooÐÔáá]ÛR=3P¹†BÓËq£¸U9;ˆ^ÙÏéðk¼xIñE€.åд¨î_U§óšéª¶PñÕˆPXç¶:óŽÙá=4C¢é²ÞÇz¤0Â’´'!Ê PÜà‘´ŒôÎzf³]éÒ>·Ñ\yVâÅžúÙ¢ —EÎny½9#'§nµS†4Ý/!Ñtá¨y†á¤€·ÓJÇ&@2 '€}«Wð›ø‚8uõÖmVXíµ ã·»èa¼+Á€ë÷Åk—^µÕÿz×î$™&B!dÁ “ŸÞ÷$ŽÇsaª›r’3©DOHQÈÇOå[­«[Þi³DD{¥_;Lnf9Èã=ÇüV»ªiÊbÿŽ;ƒs4Q´ ÿhãýÉ# ÷Éø©¾·Ö£¼Y•ÞÊÞÛÆv*7ðîsŸÔô®‰õ7×I"G꼄£ÏcмÐîPýmô…óåòã Z¯B3÷?<óYu`$¸³»L:Û¼¸û¹ ãžy÷þuSþ%">éÖ$óJAhÒ9&Sü\¶zŸ±©ñi–ö—_§7w¯–¢#ÃlŒ·¨„n=FAÏVϵµœ±<Šã/ (¤ ‘ŽQZ½Ë¥Ô–OæOb,Tàñžøçäõ­fmZá¯PBBynëAPpO$~½«fƒQI„í5ÂÆÐX†aóËç¾rF+Žè©MtúÃ,×' !åwî?JíšÔÖ×–ö²YÉæÞ+yI„Ý»ŽF0sÇ?—<îö%³"í’ln¬œyéZˆõT-p$/æî·!àdqŸá#‚{ŸjÐu7RÜx‘ÆæRù¨AÈ”9Ê’sYbi³É€’ÃìTµ¼C€ªÊÃiaœÿ ©Ÿâ䀩"8²ÏÉù¯‰7•• ©s§½löúÃ4Q[9™­ôÒ²¶ îÆ:oκ&‰âû;[i-® i¨/$xÝÉ;IîOþ* ­Ô[[«k˜|ûç2$lÜ@Ç Ù<Õåœ ­]ŒZÜÉk5“2J°È Î1½ÈbÀûuÇzØä½ŠÑ¬mÁ“ÏžFw" ãpËdàŸj“…Ì>!Kõ¸i4ÍFÀ@𱬣=q׎ŸRê7‘ÞÞ-Äq¶Ÿº-˜„åN¡ç ôéÓK×Úá!HäÃ6¢ëb•TðØÜQÛß>ÆâÐjS„‘K[Ý”Œ4`‡žàä{àüVÇ⻨×MúYaiñÄ 8Q޹û× ñ¯u¥O¥6žÒÚù1¸.Î}þÜõÚ<zÚ¾•þ#"*ÉÆ¥ÿÏ"ˆnZ\†!n•î:ŒóߟëW1_Dª™H§V\3NÜþu(LŠªØ;x ïߥK!¶‚rFHýíáIWÿLx}ÑWhöìËæ= ÐVûB³K…ŽIh£U+Á ŒóÓ½~UÔ­Ê]¼j’6ü#?#Žj´YAƒçÆY3€IÇÆy=3Z—†-ìmtå¹¹>Df¸¼|zœþy8©x£Å,±ßiþ¼ºÅ¸Te#CÝxéß½QxwÀ°=›µó2ÝÌþ`¼ÜÀÄz{óÜóùÖåáŸ6s-ÉÖžê-¥VÞp?|@ý89÷þ{…Õìp-ãØ’óO·2Ìp#X† äœòvœÛ9íZ…’ê—2Oua_jhò}TÖò;Œ•Ø#ð…Ïæ{b®—W6‚v¿‚9µÀïs$ÀG´€vŒßç½RÛèñ;[É-›ê-Zvy {Žà¸ÏO }«CúX¡Hò# ¤Ë ºóƒ»ûñþ•Ó<9¬èÚƒNuŽ5ˆ€6î31þ¼ÔKG«Ý oRi᳙垒­…çK`dsÎ?äTísI—H“HV•¦7ªäÛ<{V2»{}›¥BÔl`x“IXâ’{ó¾î_/8òyt9=½ëi²Ðì¡¶ŠÖ uµŽ"+‚™çváÏ8÷ïU÷ºÒøfƒRFž [È"¹äí(8üÆs^ˆt¡b/’þ X˼¦EXëÈÿzç‘kñø¯Q¶Ûmq.¥Ýá’l‘}0¡(è+p}Cü.Îêîê3h­pI”c’Ç<Ê¿>j:¼ºóA$—ÌѺ%¢³bÆ2ä…üÈÏ<“ùWFðΖÊ-à¶}À„»’@< –ý1ü«­Å«Xhú%ÝüÛbŽ^eiÐ(`£…ç¯|rOÍ~DÖõûëíyqºUY[þ‘ŸÌô­¾mU§´–…Ú¢ äzw1à(Ç\zÖ_ iæw¹š=§p áx¥(WISQkÃ"còHüªÆÿT„Æ¢TŒ uÞìÇÕŽØöïúfµ+ f'™d7q%“@c¶„[Ÿú ù“'=H éÈ5h&‘<‚ÈëéhßÉ꼨üý±ÅqßÚŽ“âY/ìæÓÄù ¶Ë2©. Á8$—’8½síëÅ6ί²yKav9¶DäîÃgŸ¸É­¿^Òç°ºÒEÎ¥$Ÿãqýt÷rGµY76ÂW†?„ñÐjç^ ¼ºÕ. ^]Øz¿Ö#À0m¹äž Vàþ »ÿÕ5w¹’¦ªtk«c™ØH%Žs†8s€{Õ­ýü^ ðV›áû-¶z®½ŸTñ¹]A11Î@ Bã¦}ëê1ˆL 1° ’wœwé×"«”`ÈI,ÁÑAà}ë4Þl„³¡©*©Áå^tëYo®BÄÉŽPÒ|nÇ<{ûÛæ³‚è™#Âî+!Óö~§â¡ÅoujÙ͹ —O~2aš• Á3Éæ3ùÁLgcÿ,œÔK›7ŽV6ìæ#pÇôãŽúV;Ͱ0…]ËŽ²6=9c°ïWVÚŒ¦Ú×2‡˜“¤±ÍŸl ¼fŽÊÞ;{‹¯9äQ<³K)% =€#Ž}ëcѬâ»ÓïŸë¼Ó¢¥¥Þð\~9é×§J¢´–ÚÎh¢ÕîXÇ`L–ÇÿÖ œìaׯÉëžkVú烙åÓ`Y™–HáÜ¡”gk=û~uÛ¡ñ‡e¢À.®À•,‘ž7 &ÖaÊd䜎qÒµÛiRúÒyx܌Χ2)'¨äryâ¶íS{›i™c‡ÌŠFšD Ã߸ãµYKäg&"$K9dÇ—Žüÿ}*¯TµšâÏLk>£é/–éËà˜Ð©nî¹È÷íSíåºú©2#eVW¢ä;`‚89éŽ~:t« TÚY=Ó*ÉÉä:³sb0p=Î8=*ŽþöØX^7šÈæ1kÈ1#cØÀÜÀqÀö®yÙãjâK YE²©àŒ†ûäWÝnä[i÷²$dܼA-fnƒ>Õ¢iÐú[È·‹såÜ&ã¨ïÓòÍt‘«amtçl±!‘ã#ûu¨æµ¥ÝÇ̱$SºÛ `g>®OSŽ£®y®g¨Ý%á(XGžœõãò¨Ù@­+æ>v3³ûéùÔ!lãpI•çap?­yYŸd«… Hü=²*Zií$r4%HDó;ð3Ïz÷(´X-ºÈ³?TŽrºî؃Óâ°yáX¦0 Ú{ ~µ,]–HÝQYâ!bfãh?Ôôù«;MA w)-œS=ÈÚò<{Œ'9ܤþ‘ŒóÇä ¸˜)ž& JNæ@¬Tg€NN01Ç=Ee±¾Ôô™`¹·¹žÙÙ·.Ç Iƒß=y­t;?Y5«ßêi¿…ÑBÄI2œ¶O~{cŽ‚·O ëWZ¥­¤“Bb-v&C–=C9=~ý*Ç_·´[››™ I É‘>â ò }‡|V…â/\Ø_i·º\‹$)pr±ž ‘P@Bõ÷ÅmW+§É*j@]Åçݸ‰dUd“$ãÇÙç=»üÖüI/¦^*Âò•–)7‘•ìs·'ª5‘äŠè\6íñ¿øä1ïŸÒ·¿I‰á)–íÕqu´´mŸQ /N™$w¨ž"ÑPÓ5™î-!Ѳ6ÝÎ?'ðç·ùÆxøéRƒL––*ðÍ,m,Ñíc!$ñœà|ã¥DÒ)c±IãŠòúÒCi&Þ åsïþµSáýWX°ÕŸHñÜL†ÜË ÆFýÎA`8ÏÇÜWBÓ®~¢·{í®£±‘¥Ú.Üm ž;Ç·5Eq%æ…¬%µÅÔÓiz¼Bæ˜Ü˸zsÓOLu5ÐaI`XadX‹©BG‰Éã¯n3Ðõª8ÌQ ¸b…ÙÆâîHÚÇ9_p23ž™¨èK)’âXÑ„‹û‚ÜžœN g†hg»H‘U‰q¹q³gäóýjHÄw2FÙmŸ¾‰ŒƒŽ@éÜ{~.üÖyne‰ZT²úØå•DÆÉõ7<p1ðyâ½Ü¤…Ú%ÿ¨v!6·áÇ#8éÇqŸÏ­a‚®|£3.øÝ„ªÃðpØîª;AåµÄÒM Gu $0ï,A@ÂyÌý£jV‘ÈÛìíÒq,'f\¤ç ÷#·sÚ©SIºŽÖ;¤gÙ<Üùgº}Å#Ôæ²‘>¡69 ÁHÉùí[=ž¡Ä oRÃ$üç¶8¯Ôžñ߇­tm/L—T‚Îâ+uKˆ¯ pU#q‘µ†y$`ýøÝ|a¶îÒÇSµ¸ˆÛK›,ª7pzc‘üëòεH#¶zŒó]bÇQŠÊßÍž6¾¾Ú«0³Æ Èâ<“Æ^½:V½ª/ø…åÂÉl­ó k¹#ÚV,JŽÉêx<Ô;Ÿ É~·2ië ´³¦“ Ëìr:“ÁÀ? ÅpÝhêz]ÄúUô°››;Þ|p댎¼·ó«ßéW~%Õ#—Xvÿ ÓY¥Š2°<1tWé[ÎÀ («ëØÿÅWþÐ"y´û+ˆ^8n-.r¹ Œ0ÇŽOðœ{÷­H‚soõH..ZFr&P¥“ íü¿®ßÌÀlHenvÓµEº†)Ô´Ð¬Š¼•t'q¹„:f•ãn[4«X´­6åd½¼Ú„ËÀˆÑW¸Ï\WJ]ÂÝí"ŽÒÎÚ6TŽÝùÒž à`}¹'í\ö±tLºE­µÂK( ÷«a£Â+Ì‘ùÖ‘¢Ùy2,ÍË»eÃwrz€>uî£Óîu0f…"‘!|õPzôþ]{h~5ñUƬ¶ú$R4v0íYw20ÎûuûóÚµ3N†Òk7¸P!š}…Üp{ƒöÿzØïmÒ]I,-ÙÞ<¤—L 1ÀP>?oúCÛ$%c匪‘ü$pF}óW–ÓIʺÆ#é@A%ÇüÕγ5¥®•6¡:ͬfhÉ᳌à¹ÏjüÓ{-Ωqq¨ê…šòC*ùŒàíéÛ¦+h´×mlXi¶¶óýÚoTsŒà½?˜üþÛ\ÝßkJésoohIýæA õ<ö8·[‡ú¸ÒÞ&‘`f•:ªƒÈÏlŽ3Ôf¶ÓãšÚt-–¶ì| ãþ+„ü+a£ÛÇæ[L5 ¶ý\ò'FpFzpkxe‘…qå㊯T€±£VYíÚVYXã;†HëŒç8íZ%ýå¾£ršVšîö‘Üyל®1ó€ûƒWï¦ÜCbÚÚfµ·g…7ÀàåïV>CsiÍÊåd%Q×s‚xùÀæ¦jk½oR&ey!Øw·ýÏþ#æ¼èz{L‘›xâ/ ÎNVýÞžL}êítûhÀ¶ò”¤DúYrIÈùëUqÝÛÛÞÏ ±ŒácFHÛzúYü5«xãÅ‘éWšnš¡á†Ð=ÔÀàÎç‚3÷ q×ó¥Ó5Ø<¡Is¨ÛÉ ÿˆmZîÄÛ $ȧœŒnOÓïY¿eï¨j÷˪kq{ ¨)l²•ÌË;rÄœž¼u8®‰‹Û¿«óX_Ý‹ÉdNÔ1¬;†HDçŒõþ[Ŭè×wpJ›V×jÂBŸÞdtÜž1ñQu¹¥ž-&7Uºi¶Ü©$E^sާ<ÌÔùe{XŒÂÄ‚ÙOsÛ5OÕÍô±¡µ’DRA’&á›Á'¦zÕ½‹XIÜL‹{*E'%ËÓìx¯º‡‰bÓ4¿­Háyt÷ <‘ÎB9߇z’?.ÕÏuŸFºŽ}«Çl¶>T“iþXlO!e X7#(NÜà6 *¶çX…t;¯iÖöóY¦¡ä 9æPf2€þ0ϵqÿø‡\¾¹ºŒŽÂÎá™cXÂyÊ2¹ôQÇN+dž ¸Ôõ«®'1Ù›ˆ—Pv¹TýÈ9` Œgh8ä;×pºÐîGˆíïl¬nµß ÙÙE¤E5ÔÊŸˆy{HbF[<׊ã_´írÇW¾Ò/-l“ÛÉ) 9p#-û±¸òJª…ϲ֗v’ÜZ#†'ùj€Œ¿GëZú7ïʳ¨òÛ&G=1ÔšµS‰dCû·Ø J†<–Ø÷#ùTË[»Y/–$ˆAì1’xøíÿšº”Û·ý9& x,Ø;OùÇ¿qŸš‰=Ôv‘EÈ'…÷@Òª€@ê9ç5 7T.ÝÛN[<ïùã¶jûF–ÞèɧɕäÁ‘XÐó×¥KÔ|1¨™¿èÌzŒX.XH¡°G AÎ8ãúV¡6ûV*ñK‰=i*çìkÌ’É5äWz°ªŒŒI ?Ó¿µMkûç¶613ý2NѨ¡<}êîÎA6›%¥Ã¼¥'r‰Œ˜Oáî8ãž>Õ6ÖÈDÐ$±$¯åðÌ£‡nä÷ÏïY^îî[i4‹¨®D;·c$‰<°YAnN8Á=}ûÔ-D¼»³¸–ÐF&TÎaÜÜ{{ ì^žÚ (¶fX#d3ž9$ŸošÙ¥W{‡”FÚ[F†(œzf-Ž£ŽÀ{þ/Ф›÷@í*UBªC)Ï9?cú×¶£t")ÖPÍsê ç³…è}ˆã~*·S¦°»êB#&c|%¾qš¸Ô.®í59X,VQÈ£.åãœ0ç'ì+^Â+ëE’(™-¥2Üyç#­–ÈqÆzâ¥Ç{aki¨iz¼ wd™žÉ‹`O dÆàö q÷ŠÐd±·Ò-fŸ!¡»EtÈÿ´ÄäߌŸÖ´ýCV–Vhä,£ 4‡¯âª Ô’â2ÎU?í©ÛöÏNùÅ}#³aAãïŠ÷¶=‡÷W;ÙÏûé^c6á¶Ÿ[ò8'8ÿ|V_.&oD˜m„e”òܹZô"bŒ¶òy’F¥¤ ¨{z‚ÌH%w–Î2FqŸé^Äg$2ó· çç¥|Œ×Ó¹¶ž:óóS c“È$q^‹cݵWxQœ‚=>Õgc©`CÌÝÛFÞp·šGdFTäžÝÀ¬pBVãkòØáJ‚{û¿n+ èž'L‘b6ûWéV[Y#bòÁ É#âº|š½¶³ ­í‹ÂðǾÖán£`cq‡ ŽÇõ¬Û« t>TmpçͰ%¢Ã`Œ÷ô>õ®KomAC <—ò™# ­ÏC…n9ž„Q5K {ètk¥…ç¹·ÔBLŠïÀCßpÄcíWÂâå©Y!±´ÓwJ¢4-°aÇÿ0^O`yïTÚ$³]ÛÍnþAÓ¤ºKÄR„d/£ÌqŒ†ööâ·»ûˆYŒ)$‹,^ZIqÞ\q“Щ—¿½WÇg8·š5fò‘ÉXÔ…eÚxpGNq“Ö±Û\EÃ<IU¼Ádà¹Ç¶sðµf¶’;õ"Ig2K„“>RŒŒàp§íÔb«Ž“k_©_ú›;·žÞV#dýºT«Í>+Ë“4оrØÊªbꈇw$·¿Ö’ßPdC<äÉ(U q“ýûÕæ·7ø¾€òÃÏq¦í¾ƒÌA‡xÈ`‡±È`ðjeÖ³u¤K ÞJ^:w\BÊsfän9Ïâ$`õÅXÞ÷n‘ rŽî5Þ2¡Á=þsñý*Ën’P_>§”1(:gý;b« l4D^9ƒ~é¤ÿ)ld×;HãØÖÓooõ(—+4 qƒ×\2àþüã?ø©(Î’˜¤ue>½!PÃ$8Ï¿ÎkåäVéå†VhåÏ—Ôùg®F9þœñP–f‚0Úù'È•‡9'ƒß±Õt²Üý}¥Ò¤8¸ò2D„t`G#¨ÏJƒ£_E=âéßHl®~bmTŒdméÚ¶-¾leÚi#^= _<õïÁ÷Í`’Ò)ÈóbÞ® þñPäÒ"h˜Á+¤Áò°qß©Çɨ-o¬Ú·în<Í‹¬99íY¿õ†±dO¸’vˆ§˜¨²6Õ© yÏnÕ³i'ÐZßéµ%½ówKÈæW û2¿Q‘×p?5.éìçU’Æö ¸Û©”e眫ÏØµ~(¶×/£‰.ÙYTDªý®:ã½wí*k=?F¶{X3+Z+]O7;ÜŒ±'¹ÎxÎïµ[¦ÔR+2¿Q+’ñÄ£p8çŒþf¶=+Ú–£x²71\‰MêäA‡'ŒõàîEu›O Æ!”^ÜÉu?1Ai ­.GLŽzNz}«jÒ´£$QG¦­µ¬JJ3ºn.{‘þon½qRî4«. „‡•¤Ì_yïÚ£>¡¦éˆ-Ú_>ù¥aº¾cÔqØmgÇ¿Æ5]7OÕ×S»Õ¤S,Ép¡¢dò6ìç9àzÙéóÃ2CbðClV¦rfÜÃ*¬{çô®¹wsº­Àqña­#oÿÉ^2Ã{ý¿:çÚ®µ§¨¥œò–XH¸œïÇ–«Ï8?=:óVNŽ¥Ð°@tÿ ì Lúµ†RC òz2Íø@è{óZŒü°rrzüœgÛæ·Oê)a¤“毜ÎÞng#¯§Ûø¯ÉZµÎ­âFúf‘ÛÎÝ_ø}*ª1ìv­€C“\†…Œ°€ÖèAÀR:ç°Îsß?–u›ÿ_EhlvT’@R(ò¢gÔsÜþDûsZíŒBæVwvbÓäŽ@íýûV٪ͽ”B|«yÊ" £,;GÏO·ØU–•Ф×w#l×@ÈêW!!³ÇåŽ;Vï£Ú;¶û‚±®FÈ€#ƒÜÿâ¶[y#†BÈ ,$’ïöûW>ý¡ëq&š±<³\I´ï'*œã9]Œ1žbØ?ˊѵ-Næê;k)ÉG„u$äwɪ9&óq’Áœ9<Ö{s`ì_ruç‚sÆG÷Ò²¼‰ÊÁ\ŸVÒ~ÿ=©ż£ÊlŽÝqž~kãÆ¾fb>“ŒçŸÏúV!<ñ•Hàw÷©+p©èÁb@RÇ÷Ò±›€„–R3Ï?ŸëR­o­’]óÚÅp½ J zvÁÿšøÏi6q¤òxÀ’>q™Òn,´Ûä¶ò¦’;¶0‰Óahá¡ç¦FÜ[#ÞI/Õ\Â$·¶À´W1rvsÈÉÚ¹ã¡ù¯mÍÌ—±Km4é¡2yL¼¤Ûˆd-ר#tÍI[[cªI"ÈV½±`<µaŽ=óÏ>õSigýÔ…{ÆXí¦1¶YÁ8÷Ã~ßUø‚æñša€#Gtëõfp£ðs×Þ­íb»‘tÕ¸‘}hdByQ· p~ÿö{Ö¡s¤ÜY\N Çž°\0SøLªy·5°xfssõÖ’æ#"ªª—ÉN¸oÔVÛ§Zë3iweŸÏÃ÷‰Ôä?–?:Ás-¢][Üœ€a[`ÀŸVÑœ;óÓ­@ ŸðTºl"æýw^ÝbB§«ç±=@Àç½v&$±ÓãFÅå1™W·sýzÕ¬x«RmAæt²³“ʳŠ%ÇžAæc‘œ}ë¤Û[à !aV%ØHr+øÇÅ‘ØÍ𮡭O ‚ÚÒXÇßÌ!Gáÿ:k¥ê:>”dÔ Í$ó´ò^Ü>IwÆ¿1\{Ç…ãÚŦDŒgº‘có”óØÉOßþdø{V±Ó4õ»{ ÖÈ0<920àÄ㿊«íuM[ÄòÜÝÜLÖ¶±ÎÐÚÃ@Î?–88ãó«­;N³³†ýHÞb›W¹˜îl6 §Ž¹í[D2(V1•Ê"9ÉpŠ´ï_J-î¥ÓäŽÞxa.­8l3ÿ ç $ÿf²øoB:•©j?õú¥þ^Y¥P|®8ìúVé­m§Åsw8Š 6Ág‘ºSí·¿<õþUÏ®µ›Nò{½Xc§>£óŽy®_âAuu«,@©D –Ý»¶°#ŠØô¥†Ô,Y¶‘ù­!ãxÉ={sŸÖ¹ßˆµÙnu]FBªVXŬJœ°=¾ýëSìfgü*AÎÁ_©|+¤}‹b“ Wka4±³] ätÀ5kmMqÇxÉ÷M1$;ö?횺ŽÑä\Ní±0Lj¼qÁ>ÿ•EÔâ‘Ô˜ßË…Pï=7w$cšåº†§ç‹«]6Y 6ד! ;ê_¾Hç§_j¼Ó`Y’Ü’…¢„U9;±Éþµ»¬²Ø[ÙDU£†I™‚“´sÁî2jý6^ÞÛÁŒ"·…æüM• ×ãqüª›ÅV1Eh÷[<[sî\ôþ~•öÂ{˜R?KÉ‘*© •Œœã‚8Èï_]ÔL× M l>™8;q÷Àù®Aâ]n[˹¬`–bó’—NŒyQŸGnJ‘©j³i>šæÖhÒå•m,ÜN[ŽžàqZ—‡<"×.ou'iã÷‰$™Kw=É=q_¦<áû-Ëéà‹bÍëº`y.Øãðë[Ôv@A‹bżÒÇ+Å•‰'aàgœž j^%ÓlïmÞ]#X¸Ó¥Cå¬S3L³õÈÈ(HèrG'#­PêOŠü*ÐjZN¡kªDÑ„–×`Ýœã'# È<û åßEâmIæ··ƒS¾¹vk©ôß*B@|‘)SÇ'ãõ®“¢EûH²ÜéZƒi––Ëgsg/–vÂ8GĪŒã¨Þ&ý¢éÙKiáå&iâúo9‘£˜üM´ã“Ó ƒæ©| všþ»–§h—RMÔEfŒ\H¹,ìêA'$“íìwËÏøsE½¶cg 0j0³Ý©vu)€/“êVÇ$þõ®Qâ?øvûSÕÃÍ c…eÚ–ó!õHbû†0¹9$œV«§è³xo]TÄBÕ&¹³¿S-”Œ¶;ät^‡žõ}àŸ Zi°~ïÎY"€>›hÎQ¦wrÀõPH$wçœUωµ­2æÎGÐo®SλdŽà¢ààc̹ k“ëútZ~“ôr¬·ê—Êíw ÉFPIã¾Ië\âþÒÇOHQ¯!cñOÎj `yÜG,{ÿ­E¹ˆ¿—$LÊê=@±ŸÞ½Ûä# K’pIbÏqSm.-’EÎÖ?‹ÿéYe<ÐÐ)‰SמÁ¬‰b4e$ „ÈÆœÕ„sk«f÷‘\Î]RKg·˜®6¦§ |U^•tå-£vóefØD˜>R ¶=ú÷ûU'Š/ÄÏ•rénK'”üý ø®X²Écv×+tÒÊ¢àœœsɵ»ÉdžêIä%¤|1aïQB08p ÷ao,V4vhåln9ôØ|ñY ‚6$JΡ$!qü#¹ç¿û׋‹h BÈÁ‘r}G¯ûTq0PãŒ#õýJ——RJ3!b7{uöþµð HÉH2IÚIàŠÄþœ,ƒiÇ<“×°æ°ì,¥—ÒËž3÷9çûë^£‚BÔ»‹ŸHçœu©¨®À ¡f¹Un¿9÷ý~ÕŽ1ÉDË ²¹$ ’ =ºRV1>^ÓÔ I ‘´¦m„ *4'÷Ÿþü|ÖVÀ7­VEܬA×Ü{÷Vx5À¥ÂùÑu*ÝTÿ¥KHa˜†·2Gž¨é1ìGçÇz¼M\Í óÌ“½˜é¸z”gƒóùT©5m:k-àJ—>TC$(éêÁÈÇnµ_`"K»I…Ç“r£¶@>bƒÎ;ûλƒ­Ã%ÄÐ»ÇÆeÅ©aæ)è$àôãúÕµùsi#"ÃvV4¸-±À cœwè+P¾:•ž£¦Y¼bÖêÆõḞº FÜüœ~/г†&ÕuiÚi7Jfk)¸€r¬1ø½8Á÷|ÕäK¦È/`’Y-n¡ÈÀ`£äŸlŸ~j²î%ž‹©ç/åÍ ñØR\lçž¡[ÿÝ{¥Í¶ ï"BmX§™»ÂçÌV—⛵µÔíËù­iub“;£rH,¡¾zcòüëÖ¨ØF‘=«K!qå·N™ç¿Zè«{ ÜÀÍ7¨æHQ—##ôªí]ŒWPDƒ0ϺY㨀r0JŒõþUKèÑŒ8,¡¿z \g®Aç=1ùÛYÜ[Ék"Kn&ÞDóJÏøˆÎÏù¨¶“mºžHT$C˜ÁR@ž?JUG<…äÂ[òNíåzíÇCÏO×Ê»#)`ÙuádOÇíלsßÞ³I ]èŒZP»K$ˆz|å_mæÁgt•˜¹’ó¼¾øÿŠÌî­ûØÊm‚Bã# 8ý+0¹fˆÃ f6ÿÛÁB:ž?¼äÈ¢9•œ¦ANÜmæ½ÎX8¸cå´Ê Àe??èk‹ÂÖ±˜ ò¼¥%·.¹äAíÓïÒ \ÅŒ±Èñ•‡ŽH²¥ðÛžyüû×±À*|ð1"‰[bC‡|sÏp9á'YdX¥UãôÈÏNäwëù×ç_IJk3»É$RDŒ|˜Áà cyýNuoÙç‡íãH5 ȃyŠïŒ¿€ç{öÖ-ÊÝ\tU‰H†&/î}³Éö5çV·kÅH‰+f„“ ?ýÉ褎¥AÏQ‚q×w¢YǦÚCn‰/#ìæL“ÇÆ3úTëßú{J½žÛdw ‰OÈÆ@÷­ög óË{¨ÞÂòÞ\Ìê]FwO'8àv®¹yi%ô%hå`Ôlœœþb¸?íÚòÎÝciíìGÖG·Ë…ËLø<† …çˬ5F+¸bÕšk:'Øä îQÀÆzp:{Wn±¶Ðî­­VÂ&¼Yã2JT€mØg€x9þXÍ}‹Bš / iï /ë³EÉŒž‡9À=>ÿʼê:Нn‹¥œ8ùpD—»×=Nç¸÷­2 øŽÅÒç]²Ùnf"•‰Áô’Ã9>ݪL³ÎîJ±“Ê\råB¿ú Ñ.n'‰dÖu êÅ®Mµ‹–‘³É¶0@ç·Zƒ®_Ì–ÞÌÎon0±`€QO^G^ãµj ; ¬„ßCº_sŸ¿oÊ· æMA¢™Œq®ùœ4ö<õÇ?Zª½‹WšiVéKK[§ÅVc‘Üm<{sX.lo/Ú±¶‰XáVRÏ=AïSm´d±• ÄðÛÏyéXOD`ŒçòÁë[+Þ&—%½ü¤Ѳ&õ;¸Ü;wÿŠÙN±d鿣#€™þé÷üEw%•̪†ÚÞ2 Sæc°ûãù×4·2¸}Br|ùËI¸ŽK7_¶úTÛ«¹náú["â7ÀÀîéŒöK¨øhÛZÇ<§Ìf´@þ#×ì?Ö±øoKŠæöÒ&‚WŽK±›8'¦Oóü«»ÛÛ].`Šèùh˜•9E¿l}ñ[-¼vןJà> êÄ`篿éS×r(,ùð.ü ŸzÕ¼O©{GŽÚ`—s"¤åwc/p2N+Dð¶— ·¸·$Éå^º3IÔ‚ôǾk¥XhÑE&V0â>áßûÍ]\B.lÚÙA7¡Õ˜æ#œƒîyô¬²i²<¦â@²6;gùb°ø²æÝ †Iœº[Á5âۅɺ—aTìI8=N;Š¡Ñõ¨/ldÉ%´1Ä»ä¹Pãëßœõö­kÄ&F ³ÝXÁ <ž©ºrqÛ5¡[Ü[é©$÷Yyg$ÄùëœóÖ Y–ñ©oŽbÓ­ÜL°n>“ݾIä|WðÝœWS‹ƒ [9|›dÇñuÎ:à týk£ÜÝ[ØEæO+(' ŽãßÚµUÕmõ;Ë6XžkVi&•™¶‡`¤*c§’O<[:Ù[Ü(¹ßn¬bD±ƒÄ§¦ÇJ4 7Óo_§6Ïfñù|Ë’ œŽ æ¬t«xî.,µ$Чk&µ½çkt?©<|Ôé$»ŽàH÷^]¨•öœŒÐsŸÏÞ¿5þ×<3sa{ˆ­l„:n «orÈW‹»×ÓzleIö¨²O­ÄjQ[M%•£lº™‹p dûüu÷¯Ð~>Ô$mgµó&¾`GeÖVGq‚A>ø"¹Õ¾Ÿ&œ–¶¿»‚é¢kë· JëÁbsÀ=psÇÚª®LµÌZg˜RÖ;¤ší² (Îç´ý‡9ÍZjþ!Š{qk4Ÿþ¡Óó,Ì<üìqn¹ù­+Ã×PkwÎÈmí"Û­°öÔî'ßíZíÄ~mü:]„Šé¦¨ydP=2¸Üà ãÜûb¹Œ’µÌžeÎLûŽ÷nþÃô=*dc*I$€¾–Å}‘‰Ãg>ÿë^¤Hrw ã’sÔwæ£[³Ç0  •>ýºæ¬FÍc„,YÈϧ½<ù§[î’(ø€1ÉÇ_˓ҤÁ*ª¶ßHôH¬âæ_)°Q˜)Xý\‘óÿ5‚¤c*È™8AÆFsμEq"e^÷Éçóöýjk,r²J@ /~>Ýj8™—',уèsŸéS!œH¦Fr/¥”ĵaom9@ê…‚²ÉŸNz`õ|Ö+«ÞË,Žß¼t%ƒ/8ìxäb¡G-ÅœªÑ—keŠûŽõ½iSÁ¨Au%Ô’Ëu Kiäæ'PÁžØÓ¥£42ÈÂ@Léå<’®0˜xÙ(‘˜í/º<óŒÕõ³êæÏNó£K…&+sq&¯dùçæ©¯të»;‰-¦áž#µ¢`A ût5.ÖðÃÂé.Ò%XäcÜñšƒ4d`[ÊG˜¥Êºm<žŸßÅI²•â‹Ëby»ÃíÉ‹“ùà~•{e5‹šæ6uŒ²*”` ž˜ÁüñŽõ>ÃY´ÒÞ9m6–KžeÛç Ç|ð9øà·×õ»™`ÑÉ»±º¶™¦‘¦\y¸l‰qúc=ê]þµ$—ÖWlWkD{ã½¥kÇ#q9nxûöãµl½º¾»—V-ãYížÚßÉbvG»r‚½'ùÖÙqr“é’„TW·`°ï<;8 vÉç5ÏuÝFâÎ;á(bÕ Ø¡ä®À vçõ¬VwóÙZ™Í±–Ýß/ 6)È'#§üÖ¿âwo$p\0dŠ×ÍÓ$-»Î·s’™ÿãÉûÍIð•·™äÜ#ú´•XóÐôíÿ5Ö.•®-¦ÿ •c½æZÎȃœô¸þuP¹¹Õ­¬ü´€òE¨¼±mòdUÊ·È=;ðGÚª­îašdŽt+Fú˜Ýr0¤öíƒúÕëIçYˆl™-쪲ðPIX$dßùf¬nU¡·ØJêÑÆvIˆÈÏ#Ú¾ÈÉ!Yጳ̈d µpIlþ_ʱÈÛH–Fdueˆë»ç߯³À© —`Û S‚HàòÇ=@ÙÉ „rPFóŽ2}êÑ‹pÆB¬Ò™Td“ßï×ûéDw èfEó €Ä=^+Üž¶ …È üW>ñ™u©iöú„’MfæTÀ­Ž9î{|gæ·½Él¡eE1C̈ǂAóÚ¤Ýjöö“Gj_ÊiÁh21¼ŽqŸ‘ï_›Õ¹-׊­obžÝœ°Û2ZG.P„ÁÞ߭nú.·>­lo$Ö×^žìÚǧÆUF21’þ˜–$Kt¶x™Œë9BŽ[p=<×0¹ý™éš­µºØêwv‘[®í<².Øøã*0HÇ}À×ñ€|[‰n´ÛX/¯Þ%ÃxÐ6ÉÈPð‚@ÎÞß©®_>—¨ÇtðËm$óhåá¶yÆ nš.™â+ÅÉÓ®ím°!Y®m]C†þOõø®³£xwVÔgŠÖ×I¾»šNCfîJ1£ÀÉž:{×L±ýøÊHößD†7ºº6¢Ök¨¡“*vïerƒ´à’2Û;n±ÿÓˆN±¸:·†'7»¹ŠK¹"[p¸`ÁÊæAŒtû޵öÿý1ø·T²Ôo&¸ÐÑmá3XÂe™Ž¦¸ÈØ6 ¡ˆÂ³¸öÇ5Ï/a¿µk+&šïÁ·Öö€2*ÚËk;À9%awa€ #¦k’ëš_‰­í¬-otf .IýFãLž»#¦”0:Œç¯5®Ássq)³³PòÅ–…UÞËþµ¿xsÁž"½´µ·³Ðu[û«–34VzdÒ‘œÂ)=¿#š¹’ÆapÖ’ÙH.¢•­ZÞXÈhØpWiäñŽjêÞýƒxÐÛ¦§§øz+)¯wMm§êWÐÛKp£ƒ ŠCÿ-§Ø`æ¦Iûý©EpaƒÃ“¼·„<ê/­ œѤmàœàÕý”øãHe¶»ðþ¢ÒMß"¾ÜÛ[[ìÌEn% Z¬+‚ŠorG!p@íÔ|U¯“»Çq#mÂÊâ!€™ë“ìEdžÓL’9^¡-"„[äà¾Iã¥zÒR;D’qïŽö1ɸàg-ðO¸â­î'Ô<›7˜‹,E2$~Ož*·XÿÔtù-.mmåŒYKÏ4`”†]Ê{úSiz›¡xy¾–fµ†ÉZõ  Oµrsúgï\ÖßZÔ¼E¯YÜ!‘4Ë[o>;R„“êÁÆ ÀÉü»VÃ}"Ü;^;Y‹†ØØ£_aß÷­*ìʬÏ9 Çüh{È}¿JÓ|E¨K©ß¦‘j6YÀV9 ’|Öù>Ã8Ç=ëeÑbM&2@w2NsÜä |äà\kÄ–Éoâ-SÈ™®c[Æ’IòŽÞ¦CîU‰ø÷ª†¹F(XŒd68í^­îâ-äþŒôÇkÜŒþdªÄn'n‚ ëöý*,Èe²«8ØqñU÷s^¡ETýʶæF<ÌWÖ’W*aÝ †$ ü¡ëµHVl’ÌÙ'Ô=ÏZö í¶N?ˆð8çï_C…;NKà’N?/~õž9^0 r¶HpIÿ›ëN6¨  àœÇ÷Ú®ôéôä‹P:”ZƒJú{&‘%…ÚD-nò Ë"²·˜˜Ü §‘ê¨SFÒ1;½Áæ½+˜w¥rCf9ãóÇQRžòK” ;³”}lI×ÛùT&uˆgás’qùñYxn"WŒª²¸$úºAþ£½x1ÈÛ¦cV}¥²:{uýjZHˆ1†e 0#þOÍzF’ Æ"¸GR©•í‘Ûòï[î¯y§ëÚº@RÊ÷G²ÁŽy}J€ž/Ÿjûccþ§Å~£nð\$„‰"maÿKò#5—K×4½2ȤW[›z ÷YëÁ2Gc²ÛëZuż1EtÒ¥Úy’•pJ8'÷gž¸ÁîÞ©A"A ÄBK*¤ ‚C¨<ƒÓнñމes¡­ÕŒrÅsbªcóå€È#ÕÉ鎞øª-ÓR²1À°—†LI!ÆÙ0„õ“ö­žÎø[-ä ò£¢Ç9ŒŒ¼c¾y­¾ÄÁ«hÒG y¢ŽXäw9 ´„œœõ0G8­2÷ËŠ-¦Û$wgu¾Ïû “Ñ¿ü†z÷üêæÂ]¬‹$‹#?®-­øqO‰í÷¬°7—.Ùc šDh‚…ƒŸIÇSÓžz{UÕ¼ ÕáxÕ÷E'<¯O·Jòª,ä[‹eÃÈ|Â6V@xhÇ\dg·||Ô®¤vŠ)^XüÉî²aqž;`õ#Ü{ñV–á|ó<¶Ôî§@1úÖ ƒº2G‘€Ê@p9àŸš÷nɈ£ÝÍ· ŸP?ŸåóXâI–WQ8sœD …Ü9<ô`*ÅmÆÕòØÜr ãc q–èzŸõ5­¿|· TÅ‚«~<ù{:f±ìtòÝfu”¹f%Øì#€Ó­U[¼ò Ër4IŽ K’#†¨99öãyVÂDŠ¥»ÅI$F˜qÎçZ¯…´>ÂÎÝ-ÄK?’iЂÌç®Iùé[ݽìv*ðªL±*®|Âz9íÚ¬,â–Þ»aŒ»¹'–“s9ÎGSÓíV&Þ=ÞtxócCæ³=#ØãÚ©¡–4s”‘Q²‡ Üÿæ½Zéòß]›„1¢CÅ)"ž}¸ÏûVÕo4v¡m]¬‰C'ýŸcŸnxÕÆü{«\\ÝC£éÿˆêo1&Ê –µP Þ[€£ä‘ðx­P~Í5[’¿âFKWb%–+y|ͤóŒüqü¾õϼCáÍGÂÂ9n#_£•¶Å åŽqœw¬ºú}žۻ»›kÈäÛ D€†SØûsÎ~q]ææ×Ã?ú:sÅŵãÛyßyÄ;ËŽÙ÷ ä9®Má‹ø„7ºlÍs4ëvg}É*z ÜäûüWR†ÕîIo£¼mFxVŠn®å¸ ‘…S€{~õao¦Ý Ë]?Y2ÿ‡¯ýBˆnË 8WŒäë[´Ú•»É3\ù¬»¤íŽ2>üãó­ƺý³iqI£j>n¬“ùZIµewœÈ62ìçñ)98ãj«ö]û8¼Ó﮵oÛÚ™'·"ÚÏ]ŒÄdœäÎFGzéÞ$ð´)h.´Í=M=<ÿ¤ßŸ®=°9 zòN•KÕ/4s}nmûR³Ž ìî”H°!Ų>sœ®âF+ì8îzöªhÊÖ²êèw ÕÞ»{ G·l<•ELz°ì#SŒÐäüñýìš%Ö…¡Fg×ô{(Î¥,®_éá «FØ\ŒnÆIàsV¶-­¶•*x§Ä"ÞÆæùåŒjšt¿U«À¹þ™°`ð8Æ%GC\š®¥câÁâ>½â3Q3'„tè­ÕQ¼Ùå²¾p*³ú†œ w'ñ=Γ¥IŽît»™QN™é¦÷Èó3¶2cB U'v8=3¦xcQðŸ…ÓR² KoyÈ¿Cò9«‰jÿý>ø*Xn!ÐMæ‹yq'Ô[t&K}½FÇË2’@üDŒŽEpßþɼuá½9/<›Mj(æq"èiq;EPÂVMƒ ÔÎ>Ü×Xî-÷FQ7Mp×2³Föã:¯OÈu¯°ÝÝii4¸b¸´E°ëÁùÅrø†ÚKF·FÁŽÔÜK*0ÍÓ£õn~+Ú_µÔÒM#ÊO“=8üdž¼žjÊÒTˆ<7ÒÜ2y†vêR~Ú÷amþ#ukn|ÆV¹Eô‘’ORG~+ôV‹âmf—G·|}db‘ú_a Ä7~sÉëÖ³Os5åÔ³E:Û[iÈZô(Þά¤ù+ÙX¤žvçÍZørúÞMÂh–T%VSn£qL’Kd“œçïV³ªêz”rÖ+sÚdgQ–7¶ý¼wüªðÛ™ x®m„³y‹°œÈ½ûp?Û¥WI¥K+Å W‚1;Ç“ R3œvÇn+5½Œ¶“Í H'c q,˜]¼uÿŠûsg+[¼³Ïå,Gyo4¨Ø9# Œg­iI¬ZêrÀ¶sÿú¾9<°2öñpO·ÜT/ëQ1K 6éš!7Ê­…™›W±=úþU©ØÌtó$VªLæÆ+<¶A@9${ŽOó©·×¯;ZÙ  CnfœýÜçþ]>Pk:¨°²žÂ ¶ÝÝÆÑ©ÛŸ¦VK~™¸<Ö·¦’Ó*yh¸‰Q˜¶ ÛÇóëù×Ý{\k'Ò³‰aÔœzr8ëí\’áÑîår«pìÆG'÷ížzwæ±[§œÛ…^¤œóý榴pî„É’8ßSZÉ©ŒsžzžO÷Ò½Æ|Ül‚yã§oΤC¼ï¶ x¬ËÌdº7'ÒE}†&¸”*°`FrpûûsŠ˜Ð… ¸‘X㣎3ÛóªùRtewBˆó3")Î>?¼ö©ñÚE'¨0Õw0!‡=nÿŸÚ£,6p²·˜¯»kddŸìÕ‚D²DÆyIP3´‚͘Š#ª£Ó'L—êGcíÏÚ°%ÛsÆáèã‚<ÿ,Öd´(ÒIëvö%±·¯¹¯rCæGõîÅÈ@­&à¾Ä`Ž?¾kb²»Yc’Æf’T— ŸNz62>>=ë=­ÌVwi ¡Ù’e1zÏ©zãŒw&­¼I¬Í¨5¿‘¥ÙAnc·m>Ùݱ’[¢xïžGnkQ¾º“Ty…CA‹×ÆqœŒûöþU_%´±RH=%ãføäuþóXîmàŽHï±ÿ÷߯޼@Êû‡'ryç°Çö*ºv "Ä7 n\dõ?nkÁ1}ÈþU:%tÞJœ)ŸLWÉ^G'IãqÏÒ¤YÇo,2³¼ŸR’/’x#<äýºc¾+슡݋c£Ž¤ÿʽÆWeÀ;½CçÖ±ÝÛ¦L‘·¡¹QÀ¨JÊã$†Æz”‹#ùÌAR¹Øà UžÝ.l`½7"I”£Ã.F~ÿ¡ª‰‘ƒU!Píb[ûó^–" 9‚03ƒïýûsSP±´c÷‡äƒýé$Í*.å`PNA#ãù Ä·+»Ò^ÿëê†CcxÆGÎ>õši’O5æQ´"ªC`À$Çl“úÕÆ”4»ëqbñ-ŒÉÈ·Í–7 ÙN{{fªn’æÕÓk¤ €±#äŽ;éR¬V}NæÛM|Éïnâ·‚7!Av;AÉàry5Ðï¿fþ"´Š#l-µˆÏ˜“-¤o ‘&fQÈÁèO|W;”Ê®ùÝû¶*XŒ`ƒŒóö«;mfês­ÕÉ0ùÁÙ™¿‡¸ýR}=À™Ók³9*Š©øŽ{ʬ,g–Ы"2ùm„?ˆNpF+eMZêìâᄉÑ7g÷øãû5i}qôöñF²N'ˆƒ‚ÜW‘Ð2÷ëWPê—‰hOýCZÛ~ ¥ H3ÈaíÛ·•L¿Ô¶Ú¨K¨m¯£³hvÅÖ×$§¼c¡5ŸÃ6—úZj\ΓI%ÊE Êz`uý iZ¥ÕïÖyºŒOo$²2Iç×´íÜ=øþzÕÖ‘¨FB-ËKµX —‚7þÝkk’?¨–Y´Q6_y˜s¸œññR§`Z)âxäã÷œ‘åäsƒùô¯ŠÉožeUk…u–%`Tr ‘î8ü¹«#†Km²I¹¡R&•P£»vï×íUá§ŽæÑÖL†Ü³3úyêp2+$¦9I`|»ŽU„Ž1"ãŽ9Æzò‰,I Øsåyæؘ `™‘¬‰*—ÈÁ]•23ßàû|U¢Í«à•aëݼò}`Eúo91xüŽv'=~pk#)p$D1ÿØIT€2÷çßúUE¡–ÎÊQft¥Þ3lÌGîóÇž¿nµöæüÇ Ï)aPd(ž­€òOè:æºýÊyžHÉbf gœdç¥vT[‚ Êì¬O¸`ÏŽõ´I O$Œafäô^2ßõÇçT߻ԅÆßÿ¸¤ó÷üýªLÚ^µÙ¶vCä—Ëž{ðJõm®èz~Ÿ+;Çjëå´„Îpz÷8ù®?¡ë> Ö|U%Œ7FÖÒúgY.¤Ìòbb¡O°;ñï]‡JÒ4}¦xÕÞîåØOwtUžëð3ÇaÀ«Û§H¢3°1"‚丼ãúþµùãöâ«=VÈé¶F;›•›s(AˆvôûçøþU­øG¶»Ž_­µk‡»Ýó#ÀR:Éù¿ë_ Á}Õà‘Ùøy§Ù‘ðq‚N< }«ò~¶“xgÄ—vV¢y ²»Ýo<¹V• ÈÎ9Èøø®ËáKêbMbáÌr5‰[‡š@J§#ÙÈ?‹ó­•¯÷V“_k)+s–eÉ zw=3zŸyma{ׂêKx –’T“ÊÁ#vpO#ò÷«=ØÉqk«YéÊ’×éc (‡‡ÄIÇSüúÕµÏí"&ytÛ‹;Ë+ëFhšÕ\…ÆG9<ž¸ç¯Zµÿšö{IeÖZîmÓX*l 0³éùŸŽõx Ôp®¡5ͳ8·6ù[R[*wž”䞿Լ}ªêwÚLw­¥Do`Ó¬§Ú·÷ ãc–lˆ’5bÙôÛ{à×V×®!O¦i>—lu»8ïÛwu; •ÝD¤¶ðŒ3¸³ƒÓš¡Õ4#O±ÖuY¼@ö–æGÓ¡½2«Æd|3À´€o8<ƒ×£JÑ!–ÃJZ؇QÒ [•Žá#c¤ ‘ð£/–ázàäóZfŸám'ÂÚÆ·­øÌÅâ½BüµÆ› –ñÊlíK’3˜L2Œ(célÔ.¼M©kw:õÿ…¬´­Ã:sð^Ò}v`Æ¿¹¶*®H,«’Mnzž§§ø{Áú^½i=ÍÖ¯{§Ûê—ÊæEÛ"xöŸÂ2Ü“é$+@Šö[«[Û¸%{ï髪^^ý5ìÁˆf #¾G@H`äâºÄ-}ªë–Ñê7âûM›GmYŸL°gpTª¤(Ë•U;Ÿpç@8'"Ç\Ô5½ZÝ´o iú†Ÿå°Ý_%!•NîY†)S <÷$ »ð”>3†­¼Kum'“çaЬ’J‚_ÝqÁfLç€NFäñr—/+¢Å …ȱvÈîrªÏ~:šðÑÈ/ u …£ú€:aŠžY»g§\ö¬Wiz ‘Nð´Ñ¤oq Æ wmSŸN쌟oȉ«*8[‚Ì‹Fâ ¯^†¿?ø¾ãÁÑkž—¯xcJ—N¸gBÓÏÔXÎN 1’'Ž2?‹·)ñ/ìA5«+Kö{¬Ûjowj$Ò´û«¸ÌŠ….ùØ HåN:•øÇ^ ñƒµ)ôOéwvÖ³:DÒÇ•»ÛÕ’A”t—#±ÇJÓm-JÂÌA.ì Üç9žážiCz≆џOêïѼ©tÒðA¸P[o¡³÷Îjã]ñ Vò½®™÷…»¸‹‚[¸ÏÇ~½j×Ã,’ÖÚöÎ{„1°ËHç'“€{Ÿ~k«Ãâ=+èÖk2Û€ Ä_~Ý~*×Ã’ NÜys(I&2]M`È œ.AîqÔtãäXê7Ö¯p,¦Ö÷²]Enг¸#sã#ù­ÎÞ[{WÚK½Ã€}`ƒ¦Æ}ºšÍôP˜£ürùY+-Ã嘓““úñü¸®ûBñ^Ñæ³Þ_"Þ$®1‚ÜtÀ=3É® á»éát…VQÁb\?¿>:có­Ši \€àá™TÈêúýñ_ú {ƒpÒK!12yj å€È9÷<ŒtçÞ‰ª¢Æ÷ÒåJ.;ÀÙÉù­âá¯u+»Â²ysJ¨ƒo1Æ>*ÆîtÓ’WÀôûÝÁÛ°Û>ØûóÅiw©wõ%bÀšE £$½ò{óŸÎ½Ib°ÚÁc,rË™Œª›ÀÚJƒ“Ž> F{[WXý2½ç‚Gj–mâ‘£*Tàÿ ¬ €eJú‰H<Ž?ÈÔ‹t*Hq´ïÂí_Àyþø¬óB“m“€ÀÉ~+ $šHˆÚ1—Áü*{üðkû,ÈX%,²~ë0pr9³þµb.g 6æê±±ÈÀ¿Rjp[k…ò›z‹Ìr­Ï<õàt¬3Û,M Âp’ À-Ô ø$ŒãçÚ«ç&)e À7|=ÿ­f¼°½[Ôpzò?Ôgò¬wN…UZßzwçñóŸï53”‚ äl•ö5yÊÑÆ ]üüX=Oµaå‰H€Š?üUSHbb#V[ŒŽOåSbÔ’I ®w¦xøÇë÷¯BîY2C9h¸è=|çïÛµY‹Æ‘q!ĬF1‘Óô÷Í|vëe,rZ¡ºó|Ñs%ÀíÛ±ÅU‡ˆmÊÞr”‚OòéV%»¤HѬʙ>jö=}ñö¯I?¡•¼\L­€£¶qÖ¨.­]%häR^‚¼ñ÷¼Ìî2|°>œ:+Èëêb…zätø¯žcÇr:îÇÍy $/éye=hÒ¹`ãÎt=*BJ0l‡Û´Üô¬æ&Á¸²ã+¸gàÕ婱wi¥µ •@Íé'¡a´ uÎ;W½Fê¤jˆ@Cþ>•MtÏʱ¹@`OŸŽõæÉ ãz¶J?ÿÎ9¬o .[ñep1ùþµž9T©£<Ô|×µmŠ6¡-œGþ+èZBÄHÎÞ8>ô{rªHz¿ÊpkÈ$.Þ¤ržTŸé^·ÌHÌ…HÀPǧ<Õ•­ß“8–@J•`TÀð[ï[Ž–.¼ÅÓ¤µ¼–gTŽ'Œ‰#Ç9 ëŒq“ì3]Æú~•¤ézcxk[Õd½¡º²–Ø †"›³æû„ÈŒt8ç:«+´O,‘^µÓy·P¤% üž¿|T+û(CzP™G0¨àF#޽j¾ ‘Q˜©€Q)'Ë?íVv°[ÜYê2ÜÝ•¹ƒl–qÇ~©™ÔÏáUPXŸåPRêuÎérêAU á°qÎ~3VßVnBGpQ|²\z³‘Î.jUž¡{ ÒùS£Ã<o"?Oõ­¼G§ßéWbúC¨Ñ-½Â±<©ÆÎ>~ïjÇáèÑ£ŽxÅÍ›™í„­³ “ÑñqÓ€{ÕåíÚY´R³K!ŠãÌI%€“ß+‚©|gwkªÛAwK¶r乘n ¸{ Üñߊ֓P¶v±[v“q|ó€@‚sÜ3þžûªÍ=¡¶;üÐW̼œHÉñžGn§Š¸°¿Ã%ÄXŠRí"Z“ƒþ!ú*e´îÐ0‘՘ɆAŒŽ8#àæ gŠâ)™áXü™¼Žƒ=þ9Ï?42H=ø™p<ÕêIÈ}³ï59’393lŠ@?sÁøûÿ^ýjJÅÇŠðà À ÌCŒt5àU)Õ¥]¤:2ãÆ}ý«âÈrÍ !TíQ³>;ýºÏi:£28R†8ÿb²HŠÄ„* a¹¹ãŸøëZÕ©I'¿ KF×»’AR: ~|t¯wó-͸LË or»Þ¼ÿ,ö9§xr -á’àÇçJÁcó [Ÿõ­ßNgFúkiß9ð8›bOù«›‹Û›XåŽ+–+8ˬ‹ÌæsÐãš…¦Cq<˜n«nÆ?߯éñ[Tk˜ôËvûnq¸sÇÎx­{Å?Owé¶6y©ybWhSEB—ǹ'ô$Ž+SÑV*öìZÀÉy¥BòÏç¶‚1´u.Ocý*î cZ†Ôßÿƒ$ú¡ŸÉŠÞéÜ0S“¿oe$Vûkm&³¦m¹±ŠmRK@/ã»”,VLy8c8?Óó_œüE¡iúF«:[Û*AhÎ÷‹1«€Þz.NëÇSY<)¯Ý Ù7ÛAØá‘Ñvîõ±9$°=>8«x—XšÚÖÚ9RÎ|Øü‹V,ûŠôÈä€ í‘ï\¦ ûûk=BÊêÒ9Þù>¦º‹s[0*Û• àv÷­ûOñ6Ÿgáx´pž]Ô÷)-ÕÓÆ²!È@ääŒg§=ëÐ,®µÈRî6ÖðFÖñØÜ&âFKdcñŒõäóïƒ[ÒåÑ!º»Ön´½Ò 6Z:Là.z¿PIÏ¿§"º¯ƒµ-½W:î“Ö3¶üã’}³YDpÀ$MÅ$s–“‚ÛpoÖßK6?TÑLÎÄ„B|Áü#=†IÍmÞñªøj)l¦·3Œ·™æ†ÇžÞõ>ßNÔõJë\²¼•¾ŸmÔ22ç«r:ŒRyàñï]ºÁµK»iä¼¶v0¨ ÛX.â-ùþulÚ”–À¼Ík73)õãο:~Òn¥ñN¹j,A6ÐDaM¹îyƒøsÛíÓ5-,"Óì¬íJ©XbóLŒG©ÇÏßš«·¾[Ëù×b; Úò°ãàqÏLü~µúî%ó­âµhÙc¹‘È2x9s»ùüUMΦ$e´´SB¥ òÉóË7Ü•zsÔ×È¥{he,цlf9ý÷ŠÕu«™å’KeĹäç$°üºV;aÀþd,Y‰w.F'Ž>HŸÅgiç>LjQв.öü¾jž¦w@’lOø©qÜÆ‘¨‘ž0zb³¡i÷<ÉQ½Y±ßëùg­<–3øÿÁÇä?/j³k_>=û™€î[üª¹cºyB©Xä' [¡íϵ{Š$vc6ÞÚp¤ö>Üæ¾Í2áBE™]£ÖNN:óúTÛHÝÕ™ˆFPN ’3À'õãžœÔYbu™N©p6œt¸ÿzó=œ¨Ëµ|ÔxÄ¡ÕÁôž>ÜRDo)*eFÖÅ×ýj4“˜Yw–l`u#±¨,Ld2"“È=ûô©†îÖå䙡Úî†w``sñ^ÛéÜ€žR¸oZÎÐû‘߃U—ðMÐO«fyëýj½Iq+œ©æ¾íb¾Ã§^k4j!· òö¦æVÀÈ'Š3Æîôä{vüªPºòÕBŒ¸Îzžç5ådg ÿ‹ ü$çÿ¥Jv2"ƒ‰œ÷Ç#ûÿJÃ$aI• 0àzOõ¨îªpûŠ€y :n+4q¡f`ÎGaY$`ÛNwL>8¬ûv20gIcd6?>:T¡4Ò>çc#mçÒ=c Ïä:×™3nd€õ3^ ÊtB3Œçºs_#=Ã9ùÙñýk5³Î²ƒä”Û”ãäœôé[M·Šõ;`‰4©{lÛCÛ\‚éG«¿^„u5ƒR– û™&·" YöD0]¿d |ûÕ+Kæ’¼ÌW…`ÙÏåö©0ùW-°qÀ2ò ?=jçVЮt„‚Wº·‘.Wpoà‘œdŒg¦z×5@a˳º…xÆ<Ä$œ1Óûçæ¾)}ò)Ê–]„®?QÒ¥í–4[³°I5ñ5 !™•d— Ž0}øù«:H£cmšÕ£—ŸW¾}ýëh¹ŠYtM^óvÑß.}e$c6ÃnQÇ$°ã#jûƒÄlð[ÊKUóFáedƒî s6Y¢š[ISJYüÖÿ§jQÉlÚuÒ¡‚WÛæH2b õÙÏÛŠÙ$’Ò(mâ7ÈçÉ;X‚ƒ^;ŽÇoçUÿV’J°F.`k¨]`ºp ½±’jÉ£x’K{¸ìõKV 3˜¤g\_óñÖ¶¨ŒË8°.O¬°“$QßÈþµ:I¦ÄŒ™¹ DJÅN`•Œàsýã,7*eBŒ§ÍO._þÉã¿ïS˺Wó˜:FîPAäßôù¬N¨Oœ1 `§ÛúsÞ².Bº>¿ÂÊØçíÿ5~ž7Ø7xÈÈã×»°ùÏ÷š¯¶/ ÝÓ`l’E’@­’ý³žÄû|ûTØ‘ÖYå‡tñsr"#‚rzgƒŒb´ :Ýb¸ž7)°íõqÇU3úþu´é¯ ´bhB<ס˜ÄÌÓÄŸô5gVŒÊ] ’aHgÓnOÚ¢G©ê_->â–8ÐË f¶®ÎMl-âk{IÁÔç†ÏèCÞu8weÀÆ9ÉÜF>~j ^jÓ™®¦œ/ñsqª_E1c A‡­€ï¹'ÜgwOðÇÒ=´P­µýäRÞÛ†3ÎßÂw“ïžœ}ê&©qskmgk-²ÛýCGiux$\`€ È$ç#·5©ê7½Þ«u£é°ý>§¬w77>m茧®{ñÚ¸§Šõxfš0Ja»I{t9ó}—Y¥]Ánl¦µ/rïæ‹ûx6±E Œ÷ÇošéÚŒ5TßËæY‰ òl’éMªAÜ@•nýÿ•WxƒFµÓæÒ´kÈe»Ò,õ/«¸»¶ˆ´—#ióA<…8 2Hü9=«ŸxŠôëw†{;7·²°O¤´ò“+jHäŽç={溂¼_wog$Úeíì‹Ú--ÞB¬=‚@ûñ\Ÿ_ׯuýFK¹¥»I±‰"%ë´g¦+¥i׺—øT6v Ü[J±-ÅøV"%ýÑoáÇ\ ìÚ=œ?K Z:’§žæ2,˜8Ç'œœû{šúñ^Ú}}©–;¡¬í4éêq´mˆ°ÆÔ'$à÷­kÂwSD³Çt¨¦9MgnÕìŒrN?­u-.c¶´’æ6¶ÎnVvʰ;² ’Ã#'=sÇZìžñ-Ô,²'‡ÒâÎßDk™5û+Di #3BÌ«…8Ú718“Vú¾­ªÛø/^Ö${{{k¶&ÂÊÛÌxY6,®ääd“É'â¡hóêï µ§ÖiÖZ%ŒB;¹n5X’Q°l<ª ±'9Áè:ÁÓõxtSŦûÃúÔÓë:Æ£õòˆÙ!±\6âË"•mª\‚03ÍlÚL÷sj¾6Õµ?jW-–‡,þÚÑÍÞü´²"Á´F7§ Ù œçÅÖ³ Ãáí*ÎéçÑ|;}o«êÆW7áŒÐÃÆUrämçÇ8°ÐRÍ »òãöûÕM±±´Ï•{ÕÍÜ¡åœvÀ¯_å÷­wZÔ¤óödÞ¤†RÝ·Z‹¦Ý [YænW{IŸcŽŸŸÿ¬5ÝÍäòNÅš"û¶(9 tçì+Õ¥Ôo(šDv Øž=³Ÿ|gó¯ó*9`r Óãš§2-ÌR9 Cf€HÿoÒ¬!Þup1$~@VbAPAï•¢Å)G(9TÆÜ¨ÀÿJ—”‚)ʬ’LçrpB.1Œ}Ç¿½d·.!c""K# ¸bJÿ<~_kä(Ð  ¨m›ÏñsÁþýêÍ•¢t„>3†ïúýë*Ì¥ÀØÀªär@5 N-®¾¡£Œ²¬R †Çžß•D*ó)“spÅ‚Åǧ?ŸjÅæM$p—°q”qÛ?—½HóDe$˜0,‘žƒùàµòwv•C/·ŒŽ½Ò²Á"nXƒl* vzõqqDTI™„€¶ÁéyÏ9þýª#=„ŠB¨\¥zE9€!—Ë'„g;¾:c5éü¢Œ‡à=óV:ij° ÿñüû×Ù-]4o˜ÈÞÆpO¯÷Ö£! '—gqÀ=Áë·õ«y.‚$Q’s d§ñäŸïÚ¼³ŽsÜ‚N•Ž)Ÿøƒr1ùTŸ1ܼcõ÷ûRr¥¿w­FrTã8'û"çm†8  ãžçã5*ÝçKy® q£•,·•îvñïî>õäïíF\ƒ¸Žý8¬¶šœš{¬‘úðÃz=_³Ã?‡5Ù¢ú‘&vØV»\°SŸÄTuÇŒž+,ú5­ì¢+È +–ŠðcmØ9 ÈÇ\{¦£ÝëóVÙ¥-fò*Ídà>6÷>ăŽþVÚ?†ˆe•ì$Û P ›†EǼŒØÉ㸫Ù|¢ä[BK¼ù`}6Fìuô’NxãžõE©xRúÚÙÂA3¢Ý(ˆôçŒäýª§BÒìîõ«(u3t4ˆçVÕ ¡EÃÎBîàGíù ϯ%ޱ¨YØî4µ›:t“(a# p[·ÜvBn^ÖfHë´å@sƒÆHÅKÒõsa;IT’`Þr0$8`00H¨·sA5äÂ<¥xÄwŒílÄ}Æ*Éí"Ug±’W”x9Æ;ÿ®9èjïJò¦š'žéâžÊuýÛûÝç@Aû[?xV8¼Üâ0F|–9øç‘Ÿ|×–³ŠP‘jD}\jóÙ3ë ó=øÎ>ÝêåèÖw 4˜nfu\•å~@Çò­‚ðãtÌ Ç´²¨\zO?o~Þõ ­$+´ÆëŒÎ¤ÈïŽqØçõ©Š‹#ya¤@˜Ë'Çað:éû™ ùCË8ˆ¡ü~ç^ A†VÀÞSi*|°FN{‘ñR™w`T‘W',xÎO~£íüª¶xË0…ˆò#,pYð}ûdü׈[Æ‘»™TFê\äÈ=³Æ®¡ë×˵ûÄdÛ!wÇ—sŽ¿ù­ÓSñ¼p¼žb™VØ‘‘ÙqÓ¥k­âIµ‘ ´5œQ)-¹÷äôÆ89øýjÊæþ]1D÷(å×ÍÝ"ä»q’HÇÇúVñàøÂê-[\¹ó-tÙéúdI…iBäJçøðxÇÇ<`Wm¹±³xšêòê9–^iN!ÐLtþ•­ÛÉ¢AxÍ&¡¡4$²%¡.`r1Ï·¬õÅô Äè¢hD„Ž£q<©²óTzíÞ› Ío ”Öíx‰wo&6¦0Ä’q’8ã$Wçc÷šµÝ½…Іš ž;™À@8ÎzEPhÚ.£¦ê‹+È#† ‡VžOâ#<ß#¿=+¨é‰¨x“Q‡O³Ÿèà˜Ÿ5Ã䪯,G¶G·s÷®³¬YiÞÒ&k‰>¦Y,m碪‚NqŒg9'©ÅbðfŸa¦évëmi ›¸’y‹(V#ðóíýóW~"ÔÒ "÷Mðõ·ˆ5¥]>Ö{dThI8yI^}1îon½~y›öi-†¾º9Ôì’Õ,êçR¹bÜÈÀå›ÙGZìšv$¾·Ð´ØçŽÕ¡i_Q¸¶ýi,NåAÜŒ >k.‰áMNÙ/aÔÐ@"Š9l¬¿ý´‡ŸSu #·øÍ¨^:<—Ö¶rKnéšÎK•y/e ÄM É=—Û ÕtMhÇb·imlÙšÚv'ëîqÔ;ÕÕ­üJ$k3q'ÓÚËqû·&çN@l0N;fº…üi®é¢hz<2^Ë:ˆ º·iLÁؤ`2³ïéǽmOˆ5«]FÚ=cGÖ'’úkIËC Óĉ„󒮯2§Ò0ÜTM7A‹ëBiú¶»¦Z‹Û›Û¶6v·ƒÒº¯ð !F$da²Öœç¾1ŸÏ]§Ì—vóMiôÆu•ÏÓ°*¹F9Ϭ§ÕÓ ÇmÓ퟽QB¶öÓÛAw=Á¾Ôožõ!œ†ëFÐÁõ9<Çö†Ú+ÝÝÚø‹MÓõ”žÀý%Œ7j­±,ƒÕ½Ck) Çzü×kàßÙ5Þ£§½Þ­¬ê cd&½Ó¦Œ@on°äB’íÊo-@fËdäö®'ìÖOK«Ù}V•¤K`ñ]Ùk"í¤6 a"ÁBºõï“Ö´ï~ÊÒj–Ÿ´øõ‹ƒÏ’ÚÇõÏTÞ²7—’£’=«ð¬’ª™2Î*’ðcã$~{WŶY• ­±!™]ÛÀïUÂyf!˜=Ä2F>Õ0ZÌéXåKuvFS€{¿ÇÍD¸’#(Y×þÚíÙá½H·š&Ìp«G´nô·-ñùVHîKÁå`21Oõþø©ñ@¹ X08#ØíQ®^ᙄ\º²1,z–ç¯"Âu6ò¬°§Eo,çŸQûvª³$÷LÒÜ>Ò[©|î=9>ù¬·Dm÷:Že“õc#ýóXMÁÈpäFÊ@ÀûšúáÞ$1ɱRIA,{üû~uðYïÜK„ݺG*AûkÛ,1žÝfV8”ãœvlt=«ë[,ù,\ŸÓ‘ÏÅ-àÒGKw™c° *·É¯^L—ˆÚBdeõãÛ Û¸xoÂ1êVÚ´­¨Åk{§B“Z[^«v0Ùõžü1Ü•­íe…¢ŽÒQ{¤¸3‚ €séÇǚþY-À”3Åþèí<1ÆkÞØÛhfò²9}¿Ëßý+äH±Èw¨T€Íútùª×óm¢ŽJ 森%á‡ÒªÄ…`F÷¯«o{^qgI”Íé8)ÐüçQVI'Ø3^dÁåAè^*lÎaTÞ¡ÈYŸÌãp#ƒúþb°< ¸£úA†ž¿¨¬f9#$†Ü qØ{ý«21pÛ@OI’}_ù¯±°$9Ú@ôÇüW©Ñ㜜œðjlw*›QËS ®3ž¿¥f[X%bñ¸b=JíÎÞ8SùŸÊ¢Ï ð”dšD%£T>Ÿcýû|רPUÛd‘°\g|ÿ<ÕÈËE$ªŒÙ2©ìFxøÏëóQ£,ž²='váßÛ#§j„ñnœS¹7ê?—ô©±ˆÔ1|õ\¬j:ŸróXUÒU1ª¼DåK äqŸŽõóΊJH .Ñ‚Òu>Ùù¬Ö6é=ÒEq9·¶g§ »Ëã#?<â¯ç†ÚÉå†)¡¹!*`BìØÈ Ð÷U[Ão*ø ª¤t tþúÔíÄ&˜d¨ FF?¾ŸÎª c%—ØÆ@¬ëEëll`üâ½3Är˜q g<oô¯¬Y™YFP78=3Åa`w,œ µŽ9X6qøN[ Óë9gŒ>éã®1»µd¸màrØ-ñÏÞ±F ÈÁ~€Ž8ÁÈþµ”†Ï¤°àmÈḬýĈ«ÆïÄ¿¾*âïMNñ6<¼2Ç’v‚¾zãÞ©eóSvX€0Tÿxí_mõ”eð9(2®8'ŽGØùÕ’jd'E&Í€œ §íÍz33·œäµÁÔ[ñƒÇô¯,@ 2yR£¯=kâFCîÈÜØãùâ­­nö3EzÞu°ŒL ÜsœqÏçž+~ÒßEÔ v‰>ÉDÊæÞXU€Œ`žO$¸==ùçz½Ôt}>ö'±´µ(ŠÆk’°ÄŠ¥rHeÆií9èI©Ú<±Þê÷°ÚAt—6P ˆ€¼IÀ;†%ônè ‚zs×­DÖu:'Š ÔÕVáÕ§6¸>Z€Izô'žØÏ½h·ÖïkÚ­€’ØLâ+…hÃÁƒž€€}ØÖ‘4¯{)fl1ôê*3ÏóªÙ’Iq`AÜq“óÏÅb–LÊw)W+!…#Œf€>ÒwwÈcÏ9é_âhò#‘—iìHÁÿOù­ŽÊù¥ŽH̱¤¤¯(âLÂO^z~u°kWÆ{MJÌÉ"ËŽç{ldvàžžÕc¥k‰¨ÄdxWê`;c!àç±®\Ë~¶Q4sQäà*ñê9oŸË¥PAû=Öµ+Ée2½ž˜ï˜^T`ÏASœwÆ⺞‹ Ÿ G·šúp“0ùªžf‹ qÓ®IûUÆ¡i¹ososm*+͵a7ì䲎¼8þF®¼7¡izE¼"Öú¡A,íæ3äÓùVÎÑ I!¸0Æ[~æ™äV‡o¾3\oź¶§«ê[áþevé º“t™ìÀùÅQÚù&i-ÂGQŽ mÏ~O|œ ç ª é®|Q,7’#[D<Ž˱zåˆø®‘/‰t(uso*CogbÈïJ>®Mà¨ø°éÈæµ»ÿ]x–úÏu¢ [)~¢ÞÙÏýçäo9è1ýjà\\%™½¾Õ£²eýЄ©R2Aˆäû|ûô­2ÒÛUÓõK­Z9õ5±ŒI%´—îic8îÜñ’>õÓü<·¶©q­Ü[ÛO©<ÚÖÏqu²Þvà’=LX‚[ãŽ*ÞâÂQ¨Ù¥Ž¯s3ÝÜD—°ÀÁÚfPw þí2;qóÎkp•áŽD‚@Èâ#äz–=Ï8ü¹­C[ðõ–µk:ݽƒ@åo%kˆð‡œc8ëÛ'ƒRtë]&ÖVÖÒÂ×OŠßËMGPg-(#×°à†…-×9㌜7:,¶°Ø\Z¼JVŠò{l;NÔ<–TÆ;Œäé>{ in.$·’ÊKì\[Þ¬ÊìÑ€UãS“´õéúœúW…­lõ­SQ¿»H­Eå¶›§éê¥U›¢“ƒéÆN3ßRÖŸTñUÆ—a¢hZ½¦†Ö½êúYµt npU'Û äpxªjÓCµ­ë–7pÙj:…¾¦5ÔóZ¨ÄѪE•Þ}yrØÏqŠÁ¦þÍí¯5ë>æÎÛPŠæy4 ½RBút!‡”ù-½™èÄ`ç= o2ê^ ðí­Îµmaa¢ê1Y½¼°IpM® î;—¨ÎG9Á©:íž‘©xzÝïµù´»[›5–Æk+¥UŒ`¸p%Îóƒ‚DZ´×¼ñ>±âX|àØ'‘¬4æYï£Õ^aw[CÎÊ@$©Ú3êl ñЍ¬¼-gc‚›À¶ÏŠu ÛhõmGR€Hu?Þ¬Ž¾i‘Jú@S€8Ækô/…ôŸ éš®§•á]'ÃZ´vÑÛÜ2Å"é ¢ªãwÆN·´‘‰HIZ‡#qÉ`A;qùטáZQ0·XC¶ŽÙEäñíÀ|Ös“ñÎVÉ—W°M-¼hš}ÙkY÷å¤V‰•Û§¤n`¸ï·=1_?i6_á~,Õ¦Ðo¦†ÒYËßÅ; pI/Œõ^ŸþÍipifK¤¾²Öm\F&«=”ñÁjÃ$•+–Ýœa—¿\W?ö«ø~ÛYµ¹ÓWıÊM°Ö¼ÖD·CøvÈáÏ#=ÍhÞ"ñg‹n¼?}6‘¥­ƒC ‘5½.F9b#+‚v‚ßàWä¡&-™e•¼ÄÿîsÓ'?j̲]ZòÂŽDmŸ0ÿPqïŽâ±Ù_,Žd""¶×,¸+þõnn;–†s\ Hàäó…ûó×µT\EìÆÛž¾ç'澬m_mÓ9iSøÏ@1ÇûWÙ-¼Ä7) lƒå†#Ô=¾k \\«7k;)Œ`c¡ÀéV‰¨6ÖY[v R@Áçú{ÓÉI"U‡k:¨!²rÜÿ.*=Åš²ÈQ¤8êG, #å?cÍGHÌ®ô2HÃ8a¸Í{H\$R°´ŠÉ;Ž1ÓàsÐV5ÌŠeU ¹ 奸<Ò¢Ýj nèÜ®ÂÛAsßþkä´×ÄîÌ!Œ€‚7guëúUŒI凈Ò¾™ ošÛ´êúMšÙé¾]´1¹iJÂ3?9Ú}ðÙã<Õ%ÍÓ^^]ê3…77W <¢ žNôý* ™Ë¼«1GRU!,pxÇ¿Z°Óïá’æ1v^VaѶÁu^2FsÔ‡"¦K&I#Ä– Ÿ[(È\Œ63Œÿ¹¨—6¦f ŒÑ P g'°5³Ä«¾ág ÉB¤`Œwï^äË€ê;¥àsïüê<9YŽ ªÌ£cúÿ­^Gm¾P~ »H€‡È‘Ûù|Ö M|—2ºˆÚ1Ë,sóUw'ևˇ­Â`@s€=¹ãýª­„·8q(ÌnAÉÆ}¿^k*1\4܆¸Ù÷š‡ÎÚÙV9÷cÜŸÐýªDÖÀ\˜Õ$VvhÕ gç>üt÷5Šê#çÌŽêÛ YO¸8ýIý+äŠ3?“çcr–#þØëRíÒxŒ#È2¸.ÊKG|}ªÃ|)3ÈÒI4±,ÀyŒ8'ãûÅT·™ûÍ»R?0 ççåPÄÒ¤Ží†HbFyããµCó§\äîÁ!G`Og Åà*ÄúT¹< جÐÊáÊ M¤ã L+ì–âxös/‘žsóùÿZ‚–²ù󨈠ã$ õÏåYÙ¢‡rBÞiLm*Äãõ¬i3d™I*g)‡·õ«»(.®î$ú1¦ :‰ÕNWž2FO¹«kmGëà{K¸•‚c„*UGPyãœvëW6þƒQÓe¼·–7xn$†hT‚c‘_NJžÕG6•(‰gDÝos;Aqø•Uˆ“ƒùÕ$úl¼ÞlGj¾7`z‰öý*¶XŹ.„ãÁ›h nì²nCÀö9ý1Yâ !pÁÎõ'ý¨ñ#«)$äŽù¬Ï§µ³Y£1eöÿZÉoeÁi`Al¿ŒW›Ë'P^0ã(B€Ã#œ?Z…IxØ3ä)#ñb¬-.ÑTÈíe2žO#úU€uÆDaÒf lÃnqžÿaÞ«^!‚Æce;AXñÎ_ø¨ Õ¥Ž0ùÁ; ûûT™®-Ðʹ ŽÁدp©*LyuïÅO·FSxPÞ²¬ëÏ_j°¾µòa2Im‡v27¦`FsÏN;UE½ã[Î'_LÑœ*7B=¾â»‹ã};“SÓýk¡íäX×ÊxðT®ÅÛë› Ñ$º¼Ò¬õvži”q4 ˆY„’ûËc ´ŽO#«WÖ¼/«êšrÞéúÅ—‡m®êâ1$R½Ìª .7r?¯Jè‡Ä¾¸·ŠîKÏé JB¨Óm®AQ·¡,|þ#Œ`qɨ?ú¯öpÒÜÚÉ©xŠß÷c鮡ÓmÝå'vs?oHáÏSù×Eã/X%½ˆÛÂÄ¢ÝÍc3“»ÉùÀcþû Šü;u,Joæ·’¨—ztƒo d˜Ãõäã°š°×!ÿŠÅ‹Q¹U­ïîï r¤íÚ?rAb;ß­jöŸ±ï]6§sk¯xnál`ÞÜCªLÑ ’5$´sñZÆ·ûñÄ71?Zð­ÂK$vˆ4ýu¦iÿ €“ޏ©­»Ný‚ßhh±øŠÞÂé¬s*ÜxšÎ0£¬Üc¿©±Îk[¿ð}Þ•¦M 3éÿ_+Y©¶Ô­fxü³»‘ʶ:u=8©Úoì§Åv6öº®¹¤¦‘fbg±ÿÔ­­ÛP—ÒxF}ûBäò r;VÍ¥þÎ5”¹SÕ­íD0Z%Ö‘¤Iâ;E8º æ`ŽËÔç'ŠÕç¶Õ®µ›ô½’ÎÅ^1o"îÚwž,álfÙ»#ž¼|VÇk£jËtÂËF¼Óü;nD’³oÔæ#jD'’FO|€µ}£øY «j–Réú¼±¼÷sº8ò‘¹X6·d\dã’½rOxöæÇX¹Óìá2Ci(ÛtU¿ê”Œäl“Ç\š‘¥øŠçÄi3$ºp¼¶’kFxŠŒ\õÉã<Íu½?L¶Öl"›Q·hm•=7MŠB"\‘Ž9,AltëL¼ñE®ã[í7P¸[Ý.ÒÑú+¹ŠÇ ¸B® ±äÓøy sVö~,»ñÍô72JÛ Hm~˜¨ÿUÈ]Í€±ƒ¸e¶Û@^y®Ãcm®ë^µÓÂSL—wQ[\x‚;ó'Ÿ ‘U™U‰9b¥s€ª 8$t¸µ¯iÖºš<:-̺^Ž'[ßšIE ¥‘}oé<Œä|Õ-Η«Çá-jùõ;¨t]!nGŠÄ´r\ ¾æ*¤«2ã-´vë±+Í;7ˆ/"‡I¿±ŸeÝÕæ£-ªŒF¸B˜pä©9\RzTjš”7z5ö‘wáè|e{imþ'{wj©*B&9GÌ€:IåT=—Êá> a7u ÞÓGk×ÓôŸ Y͸™v‰¦€ŠrHzúIÎXRÃÅš4ZF½i xVÄêÚ¿:M³]‡u1ª$dƇ`R¥€ÝÔž™5Ýü%§èÚv§ëZfˆûPµ[yo!ˆ»•ÝÌÎK$vû8¶[ KNÔïu;[G†skI{ ˆÔÞ=ÀÚG·…Øœ`w¨77òC¡Üj­oq ±io¨5›…ß/å£p>šþ}ßøëQ¼¾ºŸ\·´i5nÌ–òÆ\’ÊÊ³ìæ½Eû@Õµ wѬ-ẅ"î·‡•0FÐF<ú°xàñZ­ÍÜñÄ–³¨KxÃÅ´(°jŽ¿ŸkΣ$¶Úöª|€–V_¯‘t#bʤ„ ŒŒõ ¯Ëö²ÃÁ‘È;¢4à÷Çó¨×.’lX Äsß öûsYc·´¢L®Ó· ³øG¿ÏÒ¢} ó ˆwnF™²O^N{ƒýj}ÅK·¸‚è³/þâíóTžÝù©vÒÄ¨ÑÆë<ˆìä¶ ¸ÏéùÖ%¾x˜ Ú±ÌN]Ží¼ÿ#ÒŠÄJîdk1ê¹-Û;GçR­'‰‹y¨$ˆbË‚>¼Ö‡–›Jª6ìzóÿŠ,ç‚äg,HoaÓûù­ŽÝln"eˆ;¼nVa”Ï·éXîí™c-¡Ø y|€Äg€y犅å\‹3ª­´FÈÏ#ø©1ê3[*,ÈO¥ŠÈâœÿÅF¹½Í´0Æ\"þó2>L‡`v?Ϊ÷DHVXÁeÁ@0qß¹ÆkÕ¤j‘²™/–ÈSëú×¶„ )*’èrˆ£ªõü‡É¨²KH¥ábglr8äÓþ*îÆêw¼·ŠÇ¶G‘Oâ$ÿ@c?óUæ» ê±.J/2õ=—·¾j™…BEpÏ1f\NO5– 3•@ØØF0AÆñR ç/–I´€ÆKm=÷Ú³½­ÕÄbkul°ÿ¶X #ÿ¥a6WIjòùm•ä†B?LõãÛ5±gC¹°¤²Œg¨·2zA z¹À>oÅ¢ÛÞI ¶‰ms«Ü «©#ÒíåuÁ,=*½0;p:šÛtÛ–µþ!†K :Â+µ¼Hã1æ%ëè8=So^keÒÿlK®i÷º=Ö—¤. )â<ô™d˜6ߥàòpqÉÏ\~RÁ;Šàma·gŸoÓ­7QÎvþ £$wíñŠ:,ˆñº†GRާøàŠü•ûR𿆠ץ]>ÊÚlüÛøãg”Ë1$îêÄ6ŠàöÖÖVZŒÅä¹X®-žñÄë³HãŒãñÎ{Á±‹FºŸQ¶–þYm ¶ Ï•Û6æÜ£pñ´b¹§4ùφ¯Y>ņ2à3"ä÷ÛÎ;W„^Y‡ET‘%„Å!‘z ž=…x‚ÆîM›å†!æwþx<|b¥Mq%« DlÆb}©£ñß§µe°»1§’`È‘Æ÷|ò½qñÏçÀ¯7¶‘Ü4ŽsŒì“ŸµUÉiäyD°&6ÜŽ 8íŸÓúÒ+Éã2«.øÜ–!‡Æ?æ¡Ä!]Ñ$uÃíñƒý ]¤°¿îå–Pªãöø«©Ú=9#‚âÄÀá SÃ09EÆ}ÉêxéQäúYaY#uX ¶ÛºuÉ?$óýâªîeEÊ8h¤b¬vä Ðö¯M!yˆd µQßÖ°Ã ±/*ƸLlN0sžùé^¾® fË#wî\ìÏ `÷Ïõ«±¢in¡Sc0¹‰HÞzÛÞ*¾{V %å”%h‹²(8u–Àãó¨Ö·ÄBLмw p2"†}°*\)t‘Ü/bH7 Þ‘Øã±ïŠÍ¢>=l’"á»çù¬» ™Ö,]ú€üDõÿNkÊ\(²ŠN9õ9ªÙÄ„*²¯rƒ†éö«ý)®-§YÓ‚®ØÎG_×­…]#¥Yw®á•r=8'#ƒžÕžá-äˆA;¨Ï °ß|ýªÂ/aŽß+¯—8.ƒÏ89ü«Wºì‚V6dÚǸ'õÈâ Ÿ6ex̬…ˆdŒvïùÔ˜Òd(ÅÛƒ†Ï¿Oµežâu)4 ’ åù b£,Ò‡rXGe}ªm£Í¿AÀ€€îÈëüÿ­cDµ—2ºãz)Úç§ {ž[e`«nƒ;\öÿÆ*0†òEh-"iC+%Š’GÇ¿j·Òaˆ£¹ÙʹGp§-î>>Õ8ÜÙÜ\"y" ¸bK_qŸÊ¾Mzð̰Ë(»¶‘AXÜ´äÈóÅU]ÑîÞZ0x¥FóÊçïTÓÜÅm)[s! 8èOlÿ½K‹k«m8pÃýšÊD±…C0gi¯1Jé -–vwwïýñY­®YØú‚…É޾ÕeÖñJï&FmÀœœ°Èãý1X.NÉ¿™ 9Ì@úþÍchÑ‹ m ç?¾•òYÈÈ£ËEb£cå¯CåÅXiz£i×SÉi¢q¶ ü ¸zÈïŸæk®MnÚÄf¡icÕæ¢Z23¨ ’s´ci8ëÏSš¹×m¼7áXV ½.W»¸ÓM;^I7—$¨ T·MØ9àgža}cmQϧÞÁt³Ÿûq  ?‹pü@Î;šö–âÞ)s¿i‘þl{V—qlñ]31?‹$×?Ö§Ú\#,I4lcSqö›œtûW«É‰…#_&?J:ß¿ôëPlÙ¡l‰Æ1ÁµX‰–ÑÉ`Øväúr =ê Û¼m$öÓ‘¶\àz[iÈëßæ°+ºH˜> Û?j°’ïë€,‡Ò¸éñü¿Ah$I’êÆ ½~*MªÅ,Ì]X!R'³ÏLU¤ºCÉ»ÛO Ô¥ Kmd4+“É÷e³Ú­‡‘žILz{ç–÷LÔµ€_¢2Zƒ-¤¨M¿˜3Œ4j, l9àç½O“LY4¶¶rƒºÆñÉ"V ËǨ©ì2µÅðÔV+(ŸW”¬R-Ìs6Ávë¸ìƒ°¨Á= äf¹»Øý]ÍËL¢ÁZc-¹m™rr£¶MÙÇÞµÝgJÔ-Ë’S$3Ÿ©T…÷(ϸ=»~•«›nvZ I‚Ø•yÄðsñÅUÞ‘]6!€ c±©±ïŽ0ì„[Èþ™ ®TäýúóSot««eE»°žÞiq2‰ad*‡@=A9¾YFU$TwØw"±lçýêÚy7Gi¢ydÅ2©VÆAùÿ‘[V“¬Åk'Ñ]"¢4a ˜œãŸïŠØ^æ+—º0HèM¡Bqœ0ê—ó­MaÓtÉdžâ>løÇù»‘ÿä"¶ËÜ\Z­¬Þm›ŽJ¿Ý“úÖÁ< $˜TÃ$äܤ€ÿû@އ<ÿx®koy©*M¥i±ÆM²+ åNÐ1ØZé6²éêÐ_¬pMu#MÎC­ÁbIû“ÇÇzɪ¤QBdbw€éŒ8ÇQíZ~—©iè×ý»Ní ’!À\ð:pGúV]CY²›ÍÚ¤ìWj˜âÎrzîöê=ê=ŽŸ¨Ò¬ïo ƒ˜ˆ ϰÏO¿ZÉgåZÜ´wŒÎá·ù²°l“×§ò©º²Ø;G ¬®¯qµ¥’ÆÁ×9ííüêÒ×M{xÑíµ ¡ÛÎPƒqóùÖ{-?[W:âÞ$’´É¡l`ddÁ#+ÍÖ¥ªê.&“¥­¼©9”¸`›‡'ì+Í׉íÝV&IÉWþ/·ûUzêVi‰sa$’ÈåšH“ì8ÕâK©ï$a²mc9òÂç_ëX’âæÞæT[7 äÃÉŒgì}ñWVzV¡j“4—Éiç³<…@;‰ê9Îzž‚ ¹Ðâ”JöÓ>èfs¹‰ç#ØõÏ5âçZs Áeg,²2„y^2}ù |b¶ÏÅ6÷7óå˜ùëŽW§oÖ ^.¡¯ßËu¦Í,Vð\Idޝ‚åH }ù9©0xaíÃÉ$ò<Ì-#`é|õæ© ½ž™|Âú&ºŽ@ ¼€¹ˆŒsïŽjeàÓn¬/®e)Æ¡í¡Bööç¯j—¦ÿ‚_Û‹YWè§*ÎŽM§ÿËžæ*-ôVÐÞÒxoŠ…#ºœ C7ð±Í{IJªçµ±êÎyÍOžYž "¤S('Œ{éž=ë͜ϕÂËŠQ‹èãŒ÷þñXvøäòc**¬ ÞxëÓ¯ú×Á¶Wæ‚@LðOLR %V“6ÅÞ_ÁóöÉëóSÅ!2mPáð|ÕpBH9íÈïÏ?QÔ/õD†+æ¶ŸéíþŽ …EÈ\ŒdޏÀçØb«ãÒ$y)*È#Ëù_éŸ|Jùya3[ÿÚ„2“€{}ûóU†ÓPŽ6 ä‹Öª€á|àk,vöÒ[¤1­Á‘˜Æ]ö$cž¾þØãæ¾Úè*#¸¹óâ-‡{”ɾ1“Ö­¢ˆÄŒ"2ź}¸ïùTäÑnÞ}6ÞÖþÒÞ=NÙÙf’]¢ÛêCŽÄŒ`õöäUn£cy§HÑ—ŠåYÙZ[Q•cðqœ|‘ùUd7Öí4±‡ &Õ‹qÇðç<|Ö[’Ïôdõçüwæ°D/£yc8`0üçíúÔ„•˜ºÊ\ncéÉëúU¥¼VÑÆX±vq”R2ïÿžÕd£lR:Æ‘…Ã09SžqÔsÇ«âÍ Q¼ª¯™ƒÔ–^ŸØÏç^.®#MÂØ¼È¸ ÏSý5òKðb†(÷´±‚r)dò_Ž>+Æ¥׈Ú6ˆ\3’ }ðqŠ ¸³¹‚fÁݤzT›H#˜È'™ D$‚r26Œ÷æ¾Ü ’k6YJB h›Œg H=þFp!*ñHLn››ý°k0•y–îÜ+–Ç¥Gj¯!ÞB€n ]÷gŽp?e´¸IüÕüÂç® ç56+™­i£RN÷W<üv¬ÖòA,žs¶åÁ`¨ÍzYcY‘ª9fÞp§ö© –w¸Èq`¨O§çŸïôªK™þ›d8`",²o=Xô=ûw¬"3<ªÃg.är‡ß9¢D7Þëê;†7Wˆï ‚ ¹Èçæ³%ÂT`@läŸluýy¬r]F†8’ÛC„8cïV±ÀÓÀwæF‚‡² q×ßõ©N1FêLm¼ðíýó¯m Ä"y¥wqŸF/ñÓÚªåÎéÆDO|ÁŒïýóAo$¥».UBgê;W}ðΉá]m[R{{d\ŠÚ UçµÿmÔ„Î yƒßçžMgHÕí—Oyà‡L7¬×7†eËÁòŒdF{€¹'¨:é$Jš)™\ßùÚ‹cí'j’Ò>[Žs[†¿m,FëPÓ<>«Ÿ<_I .ãrª‚ŒQµŽG"¶ 3Ið”¶×u &gà3\‹…xá-èX¶ãÓ—d$g?j¬¸ð'†#Ó©ÚÌy@·`X3¬xà>òGˆûŒ|ò™´½Eìçh´ÍNa žCÜEa#$%9eÜÇ<œôìj>Ÿ§ZÏ Wº@’Nb ÛÅïÁ«—ðì÷6²]FÀ˜Ÿù'8P=¸=?Ö¨áе'šèºMvˆ|É áY±Â‚z“íóU“Y»<Ñ4g|{w¸8À#+öÈ9ù¨rÀm$ 9eÜcÛïÅYÂíˆö¬nÜcÐñ×?â¾\ÚOfr¤•AŒ©ïœ~I¯wìŽKòùH¹Ë­m1jZ¥,ãZs¬¦q$×Vóà̹ܧ©Ç¶+g²µÐÄnþš+w·¿´1Åc>v‘rr¤`¤uãœWGÓ4û&³Ó/´í@3_C(¸³‘Ch"-UÏ8f+¸ÆÜÒÒ9V8W|î•[<·6}¿óRt+m+M³Ñ Õ ¯(=Äv-¦ùžl²àÜÙ rƶÿ¦_ZZÞØËݧiÒÏ¥$Ka`öÈrA`GsÓ5ãL†M;PˆÌ°Ëmsf— ³ÿì£àbT}Ž+k‚ïÂú”³ ›[x CpØå7cŽ;žßÎ|š@¹ðö¡£ ½­Ãd“܆Çœ~•Ï|D÷¤Mms As›¤Ç,}Áùø©~Y*ê2L‚Å“ ,1ßž½ëa›ÆñE8Ú NCIã±þù­s@qÕÊÜ ÅH=8Æz~U?ÄEs[¥ÜŸR$S+î;ºñW:†lÒæ½{‹Ë‰1óå$ ö§éñ^|C§ØG§„†IP† °ñÛÞµ{-‚ c‰w©Ã¤sœUÚH®¦K‰’(Gâ8P¾äÕ}ÝöŽE¶ vIÚ@BÛÏn{sÏ­R!¶Ž+<‹È‘o~jæÎÛ›GÝÈúYv{ñ÷éV–ú–­,wšbLö×.ØU`_Þ.8mÝùöä~u®GªxŽK¸M¤ööÒ½µÄnÁ=Xãô#5çHÑlÀŽêí„÷  ùbÜdñzÙÚûÊBˆ„Ç”S¢  ä, AÅÉÉ=—÷Å`3\5Äöl²]Œ„ÊAÆyÀÆ~Ýêp»¼žÕ¿Äux"•X¢[ÅöèI'ŽÍRNÓ\ÈRêøÈ‘·€O‘o*l‰%‘[jÅŽKqŒ}Ï5êïú VÔ¦±Ahí½¡‰ÕWžJŽG{üU=ÌL¬™VPœúØ/¯CÿâÆÎÂæäEÓ-¹r|ó)çß“Ó'5c©i0ȾF—p²¼Q´’E¿'O=¸þúU•®µäØÛÆ`1V#èÎÌuÏê9ø¬Ž÷væ)d\HOåä >ãúf¤X½“Læ{¨æ•ÌInQÏAœ/Jq©„ÖVþÊÓëb†%·u‰2$#øø÷銰ԼMcqc-ºÙ^‹Û€c…YW äõëžý‡j÷zÚÆ›kmw.§<°Áˆàtœþìc‘´ädžýHûU–Ÿcª]­¶«ˆµ®†&IÓ‘s錃Ž5ºxö§âht˜ômrá5;hôÿ¡W–‹p™ŽL[XŸÝ§â'§9É­OJ¸ðÇŠ§kMGI}:86{;{)9ë“ÈÉéŠÅ¬~ϼfDÑõû¨7Je˜êZ2Çå¯9;ÒF,IÀ>ž2NxÅlëà‹Ê†×Uðà´xíuXÃ6P¾ìI´ìÆ=}2@ï\wö½ámJþßÃz­´Í¡šålICêÊ€S ð~zµqAE ‡»HÁ'²ÿ:Ëä[\f?¦p'/Ǩ|àäÕd¶hB¥BÅœëäã¯Æ?K‚¥G–iá|ªÄä’>9ãô¨Q·”Ñ£ÀÅYðÎ}Ž?AŸö«‰'$I墭¹å gϱ?c1Ã4‘Ä´Ýèq#ƒÏ< ~_βBŒžt;’%Qå–+ø±€zvé]'±ïÚŽc™<= _^iÌ µüì-ár§D²¥†ï =k¿xÿ¤Ké㹿ý I{¢ÙÙFâßEÒïmä—Q`§×樑b\ã ÍÏ Æ{¾ÿÓ/ì›Âi6¯«&««ZYÚý];·¨,‘[”\¼ŸºDgèNÒJóµMâߨV£.€ú_ƒü-©Íõn`Y·kHǵ6)vÓ¸1Èæ¹†©á?ØN»¨<Ú&¹áh"·gµ“C¿bÓKÏîü™ƒ§‡PIü#“Z俲ŸÙ5ö£§‹(üce£¬q NG½µy¦9õœl(¾œtœñ\'ö©¡x{Ã~8¾Ñü/{sáņ ´ûÛ°»Ø<`º¡s†$¥iFÆæâÕÇV‡˜ÙTêB?žóRgk¸,¢°1[\ ‹b‡ÌŒ‰³ŸIê¼íãúÕ\²ÌQP›`"ž@À.ð<ôÈ'Õæ >T†;ˆÑ& IxãÏ$ç¯åØTT·xXƒÕæ—”ÛŽ àûŸïî F#UK_zd“÷=*ÂÍ.n,æ–Ñ£µÎ.FIçžó^ÌnÝL®IÙ„|D˃öÔ˜"‚ eYÙ¤l£+Žßù’0 °·Ó.ÞFLÿZÍmGÌ› ¸ ƒ&>÷ö¯ -ÃNè²¼)ø¶o#oÎ+-…ë}qH¦;ÊeÆ7Fyé[6’úŒÂO¬k·UÑ`Ÿº8;F\òq¸öö®ƒ§ø>Æ ‰bÔníÞ}U"ºŽ)dòËB¬²ð60T÷Ç^El¾!›J𥽻¤×º­åã\­“‘$ZB™2’€˜ÑTìäå°{Õø¶[ýUoïllVÚÖF½‚Þvw¤[R:àòpFzt­ãF¾Ö5«ëûíOL×4ïmw±Òl%{Y.ƒÁÔ`ÝíļI¥h—Ò=ï†õyDÓ$ŒŠXí*:œ¦ÒzŽMPi:Ž»§Ý¼V²L΃Êx“smaŸIØæº-´úÅÒªéRMH^3ôòƒìF>ÿ½IÒ|>·Ïq5Ü n³A[ùÌ•LrG¾èÈÚ{~U«ëÞ†BlþLK:@²2çÍbÃÓñ×? ~u¤K¦ÝÛG¿d¡¾¡•JŽ€†üÏô¯–ÓÈ'– 7M)2&r[ÛóþµKuò/-Š…rB>ÇíÚ®ôŸêúš4öÃ$*¬2Ž’yéßýë pÞE4Ï:ãÊr»q’p{Œg5Ѽ;¬jZZiCcÞê—Cë’ÝC\H¤nHF9÷­›Zñ[é±_j^T×2À¶¾Våo8ú·`™`¹9øí‘oá©!¼ðÈú1qkjÂâ6x§VX¥w AAʆ »Tô¨ÿãöºqÑAåÃÉp¥Z6<‡~1‚+\m^;»õú«ke·… ðˆàV(@m®Ûy|;㱦¡uÄV·±Ïin<ðÆè+[©ôE'‘“œGåV~ñƒéw»~•¬î¦’ š¬rì8€O#olƒß5Ø´°öDjzθ¶7žvc±òþ¥eR;”wéÆ8ö«>MGRÔfú) Ö:£=¥öŸó|ØØå}JIpCsÐ×ÂÖO%½½Àd’x¤G$¨,äddþ™ø®o£hQYks »q9ž÷¶¨ °·³)Ǥ9#’é[möŸ¯Ë41É´¶ lŽî+Œ5ºç°G\ìO½eÂÝ%–)ZèÎW¢P6žŸ=¹Á? ¨²xm/&U¸µ…#I<Ͳº&YsŒlóÇÁæ¬0tí4é¯å][ZDÄ…I‘›œï9*CƒÓ““Ís+«[;V»¸–²{ÐR!0Ãȹç$tÏŸŠÔ¼A,Ú‚ÞÞÞÚã i!¤j 7wôñù9çL»6îÓ˜¤\FB¸àóñ[‰­ÜÀ#‰åRª…€ëÁžõ±ÝL5]9í®UžâÕK&d‘Ðs‘ÐöûÖ­ic©ÝÊl`Ò®dIccÛüÀñþ¢ºF—û.¹[¹ºÓÞK“$i^`9ˆ€Ktê¿LWça¨\Ę̀êÎÎLey Óßâ§i÷1ÜȤ±ÎôÏ%p1ü«{:æ­goÓ¨‘YB¶r=‡ó^d¹Õ.‘o§µßnÍŽÝÛ—þ¼w¬Ëo;¥Òi×±ÛÈ:FÙÞGÃÓ©ý*ªe±Šë7v×P[Îà ¸#¶ÉþU`âÖ;›1¢ÛýD¾ky‰¼~ó yç續UìþÖ®¢Šõ»¤‘ KÁ<ãäöâ¨WT¹Ó#DÞà7+÷öçšÅ»q­ÜCm§Å<7îc1lIíúŸn•´Þ­–Ÿ¦°hç³yÜÉ4v3‰ÄÓ0œîçœ çùÖ½=ËXE¬wRÛIh—_R–…$¡Ç ÓíT’ø¦Ð( HʘrF2ÿبrxÊÙÊÇo|¶±éúw«ß]Ûë²Gæ F™1¸uÀÇÚ¶ûß Ã0';Š’ìÑÜý?ëZÖÈ-G’ˆ%1 €’=J8Ê¥[ /ˆ‡OêãÑÁ&.¼gßà^o¥¼³h,ï­/$v“ËÅ%Ÿ0yê*ÖßÞ*ÕSþŸO]2Ò@3y`ù×$Ötû‹{ûË[8œÛ“¤è¹úe|}¶“Ž}¹æºÌ>‚ïÃPAâ+Û`;ƒ2ä’A‚H¬e1JãÌ[“2’ªr Ç|>Õ4ëÒ]³Ú-Ì3GäîwŽ0L^Ãóì*<çOdŒ)r#܉õãnÄÔ{ÖÃ¥j0Z[¬qà…';FrHÿZ‹Åñ'Lår9¬¾"ÿéûö«£EçÜøFwŠÚº”Yê—¢ ´€FåØyÚ8üëõ‡ÿM_±Ï §„4Ïx“D¶ÔüA¨ÞÉ{¦JË¥B„Æ›coIbUŸyþc×ë««D»Ž8¤y’8çIÙa}¾vÓî¤õúTªåß¶K^ÿö}¯Ç£N#š+u¸¸€Æ¤]¬¥Ð“ø@P[#ŸOäœË¨47E¸hÖEŽW†B7òIç ý¾ãŠÙmΙy¦E;Éto„(„ÈãË;‰T=±Œç'ùU¯ø­õ¬÷‰k,hey$‘d8lg¦OóëÚ¹Þ¡nþ/-oQ…ÌlˤÜÌ¢0³°á öbäÿqÖ¹SÞÍ ðúˆÀ›L»Om!`ÑȤ†R3†<}ò*¦ûU2_,’³Oˆ™C²mÙ׎IÉÍPN%…ðC.@h·);—žõ"'•’V‘вȯç þÍNƒQi‰cŽHÜþõd… ƒý `˜}TƒÍ“fÀQ5éžÇe C/,ÛcI6Jˆ9ÁÇNÝi6£0¶BöŒ@Ï#ó#½}Ô¤µ‘Uà™Œ¹,a Üc€Ùù~kF;›fزó€§¢žGO~kÌÓ‰aÏ©O}ñùV›(…™wà©Á#ŸÛµzY˜˜ÜûC)Úxøö÷­ûºµç×C$¶Qj>Lªæ9J‡^p$î dð3×¥v¯øq5}NÖ`R‚宼‹hÄ‚m¼¶åbN舛 äcµ­É»Ò58î5-:X‚9»dW·–2vnÄ3ÆAã9­ûIðî‡iqf>Šæ{”ÂÇé%X¯¨þDg«&º<_“ÕÂéÑ*l½¸´/ºäƒøw ž@ÀŽ1\/W1[Ü‹ýk»–¹·u¹ŽS!6¨®Ê°þ1…#é[^“â½#B±‚eðË[]Èò5×šÏ º ?Œ¿CÆx®¥­ÝÛéZ~rÛÜ›‰å¸·kXßɲŒo$—üM‰8Çen;yuâH.B¶éO¦)ÕI’ òqÉ䜟~¹ª("ÔÒúw2yðœHóœIØ1Î犉ÿ¨m‚Ç –°<ðK¾òÖïj®B²·V''Š®Ô%Ó% $Ð[Ú´l™n€6õ÷ëúö¬Özm¯Š5I­Ñ|ÑcŽ<þéUA9À9È#Üö5s)Ñ4µÓo,Òi!M¬#‘ŽÂ\œ“Ð’1ÃcŠË¥éÚg‰f½](­„®‚Wâ.=[sÔ°Ž?Z½Óü+{[KÔío¥º±D*ÆÏƒÉ'(yç8 qPüAáÃcq -Þ—«ÚO-|¶>c¤2YyÈçHù¦œFÔ!{9¯´©.$YRpÉ]NU¼³• g¯ÏëÑ/t\Ò~«XúËív^KµŠ%Hd‡hXÙJ`³Î@ãâ´‹ß h$ïoi>ðCK"NòyxÉÀ¸Üp9üë ?³÷]AžÎåu ,Ç,v×1*A;Žâ;möãßšÞÒÄë7Zv—«i–ë§[M‹¹­­ÑZã„ô–9$ciâ·{_Ø~ÐuÝsLÒ$šÝt·2Û§œßÅUÂg!¹MF+iôù´åTòÜ™$ÿº§®qÔñÔäÔÍcV‹Wu²¶VG™q5Ë7GQާšßÂv²Éo¹Ç–#W’lòG¸¿Ò®fItýNÆÛFž xï"rñ¸È”¦ÞH’FOjÕ$¸Ôô­K[ƒÍIä¿mó\ ?º ç°=>+l²]gE±·Õt]zkytø¼ØaR¥€=$CqŸÅzUýí?ÄZ}ÀÕ¢ñdRjSưÏcuÁÉ SÊP¼d •ut«?þ¤|I;éšcév¶¢Cå^ëS(‘•‹¥b]«€]§°Én¦¶«Ïþ ï´ÙtË›»m*{;‰w}¤ e\rêûˆÛ~2jÆÓÿ©¯\JÉ&‰yn¥HÚã> z¨À>üãØÔsöáácþ"Ò’ËS½Ñ.­­#2,‹+Ê”ÝéÁÁéŠü#}o5È"ÒcnÈåØ)<äg9‘ï[N—"ÚÁ.$¼R¤{ÃF62çóíÏ ã•dÕo.¬án‰´˜ —œ`ðSñ ó‘üëU—QŽÖê(î]fx¥ ÆH߃€ÃóèOµríUµýrêåÉyõ)exem»ƒ19Ïæ?Z¬¹·(þO¥ÜíŽ\ÿ'íÅRùÄ0ŽYdÆÜíåW9ïVkK ë{u+ÁXÔoa…á~üóÖ¥_iZÌ- ¶WŸá²ˆÁ²ú@Nø%@bGB}øÍ}‚ûUžXÆ«©El ÍuBÜîàœg9ÎjŸ7—–÷Ï5äJ†H$¾s˜œÄò2O¿jéÞ ðÜšÖ…â9ç¸Ô<‹ h–Óè剄»üÀêÄ‚Î0£€Aõr}µý?ZÔ‹ÃnêÞ]Œ~C„Š4܃!r@ùšû%Ü׌Ÿâq7 uhÈøÁäå±Áþ•"8nEÆŸu‘gW2ØÜ€Ë‚‡ªœŒíaö5öãÃ÷šù–Xîìî þa’(Ë;}~¯NàçôÍl°~Êío-Öç\k‹Égwúu³¹Ù"(b¤° Æp1Í^Úx[Fðìrøuœ Z¤”I,¸<vÎOÜâªí¼u¾4‹+6šØÜ™Ù®J¨•ð$ƒÀj¶’Ù®í’é- †V|\’zFGZÏipégäÜÅh^Þ*$„3(Îs»ñrz~}jÅ©g\$2ËÛIç#櫵=#I³¹6×òI½¿z—ZTÿÖâ±[I¥éÏ'øMõijÊB=¢ËÈïÀ3PÞÿÄ7W[Ϫ›¼“b#ž¹tuæ«f—S¶s ȶWÓ>ÙRÔng8ÁäŽßj¾Ó–þ+˜.þ¦÷Î[…Á˜½ûc§oλ֓­ýmªÈ©!r›‚?Pâ°ë¾²ñ_õQ²_,%`¹YYL<@=°j‡šêÊÆÞŧukxö;¨>³È õÇ>ýÅAñ2Ÿ§»-ÁŠ@¬ÀœÆ3’•lº^¿£EÍw402å”7sð{×<Õ<[k¨_jÓC¨O$‚ÎÎÆÛ$N£sI!#žëŽÜ0ÁÏÓÞÎóØIit¦y.V1æûާ$g·µlW—wrC.mvcµŠb©ª:“çHG1©Î='ëÔV 2Þn½ª›ˆ& °Ê¼ÇÀã;pN;sVzv­ko²ÑôÛ(µ 5~ž{»ÄØÁÆ=É\Ü|V[[‰5m>ñÍÃZHQÚÐeg Á;—€ööÇ\ÖŸ¯=á¦ÑÓ' ¹gòd^Œ’H<ýˆö«]6îÊÒ=7I æ+‰¢úÈœ*¹ÜÜA<þµÐ,µÅ‹KÔµt`k«Æh“xUþƒŸÎ©­n/týêö{˜ÞöçWkXÜ—B?2ÌGÅo^²[;!ûÈoܱ¹ŒŸÞ±ÎG_éZ–£­4^=xîþ²Xt†b€DJÛ™a‡l’G|ðk猴X|K­[§†Û6{bšY ”rIê?§5Îõ/ ø“K¼µ´µº–õe”ìòKÇÆáÆ@ƒƒß ëv^•t¯õû†škhÚHc@'ñIä’{~rÛë›x”‰læµ^¾d®BŽH$tö÷­§H›Ãó[A±ai·m•ä —n¹±ž*V¹ebaÛ8I_ Q!W©Ï|j×¢v°ÀmfTYäÚÌ\©ÁÏn8µ|ž7‚ê‹’÷pÊT‰<Æ`½2>éVogkË[f–+uýàFáíð~¯vV-ª^3$¶ö81½‡Qóúññ[)ñ™g5Í£ +ÃqYgÁ;üpyª-bHõ‹3níð5 ÈÇ 9¾jÞ×KhT‰žiNe•ùÎ}Ï~8ªNÒk9å…œ-“bXãW OœçŽœßjÙ4eÒã},×2.çÉF1½~ݬž$ZO/¥o*Á±¶à’;íž¾ù¢Z¥Þ ß¼†Wxr#x˜Ÿ(ùíÓí[þ—á’®§¾b›s"¦ÖÆ0x#¡þu¬xâ;-1ü8öb(ä¼¼–‹9g ¹/ާ’}È­]ÍÄ…šÉöº1G”œz±ÂןҶk{«‹k\Ë2¯—°ÞÛ*aïˆSµHöÏþ+ jVX1¼ôVò‘Ö•vçüÜñÇA©YO|-®­Õeœ>è¡PnN;;pGJåž$ §¬§–Ï{ûv·!~ãúVªÓžk ÎÅãð“Ú§\Û• ±ŠîcÁÏLsí^@‚pÂ@g2ȹÊ‚>ùÿJ·²I¯"¸·³·¶ºžâtï!ÃZ$áI dŽÜä``ŒÖÓ‹U¹¦â¾™—(zr£sÛ5è\É´–¬Å„ 3I$_‡äcç½B7w&Ù`@1žç<œ{õ©¡s Üͬs©Ž5b=c¹¯æ8¯’ØX@ŠXÊ]ÑvœW'<ŸJ†+DÓ%KW'’æ3unÊqqŽŒqòsV:‹µÈÄÖ‘ß]ˆ<©c3°Þ½x'Þª,§’-C̒ѧØÞ{BW;ùëüþü×ï_XýW…ô{¸`MiÆÚN|¢@àOr>õmq²k‘Ì*n`löDÃ̇#9Çþköö³Çåy×®¡£Ý»;‰éžsž~Ý~õ¥Ø9ú»‰!¶‘.|Öƒõh¸ÄyÓƒÏ<ÕÌ·1IoÛ«¬bt`»‰däýúÕ¨º‚3Ÿ8ík"™eÁ$óϰÈ9¦ºeHWÈpy¥rÃ`¸ì;T_xwÃ:œmˆt»)æreIcR¯Aà:áÀÎxéÅ~Fñ¾‹káÍbkM.7‹Ož8ÃgŒîVmÝÀ8çØuç:Uþš.ÎòÒ`ÿR¦?¥PI2ƒŒu‚Î:{TX^[+«xï`*¡ÕNTåA#æÚòð¤ú´Ì%ÔþˆËœá؃À$ž§ž•YŸý7htýBÚ×Qcsö\á€<3’W©Ðmuý[L’Îà5ÄÒ´v·qê~IÓ‰É3c}ŒàpzWê;¿ÙTVÿ½Öne¼–óü»å<—Àl žÝ¶8­oZðGˆlÅ›Ø[K}o ¸úÏŒ_$mÂXcžµ¢êšF¡özÄÚeŸÖiÔ .9q•èÄnñÍSOoõqÌͦÏh’VAû³4y8ÇàœŽ?­-à€[ʳ&ÈáU‡tÑ ±ÆrO¾~+rðn§/†íõ1í/obñ1ÆáØW!ÀeÛø·+cß V€|;­C®³FÞ[·mŽöAæCËt$z”)±$ êVº}œš]µÃO9¸[Øá’Òk¨'¼Ø 0ð <÷­ÞÆÒ [Ñ4éºm„pyQ[êr¬»]‹èÀ¹ø$äþU_.§¡éÓ4ŸS4j# ¤®8ÆNqT—~(¸[©N ‘•WHärIÎOÇéþõªêwn½Ôj•c%U€ÉÉÆOþY8y¯q·ýÉ¡1Úxà…TeP¾Þç®zý«4×ßNï$vÓG  %Áb§8ã '¯§óª-G_Ô¢h#€¼È_°ŒŸP=1Ó#'žù©xŽW²W¹¶Šîùb\±vŒ0ÎB²çh#ãßâ&£vn,7]"Û[jÍ´ÎYr=ˆÇ`àœò+ñtZí†Zál®noà¼\43 ,„g>Ø=éü¦HâOݬÇ~2Gþc¥fñ#ë0ióK ð4as-Ä­´Ä½=ÍqÛ‹vŒ%:„ņò¿L€9üù®qse$w.¤íiP›ÿ5¹i–s¤+»M·¸+ÆæÚIûäó] Âlrjk5í…€…C$‹üX=@÷wãz–'Ö@O·•löW÷“¶Ê–:»KI$hmÜãÔ<ðsÈíö­²3my¾—ÀóÉzUNål‡<¶îƒ·çRï4K(ʤpD¬[2M(oßÈ;·<Ò Ûx–[H•-»E+,–Ê`ˆ•‹ƒôù—D‘ÝXÙÁcB[ÝÊ7n“Ü>ܧZ[ë7úµÕãÛÜ¡X!·Üž0_‘ß æ¬î´;Ý^ÆÐYE5®ž /<|Îo#CÈŸÒ¢Ù§<ȶw3’K[K9[sYƒÿqð9ü ÷¡xôèÓ\Û]Ì#XFa†XŸ1ümÇ~;üÕ=¿¯ïu ]<ÄHu[ÿ® 19TP‹ìJ€2sŽÕ.ÛÄ·ºÏׯÝ[¡‘à`Ãiü õ$óùôÅt|C¶˜¡?S%³Ê¸`àéúÖÕ.µ+x~{¥ÙôñX;³o<§<€|U…¯l®ìdŠúÖ ìf)å[\ |îPpAºóÏ5E7ƒ´O^Ö-tÛ™tËK8-î xÕ„H•çœaAÀÆãÕ¼èZï‡<#®Øë6FúêþÔ%Á»·¹g“$“†PqÀȪá]¥“éb·û[` 1R™9 žyúüÞñý´ÓZÅç eo<¼f-ù=W?÷;ò9=jm¯€¼FÚ_•tmPÅ#\Gg ãÌl`Ú;gÛ¥s­KJÔ,ã¾·¼ŒnÞ ¸Œ¹Ý‚ `õãýxªc§<Ë(žîØ;¡…aªˆË¤sòO~G©_é3…šöK‹øgXm¢ ‚rÏl â¥ÞM•eo¶Ig+!DÒœ«“Ç_×Ú¿ÿÙrst2pdf-0.102/doc/montecristo/montecristo.rst000066400000000000000000000465311463013543400213270ustar00rootroot00000000000000========================= The Count of Monte Cristo ========================= ------------------------ by Alexandre Dumas, Pere ------------------------ .. figure:: if.jpg .. .. header:: ###Section### .. footer:: ###Page### .. raw:: pdf PageBreak Project Gutenberg's The Count of Monte Cristo, by Alexandre Dumas, Pere This eBook is for the use of anyone anywhere at no cost and with almost no restrictions whatsoever. You may copy it, give it away or re-use it under the terms of the Project Gutenberg License included with this eBook or online at www.gutenberg.org Title: The Count of Monte Cristo Author: Alexandre Dumas, Pere Posting Datd: August 15, 2008 [EBook #1184] Release Date: January, 1998 Language: English Character set encoding: ASCII *** START OF THIS PROJECT GUTENBERG EBOOK THE COUNT OF MONTE CRISTO *** .. class:: attribution Produced by Anonymous Project Gutenberg Volunteers .. raw:: pdf PageBreak .. contents:: .. raw:: pdf PageBreak Chapter 1. Marseilles--The Arrival. ------------------------------------ On the 24th of February, 1815, the look-out at Notre-Dame de la Garde signalled the three-master, the Pharaon from Smyrna, Trieste, and Naples. As usual, a pilot put off immediately, and rounding the Chateau d'If, got on board the vessel between Cape Morgion and Rion island. Immediately, and according to custom, the ramparts of Fort Saint-Jean were covered with spectators; it is always an event at Marseilles for a ship to come into port, especially when this ship, like the Pharaon, has been built, rigged, and laden at the old Phocee docks, and belongs to an owner of the city. The ship drew on and had safely passed the strait, which some volcanic shock has made between the Calasareigne and Jaros islands; had doubled Pomegue, and approached the harbor under topsails, jib, and spanker, but so slowly and sedately that the idlers, with that instinct which is the forerunner of evil, asked one another what misfortune could have happened on board. However, those experienced in navigation saw plainly that if any accident had occurred, it was not to the vessel herself, for she bore down with all the evidence of being skilfully handled, the anchor a-cockbill, the jib-boom guys already eased off, and standing by the side of the pilot, who was steering the Pharaon towards the narrow entrance of the inner port, was a young man, who, with activity and vigilant eye, watched every motion of the ship, and repeated each direction of the pilot. The vague disquietude which prevailed among the spectators had so much affected one of the crowd that he did not await the arrival of the vessel in harbor, but jumping into a small skiff, desired to be pulled alongside the Pharaon, which he reached as she rounded into La Reserve basin. When the young man on board saw this person approach, he left his station by the pilot, and, hat in hand, leaned over the ship's bulwarks. He was a fine, tall, slim young fellow of eighteen or twenty, with black eyes, and hair as dark as a raven's wing; and his whole appearance bespoke that calmness and resolution peculiar to men accustomed from their cradle to contend with danger. "Ah, is it you, Dantes?" cried the man in the skiff. "What's the matter? and why have you such an air of sadness aboard?" "A great misfortune, M. Morrel," replied the young man,--"a great misfortune, for me especially! Off Civita Vecchia we lost our brave Captain Leclere." "And the cargo?" inquired the owner, eagerly. "Is all safe, M. Morrel; and I think you will be satisfied on that head. But poor Captain Leclere--" "What happened to him?" asked the owner, with an air of considerable resignation. "What happened to the worthy captain?" "He died." "Fell into the sea?" "No, sir, he died of brain-fever in dreadful agony." Then turning to the crew, he said, "Bear a hand there, to take in sail!" All hands obeyed, and at once the eight or ten seamen who composed the crew, sprang to their respective stations at the spanker brails and outhaul, topsail sheets and halyards, the jib downhaul, and the topsail clewlines and buntlines. The young sailor gave a look to see that his orders were promptly and accurately obeyed, and then turned again to the owner. "And how did this misfortune occur?" inquired the latter, resuming the interrupted conversation. "Alas, sir, in the most unexpected manner. After a long talk with the harbor-master, Captain Leclere left Naples greatly disturbed in mind. In twenty-four hours he was attacked by a fever, and died three days afterwards. We performed the usual burial service, and he is at his rest, sewn up in his hammock with a thirty-six pound shot at his head and his heels, off El Giglio island. We bring to his widow his sword and cross of honor. It was worth while, truly," added the young man with a melancholy smile, "to make war against the English for ten years, and to die in his bed at last, like everybody else." "Why, you see, Edmond," replied the owner, who appeared more comforted at every moment, "we are all mortal, and the old must make way for the young. If not, why, there would be no promotion; and since you assure me that the cargo--" "Is all safe and sound, M. Morrel, take my word for it; and I advise you not to take 25,000 francs for the profits of the voyage." Then, as they were just passing the Round Tower, the young man shouted: "Stand by there to lower the topsails and jib; brail up the spanker!" The order was executed as promptly as it would have been on board a man-of-war. "Let go--and clue up!" At this last command all the sails were lowered, and the vessel moved almost imperceptibly onwards. "Now, if you will come on board, M. Morrel," said Dantes, observing the owner's impatience, "here is your supercargo, M. Danglars, coming out of his cabin, who will furnish you with every particular. As for me, I must look after the anchoring, and dress the ship in mourning." The owner did not wait for a second invitation. He seized a rope which Dantes flung to him, and with an activity that would have done credit to a sailor, climbed up the side of the ship, while the young man, going to his task, left the conversation to Danglars, who now came towards the owner. He was a man of twenty-five or twenty-six years of age, of unprepossessing countenance, obsequious to his superiors, insolent to his subordinates; and this, in addition to his position as responsible agent on board, which is always obnoxious to the sailors, made him as much disliked by the crew as Edmond Dantes was beloved by them. "Well, M. Morrel," said Danglars, "you have heard of the misfortune that has befallen us?" "Yes--yes: poor Captain Leclere! He was a brave and an honest man." "And a first-rate seaman, one who had seen long and honorable service, as became a man charged with the interests of a house so important as that of Morrel & Son," replied Danglars. "But," replied the owner, glancing after Dantes, who was watching the anchoring of his vessel, "it seems to me that a sailor needs not be so old as you say, Danglars, to understand his business, for our friend Edmond seems to understand it thoroughly, and not to require instruction from any one." "Yes," said Danglars, darting at Edmond a look gleaming with hate. "Yes, he is young, and youth is invariably self-confident. Scarcely was the captain's breath out of his body when he assumed the command without consulting any one, and he caused us to lose a day and a half at the Island of Elba, instead of making for Marseilles direct." "As to taking command of the vessel," replied Morrel, "that was his duty as captain's mate; as to losing a day and a half off the Island of Elba, he was wrong, unless the vessel needed repairs." "The vessel was in as good condition as I am, and as, I hope you are, M. Morrel, and this day and a half was lost from pure whim, for the pleasure of going ashore, and nothing else." "Dantes," said the shipowner, turning towards the young man, "come this way!" "In a moment, sir," answered Dantes, "and I'm with you." Then calling to the crew, he said--"Let go!" The anchor was instantly dropped, and the chain ran rattling through the port-hole. Dantes continued at his post in spite of the presence of the pilot, until this manoeuvre was completed, and then he added, "Half-mast the colors, and square the yards!" "You see," said Danglars, "he fancies himself captain already, upon my word." "And so, in fact, he is," said the owner. "Except your signature and your partner's, M. Morrel." "And why should he not have this?" asked the owner; "he is young, it is true, but he seems to me a thorough seaman, and of full experience." A cloud passed over Danglars' brow. "Your pardon, M. Morrel," said Dantes, approaching, "the vessel now rides at anchor, and I am at your service. You hailed me, I think?" Danglars retreated a step or two. "I wished to inquire why you stopped at the Island of Elba?" "I do not know, sir; it was to fulfil the last instructions of Captain Leclere, who, when dying, gave me a packet for Marshal Bertrand." "Then did you see him, Edmond?" "Who?" "The marshal." "Yes." Morrel looked around him, and then, drawing Dantes on one side, he said suddenly--"And how is the emperor?" "Very well, as far as I could judge from the sight of him." "You saw the emperor, then?" "He entered the marshal's apartment while I was there." "And you spoke to him?" "Why, it was he who spoke to me, sir," said Dantes, with a smile. "And what did he say to you?" "Asked me questions about the vessel, the time she left Marseilles, the course she had taken, and what was her cargo. I believe, if she had not been laden, and I had been her master, he would have bought her. But I told him I was only mate, and that she belonged to the firm of Morrel & Son. 'Ah, yes,' he said, 'I know them. The Morrels have been shipowners from father to son; and there was a Morrel who served in the same regiment with me when I was in garrison at Valence.'" "Pardieu, and that is true!" cried the owner, greatly delighted. "And that was Policar Morrel, my uncle, who was afterwards a captain. Dantes, you must tell my uncle that the emperor remembered him, and you will see it will bring tears into the old soldier's eyes. Come, come," continued he, patting Edmond's shoulder kindly, "you did very right, Dantes, to follow Captain Leclere's instructions, and touch at Elba, although if it were known that you had conveyed a packet to the marshal, and had conversed with the emperor, it might bring you into trouble." "How could that bring me into trouble, sir?" asked Dantes; "for I did not even know of what I was the bearer; and the emperor merely made such inquiries as he would of the first comer. But, pardon me, here are the health officers and the customs inspectors coming alongside." And the young man went to the gangway. As he departed, Danglars approached, and said,-- "Well, it appears that he has given you satisfactory reasons for his landing at Porto-Ferrajo?" "Yes, most satisfactory, my dear Danglars." "Well, so much the better," said the supercargo; "for it is not pleasant to think that a comrade has not done his duty." "Dantes has done his," replied the owner, "and that is not saying much. It was Captain Leclere who gave orders for this delay." "Talking of Captain Leclere, has not Dantes given you a letter from him?" "To me?--no--was there one?" "I believe that, besides the packet, Captain Leclere confided a letter to his care." "Of what packet are you speaking, Danglars?" "Why, that which Dantes left at Porto-Ferrajo." "How do you know he had a packet to leave at Porto-Ferrajo?" Danglars turned very red. "I was passing close to the door of the captain's cabin, which was half open, and I saw him give the packet and letter to Dantes." "He did not speak to me of it," replied the shipowner; "but if there be any letter he will give it to me." Danglars reflected for a moment. "Then, M. Morrel, I beg of you," said he, "not to say a word to Dantes on the subject. I may have been mistaken." At this moment the young man returned; Danglars withdrew. "Well, my dear Dantes, are you now free?" inquired the owner. "Yes, sir." "You have not been long detained." "No. I gave the custom-house officers a copy of our bill of lading; and as to the other papers, they sent a man off with the pilot, to whom I gave them." "Then you have nothing more to do here?" "No--everything is all right now." "Then you can come and dine with me?" "I really must ask you to excuse me, M. Morrel. My first visit is due to my father, though I am not the less grateful for the honor you have done me." "Right, Dantes, quite right. I always knew you were a good son." "And," inquired Dantes, with some hesitation, "do you know how my father is?" "Well, I believe, my dear Edmond, though I have not seen him lately." "Yes, he likes to keep himself shut up in his little room." "That proves, at least, that he has wanted for nothing during your absence." Dantes smiled. "My father is proud, sir, and if he had not a meal left, I doubt if he would have asked anything from anyone, except from Heaven." "Well, then, after this first visit has been made we shall count on you." "I must again excuse myself, M. Morrel, for after this first visit has been paid I have another which I am most anxious to pay." "True, Dantes, I forgot that there was at the Catalans some one who expects you no less impatiently than your father--the lovely Mercedes." Dantes blushed. "Ah, ha," said the shipowner, "I am not in the least surprised, for she has been to me three times, inquiring if there were any news of the Pharaon. Peste, Edmond, you have a very handsome mistress!" "She is not my mistress," replied the young sailor, gravely; "she is my betrothed." "Sometimes one and the same thing," said Morrel, with a smile. "Not with us, sir," replied Dantes. "Well, well, my dear Edmond," continued the owner, "don't let me detain you. You have managed my affairs so well that I ought to allow you all the time you require for your own. Do you want any money?" "No, sir; I have all my pay to take--nearly three months' wages." "You are a careful fellow, Edmond." "Say I have a poor father, sir." "Yes, yes, I know how good a son you are, so now hasten away to see your father. I have a son too, and I should be very wroth with those who detained him from me after a three months' voyage." "Then I have your leave, sir?" "Yes, if you have nothing more to say to me." "Nothing." "Captain Leclere did not, before he died, give you a letter for me?" "He was unable to write, sir. But that reminds me that I must ask your leave of absence for some days." "To get married?" "Yes, first, and then to go to Paris." "Very good; have what time you require, Dantes. It will take quite six weeks to unload the cargo, and we cannot get you ready for sea until three months after that; only be back again in three months, for the Pharaon," added the owner, patting the young sailor on the back, "cannot sail without her captain." "Without her captain!" cried Dantes, his eyes sparkling with animation; "pray mind what you say, for you are touching on the most secret wishes of my heart. Is it really your intention to make me captain of the Pharaon?" "If I were sole owner we'd shake hands on it now, my dear Dantes, and call it settled; but I have a partner, and you know the Italian proverb--Chi ha compagno ha padrone--'He who has a partner has a master.' But the thing is at least half done, as you have one out of two votes. Rely on me to procure you the other; I will do my best." "Ah, M. Morrel," exclaimed the young seaman, with tears in his eyes, and grasping the owner's hand, "M. Morrel, I thank you in the name of my father and of Mercedes." "That's all right, Edmond. There's a providence that watches over the deserving. Go to your father: go and see Mercedes, and afterwards come to me." "Shall I row you ashore?" "No, thank you; I shall remain and look over the accounts with Danglars. Have you been satisfied with him this voyage?" "That is according to the sense you attach to the question, sir. Do you mean is he a good comrade? No, for I think he never liked me since the day when I was silly enough, after a little quarrel we had, to propose to him to stop for ten minutes at the island of Monte Cristo to settle the dispute--a proposition which I was wrong to suggest, and he quite right to refuse. If you mean as responsible agent when you ask me the question, I believe there is nothing to say against him, and that you will be content with the way in which he has performed his duty." "But tell me, Dantes, if you had command of the Pharaon should you be glad to see Danglars remain?" "Captain or mate, M. Morrel, I shall always have the greatest respect for those who possess the owners' confidence." "That's right, that's right, Dantes! I see you are a thoroughly good fellow, and will detain you no longer. Go, for I see how impatient you are." "Then I have leave?" "Go, I tell you." "May I have the use of your skiff?" "Certainly." "Then, for the present, M. Morrel, farewell, and a thousand thanks!" "I hope soon to see you again, my dear Edmond. Good luck to you." The young sailor jumped into the skiff, and sat down in the stern sheets, with the order that he be put ashore at La Canebiere. The two oarsmen bent to their work, and the little boat glided away as rapidly as possible in the midst of the thousand vessels which choke up the narrow way which leads between the two rows of ships from the mouth of the harbor to the Quai d'Orleans. The shipowner, smiling, followed him with his eyes until he saw him spring out on the quay and disappear in the midst of the throng, which from five o'clock in the morning until nine o'clock at night, swarms in the famous street of La Canebiere,--a street of which the modern Phocaeans are so proud that they say with all the gravity in the world, and with that accent which gives so much character to what is said, "If Paris had La Canebiere, Paris would be a second Marseilles." On turning round the owner saw Danglars behind him, apparently awaiting orders, but in reality also watching the young sailor,--but there was a great difference in the expression of the two men who thus followed the movements of Edmond Dantes. Chapter 2. Father and Son. --------------------------- We will leave Danglars struggling with the demon of hatred, and endeavoring to insinuate in the ear of the shipowner some evil suspicions against his comrade, and follow Dantes, who, after having traversed La Canebiere, took the Rue de Noailles, and entering a small house, on the left of the Allees de Meillan, rapidly ascended four flights of a dark staircase, holding the baluster with one hand, while with the other he repressed the beatings of his heart, and paused before a half-open door, from which he could see the whole of a small room. This room was occupied by Dantes' father. The news of the arrival of the Pharaon had not yet reached the old man, who, mounted on a chair, was amusing himself by training with trembling hand the nasturtiums and sprays of clematis that clambered over the trellis at his window. Suddenly, he felt an arm thrown around his body, and a well-known voice behind him exclaimed, "Father--dear father!" The old man uttered a cry, and turned round; then, seeing his son, he fell into his arms, pale and trembling. "What ails you, my dearest father? Are you ill?" inquired the young man, much alarmed. "No, no, my dear Edmond--my boy--my son!--no; but I did not expect you; and joy, the surprise of seeing you so suddenly--Ah, I feel as if I were going to die." rst2pdf-0.102/doc/montecristo/montecristo.sheet000066400000000000000000000012431463013543400216160ustar00rootroot00000000000000{ "embeddedFonts" : [["SCRIPTIN.ttf", "SCRIPTIN.ttf","SCRIPTIN.ttf","SCRIPTIN.ttf"]], "pageSetup" : { "size": "A5", "margin-top": "2cm", "margin-bottom": "2cm", "margin-left": "2cm", "margin-right": "2cm", "margin-gutter": "-1cm", "firstTemplate": "oneColumn" }, "styles" : [ ["bodytext" , { "parent": "normal", "spaceBefore":6, "alignment": "TA_JUSTIFY", "hyphenation": true }], ["footer" , { "parent": "normal", "alignment": "TA_CENTER" }], ["header" , { "parent": "normal", "alignment": "TA_CENTER" }], ["heading" , { "fontName": "SCRIPTIN" }] ] } rst2pdf-0.102/doc/output/000077500000000000000000000000001463013543400152105ustar00rootroot00000000000000rst2pdf-0.102/doc/output/.gitignore000066400000000000000000000000021463013543400171700ustar00rootroot00000000000000* rst2pdf-0.102/doc/output/html/000077500000000000000000000000001463013543400161545ustar00rootroot00000000000000rst2pdf-0.102/doc/output/html/assets/000077500000000000000000000000001463013543400174565ustar00rootroot00000000000000rst2pdf-0.102/doc/output/html/assets/.gitignore000066400000000000000000000000001463013543400214340ustar00rootroot00000000000000rst2pdf-0.102/doc/output/pdf/000077500000000000000000000000001463013543400157615ustar00rootroot00000000000000rst2pdf-0.102/doc/output/pdf/.gitignore000066400000000000000000000000001463013543400177370ustar00rootroot00000000000000rst2pdf-0.102/doc/rst2html-manual.py000077500000000000000000000023341463013543400172610ustar00rootroot00000000000000#!/usr/bin/env python3 # -*- coding: utf8 -*- # :Copyright: © 2015 Günter Milde. # :License: Released under the terms of the `2-Clause BSD license`_, in short: # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. # This file is offered as-is, without any warranty. # # .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause """ A version of rst2html5 with support for rst2pdf's custom roles/directives. """ import locale from docutils.core import default_description from docutils.core import publish_cmdline from docutils.parsers.rst import directives from rst2pdf.directives import code_block from rst2pdf.directives import noop from rst2pdf.roles import counter_off # noqa from rst2pdf.roles import package # noqa locale.setlocale(locale.LC_ALL, '') directives.register_directive('code-block', code_block.code_block_directive) directives.register_directive('oddeven', noop.noop_directive) description = ( 'Generates HTML5 documents from standalone reStructuredText ' 'sources.\n' + default_description ) publish_cmdline(writer_name='html5', description=description) rst2pdf-0.102/doc/rst2pdf.rst000066400000000000000000000134271463013543400157750ustar00rootroot00000000000000======= rst2pdf ======= ----------------------------------------- Convert reStructuredText documents to PDF ----------------------------------------- :Author: Chris Lamb for the Debian project :Manual section: 1 :Manual group: text processing SYNOPSIS -------- rst2pdf [options] [input] [-o output] DESCRIPTION ----------- The usual way of creating PDF from reStructuredText (ReST) is by going through LaTeX. The rst2pdf utility provides an alternative by producing PDF directly using the ReportLab library. OPTIONS ------- -h, --help Show this help message and exit --config=FILE Config file to use. Default=~/.rst2pdf/config -o FILE, --output=FILE Write the PDF to FILE -s STYLESHEETS, --stylesheets=STYLESHEETS A comma-separated list of custom stylesheets. Default="" --stylesheet-path=FOLDERLIST A colon-separated list of folders to search for stylesheets. Default="" -c, --compressed Create a compressed PDF. Default=False --print-stylesheet Print the default stylesheet and exit --font-folder=FOLDER Search this folder for fonts. (Deprecated) --font-path=FOLDERLIST A colon-separated list of folders to search for fonts. Default="" --baseurl=URL The base URL for relative URLs. -l LANG, --language=LANG Language to be used for hyphenation and docutils localization. Default=None --header=HEADER Page header if not specified in the document. --footer=FOOTER Page footer if not specified in the document. --section-header-depth=N Sections up to this dept will be used in the header and footer's replacement of ###Section###. Default=2 --smart-quotes=VALUE Try to convert ASCII quotes, ellipsis and dashes to the typographically correct equivalent. Default=0 The possible values are: 0. Suppress all transformations. (Do nothing.) 1. Performs default SmartyPants transformations: quotes (including backticks-style), em-dashes, and ellipses. "--" (dash dash) is used to signify an em-dash; there is no support for en-dashes. 2. Same as --smart-quotes=1, except that it uses the old-school typewriter shorthand for dashes: "--" (dash dash) for en-dashes, "---" (dash dash dash) for em-dashes. 3. Same as --smart-quotes=2, but inverts the shorthand for dashes: "--" (dash dash) for em-dashes, and "---" (dash dash dash) for en-dashes. --fit-literal-mode=MODE What to do when a literal is too wide. One of error,overflow,shrink,truncate. Default="shrink" --fit-background-mode=MODE How to fit the background image to the page. One of scale, scale_width or center. Default="center" --inline-links Shows target between parenthesis instead of active link --repeat-table-rows Repeats header row for each splitted table --raw-html Support embeddig raw HTML. Default: False -q, --quiet Print less information. -v, --verbose Print debug information. --very-verbose Print even more debug information. --version Print version number and exit. --no-footnote-backlinks Disable footnote backlinks. Default: False --inline-footnotes Show footnotes inline. Default: True --default-dpi=NUMBER DPI for objects sized in pixels. Default=300 --show-frame-boundary Show frame borders (only useful for debugging). Default=False --disable-splittables Don't use splittable flowables in some elements. Only try this if you can't process a document any other way. -b LEVEL, --break-level=LEVEL Maximum section level that starts in a new page. Default: 0 --first-page-on-right When using double sided pages, the first page will start on the right hand side. (Book Style) --blank-first-page Add a blank page at the beginning of the document. --break-side=VALUE How section breaks work. Can be "even", and sections start in an even page,"odd", and sections start in odd pages, or "any" and sections start in the next page,be it even or odd. See also the -b option. --date-invariant Don't store the current date in the PDF. Useful mainly for the test suite, where we don't want the PDFs to change. -e EXTENSIONS Alias for --extension-module --extension-module=EXTENSIONS Add a helper extension module to this invocation of rst2pdf (module must end in .py and be on the python path) --custom-cover=FILE Template file used for the cover page. Default: cover.tmpl --use-floating-images Makes images with :align: attribute work more like in rst2html. Default: False --use-numbered-links When using numbered sections, adds the numbers to all links referring to the section headers. Default: False --strip-elements-with-class=CLASS Remove elements with this CLASS from the output. Can be used multiple times. --record-dependencies=FILE Write output file dependencies to FILE. EXAMPLES -------- $ rst2pdf rest.txt -o out.pdf Produce an out.pdf file which is a PDF version of the ReST document rest.txt. rst2pdf-0.102/pyproject.toml000066400000000000000000000004271463013543400160220ustar00rootroot00000000000000[build-system] requires = ['setuptools', 'setuptools-scm', 'wheel'] [tool.black] line-length = 88 target-version = ['py36'] skip-string-normalization = true exclude = ''' ( /( \.eggs | \.git | \.tox | \.venv | build | dist )/ | tests/input ) ''' rst2pdf-0.102/requirements.txt000066400000000000000000000070231463013543400163710ustar00rootroot00000000000000# # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # # pip-compile --extra=aafiguresupport --extra=mathsupport --extra=plantumlsupport --extra=rawhtmlsupport --extra=sphinx --extra=svgsupport --extra=tests --output-file=requirements.txt setup.py # aafigure==0.6 # via rst2pdf (setup.py) alabaster==0.7.16 # via sphinx arabic-reshaper==3.0.0 # via xhtml2pdf asn1crypto==1.5.1 # via # oscrypto # pyhanko # pyhanko-certvalidator babel==2.15.0 # via sphinx certifi==2024.2.2 # via requests cffi==1.16.0 # via cryptography chardet==5.2.0 # via reportlab charset-normalizer==3.3.2 # via requests click==8.1.7 # via pyhanko contourpy==1.2.1 # via matplotlib cryptography==42.0.7 # via # pyhanko # pyhanko-certvalidator cssselect2==0.7.0 # via svglib cycler==0.12.1 # via matplotlib docutils==0.21.2 # via # rst2pdf (setup.py) # sphinx fonttools==4.52.1 # via matplotlib html5lib==1.1 # via xhtml2pdf httplib2==0.22.0 # via plantuml idna==3.7 # via requests imagesize==1.4.1 # via sphinx importlib-metadata==7.1.0 # via rst2pdf (setup.py) iniconfig==2.0.0 # via pytest jinja2==3.1.4 # via # rst2pdf (setup.py) # sphinx kiwisolver==1.4.5 # via matplotlib lxml==5.2.2 # via svglib markupsafe==2.1.5 # via jinja2 matplotlib==3.9.0 # via rst2pdf (setup.py) numpy==1.26.4 # via # contourpy # matplotlib oscrypto==1.3.0 # via pyhanko-certvalidator packaging==24.0 # via # matplotlib # pytest # rst2pdf (setup.py) # sphinx pillow==10.3.0 # via # matplotlib # reportlab # xhtml2pdf plantuml==0.3.0 # via rst2pdf (setup.py) pluggy==1.5.0 # via pytest pycparser==2.22 # via cffi pygments==2.18.0 # via # rst2pdf (setup.py) # sphinx pyhanko==0.25.0 # via xhtml2pdf pyhanko-certvalidator==0.26.3 # via # pyhanko # xhtml2pdf pymupdf==1.24.4 # via rst2pdf (setup.py) pymupdfb==1.24.3 # via pymupdf pyparsing==3.1.2 # via # httplib2 # matplotlib pypdf==4.2.0 # via xhtml2pdf pypng==0.20220715.0 # via qrcode pytest==8.2.1 # via rst2pdf (setup.py) python-bidi==0.4.2 # via xhtml2pdf python-dateutil==2.9.0.post0 # via matplotlib pyyaml==6.0.1 # via # pyhanko # rst2pdf (setup.py) qrcode==7.4.2 # via pyhanko reportlab==4.0.9 # via # rst2pdf (setup.py) # svglib # xhtml2pdf requests==2.32.2 # via # pyhanko # pyhanko-certvalidator # sphinx six==1.16.0 # via # html5lib # python-bidi # python-dateutil smartypants==2.0.1 # via rst2pdf (setup.py) snowballstemmer==2.2.0 # via sphinx sphinx==7.3.7 # via rst2pdf (setup.py) sphinxcontrib-applehelp==1.0.8 # via sphinx sphinxcontrib-devhelp==1.0.6 # via sphinx sphinxcontrib-htmlhelp==2.0.5 # via sphinx sphinxcontrib-jsmath==1.0.1 # via sphinx sphinxcontrib-qthelp==1.0.7 # via sphinx sphinxcontrib-serializinghtml==1.1.10 # via sphinx svglib==1.5.1 # via # rst2pdf (setup.py) # xhtml2pdf tinycss2==1.3.0 # via # cssselect2 # svglib typing-extensions==4.12.0 # via qrcode tzlocal==5.2 # via pyhanko uritools==4.0.2 # via pyhanko-certvalidator urllib3==2.2.1 # via requests webencodings==0.5.1 # via # cssselect2 # html5lib # tinycss2 xhtml2pdf==0.2.15 # via rst2pdf (setup.py) zipp==3.18.2 # via importlib-metadata rst2pdf-0.102/rst2pdf/000077500000000000000000000000001463013543400144675ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/__init__.py000066400000000000000000000004311463013543400165760ustar00rootroot00000000000000# See LICENSE.txt for licensing terms # TODO(stephenfin): Switch to 'importlib.metadata' once we drop support for # Python < 3.8 import importlib_metadata try: version = importlib_metadata.version('rst2pdf') except importlib_metadata.PackageNotFoundError: version = None rst2pdf-0.102/rst2pdf/basenodehandler.py000066400000000000000000000275161463013543400201720ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms ''' This module provides one useful class: NodeHandler The NodeHandler class is designed to be subclassed. Each subclass should support the processing that createpdf.RstToPdf needs to do on a particular type of node that could appear in a document tree. When the subclass is defined, it should reference NodeHandler as the first base class, and one or more docutils node classes as subsequent base classes. These docutils node classes will not actually wind up in the base classes of the subclass. Instead, they will be used as keys in a dispatch dictionary which is used to find the correct NodeHandler subclass to use to process an instance of a given docutils node class. When an instance of createpdf.RstToPdf is created, a NodeHandler instance will be called to return dispatchers for gather_elements and gather_pdftext, wrapped up as methods of the createpdf.RstToPdf class. When a dispatcher is called, it will dispatch to the correct subclass to handle the given docutils node instance. If no NodeHandler subclass has been created to handle that particular type of docutils node, then default processing will occur and a warning will be logged. ''' from copy import copy import inspect import types from smartypants import smartypants import docutils.nodes from .flowables import BoundByWidth, TocEntry from .log import log, nodeid class MetaHelper(type): """MetaHelper is designed to generically enable a few of the benefits of using metaclasses by encapsulating some of the complexity of setting them up. If a base class uses MetaHelper (by assigning __metaclass__ = MetaHelper), then that class (and its metaclass inheriting subclasses) can control class creation behavior by defining a couple of helper functions. 1) A base class can define a _classpreinit function. This function is called during __new__ processing of the class object itself, but only during subclass creation (not when the class defining the _classpreinit is itself created). The subclass object does not yet exist at the time _classpreinit is called. _classpreinit accepts all the parameters of the __new__ function for the class itself (not the same as the __new__ function for the instantiation of class objects!) and must return a tuple of the same objects. A typical use of this would be to modify the class bases before class creation. 2) Either a base class or a subclass can define a _classinit() function. This function will be called immediately after the actual class has been created, and can do whatever setup is required for the class. Note that every base class (but not every subclass) which uses MetaHelper MUST define _classinit, even if that definition is None. MetaHelper also places an attribute into each class created with it. _baseclass is set to None if this class has no superclasses which also use MetaHelper, or to the first such MetaHelper-using baseclass. _baseclass can be explicitly set inside the class definition, in which case MetaHelper will not override it. """ def __new__(clstype, name, bases, clsdict): # Our base class is the first base in the class definition which # uses MetaHelper, or None if no such base exists. base = ([x for x in bases if type(x) is MetaHelper] + [None])[0] # Only set our base into the class if it has not been explicitly # set clsdict.setdefault('_baseclass', base) # See if the base class definied a preinit function, and call it # if so. preinit = getattr(base, '_classpreinit', None) if preinit is not None: clstype, name, bases, clsdict = preinit(clstype, name, bases, clsdict) # Delegate the real work to type return type.__new__(clstype, name, bases, clsdict) def __init__(cls, name, bases, clsdict): # Let type build the class for us type.__init__(cls, name, bases, clsdict) # Call the class's initialization function if defined if cls._classinit is not None: cls._classinit() class NodeHandler(metaclass=MetaHelper): """NodeHandler classes are used to dispatch to the correct class to handle some node class type, via a dispatchdict in the main class. """ dispatchdict = {} @classmethod def _classpreinit(baseclass, clstype, name, bases, clsdict): # _classpreinit is called before the actual class is built # Perform triage on the class bases to separate actual # inheritable bases from the target docutils node classes # which we want to dispatch for. new_bases = [] targets = [] for target in bases: if target is not object: (targets, new_bases)[issubclass(target, NodeHandler)].append(target) clsdict['_targets'] = targets return clstype, name, tuple(new_bases), clsdict @classmethod def _classinit(cls): # _classinit() is called once the subclass has actually # been created. # For the base class, just add a dispatch dictionary if cls._baseclass is None: cls.dispatchdict = {} return # for subclasses, instantiate them, and then add # the class to the dispatch dictionary for each of its targets. self = cls() for target in cls._targets: if cls.dispatchdict.setdefault(target, self) is not self: t = repr(target) old = repr(cls.dispatchdict[target]) new = repr(self) log.debug( 'Dispatch handler %s for node type %s overridden by %s' % (old, t, new) ) cls.dispatchdict[target] = self @staticmethod def getclassname(obj): cln = repr(obj.__class__) info = cln.split("'") if len(info) == 3: return info[1] return cln def log_unknown(self, node, during): if not hasattr(self, 'unkn_node'): self.unkn_node = set() cln = self.getclassname(node) if cln not in self.unkn_node: self.unkn_node.add(cln) log.warning("Unkn. node (self.%s): %s [%s]", during, cln, nodeid(node)) try: log.debug(node) except (UnicodeDecodeError, UnicodeEncodeError): log.debug(repr(node)) def findsubclass(self, node, during): handlerinfo = '%s.%s' % (self.getclassname(self), during) log.debug("%s: %s", handlerinfo, self.getclassname(node)) log.debug("%s: [%s]", handlerinfo, nodeid(node)) try: log.debug("%s: %s", handlerinfo, node) except (UnicodeDecodeError, UnicodeEncodeError): log.debug("%s: %r", handlerinfo, node) log.debug("") # Dispatch to the first matching class in the MRO dispatchdict = self.dispatchdict for baseclass in inspect.getmro(node.__class__): result = dispatchdict.get(baseclass) if result is not None: break else: self.log_unknown(node, during) result = self return result def __call__(self, client): '''Get the dispatchers, wrapped up as methods for the client''' textdispatch = types.MethodType(self.textdispatch, client) elemdispatch = types.MethodType(self.elemdispatch, client) return textdispatch, elemdispatch # This overridable attribute will be set true in the instance # if handling a sphinx document sphinxmode = False # Begin overridable attributes and methods for elemdispatch def gather_elements(self, client, node, style): return client.gather_elements(node, style=style) def _get_non_default_values_from_style(self, style): """Return a dictionary of all the items in the style that are changed from their default value""" items = style.__dict__.copy() defaults = style.defaults for key in defaults.keys(): if defaults[key] == items[key]: del items[key] return items def getstyle(self, client, node, style): try: if node['classes'] and node['classes'][0]: for n in range(len(node['classes'])): if node['classes'][n] in client.styles.StyleSheet: if n == 0: style = client.styles[node['classes'][n]] else: # merge the non-default properties of this style into the style we currently have style = copy(style) items = self._get_non_default_values_from_style( client.styles[node['classes'][n]] ) items.pop("parent", None) name = f"{style.__dict__['name']}-{items['name']}" items['name'] = name style.__dict__.update(items) else: log.info( "Unknown class %s, ignoring. [%s]", node['classes'][n], nodeid(node), ) except TypeError: # Happens when a docutils.node.Text reaches here pass if style is None or style == client.styles['bodytext']: style = client.styles.styleForNode(node) return style def getelements(self, client, node, style): style = self.getstyle(client, node, style) elements = self.gather_elements(client, node, style) # Make all the sidebar cruft unreachable # if style.__dict__.get('float','None').lower() !='none': # node.elements=[Sidebar(node.elements,style)] # elif 'width' in style.__dict__: if 'width' in style.__dict__: elements = [BoundByWidth(style.width, elements, style, mode="shrink")] return elements # End overridable attributes and methods for elemdispatch def elemdispatch(self, client, node, style=None): self = self.findsubclass(node, 'elemdispatch') # set anchors for internal references try: for i in node['ids']: client.pending_targets.append(i) except TypeError: # Happens with docutils.node.Text pass elements = self.getelements(client, node, style) if node.line and client.debugLinesPdf: elements.insert(0, TocEntry(client.depth - 1, 'LINE-%s' % node.line)) node.elements = elements return elements # Begin overridable attributes and methods for textdispatch pre = '' post = '' def get_pre_post(self, client, node, replaceEnt): return self.pre, self.post def get_text(self, client, node, replaceEnt): return client.gather_pdftext(node) def apply_smartypants(self, text, smarty, node): # Try to be clever about when to use smartypants if node.__class__ in ( docutils.nodes.paragraph, docutils.nodes.block_quote, docutils.nodes.title, ): return smartypants(text, smarty) return text # End overridable attributes and methods for textdispatch def textdispatch(self, client, node, replaceEnt=True): self = self.findsubclass(node, 'textdispatch') pre, post = self.get_pre_post(client, node, replaceEnt) text = self.get_text(client, node, replaceEnt) text = pre + text + post try: log.debug("%s.textdispatch: %s" % (self.getclassname(self), text)) except UnicodeDecodeError: pass text = self.apply_smartypants(text, client.smartypants_attributes, node) node.pdftext = text return text rst2pdf-0.102/rst2pdf/config.py000066400000000000000000000015041463013543400163060ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms """Singleton config object""" import configparser import os from rst2pdf.rson import loads cfdir = os.path.join(os.path.expanduser('~'), '.rst2pdf') cfname = os.path.join(cfdir, 'config') def getValue(section, key, default=None): section = section.lower() key = key.lower() try: return loads(conf.get(section, key)) except Exception: return default class ConfigError(Exception): def __init__(self, modulename, msg): self.modulename = modulename self.msg = msg conf = configparser.ConfigParser() def parseConfig(extracf=None): global conf cflist = ["/etc/rst2pdf.conf", cfname] if extracf: cflist.append(extracf) conf = configparser.ConfigParser() conf.read(cflist) parseConfig() rst2pdf-0.102/rst2pdf/createpdf.py000066400000000000000000002023371463013543400170050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms # Some fragments of code are copied from Reportlab under this license: # ##################################################################################### # # Copyright (c) 2000-2008, ReportLab Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the company nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE OFFICERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # ##################################################################################### __docformat__ = 'reStructuredText' from importlib import import_module import sys import os import re import logging from urllib.parse import urlunparse from os.path import abspath, dirname, expanduser, join from copy import copy, deepcopy from optparse import OptionParser import docutils.readers.doctree import docutils.core import docutils.nodes from docutils.parsers.rst import directives from docutils.readers import standalone from docutils.transforms import Transform from docutils.utils import DependencyList try: from roman import toRoman except ImportError: from docutils.utils.roman import toRoman import reportlab from reportlab.lib.units import cm from reportlab.platypus import doctemplate from reportlab.platypus.doctemplate import ( ActionFlowable, BaseDocTemplate, FrameActionFlowable, IndexingFlowable, LayoutError, PageTemplate, ) from reportlab.platypus.flowables import ( _listWrapOn, _Container, Flowable, ImageAndFlowables, PageBreak, SlowPageBreak, ) from reportlab.platypus.paragraph import Paragraph from reportlab.platypus.tables import TableStyle from . import config from .utils import DependencyRecordingFileSystemLoader from rst2pdf.directives import code_block from rst2pdf import flowables from rst2pdf.flowables import ( BoundByWidth, DelayedTable, Heading, MyPageBreak, MySpacer, OddEven, Separation, SmartFrame, XXPreformatted, ) from rst2pdf.sinker import Sinker from rst2pdf.image import MyImage, missing from rst2pdf.log import log, nodeid from smartypants import smartypants from rst2pdf import styles as sty from rst2pdf.nodehandlers import nodehandlers from rst2pdf.languages import get_language_available # Template engine for covers import jinja2 # Side effects from rst2pdf.directives import aafigure # noqa from rst2pdf.directives import contents # noqa from rst2pdf.directives import oddeven # noqa from rst2pdf.roles import counter as counter_role # noqa from rst2pdf.roles import package as package_role # noqa try: import sphinx as sphinx_module except ImportError: sphinx_module = None numberingstyles = { 'arabic': 'ARABIC', 'roman': 'ROMAN_UPPER', 'lowerroman': 'ROMAN_LOWER', 'alpha': 'LETTERS_UPPER', 'loweralpha': 'LETTERS_LOWER', } class RstToPdf(object): def __init__( self, stylesheets=[], language='en_US', header=None, footer=None, inlinelinks=False, breaklevel=1, font_path=[], style_path=[], fit_mode='shrink', background_fit_mode='center', sphinx=False, smarty='0', baseurl=None, repeat_table_rows=False, footnote_backlinks=True, inline_footnotes=False, real_footnotes=False, def_dpi=300, show_frame=False, highlightlang='python', # this one is only used by Sphinx basedir=os.getcwd(), splittables=False, blank_first_page=False, first_page_on_right=False, breakside='odd', custom_cover='cover.tmpl', floating_images=False, numbered_links=False, section_header_depth=2, toc_depth=0, raw_html=False, strip_elements_with_classes=[], record_dependencies=None, ): self.debugLinesPdf = False self.depth = 0 self.breakside = breakside self.first_page_on_right = first_page_on_right self.blank_first_page = blank_first_page self.splittables = splittables self.basedir = basedir self.language, self.docutils_language = get_language_available(language)[:2] self.doc_title = "" self.doc_title_clean = "" self.doc_subtitle = "" self.doc_author = "" self.header = header self.footer = footer self.custom_cover = custom_cover self.floating_images = floating_images self.decoration = { 'header': header, 'footer': footer, 'endnotes': [], 'extraflowables': [], } # find base path if hasattr(sys, 'frozen'): self.PATH = abspath(dirname(sys.executable)) else: self.PATH = abspath(dirname(__file__)) self.font_path = font_path self.style_path = style_path self.def_dpi = def_dpi if record_dependencies is not None: self.record_dependencies = DependencyList(record_dependencies) else: self.record_dependencies = None self.loadStyles(stylesheets) self.docutils_languages = {} self.inlinelinks = inlinelinks self.breaklevel = breaklevel self.fit_mode = fit_mode self.background_fit_mode = background_fit_mode self.to_unlink = [] # See https://pythonhosted.org/smartypants/reference.html#smartypants-module self.smartypants_attributes = 0 if smarty == '1': self.smartypants_attributes = 1 | 6 | 8 | 64 | 512 elif smarty == '2': self.smartypants_attributes = 1 | 6 | 24 | 64 | 512 elif smarty == '3': self.smartypants_attributes = 1 | 6 | 40 | 64 | 512 self.baseurl = baseurl self.repeat_table_rows = repeat_table_rows self.footnote_backlinks = footnote_backlinks self.inline_footnotes = inline_footnotes self.real_footnotes = real_footnotes # Real footnotes are always a two-pass thing. if self.real_footnotes: self.mustMultiBuild = True self.def_dpi = def_dpi self.show_frame = show_frame self.numbered_links = numbered_links self.section_header_depth = section_header_depth self.toc_depth = toc_depth self.img_dir = os.path.join(self.PATH, 'images') self.raw_html = raw_html self.strip_elements_with_classes = strip_elements_with_classes # Sorry about this, but importing sphinx.roles makes some # ordinary documents fail (demo.txt specifically) so # I can' t just try to import it outside. I need # to do it only if it's requested if sphinx and sphinx_module: import sphinx.roles from rst2pdf.sphinxnodes import sphinxhandlers self.highlightlang = highlightlang self.gen_pdftext, self.gen_elements = sphinxhandlers(self) else: # These rst2pdf extensions conflict with sphinx directives.register_directive('code-block', code_block.code_block_directive) directives.register_directive('code', code_block.code_block_directive) self.gen_pdftext, self.gen_elements = nodehandlers(self) self.sphinx = sphinx if not self.styles.languages: self.styles.languages = [] if self.language: self.styles.languages.append(self.language) self.styles['bodytext'].language = self.language else: self.styles.languages.append('en_US') self.styles['bodytext'].language = 'en_US' # Load the docutils language modules for all required languages for lang in self.styles.languages: self.docutils_languages[lang] = get_language_available(lang)[2] self.pending_targets = [] self.targets = [] def loadStyles(self, styleSheets=None): if styleSheets is None: styleSheets = [] self.styles = sty.StyleSheet( styleSheets, self.font_path, self.style_path, def_dpi=self.def_dpi, record_dependencies=self.record_dependencies, ) def style_language(self, style): """Return language corresponding to this style.""" try: return style.language except AttributeError: pass try: return self.styles['bodytext'].language except AttributeError: return os.environ['LANG'] or 'en' def text_for_label(self, label, style): """Translate text for label.""" try: text = self.docutils_languages[self.style_language(style)].labels[label] except KeyError: text = label.capitalize() return text def text_for_bib_field(self, field, style): """Translate text for bibliographic fields.""" try: text = self.docutils_languages[ self.style_language(style) ].bibliographic_fields[field] except KeyError: text = field return text + ":" def author_separator(self, style): """Return separator string for authors.""" try: sep = self.docutils_languages[self.style_language(style)].author_separators[ 0 ] except KeyError: sep = ';' return sep + " " def styleToTags(self, style): """Takes a style name, returns a pair of opening/closing tags for it, like "". Used for inline nodes (custom interpreted roles)""" try: s = self.styles[style] r1 = [ '') r2 = [''] if s.strike: r1.append('') r2.insert(0, '') if s.underline: r1.append('') r2.insert(0, '') return [''.join(r1), ''.join(r2)] except KeyError: log.warning('Unknown class %s', style) return None def styleToFont(self, style): """Takes a style name, returns a font tag for it, like "". Used for inline nodes (custom interpreted roles)""" try: s = self.styles[style] r = [ '') return ''.join(r) except KeyError: log.warning('Unknown class %s', style) return None def gather_pdftext(self, node, replaceEnt=True): return ''.join([self.gen_pdftext(n, replaceEnt) for n in node.children]) def gather_elements(self, node, style=None): if style is None: style = self.styles.styleForNode(node) r = [] if 'float' in style.__dict__: style = None # Don't pass floating styles to children! for n in node.children: r.extend(self.gen_elements(n, style=style)) return r def bullet_for_node(self, node): """Takes a node, assumes it's some sort of item whose parent is a list, and returns the bullet text it should have""" b = "" t = 'item' if node.parent.get('start'): start = int(node.parent.get('start')) else: start = 1 if node.parent.get('bullet') or isinstance( node.parent, docutils.nodes.bullet_list ): b = node.parent.get('bullet', '*') if b == "None": b = "" t = 'bullet' elif node.parent.get('enumtype') == 'arabic': b = str(node.parent.children.index(node) + start) + '.' elif node.parent.get('enumtype') == 'lowerroman': b = toRoman(node.parent.children.index(node) + start).lower() + '.' elif node.parent.get('enumtype') == 'upperroman': b = toRoman(node.parent.children.index(node) + start).upper() + '.' elif node.parent.get('enumtype') == 'loweralpha': b = ( 'abcdefghijklmnopqrstuvwxyz'[ node.parent.children.index(node) + start - 1 ] + '.' ) elif node.parent.get('enumtype') == 'upperalpha': b = ( 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[ node.parent.children.index(node) + start - 1 ] + '.' ) else: log.critical("Unknown kind of list_item %s [%s]", node.parent, nodeid(node)) return b, t def filltable(self, rows): """ Takes a list of rows, consisting of cells and performs the following fixes: * For multicolumn cells, add continuation cells, to make all rows the same size. These cells have to be multirow if the original cell is multirow. * For multirow cell, insert continuation cells, to make all columns the same size. * If there are still shorter rows, add empty cells at the end (ReST quirk) * Once the table is *normalized*, create spans list, fitting for reportlab's Table class. """ # If there is a multicol cell, we need to insert Continuation Cells # to make all rows the same length for y in range(0, len(rows)): for x in range(len(rows[y]) - 1, -1, -1): cell = rows[y][x] if isinstance(cell, str): continue if cell.get("morecols"): for i in range(0, cell.get("morecols")): e = docutils.nodes.entry("") e["morerows"] = cell.get("morerows", 0) rows[y].insert(x + 1, e) for y in range(0, len(rows)): for x in range(0, len(rows[y])): cell = rows[y][x] if isinstance(cell, str): continue if cell.get("morerows"): for i in range(0, cell.get("morerows")): rows[y + i + 1].insert(x, "") # If a row is shorter, add empty cells at the right end maxw = max([len(r) for r in rows]) for r in rows: while len(r) < maxw: r.append("") # Create spans list for reportlab's table style spans = [] for y in range(0, len(rows)): for x in range(0, len(rows[y])): cell = rows[y][x] if isinstance(cell, str): continue if cell.get("morecols"): mc = cell.get("morecols") else: mc = 0 if cell.get("morerows"): mr = cell.get("morerows") else: mr = 0 if mc or mr: spans.append(('SPAN', (x, y), (x + mc, y + mr))) return spans def PreformattedFit(self, text, style): """Preformatted section that gets horizontally compressed if needed.""" # Pass a ridiculous size, then it will shrink to what's available # in the frame return BoundByWidth( 2000 * cm, content=[XXPreformatted(text, style)], mode=self.fit_mode, style=style, ) def createPdf( self, text=None, source_path=None, output=None, doctree=None, compressed=False, # This adds entries to the PDF TOC # matching the rst source lines debugLinesPdf=False, ): """Create a PDF from text (ReST input), or doctree (docutil nodes) and save it in outfile. If outfile is a string, it's a filename. If it's something with a write method, (like a StringIO, or a file object), the data is saved there. """ self.decoration = { 'header': self.header, 'footer': self.footer, 'endnotes': [], 'extraflowables': [], } self.pending_targets = [] self.targets = [] self.debugLinesPdf = debugLinesPdf if doctree is None: if text is not None: if self.language: settings_overrides = {'language_code': self.docutils_language} else: settings_overrides = {} settings_overrides[ 'strip_elements_with_classes' ] = self.strip_elements_with_classes settings_overrides['exit_status_level'] = 3 try: self.doctree = docutils.core.publish_doctree( text, source_path=source_path, settings_overrides=settings_overrides, ) log.debug(self.doctree) except Exception as e: if log.isEnabledFor(logging.INFO): # Log exception with traceback if more detailed logging has been set log.exception('Error generating doctree') else: log.error(f"Error generating doctree: {e}") log.error("Cannot generate PDF, exiting") return 1 else: log.error('Error: createPdf needs a text or a doctree') return 1 else: self.doctree = doctree if self.record_dependencies is not None: for dep in self.doctree.settings.record_dependencies.list: self.record_dependencies.add(dep) if self.numbered_links: # Transform all links to sections so they show numbers from .sectnumlinks import SectNumFolder, SectRefExpander snf = SectNumFolder(self.doctree) self.doctree.walk(snf) srf = SectRefExpander(self.doctree, snf.sectnums) self.doctree.walk(srf) if self.strip_elements_with_classes: from docutils.transforms.universal import StripClassesAndElements sce = StripClassesAndElements(self.doctree) sce.apply() if self.toc_depth == 0: # use the `:depth:` option from `.. contents::` self.toc_depth = contents.Contents.depth try: elements = self.gen_elements(self.doctree) except Exception as e: if log.isEnabledFor(logging.INFO): # Log exception with traceback if more detailed logging has been set log.exception('Error generating document elements') else: log.error(f"Error generating document elements: {e}") log.error("Cannot generate PDF, exiting") return 1 # Find cover template, save it in cover_file jinja_env = jinja2.Environment( loader=DependencyRecordingFileSystemLoader( [ self.basedir, os.path.expanduser('~/.rst2pdf'), os.path.join(self.PATH, 'templates'), ], record_dependencies=self.record_dependencies, ), autoescape=jinja2.select_autoescape(['html', 'xml']), ) try: template = jinja_env.get_template(self.custom_cover) except jinja2.TemplateNotFound: log.error("Can't find cover template %s, using default" % self.custom_cover) template = jinja_env.get_template('cover.tmpl') # Feed data to the template, get restructured text. cover_text = template.render(title=self.doc_title, subtitle=self.doc_subtitle) # This crashes sphinx because .. class:: in sphinx is # something else. Ergo, pdfbuilder does it in its own way. if not self.sphinx: elements = ( self.gen_elements( publish_secondary_doctree(cover_text, self.doctree, source_path) ) + elements ) if self.blank_first_page: elements.insert(0, PageBreak()) # Put the endnotes at the end ;-) endnotes = self.decoration['endnotes'] if endnotes: elements.append(MySpacer(1, 2 * cm)) elements.append(Separation()) for n in self.decoration['endnotes']: t_style = TableStyle(self.styles['endnote'].commands) colWidths = self.styles['endnote'].colWidths elements.append( DelayedTable([[n[0], n[1]]], colWidths=colWidths, style=t_style) ) if self.floating_images: # Handle images with alignment more like in HTML new_elem = [] for i, e in enumerate(elements[::-1]): if isinstance(e, MyImage) and e.image.hAlign != 'CENTER' and new_elem: # This is an image where flowables should wrap # around it popped = new_elem.pop() new_elem.append( ImageAndFlowables(e, popped, imageSide=e.image.hAlign.lower()) ) else: new_elem.append(e) elements = new_elem elements.reverse() head = self.decoration['header'] foot = self.decoration['footer'] # So, now, create the FancyPage with the right sizes and elements FP = FancyPage("fancypage", head, foot, self) def cleantags(s): re.sub(r'<[^>]*?>', '', str(s).strip()) pdfdoc = FancyDocTemplate( output, pageTemplates=[FP], showBoundary=0, pagesize=self.styles.ps, title=self.doc_title_clean, author=self.doc_author, pageCompression=compressed, ) pdfdoc.client = self # Handle totally empty documents (Issue #547) if not elements: elements.append(Paragraph("", style=self.styles['base'])) if getattr(self, 'mustMultiBuild', False): # Force a multibuild pass if not isinstance(elements[-1], UnhappyOnce): log.info('Forcing second pass so Total pages work') elements.append(UnhappyOnce()) while True: try: log.info("Starting build") self.elements = elements # See if this *must* be multipass pdfdoc.multiBuild(elements) # Force a multibuild pass # FIXME: since mustMultiBuild is set by the # first pass in the case of ###Total###, then we # make a new forced two-pass build. This is broken. # conceptually. if getattr(self, 'mustMultiBuild', False): # Force a multibuild pass if not isinstance(elements[-1], UnhappyOnce): log.info('Forcing second pass so Total pages work') elements.append(UnhappyOnce()) continue # Rearrange footnotes if needed if self.real_footnotes: newStory = [] fnPile = [] for e in elements: if getattr(e, 'isFootnote', False): # Add it to the pile # if not isinstance (e, MySpacer): fnPile.append(e) elif getattr(e, '_atTop', False) or isinstance( e, (UnhappyOnce, MyPageBreak) ): if fnPile: fnPile.insert(0, Separation()) newStory.append(Sinker(fnPile)) newStory.append(e) fnPile = [] else: newStory.append(e) elements = newStory + fnPile for e in elements: if hasattr(e, '_postponed'): delattr(e, '_postponed') self.real_footnotes = False continue break except ValueError: # FIXME: cross-document links come through here, which means # an extra pass per cross-document reference. Which sucks. # if v.args and str(v.args[0]).startswith('format not resolved'): # missing=str(v.args[0]).split(' ')[-1] # log.error('Adding missing reference to %s and rebuilding. This is slow!'%missing) # elements.append(Reference(missing)) # for e in elements: # if hasattr(e,'_postponed'): # delattr(e,'_postponed') # else: # raise raise # doc = SimpleDocTemplate("phello.pdf") # doc.build(elements) for fn in self.to_unlink: try: os.unlink(fn) except OSError: pass return 0 class FancyDocTemplate(BaseDocTemplate): def onProgress(self, typ, value): global _counter message = '' if typ == 'SIZE_EST': log.debug(f'Number of flowables: {value}') elif typ == 'PROGRESS': message = f'Flowable {value}' # add class name for this flowable if we can if hasattr(self.client, 'elements'): if 0 <= value < len(self.client.elements): element = self.client.elements[value] message += f" {type(element)}" log.debug(f'Page {_counter}: {message}') def afterInit(self): self.setProgressCallBack(self.onProgress) def afterFlowable(self, flowable): if isinstance(flowable, Heading): # Notify TOC entry for headings/abstracts/dedications. level, text = flowable.level, flowable.text parent_id = flowable.parent_id node = flowable.node pagenum = setPageCounter() self.notify('TOCEntry', (level, text, pagenum, parent_id, node)) def handle_flowable(self, flowables): '''try to handle one flowable from the front of list flowables.''' # this method is copied from reportlab # allow document a chance to look at, modify or ignore # the object(s) about to be processed self.filterFlowables(flowables) self.handle_breakBefore(flowables) self.handle_keepWithNext(flowables) f = flowables[0] del flowables[0] if f is None: return if isinstance(f, PageBreak): if isinstance(f, SlowPageBreak): self.handle_pageBreak(slow=1) else: self.handle_pageBreak() self.afterFlowable(f) elif isinstance(f, ActionFlowable): f.apply(self) self.afterFlowable(f) else: frame = self.frame canv = self.canv # try to fit it then draw it if frame.add(f, canv, trySplit=self.allowSplitting): if not isinstance(f, FrameActionFlowable): self._curPageFlowableCount += 1 self.afterFlowable(f) doctemplate._addGeneratedContent(flowables, frame) else: if self.allowSplitting: # see if this is a splittable thing S = frame.split(f, canv) n = len(S) else: n = 0 if n: if not isinstance(S[0], (PageBreak, SlowPageBreak, ActionFlowable)): if frame.add(S[0], canv, trySplit=0): self._curPageFlowableCount += 1 self.afterFlowable(S[0]) doctemplate._addGeneratedContent(flowables, frame) else: ident = "Splitting error(n==%d) on page %d in\n%s" % ( n, self.page, self._fIdent(f, 60, frame), ) # leave to keep apart from the raise raise LayoutError(ident) del S[0] for i, f in enumerate(S): flowables.insert(i, f) # put split flowables back on the list else: if hasattr(f, '_postponed') and f._postponed > 4: ident = ( "Flowable %s%s too large on page %d in frame %r%s of template %r" % ( self._fIdent(f, 60, frame), doctemplate._fSizeString(f), self.page, self.frame.id, self.frame._aSpaceString(), self.pageTemplate.id, ) ) # leave to keep apart from the raise raise LayoutError(ident) # this ought to be cleared when they are finally drawn! f._postponed = 1 mbe = getattr(self, '_multiBuildEdits', None) if mbe: mbe((delattr, f, '_postponed')) flowables.insert(0, f) # put the flowable back self.handle_frameEnd() _counter = 0 _counterStyle = 'arabic' class PageCounter(Flowable): def __init__(self, number=0, style='arabic'): self.style = str(style).lower() self.number = int(number) Flowable.__init__(self) def wrap(self, availWidth, availHeight): global _counter, _counterStyle _counterStyle = self.style _counter = self.number return (self.width, self.height) def drawOn(self, canvas, x, y, _sW): pass flowables.PageCounter = PageCounter def setPageCounter(counter=None, style=None): global _counter, _counterStyle if counter is not None: _counter = counter if style is not None: _counterStyle = style if _counterStyle == 'lowerroman': ptext = toRoman(_counter).lower() elif _counterStyle == 'roman': ptext = toRoman(_counter).upper() elif _counterStyle == 'alpha': ptext = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[_counter % 26] elif _counterStyle == 'loweralpha': ptext = 'abcdefghijklmnopqrstuvwxyz'[_counter % 26] else: ptext = str(_counter) return ptext class MyContainer(_Container, Flowable): pass class UnhappyOnce(IndexingFlowable): """An indexing flowable that is only unsatisfied once. If added to a story, it will make multiBuild run at least two passes. Useful for ###Total###""" _unhappy = True def isSatisfied(self): if self._unhappy: self._unhappy = False return False return True def draw(self): pass class HeaderOrFooter(object): """A helper object for FancyPage (below) HeaderOrFooter handles operations which are common to both headers and footers """ def __init__(self, items=None, isfooter=False, client=None): self.items = items if isfooter: locinfo = 'footer showFooter defaultFooter footerSeparator' else: locinfo = 'header showHeader defaultHeader headerSeparator' self.isfooter = isfooter self.loc, self.showloc, self.defaultloc, self.addsep = locinfo.split() self.totalpages = 0 self.client = client def prepare(self, pageobj, canv, doc): showloc = pageobj.template.get(self.showloc, True) height = 0 items = self.items if showloc: if not items: items = pageobj.template.get(self.defaultloc) if items: items = self.client.gen_elements( publish_secondary_doctree(items, self.client.doctree, None) ) if items: if isinstance(items, list): items = items[:] else: items = [Paragraph(items, pageobj.styles[self.loc])] addsep = pageobj.template.get(self.addsep, False) if addsep: if self.isfooter: items.insert(0, Separation()) else: items.append(Separation()) _, height = _listWrapOn(items, pageobj.tw, canv) self.prepared = height and items return height def replaceTokens(self, elems, canv, doc, smarty): """Put doc_title/page number/etc in text of header/footer.""" # Make sure page counter is up to date pnum = setPageCounter() def replace(text): # Ensure text is unicode if isinstance(text, bytes): try: text = text.decode(e.encoding) except (AttributeError, TypeError): text = text.decode('utf-8') text = text.replace(u'###Page###', pnum) if '###Total###' in text: text = text.replace(u'###Total###', str(self.totalpages)) self.client.mustMultiBuild = True text = text.replace(u"###Title###", doc.title) text = text.replace(u"###Section###", getattr(canv, 'sectName', '')) text = text.replace(u"###SectNum###", getattr(canv, 'sectNum', '')) text = smartypants(text, smarty) return text for i, e in enumerate(elems): # TODO: implement a search/replace for arbitrary things if isinstance(e, Paragraph): text = replace(e.text) elems[i] = Paragraph(text, e.style) elif isinstance(e, DelayedTable): data = deepcopy(e.data) for r, row in enumerate(data): for c, cell in enumerate(row): if isinstance(cell, list): data[r][c] = self.replaceTokens(cell, canv, doc, smarty) else: row[c] = self.replaceTokens([cell], canv, doc, smarty)[0] elems[i] = DelayedTable(data, e._colWidths, e.style) elif isinstance(e, BoundByWidth): for index, item in enumerate(e.content): if isinstance(item, Paragraph): e.content[index] = Paragraph(replace(item.text), item.style) elems[i] = e elif isinstance(e, OddEven): odd = self.replaceTokens([e.odd], canv, doc, smarty)[0] even = self.replaceTokens([e.even], canv, doc, smarty)[0] elems[i] = OddEven(odd, even) return elems def draw(self, pageobj, canv, doc, x, y, width, height): self.totalpages = max(self.totalpages, doc.page) items = self.prepared if items: self.replaceTokens(items, canv, doc, pageobj.smartypants_attributes) container = MyContainer() container._content = items container.width = width container.height = height container.drawOn(canv, x, y) class FancyPage(PageTemplate): """A page template that handles changing layouts.""" def __init__(self, _id, _head, _foot, client): self.client = client self.styles = client.styles self._head = HeaderOrFooter(_head, client=client) self._foot = HeaderOrFooter(_foot, True, client) self.smartypants_attributes = client.smartypants_attributes self.show_frame = client.show_frame self.image_cache = {} PageTemplate.__init__(self, _id, []) def draw_background(self, which, canv): """Draws a background and/or foreground image on each page which uses the template. Calculates the image one time, and caches it for reuse on every page in the template. How the background is drawn depends on the --fit-background-mode option. If desired, we could add code to push it around on the page, using stylesheets to align and/or set the offset. """ uri = self.template[which] background_fit_mode = self.client.background_fit_mode if 'background_fit_mode' in self.template: background_fit_mode = self.template['background_fit_mode'] info = self.image_cache.get(f"{uri}{background_fit_mode}") if info is None: fname, _, _ = MyImage.split_uri(uri) if not os.path.exists(fname): del self.template[which] log.error("Missing %s image file: %s", which, uri) return try: w, h, _ = MyImage.size_for_node( dict( uri=uri, ), self.client, ) except ValueError: # Broken image, return arbitrary stuff uri = missing w, h, = ( 100, 100, ) pw, ph = self.styles.pw, self.styles.ph if background_fit_mode == 'center': scale = min(1.0, 1.0 * pw / w, 1.0 * ph / h) sw, sh = w * scale, h * scale x, y = (pw - sw) / 2.0, (ph - sh) / 2.0 elif background_fit_mode == 'scale': x, y = 0, 0 sw, sh = pw, ph elif background_fit_mode == 'scale_width': x, y = 0, 0 sw, sh = pw, h else: log.error('Unknown background fit mode: %s' % background_fit_mode) # Do scale anyway x, y = 0, 0 sw, sh = pw, ph bg = MyImage(uri, sw, sh, client=self.client) self.image_cache[uri] = info = bg, x, y bg, x, y = info bg.drawOn(canv, x, y) def is_left(self, page_num): """Default behavior is that the first page is on the left. If the user has --first_page_on_right, the calculation is reversed. """ val = page_num % 2 == 1 if self.client.first_page_on_right: val = not val return val def beforeDrawPage(self, canv, doc): """Do adjustments to the page according to where we are in the document. * Gutter margins on left or right as needed """ global _counter, _counterStyle styles = self.styles self.tw = styles.pw - styles.lm - styles.rm - styles.gm # What page template to use? tname = canv.__dict__.get('templateName', self.styles.firstTemplate) if tname not in self.styles.pageTemplates: log.error(f"Template '{tname}' is not defined") sys.exit(1) self.template = self.styles.pageTemplates[tname] canv.templateName = tname # Any background with fit mode? background = canv.__dict__.get('background', None) if background: self.template = self.template.copy() self.template['background'] = background background_fit_mode = canv.__dict__.get('background_fit_mode', None) if background_fit_mode: self.template['background_fit_mode'] = background_fit_mode doct = getattr(canv, '_doctemplate', None) canv._doctemplate = None # to make _listWrapOn work if doc.page == 1: _counter = 0 _counterStyle = 'arabic' _counter += 1 # Adjust text space accounting for header/footer self.hh = self._head.prepare(self, canv, doc) self.fh = self._foot.prepare(self, canv, doc) canv._doctemplate = doct self.hx = styles.lm self.hy = styles.ph - styles.tm - self.hh self.fx = styles.lm self.fy = styles.bm self.th = ( styles.ph - styles.tm - styles.bm - self.hh - self.fh - styles.ts - styles.bs ) # Adjust gutter margins if self.is_left(doc.page): # Left page x1 = styles.lm else: # Right page x1 = styles.lm + styles.gm y1 = styles.bm + self.fh + styles.bs # If there is a background parameter for this page Template, draw it if 'background' in self.template: self.draw_background('background', canv) self.frames = [] if 'frames' not in self.template: log.error('No frames in template') sys.exit(1) for frame in self.template['frames']: frame = frame[:] while len(frame) < 8: # This is the default in SmartFrame. At some point in the future we # may want to change this to 0. frame.append(6) self.frames.append( SmartFrame( self, styles.adjustUnits(frame[0], self.tw) + x1, styles.adjustUnits(frame[1], self.th) + y1, styles.adjustUnits(frame[2], self.tw), styles.adjustUnits(frame[3], self.th), leftPadding=styles.adjustUnits(frame[4], self.tw), bottomPadding=styles.adjustUnits(frame[5], self.th), rightPadding=styles.adjustUnits(frame[6], self.tw), topPadding=styles.adjustUnits(frame[7], self.th), showBoundary=self.show_frame, ) ) canv.firstSect = True canv._pagenum = doc.page for frame in self.frames: frame._pagenum = doc.page def afterDrawPage(self, canv, doc): """Draw header/footer.""" # Adjust for gutter margin canv.addPageLabel( canv._pageNumber - 1, numberingstyles[_counterStyle], _counter ) log.info('Page %s [%s]' % (_counter, doc.page)) if self.is_left(doc.page): # Left page hx = self.hx fx = self.fx else: # Right Page hx = self.hx + self.styles.gm fx = self.fx + self.styles.gm self._head.draw(self, canv, doc, hx, self.hy, self.tw, self.hh) self._foot.draw(self, canv, doc, fx, self.fy, self.tw, self.fh) # If there is a foreground parameter for this page Template, draw it if 'foreground' in self.template: self.draw_background('foreground', canv) def parse_commandline(): parser = OptionParser() parser.add_option( '--config', dest='configfile', metavar='FILE', help='Config file to use. Default=~/.rst2pdf/config', ) parser.add_option( '-o', '--output', dest='output', metavar='FILE', help='Write the PDF to FILE' ) def_ssheets = ','.join( [ expanduser(p) for p in config.getValue("general", "stylesheets", "").split(',') ] ) parser.add_option( '-s', '--stylesheets', dest='style', type='string', action='append', metavar='STYLESHEETS', default=[def_ssheets], help='A comma-separated list of custom stylesheets. Default="%s"' % def_ssheets, ) def_sheetpath = os.pathsep.join( [ expanduser(p) for p in config.getValue("general", "stylesheet_path", "").split(os.pathsep) ] ) parser.add_option( '--stylesheet-path', dest='stylepath', metavar='FOLDER%sFOLDER%s...%sFOLDER' % ((os.pathsep,) * 3), default=def_sheetpath, help='A list of folders to search for stylesheets,' ' separated using "%s". Default="%s"' % (os.pathsep, def_sheetpath), ) def_compressed = config.getValue("general", "compressed", False) parser.add_option( '-c', '--compressed', dest='compressed', action="store_true", default=def_compressed, help='Create a compressed PDF. Default=%s' % def_compressed, ) parser.add_option( '--print-stylesheet', dest='printssheet', action="store_true", default=False, help='Print the default stylesheet and exit', ) parser.add_option( '--font-folder', dest='ffolder', metavar='FOLDER', help='Search this folder for fonts. (Deprecated)', ) def_fontpath = os.pathsep.join( [ expanduser(p) for p in config.getValue("general", "font_path", "").split(os.pathsep) ] ) parser.add_option( '--font-path', dest='fpath', metavar='FOLDER%sFOLDER%s...%sFOLDER' % ((os.pathsep,) * 3), default=def_fontpath, help='A list of folders to search for fonts, separated using "%s".' ' Default="%s"' % (os.pathsep, def_fontpath), ) def_baseurl = urlunparse(['file', os.getcwd() + os.sep, '', '', '', '']) parser.add_option( '--baseurl', dest='baseurl', metavar='URL', default=def_baseurl, help='The base URL for relative URLs. Default="%s"' % def_baseurl, ) def_lang = config.getValue("general", "language", 'en_US') parser.add_option( '-l', '--language', metavar='LANG', default=def_lang, dest='language', help='Language to be used for hyphenation' ' and docutils localizations. Default="%s"' % def_lang, ) def_header = config.getValue("general", "header") parser.add_option( '--header', metavar='HEADER', default=def_header, dest='header', help='Page header if not specified in the document.' ' Default="%s"' % def_header, ) def_footer = config.getValue("general", "footer") parser.add_option( '--footer', metavar='FOOTER', default=def_footer, dest='footer', help='Page footer if not specified in the document.' ' Default="%s"' % def_footer, ) def_section_header_depth = config.getValue("general", "section_header_depth", 2) parser.add_option( '--section-header-depth', metavar='N', default=def_section_header_depth, dest='section_header_depth', help='''Sections up to this depth will be used in the header and footer's replacement of ###Section###. Default=%s''' % def_section_header_depth, ) def_smartquotes = config.getValue("general", "smartquotes", "0") parser.add_option( "--smart-quotes", metavar="VALUE", default=def_smartquotes, dest="smarty", help='Try to convert ASCII quotes, ellipses and dashes' ' to the typographically correct equivalent. For details,' ' read the man page or the manual. Default="%s"' % def_smartquotes, ) def_fit = config.getValue("general", "fit_mode", "shrink") parser.add_option( '--fit-literal-mode', metavar='MODE', default=def_fit, dest='fit_mode', help='What to do when a literal is too wide. One of error,' ' overflow,shrink,truncate. Default="%s"' % def_fit, ) def_fit_background = config.getValue("general", "background_fit_mode", "center") parser.add_option( '--fit-background-mode', metavar='MODE', default=def_fit_background, dest='background_fit_mode', help='How to fit the background image to the page.' ' One of scale, scale_width or center. Default="%s"' % def_fit_background, ) parser.add_option( '--inline-links', action="store_true", dest='inlinelinks', default=False, help='Shows target between parentheses instead of active link.', ) parser.add_option( '--repeat-table-rows', action="store_true", dest='repeattablerows', default=False, help='Repeats header row for each split table.', ) def_raw_html = config.getValue("general", "raw_html", False) parser.add_option( '--raw-html', action="store_true", dest='raw_html', default=def_raw_html, help='Support embedding raw HTML. Default=%s' % def_raw_html, ) parser.add_option( '-q', '--quiet', action="store_true", dest='quiet', default=False, help='Print less information.', ) parser.add_option( '-v', '--verbose', action="store_true", dest='verbose', default=False, help='Print debug information.', ) parser.add_option( '--very-verbose', action="store_true", dest='vverbose', default=False, help='Print even more debug information.', ) parser.add_option( '--version', action="store_true", dest='version', default=False, help='Print version number and exit.', ) def_footnote_backlinks = config.getValue("general", "footnote_backlinks", True) parser.add_option( '--no-footnote-backlinks', action='store_false', dest='footnote_backlinks', default=def_footnote_backlinks, help='Disable footnote backlinks.' ' Default=%s' % str(not def_footnote_backlinks), ) def_inline_footnotes = config.getValue("general", "inline_footnotes", False) parser.add_option( '--inline-footnotes', action='store_true', dest='inline_footnotes', default=def_inline_footnotes, help='Show footnotes inline.' ' Default=%s' % str(not def_inline_footnotes), ) def_real_footnotes = config.getValue("general", "real_footnotes", False) parser.add_option( '--real-footnotes', action='store_true', dest='real_footnotes', default=def_real_footnotes, help='Show footnotes at the bottom of the page where they are defined.' ' Default=%s' % str(def_real_footnotes), ) def_dpi = config.getValue("general", "default_dpi", 300) parser.add_option( '--default-dpi', dest='def_dpi', metavar='NUMBER', default=def_dpi, help='DPI for objects sized in pixels. Default=%d' % def_dpi, ) parser.add_option( '--show-frame-boundary', dest='show_frame', action='store_true', default=False, help='Show frame borders (only useful for debugging). Default=False', ) parser.add_option( '--disable-splittables', dest='splittables', action='store_false', default=True, help="Don't use splittable flowables in some elements." " Only try this if you can't process a document any other way.", ) def_break = config.getValue("general", "break_level", 0) parser.add_option( '-b', '--break-level', dest='breaklevel', metavar='LEVEL', default=def_break, help='Maximum section level that starts in a new page.' ' Default: %d' % def_break, ) def_blankfirst = config.getValue("general", "blank_first_page", False) parser.add_option( '--blank-first-page', dest='blank_first_page', action='store_true', default=def_blankfirst, help='Add a blank page at the beginning of the document.', ) def_first_page_on_right = config.getValue("general", "first_page_on_right", False) parser.add_option( '--first-page-on-right', dest='first_page_on_right', action='store_true', default=def_first_page_on_right, help='Two-sided book style (where first page starts on the right side)', ) def_breakside = config.getValue("general", "break_side", 'any') parser.add_option( '--break-side', dest='breakside', metavar='VALUE', default=def_breakside, help='How section breaks work. Can be "even", and sections start' ' in an even page, "odd", and sections start in odd pages,' ' or "any" and sections start in the next page, be it even or odd.' ' See also the -b option.', ) parser.add_option( '--date-invariant', dest='invariant', action='store_true', default=False, help="Don't store the current date in the PDF." " Useful mainly for the test suite," " where we don't want the PDFs to change.", ) parser.add_option( '-e', '--extension-module', dest='extensions', action="append", type="string", default=[], help="Add a helper extension module to this invocation of rst2pdf " "(module must end in .py and be on the python path)", ) def_cover = config.getValue("general", "custom_cover", 'cover.tmpl') parser.add_option( '--custom-cover', dest='custom_cover', metavar='FILE', default=def_cover, help='Template file used for the cover page. Default: %s' % def_cover, ) def_floating_images = config.getValue("general", "floating_images", False) parser.add_option( '--use-floating-images', action='store_true', default=def_floating_images, help='Makes images with :align: attribute work more like in rst2html. Default: %s' % def_floating_images, dest='floating_images', ) def_numbered_links = config.getValue("general", "numbered_links", False) parser.add_option( '--use-numbered-links', action='store_true', default=def_numbered_links, help='When using numbered sections, adds the numbers to all links referring to the section headers. Default: %s' % def_numbered_links, dest='numbered_links', ) parser.add_option( '--strip-elements-with-class', action='append', dest='strip_elements_with_classes', metavar='CLASS', help='Remove elements with this CLASS from the output. Can be used multiple times.', ) parser.add_option( '--record-dependencies', dest='record_dependencies', metavar='FILE', default=False, help='Write output file dependencies to FILE', ) return parser def main(_args=None): """Parse command line and call createPdf with the correct data.""" parser = parse_commandline() # Fix issue 430: don't overwrite args # need to parse_args to see i we have a custom config file options, args = parser.parse_args(copy(_args)) if options.configfile: # If there is a config file, we need to reparse # the command line because we have different defaults config.parseConfig(options.configfile) parser = parse_commandline() options, args = parser.parse_args(copy(_args)) if options.version: from rst2pdf import version print(version) sys.exit(0) if options.quiet: log.setLevel(logging.CRITICAL) if options.verbose: log.setLevel(logging.INFO) if options.vverbose: log.setLevel(logging.DEBUG) if options.printssheet: # find base path if hasattr(sys, 'frozen'): PATH = abspath(dirname(sys.executable)) else: PATH = abspath(dirname(__file__)) with open(join(PATH, 'styles', 'styles.yaml')) as fh: print(fh.read()) sys.exit(0) filename = False if len(args) == 0: args = [ '-', ] elif len(args) > 2: log.critical('Usage: %s [ file.txt [ file.pdf ] ]', sys.argv[0]) sys.exit(1) elif len(args) == 2: if options.output: log.critical('You may not give both "-o/--output" and second argument') sys.exit(1) options.output = args.pop() close_infile = False if args[0] == '-': infile = sys.stdin options.basedir = os.getcwd() elif len(args) > 1: log.critical('Usage: %s file.txt [ -o file.pdf ]', sys.argv[0]) sys.exit(1) else: filename = args[0] options.basedir = os.path.dirname(os.path.abspath(filename)) try: infile = open(filename, 'rb') close_infile = True except IOError as e: log.error(e) sys.exit(1) options.infile = infile if options.output: outfile = options.output if outfile == '-': outfile = sys.stdout.buffer options.compressed = False # we must stay quiet log.setLevel(logging.CRITICAL) else: if filename: if filename.endswith('.txt') or filename.endswith('.rst'): outfile = filename[:-4] + '.pdf' else: outfile = filename + '.pdf' else: outfile = sys.stdout.buffer options.compressed = False # we must stay quiet log.setLevel(logging.CRITICAL) # /reportlab/pdfbase/pdfdoc.py output can # be a callable (stringio, stdout ...) options.outfile = outfile ssheet = [] if options.style: for l in options.style: ssheet += l.split(',') else: ssheet = [] options.style = [x for x in ssheet if x] fpath = [] if options.fpath: fpath = options.fpath.split(os.pathsep) if options.ffolder: fpath.append(options.ffolder) options.fpath = fpath spath = [] if options.stylepath: spath = options.stylepath.split(os.pathsep) options.stylepath = spath if options.real_footnotes: options.inline_footnotes = True if reportlab.Version < '3.0': log.warning( 'You are using Reportlab version %s.' ' The suggested version is 3.0 or higher' % reportlab.Version ) if options.invariant: patch_PDFDate() patch_digester() add_extensions(options) return_code = RstToPdf( stylesheets=options.style, language=options.language, header=options.header, footer=options.footer, inlinelinks=options.inlinelinks, breaklevel=int(options.breaklevel), baseurl=options.baseurl, fit_mode=options.fit_mode, background_fit_mode=options.background_fit_mode, smarty=str(options.smarty), font_path=options.fpath, style_path=options.stylepath, repeat_table_rows=options.repeattablerows, footnote_backlinks=options.footnote_backlinks, inline_footnotes=options.inline_footnotes, real_footnotes=options.real_footnotes, def_dpi=int(options.def_dpi), basedir=options.basedir, show_frame=options.show_frame, splittables=options.splittables, blank_first_page=options.blank_first_page, first_page_on_right=options.first_page_on_right, breakside=options.breakside, custom_cover=options.custom_cover, floating_images=options.floating_images, numbered_links=options.numbered_links, raw_html=options.raw_html, section_header_depth=int(options.section_header_depth), strip_elements_with_classes=options.strip_elements_with_classes, record_dependencies=options.record_dependencies, ).createPdf( text=options.infile.read(), source_path=options.infile.name, output=options.outfile, compressed=options.compressed, ) if close_infile: infile.close() sys.exit(return_code) # Ugly hack that fixes Issue 335 reportlab.lib.utils.ImageReader.__deepcopy__ = lambda self, *x: copy(self) def patch_digester(): """Patch digester so that we can get the same results when image filenames change""" import reportlab.pdfgen.canvas as canvas cache = {} def _digester(s): index = cache.setdefault(s, len(cache)) return 'rst2pdf_image_%s' % index canvas._digester = _digester def patch_PDFDate(): '''Patch reportlab.pdfdoc.PDFDate so the invariant dates work correctly''' from reportlab.pdfbase import pdfdoc import reportlab class PDFDate(pdfdoc.PDFObject): __PDFObject__ = True # gmt offset now suppported def __init__(self, invariant=True, ts=None, dateFormatter=None): now = (2000, 0o1, 0o1, 00, 00, 00, 0) self.date = now[:6] self.dateFormatter = dateFormatter def format(self, doc): dfmt = self.dateFormatter or ( lambda yyyy, mm, dd, hh, m, s: "D:%04d%02d%02d%02d%02d%02d%+03d'%02d'" % (yyyy, mm, dd, hh, m, s, 0, 0) ) return pdfdoc.format(pdfdoc.PDFString(dfmt(*self.date)), doc) pdfdoc.PDFDate = PDFDate reportlab.rl_config.invariant = 1 def add_extensions(options): extensions = [] for ext in options.extensions: if not ext.startswith('!'): extensions.append(ext) continue ext = ext[1:] try: extensions.remove(ext) except ValueError: log.warning( 'Could not remove extension %s -- no such extension installed' % ext ) else: log.info('Removed extension %s' % ext) options.extensions[:] = extensions if not extensions: return class ModuleProxy(object): def __init__(self): self.__dict__ = globals() createpdf = ModuleProxy() for modname in options.extensions: prefix, modname = os.path.split(modname) path_given = prefix if modname.endswith('.py'): modname = modname[:-3] path_given = True if not prefix: prefix = os.path.join(os.path.dirname(__file__), 'extensions') if prefix not in sys.path: sys.path.append(prefix) prefix = os.getcwd() if prefix not in sys.path: sys.path.insert(0, prefix) log.info('Importing extension module %s', repr(modname)) firstname = path_given and modname or (modname + '_r2p') _names = [firstname, modname] import_exc = None for _name in _names: try: module = import_module(_name, 'rst2pdf') break except ImportError as e: import_exc = e else: if not import_exc: continue if str(import_exc).split()[-1].replace("'", '') not in [firstname, modname]: raise import_exc raise SystemExit( '\nError: Could not find module %s in sys.path [\n %s\n]\n' 'Exiting...\n' % (modname, ',\n '.join(sys.path)) ) if hasattr(module, 'install'): module.install(createpdf, options) def publish_secondary_doctree(text, main_tree, source_path): # This is a hack so the text substitutions defined # in the document are available when we process the cover # page. See Issue 322 dt = main_tree # Add substitutions from the main doctree class addSubsts(Transform): default_priority = 219 def apply(self): self.document.substitution_defs.update(dt.substitution_defs) self.document.substitution_names.update(dt.substitution_names) # Use an own reader to modify transformations done. class Reader(standalone.Reader): def get_transforms(self): default = standalone.Reader.get_transforms(self) return default + [ addSubsts, ] # End of Issue 322 hack return docutils.core.publish_doctree(text, reader=Reader(), source_path=source_path) if __name__ == "__main__": main(sys.argv[1:]) rst2pdf-0.102/rst2pdf/directives/000077500000000000000000000000001463013543400166305ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/directives/__init__.py000066400000000000000000000000001463013543400207270ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/directives/aafigure.py000066400000000000000000000067211463013543400207730ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2009 by Leandro Lucarella, Roberto Alsina # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from docutils.nodes import Element, literal_block from docutils.parsers.rst import directives from docutils.parsers import rst from reportlab.graphics import renderPDF from ..log import log try: import aafigure import aafigure.pdf except ImportError: aafigure = None WARNED = False class Aanode(Element): children = () def __init__(self, content, options, rawsource='', *children, **attributes): self.content = content self.options = options Element.__init__(self, rawsource, *children, **attributes) def copy(self, **attributes): return Aanode(self.content, self.options, **self.attributes) def gen_flowable(self, style_options): options = dict(style_options) # explicit :option: always precedes options.update(self.options) visitor = aafigure.process( '\n'.join(self.content), aafigure.pdf.PDFOutputVisitor, options=options, ) return renderPDF.GraphicsFlowable(visitor.drawing) class Aafig(rst.Directive): """ Directive to insert an ASCII art figure to be rendered by aafigure. """ has_content = True required_arguments = 0 optional_arguments = 0 final_argument_whitespace = False option_spec = dict( scale=float, line_width=float, background=str, foreground=str, fill=str, name=str, aspect=float, textual=directives.flag, proportional=directives.flag, ) def run(self): global WARNED if 'textual' in self.options: self.options['textual'] = True if 'proportional' in self.options: self.options['proportional'] = True if aafigure is not None: return [Aanode(self.content, self.options)] if not WARNED: log.error( 'To render the aafigure directive correctly, please install aafigure' ) WARNED = True return [literal_block(text='\n'.join(self.content))] directives.register_directive('aafig', Aafig) directives.register_directive('aafigure', Aafig) rst2pdf-0.102/rst2pdf/directives/code_block.py000066400000000000000000000352301463013543400212710ustar00rootroot00000000000000# -*- coding: utf-8 -*- # :Author: a Pygments author|contributor; Felix Wiemann; Guenter Milde # :Date: $Date$ # :Copyright: This module has been placed in the public domain. # # This is a merge of `Using Pygments in ReST documents`_ from the pygments_ # documentation, and a `proof of concept`_ by Felix Wiemann. # # ========== =========================================================== # 2007-06-01 Removed redundancy from class values. # 2007-06-04 Merge of successive tokens of same type # (code taken from pygments.formatters.others). # 2007-06-05 Separate docutils formatter script # Use pygments' CSS class names (like the html formatter) # allowing the use of pygments-produced style sheets. # 2007-06-07 Merge in the formatting of the parsed tokens # (misnamed as docutils_formatter) as class DocutilsInterface # 2007-06-08 Failsave implementation (fallback to a standard literal block # if pygments not found) # ========== =========================================================== # # :: """Define and register a code-block directive using pygments""" # Requirements # ------------ # :: import codecs from docutils import nodes from docutils.parsers.rst import directives try: import pygments from pygments.lexers import get_lexer_by_name from pygments.formatters.html import _get_ttype_class except ImportError: pass from ..log import log # Customisation # ------------- # # Do not insert inline nodes for the following tokens. # (You could add e.g. Token.Punctuation like ``['', 'p']``.) :: unstyled_tokens = [''] # DocutilsInterface # ----------------- # # This interface class combines code from # pygments.formatters.html and pygments.formatters.others. # # It does not require anything of docutils and could also become a part of # pygments:: class DocutilsInterface(object): """Parse `code` string and yield "classified" tokens. Arguments code -- string of source code to parse language -- formal language the code is written in. Merge subsequent tokens of the same token-type. Yields the tokens as ``(ttype_class, value)`` tuples, where ttype_class is taken from pygments.token.STANDARD_TYPES and corresponds to the class argument used in pygments html output. """ def __init__(self, code, language, custom_args={}): self.code = code self.language = language self.custom_args = custom_args def lex(self): # Get lexer for language (use text as fallback) try: if self.language and str(self.language).lower() != 'none': lexer = get_lexer_by_name(self.language.lower(), **self.custom_args) else: lexer = get_lexer_by_name('text', **self.custom_args) except ValueError: log.info("no pygments lexer for %s, using 'text'" % self.language) # what happens if pygment isn't present ? lexer = get_lexer_by_name('text') return pygments.lex(self.code, lexer) def join(self, tokens): """join subsequent tokens of same token-type""" tokens = iter(tokens) (lasttype, lastval) = next(tokens) for ttype, value in tokens: if ttype is lasttype: lastval += value else: yield (lasttype, lastval) (lasttype, lastval) = (ttype, value) yield (lasttype, lastval) def __iter__(self): """parse code string and yield "clasified" tokens""" try: tokens = self.lex() except IOError: log.info("Pygments lexer not found, using fallback") # TODO: write message to INFO yield ('', self.code) return for ttype, value in self.join(tokens): yield (_get_ttype_class(ttype), value) # code_block_directive # -------------------- # :: def code_block_directive( name, arguments, options, content, lineno, content_offset, block_text, state, state_machine, ): """Parse and classify content of a code_block.""" if 'include' in options: try: if 'encoding' in options: encoding = options['encoding'] else: encoding = 'utf-8' content = codecs.open(options['include'], 'r', encoding).read().rstrip() except (IOError, UnicodeError): # no file or problem finding it or reading it log.error('Error reading file: "%s" L %s' % (options['include'], lineno)) content = u'' line_offset = 0 if content: # here we define the start-at and end-at options # so that limit is included in extraction # this is different than the start-after directive of docutils # (docutils/parsers/rst/directives/misc.py L73+) # which excludes the beginning # the reason is we want to be able to define a start-at like # def mymethod(self) # and have such a definition included after_text = options.get('start-at', None) if after_text: # skip content in include_text before *and NOT incl.* a matching text after_index = content.find(after_text) if after_index < 0: raise state_machine.reporter.severe( 'Problem with "start-at" option of "%s" ' 'code-block directive:\nText not found.' % options['start-at'] ) # patch mmueller start # Move the after_index to the beginning of the line with the # match. for char in content[after_index:0:-1]: # codecs always opens binary. This works with '\n', '\r' and # '\r\n'. We are going backwards, so '\n' is found first # in '\r\n'. # Going with .splitlines() seems more appropriate # but needs a few more changes. if char == u'\n' or char == u'\r': break after_index -= 1 # patch mmueller end content = content[after_index:] line_offset = len(content[:after_index].splitlines()) - 1 after_text = options.get('start-after', None) if after_text: # skip content in include_text before *and incl.* a matching text after_index = content.find(after_text) if after_index < 0: raise state_machine.reporter.severe( 'Problem with "start-after" option of "%s" ' 'code-block directive:\nText not found.' % options['start-after'] ) after_index = after_index + len(after_text) # Move the after_index to the start of the line after the match for char in content[after_index:]: if char == u'\n': break after_index += 1 line_offset = len(content[:after_index].splitlines()) content = content[after_index:] # same changes here for the same reason before_text = options.get('end-at', None) if before_text: # skip content in include_text after *and incl.* a matching text before_index = content.find(before_text) if before_index < 0: raise state_machine.reporter.severe( 'Problem with "end-at" option of "%s" ' 'code-block directive:\nText not found.' % options['end-at'] ) content = content[: before_index + len(before_text)] before_text = options.get('end-before', None) if before_text: # skip content in include_text after *and NOT incl.* a matching text before_index = content.find(before_text) if before_index < 0: raise state_machine.reporter.severe( 'Problem with "end-before" option of "%s" ' 'code-block directive:\nText not found.' % options['end-before'] ) content = content[:before_index] else: line_offset = options.get('linenos_offset') content = u'\n'.join(content) if 'tabsize' in options: tabw = options['tabsize'] else: tabw = int(options.get('tab-width', 8)) content = content.replace('\t', ' ' * tabw) hl_lines = options.get('hl_lines', []) withln = 'linenos' in options if 'linenos_offset' not in options: line_offset = 0 try: language = arguments[0] except IndexError: language = 'text' # create a literal block element and set class argument code_block = nodes.literal_block(classes=["code", language]) lineno = 1 + line_offset total_lines = content.count('\n') + 1 + line_offset if withln: lnwidth = len(str(total_lines)) fstr = "\n%%%dd " % lnwidth linenumber_cls = 'linenumber' if hl_lines and lineno not in hl_lines: linenumber_cls = 'pygments-diml' code_block += nodes.inline( fstr[1:] % lineno, fstr[1:] % lineno, classes=[linenumber_cls] ) # parse content with pygments and add to code_block element for cls, value in DocutilsInterface(content, language, options): if hl_lines and lineno not in hl_lines: cls = "diml" if withln and "\n" in value: # Split on the "\n"s values = value.split("\n") # The first piece, pass as-is c = '' if cls != '': c = 'pygments-diml' code_block += nodes.inline(values[0], values[0], classes=[c]) # On the second and later pieces, insert \n and linenos linenos = range(lineno, lineno + len(values)) for chunk, ln in list(zip(values, linenos))[1:]: if ln <= total_lines: linenumber_cls = 'linenumber' c = '' if hl_lines and (ln) not in hl_lines: linenumber_cls = 'pygments-diml' c = 'pygments-diml' code_block += nodes.inline( fstr % ln, fstr % ln, classes=[linenumber_cls] ) code_block += nodes.inline(chunk, chunk, classes=[c]) lineno += len(values) - 1 elif cls in unstyled_tokens: if "\n" in value: lineno = lineno + value.count("\n") # insert as Text to decrease the verbosity of the output. code_block += nodes.Text(value, value) else: if "\n" in value: lineno = lineno + value.count("\n") code_block += nodes.inline(value, value, classes=["pygments-" + cls]) return [code_block] # Custom argument validators # -------------------------- # :: # # Move to separated module?? def zero_or_positive_int(argument): """ Converts a string into python positive integer including zero. None is a special case; it is regarded as zero. """ if argument is None: return 0 elif argument == '0': return 0 else: return directives.positive_int(argument) def string_list(argument): """ Converts a space- or comma-separated list of values into a python list of strings. (Directive option conversion function) Based in positive_int_list of docutils.parsers.rst.directives """ if ',' in argument: entries = argument.split(',') else: entries = argument.split() return entries def string_bool(argument): """ Converts True, true, False, False in python boolean values """ if argument is None: msg = 'argument required but none supplied; choose from "True" or "False"' raise ValueError(msg) elif argument.lower() == 'true': return True elif argument.lower() == 'false': return False else: raise ValueError('"%s" unknown; choose from "True" or "False"' % argument) def csharp_unicodelevel(argument): return directives.choice(argument, ('none', 'basic', 'full')) def lhs_litstyle(argument): return directives.choice(argument, ('bird', 'latex')) def raw_compress(argument): return directives.choice(argument, ('gz', 'bz2')) # Register Directive # ------------------ # :: code_block_directive.arguments = (0, 1, 1) code_block_directive.content = 1 code_block_directive.options = { 'include': directives.unchanged_required, 'start-at': directives.unchanged_required, 'end-at': directives.unchanged_required, 'start-after': directives.unchanged_required, 'end-before': directives.unchanged_required, 'linenos': directives.unchanged, 'linenos_offset': zero_or_positive_int, 'tab-width': directives.unchanged, 'hl_lines': directives.positive_int_list, # generic 'stripnl': string_bool, 'stripall': string_bool, 'ensurenl': string_bool, 'tabsize': directives.positive_int, 'encoding': directives.encoding, # Lua 'func_name_hightlighting': string_bool, 'disabled_modules': string_list, # Python Console 'python3': string_bool, # Delphi 'turbopascal': string_bool, 'delphi': string_bool, 'freepascal': string_bool, 'units': string_list, # Modula2 'pim': string_bool, 'iso': string_bool, 'objm2': string_bool, 'gm2ext': string_bool, # CSharp 'unicodelevel': csharp_unicodelevel, # Literate haskell 'litstyle': lhs_litstyle, # Raw 'compress': raw_compress, # Rst 'handlecodeblocks': string_bool, # Php 'startinline': string_bool, 'funcnamehighlighting': string_bool, 'disabledmodules': string_list, } # .. _doctutils: http://docutils.sf.net/ # .. _pygments: http://pygments.org/ # .. _Using Pygments in ReST documents: http://pygments.org/docs/rstdirective/ # .. _proof of concept: # http://article.gmane.org/gmane.text.docutils.user/3689 # # Test output # ----------- # # If called from the command line, call the docutils publisher to render the # input:: if __name__ == '__main__': from docutils.core import publish_cmdline, default_description from docutils.parsers.rst import directives directives.register_directive('code-block', code_block_directive) description = "code-block directive test output" + default_description try: import locale locale.setlocale(locale.LC_ALL, '') except Exception: pass publish_cmdline(writer_name='html', description=description) rst2pdf-0.102/rst2pdf/directives/contents.py000066400000000000000000000043711463013543400210440ustar00rootroot00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2021 by Rob Allen # All rights reserved. # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. from docutils.parsers.rst import directives from docutils.parsers.rst.directives.parts import Contents as BaseContents class Contents(BaseContents): """Override the standard docutils contents directive to get access to the depth option If it is not set, then assign to a very large number which will effectively be unlimited. """ depth = 9999 def __init__( self, name, arguments, options, content, lineno, content_offset, block_text, state, state_machine, ): super().__init__( name, arguments, options, content, lineno, content_offset, block_text, state, state_machine, ) Contents.depth = options['depth'] if 'depth' in options else Contents.depth directives._directives['contents'] = Contents rst2pdf-0.102/rst2pdf/directives/noop.py000066400000000000000000000004411463013543400201540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms def noop_directive( name, arguments, options, content, lineno, content_offset, block_text, state, state_machine, ): node_list = [] return node_list noop_directive.content = ["*"] rst2pdf-0.102/rst2pdf/directives/oddeven.py000066400000000000000000000016221463013543400206270ustar00rootroot00000000000000# -*- coding: utf-8 -*- """A custom directive that allows alternative contents to be generated on odd and even pages.""" from docutils.parsers import rst from docutils.nodes import Admonition, Element from docutils.parsers.rst import directives class OddEvenNode(Admonition, Element): pass class OddEven(rst.Directive): """A custom directive that allows alternative contents to be generated on odd and even pages. It can contain only two children, so use containers to group them. The first one is odd, the second is even.""" required_arguments = 0 optional_arguments = 0 final_argument_whitespace = True option_spec = {} has_content = True def run(self): self.assert_has_content() node = OddEvenNode() self.state.nested_parse(self.content, self.content_offset, node) return [node] directives.register_directive("oddeven", OddEven) rst2pdf-0.102/rst2pdf/dumpstyle.py000077500000000000000000000115241463013543400170750ustar00rootroot00000000000000#!/usr/bin/env python ''' Call dumps() to dump a stylesheet to a string. Or run the script to dump all .json in the styles directory to .style in the styles directory. ''' import sys import os from rst2pdf.rson import loads as rloads from json import loads as jloads def dumps(obj, forcestyledict=True): """If forcestyledict is True, will attempt to turn styles into a dictionary. """ def dofloat(result, obj, indent): s = '%.3f' % obj while '.' in s and s.endswith('0'): s = s[:-1] result.append(s) def doint(result, obj, indent): if isinstance(obj, bool): obj = repr(obj).lower() result.append(str(obj)) badch = set('[]{}:=,"\n') def dostr(result, obj, indent): try: float(obj) except ValueError: ok = True else: ok = obj == obj.strip() ok = ok and not set(obj) & badch if ok: result.append(obj) return obj = obj.replace('\\', '\\\\').replace('\n', '\\n') obj = obj.replace('"', '\\"') result.append('"%s"' % obj) def dolist(result, obj, indent): if indent: if not obj: result.append('[]') return elif isinstance(obj[0], list): result.append('[]') indent += ' ' for item in obj: dumprecurse(result, item, indent) return result.append('[') obj = [[x, ', '] for x in obj] obj[-1][-1] = ']' for item, separator in obj: dumprecurse(result, item, '') result.append(separator) def dodict(result, obj, indent): if not obj: result.append('{}') return obj = sorted(obj.items()) multiline = indent and ( len(obj) > 2 or len(obj) == 2 and ( isinstance(obj[0][-1], (list, dict)) or isinstance(obj[-1][-1], (list, dict)) ) ) if not multiline and (not indent or len(obj) != 1): result.append('{') obj = [[x, ', '] for x in obj] obj[-1][-1] = '}' for (key, value), separator in obj: dumprecurse(result, key, '') result.append(': ') dumprecurse(result, value, '') result.append(separator) return doindent = len(obj) > 1 for key, value in obj: dumprecurse(result, key, indent, doindent) result.append(': ') dumprecurse(result, value, indent + ' ', False) def donone(result, obj, indent): result.append('null') dumpfuncs = { float: dofloat, int: doint, str: dostr, list: dolist, dict: dodict, type(None): donone, } dumpfuncs = dumpfuncs.items() def dumprecurse(result, obj, indent='\n', indentnow=True): if indentnow: result.append(indent) for otype, ofunc in dumpfuncs: if isinstance(obj, otype): return ofunc(result, obj, indent) raise ValueError(repr(obj)) result = [] if forcestyledict: obj = fixstyle(obj) dumprecurse(result, obj, indentnow=False) return fixspacing(''.join(result)) def fixspacing(s): """Try to make the output prettier by inserting blank lines in random places. """ result = [] indent = -1 for line in s.splitlines(): line = line.rstrip() # Some lines had ' ' if not line: continue indent, previndent = len(line) - len(line.lstrip()), indent if indent <= previndent and indent < 8: if indent < previndent or not indent: result.append('') result.append(line) result.append('') return '\n'.join(result) def fixstyle(obj): """Try to convert styles into a dictionary""" if obj: if isinstance(obj, list): lengths = [len(x) for x in obj] if min(lengths) == max(lengths) == 2: obj = dict(obj) elif isinstance(obj, dict) and 'styles' in obj: obj['styles'] = dict(obj['styles']) return obj def convert(srcname): """Convert a single file from .json to .style""" print(srcname) sstr = open(srcname, 'rb').read() sdata = fixstyle(jloads(sstr)) dstr = dumps(sdata) assert sdata == rloads(dstr), "Bad round-trip" dstname = srcname.replace('.json', '.style') dstf = open(dstname, 'wb') dstf.write(dstr) dstf.close() if __name__ == '__main__': _dir = os.path.dirname(sys.argv[0]) _stylesdir = os.path.join(_dir, 'styles') for fname in [ os.path.join('styles', x) for x in os.listdir(_stylesdir) if x.endswith('.json') ]: convert(fname) rst2pdf-0.102/rst2pdf/extensions/000077500000000000000000000000001463013543400166665ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/extensions/__init__.py000066400000000000000000000004001463013543400207710ustar00rootroot00000000000000''' This place-holder module makes the extensions directory into a Python "package", so that external user-specific modules can act as umbrella modules, and, for example: import rst2pdf.extensions.preprocess_r2p to bring in the preprocess extension. ''' rst2pdf-0.102/rst2pdf/extensions/dotted_toc.py000066400000000000000000000135171463013543400213770ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms # Some fragments of code are copied from Reportlab under this license: # ##################################################################################### # # Copyright (c) 2000-2008, ReportLab Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the company nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE OFFICERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # ##################################################################################### from copy import copy from reportlab.platypus import Spacer from reportlab.platypus.tableofcontents import drawPageNumbers import rst2pdf.genelements as genelements Table = genelements.Table Paragraph = genelements.Paragraph ''' .. NOTE: THIS IS A HUGE HACK HACK HACK All I did was take the wrap() method from the stock reportlab TOC generator, and make the minimal changes to make it work on MY documents in rst2pdf. **History:** The reportlab TOC generator adds nice dots between the text and the page number. The rst2pdf one does not. A closer examination reveals that the rst2pdf one probably deliberately stripped this code, because the reportlab implementation only allowed a single TOC, and this is unacceptable for at least some rst2pdf users. There are other differences in the rst2pdf one I don't understand. This module is a hack to add back dots between the lines. Maybe at some point we can figure out if this is right, or how to support dots in the TOC in the main code. Mind you, the original RL implementation is a complete hack in any case: - It uses a callback to a nested function which doesn't even bother to assume the original enclosing scope is available at callback time. This leads it to do crazy things like eval() - It uses a single name in the canvas for the callback function (this is what kills multiple TOC capability) when it would be extremely easy to generate a unique name. ''' class DottedTableOfContents(genelements.MyTableOfContents): toc_counter = [0] def wrap(self, availWidth, availHeight): "All table properties should be known by now." # makes an internal table which does all the work. # we draw the LAST RUN's entries! If there are # none, we make some dummy data to keep the table # from complaining if len(self._lastEntries) == 0: _tempEntries = [(0, 'Placeholder for table of contents', 0, None)] else: _tempEntries = self._lastEntries if _tempEntries: base_level = _tempEntries[0][0] else: base_level = 0 def drawTOCEntryEnd(canvas, kind, label): '''Callback to draw dots and page numbers after each entry.''' style, page, key, dot = end_info[int(label)] drawPageNumbers(canvas, style, [(page, key)], availWidth, availHeight, dot) toc_counter = self.toc_counter toc_counter[0] += 1 funcname = 'drawTOCEntryEnd%s' % toc_counter[0] setattr(self.canv, funcname, drawTOCEntryEnd) end_info = [] tableData = [] for entry in _tempEntries: level, text, pageNum = entry[:3] left_col_level = level - base_level style = self.getLevelStyle(left_col_level) if self.dotsMinLevel >= 0 and left_col_level >= self.dotsMinLevel: dot = ' . ' else: dot = '' style = copy(style) style.textColor = self.linkColor key = self.refid_lut.get((level, text, pageNum), None) if key: if not isinstance(text, str): text = str(text, 'utf-8') text = u'%s' % (key, text) para = Paragraph( '%s' % (text, funcname, len(end_info)), style, ) end_info.append((style, pageNum, key, dot)) if style.spaceBefore: tableData.append([Spacer(1, style.spaceBefore)]) tableData.append([para]) self._table = Table(tableData, colWidths=(availWidth,), style=self.tableStyle) self.width, self.height = self._table.wrapOn(self.canv, availWidth, availHeight) return self.width, self.height genelements.MyTableOfContents = DottedTableOfContents rst2pdf-0.102/rst2pdf/extensions/fancytitles.py000066400000000000000000000127041463013543400215710ustar00rootroot00000000000000# -*- coding: utf-8 -*- import codecs import tempfile import docutils from reportlab.platypus.paragraph import Paragraph import rst2pdf.genelements as genelements from rst2pdf.flowables import Heading, MyPageBreak from rst2pdf.image import MyImage class FancyTitleHandler(genelements.HandleParagraph, docutils.nodes.title): """ This class will handle title nodes. It takes a "titletemplate.svg", replaces TITLEGOESHERE with the actual title text, and draws that using the FancyHeading flowable (see below). Since this class is defined in an extension, it effectively replaces rst2pdf.genelements.HandleTitle. """ def gather_elements(self, client, node, style): # This method is copied from the HandleTitle class # in rst2pdf.genelements. # Special cases: (Not sure this is right ;-) if isinstance(node.parent, docutils.nodes.document): # node.elements = [Paragraph(client.gen_pdftext(node), # client.styles['title'])] # The visible output is now done by the cover template node.elements = [] client.doc_title = node.rawsource client.doc_title_clean = node.astext().strip() elif isinstance(node.parent, docutils.nodes.topic): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['topic-title']) ] elif isinstance(node.parent, docutils.nodes.Admonition): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['admonition-title']) ] elif isinstance(node.parent, docutils.nodes.table): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['table-title']) ] elif isinstance(node.parent, docutils.nodes.sidebar): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['sidebar-title']) ] else: # Section/Subsection/etc. text = client.gen_pdftext(node) fch = node.children[0] if isinstance(fch, docutils.nodes.generated) and fch['classes'] == [ 'sectnum' ]: snum = fch.astext() else: snum = None maxdepth = 6 # The parent ID is the refid + an ID to make it unique for Sphinx parent_id = (node.parent.get('ids', [None]) or [None])[0] + u'-%s' % id( node ) if client.depth > 1: node.elements = [ Heading( text, client.styles['heading%d' % min(client.depth, maxdepth)], level=client.depth - 1, parent_id=parent_id, node=node, ) ] else: # This is an important title, do our magic ;-) # Hack the title template SVG tfile = codecs.open('titletemplate.svg', 'r', 'utf-8') tdata = tfile.read() tfile.close() tfile = tempfile.NamedTemporaryFile( dir='.', delete=False, suffix='.svg' ) tfname = tfile.name tfile.write(tdata.replace('TITLEGOESHERE', text).encode('utf-8')) tfile.close() # Now tfname contains a SVG with the right title. # Make rst2pdf delete it later. client.to_unlink.append(tfname) e = FancyHeading( tfname, width=700, height=100, client=client, snum=snum, parent_id=parent_id, text=text, hstyle=client.styles['heading%d' % min(client.depth, maxdepth)], ) node.elements = [e] if client.depth <= client.breaklevel: node.elements.insert(0, MyPageBreak(breakTo=client.breakside)) return node.elements class FancyHeading(MyImage, Heading): """This is a cross between the Heading flowable, that adds outline entries so you have a PDF TOC, and MyImage, that draws images""" def __init__(self, *args, **kwargs): # The inicialization is taken from rst2pdf.flowables.Heading hstyle = kwargs.pop('hstyle') level = 0 text = kwargs.pop('text') self.snum = kwargs.pop('snum') self.parent_id = kwargs.pop('parent_id') # self.stext = Heading.__init__(self, text, hstyle, level=level, parent_id=self.parent_id) # Cleanup title text # self.stext = re.sub(r'<[^>]*?>', '', unescape(self.stext)) # self.stext = self.stext.strip() # Stuff needed for the outline entry MyImage.__init__(self, *args, **kwargs) def drawOn(self, canv, x, y, _sW): # Add outline entry. This is copied from rst2pdf.flowables.heading canv.bookmarkHorizontal(self.parent_id, 0, y + self.image.height) if canv.firstSect: canv.sectName = self.stext canv.firstSect = False if self.snum is not None: canv.sectNum = self.snum else: canv.sectNum = "" canv.addOutlineEntry(self.stext, self.parent_id, int(self.level), False) # And let MyImage do all the drawing MyImage.drawOn(self, canv, x, y, _sW) rst2pdf-0.102/rst2pdf/extensions/plantuml_r2p.py000066400000000000000000000061141463013543400216610ustar00rootroot00000000000000''' A rst2pdf extension to implement something similar to sphinx's plantuml extension (see http://pypi.python.org/pypi/sphinxcontrib-plantuml) Therefore, stuff may be copied from that code. Ergo: :copyright: Copyright 2010 by Yuya Nishihara . :license: BSD, (he says see LICENSE but the file is not there ;-) ''' import errno import subprocess import tempfile from docutils import nodes from docutils.parsers import rst from docutils.parsers.rst import directives import rst2pdf.genelements as genelements from rst2pdf.image import MyImage from rst2pdf.styles import adjustUnits class plantuml(nodes.General, nodes.Element): pass class UmlDirective(rst.Directive): """Directive to insert PlantUML markup Example:: .. uml:: :alt: Alice and Bob Alice -> Bob: Hello Alice <- Bob: Hi You can use a :format: option to change between SVG and PNG diagrams, however, the SVG plantuml generates doesn't look very good to me. Also, :width: and :height: are supported as per the image directive. """ has_content = True option_spec = { 'alt': directives.unchanged, 'format': directives.unchanged, 'width': directives.length_or_unitless, 'height': directives.length_or_unitless, } def run(self): node = plantuml() node['uml'] = '\n'.join(self.content) node['alt'] = self.options.get('alt', None) node['format'] = self.options.get('format', 'png') node['width'] = self.options.get('width', None) node['height'] = self.options.get('height', None) return [node] class PlantUmlError(Exception): pass class UMLHandler(genelements.NodeHandler, plantuml): """Class to handle UML nodes""" def gather_elements(self, client, node, style): # Create image calling plantuml tfile = tempfile.NamedTemporaryFile( dir='.', delete=False, suffix='.' + node['format'] ) args = 'plantuml -pipe -charset utf-8' if node['format'].lower() == 'svg': args += ' -tsvg' client.to_unlink.append(tfile.name) try: p = subprocess.Popen( args.split(), stdout=tfile, stdin=subprocess.PIPE, stderr=subprocess.PIPE, ) except OSError as err: if err.errno != errno.ENOENT: raise raise PlantUmlError( 'plantuml command %r cannot be run' % self.builder.config.plantuml ) serr = p.communicate(node['uml'].encode('utf-8'))[1] if p.returncode != 0: raise PlantUmlError('error while running plantuml\n\n' + serr) # Convert width and height if necessary w = node['width'] if w is not None: w = adjustUnits(w) h = node['height'] if h is not None: h = adjustUnits(h) # Add Image node with the right image return [MyImage(tfile.name, client=client, width=w, height=h)] directives.register_directive("uml", UmlDirective) rst2pdf-0.102/rst2pdf/extensions/preprocess_r2p.py000066400000000000000000000316711463013543400222200ustar00rootroot00000000000000# -*- coding: utf-8 -*- # An extension module for rst2pdf # Copyright 2010, Patrick Maupin # See LICENSE.txt for licensing terms ''' preprocess is a rst2pdf extension module (invoked by ``-e preprocess`` on the rst2pdf command line). There is a testcase for this file at tests/test_preprocess.txt This preprocesses the source text file before handing it to docutils. This module serves two purposes: 1) It demonstrates the technique and can be a starting point for similar user-written processing modules; and 2) It provides a simplified syntax for documents which are targeted only at rst2pdf, rather than docutils in general. The design goal of "base rst2pdf" is to be completely compatible with docutils, such that a file which works as a PDF can also work as HTML, etc. Unfortunately, base docutils is a slow-moving target, and does not make this easy. For example, SVG images do not work properly with the HTML backend unless you install a patch, and docutils has no concept of page breaks or additional vertical space (other than the
). So, while it would be nice to have documents that render perfectly with any backend, this goal is hard to achieve for some documents, and once you are restricted to a particular transformation type, then you might as well have a slightly nicer syntax for your source document. ----------------------------------------------------------------- Preprocessor extensions: All current extensions except style occupy a single line in the source file. ``.. include::`` Processes the include file as well. An include file may either be a restructured text file, OR may be an RSON or JSON stylesheet. The determination is made by trying to parse it as RSON. If it passes, it is a stylesheet; if not, well, we'll let the docutils parser have its way with it. ``.. page::`` Is translated into a raw PageBreak. ``.. space::`` Is translated into a raw Spacer. If only one number given, is used for vertical space. This is the canonical use case, since horizontal space is ignored anyway! ``.. style::`` Allows you to create in-line stylesheets. As with other restructured text components, the stylesheet data must be indented. Stylesheets are in RSON or JSON. ``.. widths::`` creates a new table style (based on table or the first non-numeric token) and creates a class using that style specifically for the next table in the document. (Creates a .. class::, so you must specify .. widths:: immediately before the table it applies to. Allows you to set the widths for the table, using percentages. ``SingleWordAtLeftColumn`` If a single word at the left column is surrounded by blank lines, the singleword style is automatically applied to the word. This is a workaround for the broken interaction between docutils subtitles and bibliographic metadata. (I found that docutils was referencing my subtitles from inside the TOC, and that seemed silly. Perhaps there is a better workaround at a lower level in rst2pdf.) ----------------------------------------------------------------- Preprocessor operation: The preprocessor generates a file that has the same name as the source file, with .build_temp. embedded in the name, and then passes that file to the restructured text parser. This file is left on the disk after operation, because any error messages from docutils will refer to line numbers in it, rather than in the original source, so debugging could be difficult if the file were automatically removed. ''' import os import re from rst2pdf.log import log from rst2pdf.rson import loads as rson_loads class DummyFile(object): """Stores the path and content of a file which may, or may not, have been written to disk. """ def __init__(self, name, content): self.name = name self._content = content def read(self): return self._content class Preprocess(object): def __init__(self, sourcef, incfile=False, widthcount=0): """Process a file and decorate the resultant Preprocess instance with self.result (the preprocessed file) and self.styles (extracted stylesheet information) for the caller. """ # fix keywords dict for use by the parser. self.keywords = dict( [(x + '::', getattr(self, 'handle_' + x)) for x in self.keywords] ) self.widthcount = widthcount name = sourcef.name source = sourcef.read() if isinstance(source, bytes): source = source.decode('utf8') source = source.replace('\r\n', '\n').replace('\r', '\n') # Make the determination if an include file is a stylesheet or # another restructured text file, and handle stylesheets appropriately. if incfile: try: self.styles = styles = rson_loads(source) substyles = styles.get('styles') if substyles is not None: styles['styles'] = dict(substyles) except Exception: pass else: self.changed = True self.keep = False return # Read the whole file and wrap it in a DummyFile self.sourcef = DummyFile(name, source) # Use a regular expression on the source, to take it apart # and put it back together again. self.source = source = [x for x in self.splitter(source) if x] self.result = result = [] self.styles = {} self.changed = False # More efficient to pop() a list than to keep taking tokens from [0] source.reverse() isblank = False keywords = self.keywords handle_single = keywords['single::'] while source: wasblank = isblank isblank = False chunk = source.pop() result.append(chunk) # Only process single lines if not chunk.endswith('\n'): continue result[-1] = chunk[:-1] if chunk.index('\n') != len(chunk) - 1: continue # Parse the line to look for one of our keywords. tokens = chunk.split() isblank = not tokens if len(tokens) >= 2 and tokens[0] == '..' and tokens[1].endswith('::'): func = keywords.get(tokens[1]) if func is None: continue chunk = chunk.split('::', 1)[1] elif ( wasblank and len(tokens) == 1 and chunk[0].isalpha() and tokens[0].isalpha() ): func = handle_single chunk = tokens[0] else: continue result.pop() func(chunk.strip()) # Determine if we actually did anything or not. Just use our source file # if not. Otherwise, write the results to disk (so the user can use them # for debugging) and return them. if self.changed: result.append('') result = DummyFile(name + '.build_temp', '\n'.join(result)) self.keep = keep = len(result.read().strip()) if keep: f = open(result.name, 'w') # Can call read a second time here because it's a DummyFile: f.write(result.read()) f.close() self.result = result else: self.result = self.sourcef def handle_include(self, fname): # Ugly, violates DRY, etc., but I'm not about to go # figure out how to re-use docutils include file # path processing! for prefix in ('', os.path.dirname(self.sourcef.name)): try: f = open(os.path.join(prefix, fname), 'r') except IOError: continue else: break else: log.error("Could not find include file %s", fname) self.changed = True return # Recursively call this class to process include files. # Extract all the information from the included file. inc = Preprocess(f, True, self.widthcount) self.widthcount = inc.widthcount if 'styles' in self.styles and 'styles' in inc.styles: self.styles['styles'].update(inc.styles.pop('styles')) self.styles.update(inc.styles) if inc.changed: self.changed = True if not inc.keep: return fname = inc.result.name self.result.extend(['', '', '.. include:: ' + fname, '']) def handle_single(self, word): """Prepend the singleword class in front of the word.""" self.changed = True self.result.extend(['', '', '.. class:: singleword', '', word, '']) def handle_page(self, chunk): """Insert a raw pagebreak""" self.changed = True self.result.extend(['', '', '.. raw:: pdf', '', ' PageBreak ' + chunk, '']) def handle_space(self, chunk): """Insert a raw space""" self.changed = True if len(chunk.replace(',', ' ').split()) == 1: chunk = '0 ' + chunk self.result.extend(['', '', '.. raw:: pdf', '', ' Spacer ' + chunk, '']) def handle_widths(self, chunk): """Insert a unique style in the stylesheet, and reference it from a .. class:: comment. """ self.changed = True chunk = chunk.replace(',', ' ').replace('%', ' ').split() if not chunk: log.error('no widths specified in .. widths ::') return parent = chunk[0][0].isalpha() and chunk.pop(0) or 'table' values = [float(x) for x in chunk] total = sum(values) values = [int(round(100 * x / total)) for x in values] while 1: total = sum(values) if total > 100: values[values.index(max(values))] -= 1 elif total < 100: values[values.index(max(values))] += 1 else: break values = ['%s%%' % x for x in values] self.widthcount += 1 stylename = 'embeddedtablewidth%d' % self.widthcount self.styles.setdefault('styles', {})[stylename] = dict( parent=parent, colWidths=values ) self.result.extend(['', '', '.. class:: ' + stylename, '']) def handle_style(self, chunk): """Parse through the source until we find lines that are no longer indented, then pass our indented lines to the RSON parser. """ self.changed = True if chunk: log.error(".. style:: does not recognize string %s" % repr(chunk)) return mystyles = '\n'.join(self.read_indented()) if not mystyles: log.error("Empty .. style:: block found") try: styles = rson_loads(mystyles) except ValueError as e: # Error parsing the JSON data log.critical('Error parsing stylesheet "%s": %s' % (mystyles, str(e))) else: self.styles.setdefault('styles', {}).update(styles) def read_indented(self): """Read data from source while it is indented (or blank). Stop on the first non-indented line, and leave the rest on the source. """ source = self.source data = None while source and not data: data = source and source.pop().splitlines() or [] data.reverse() while data: line = data.pop().rstrip() if not line or line.lstrip() != line: yield line continue data.append(line) break data.reverse() data.append('') source.append('\n'.join(data)) source.append('\n') # Automatically generate our keywords from methods prefixed with 'handle_' keywords = list(x[7:] for x in vars() if x.startswith('handle_')) # Generate the regular expression for parsing, and a split function using it. blankline = r'^([ \t]*\n)' singleword = r'^([A-Za-z]+[ \t]*\n)(?=[ \t]*\n)' comment = r'^(\.\.[ \t]+(?:%s)\:\:.*\n)' % '|'.join(keywords) expression = '(?:%s)' % '|'.join([blankline, singleword, comment]) splitter = re.compile(expression, re.MULTILINE).split class MyStyles(str): """This class conforms to the styles.py processing requirements for a stylesheet that is not really a file. It must be callable(), and str(x) must return the name of the stylesheet. """ def __new__(cls, styles): self = str.__new__(cls, 'Embedded Preprocess Styles') self.data = styles return self def __call__(self): return self.data def install(createpdf, options): """This is where we intercept the document conversion. Preprocess the restructured text, and insert our new styles (if any). """ data = Preprocess(options.infile) options.infile = data.result if data.styles: options.style.append(MyStyles(data.styles)) rst2pdf-0.102/rst2pdf/extensions/sample.py000066400000000000000000000012511463013543400205200ustar00rootroot00000000000000print( ''' This is a sample rst2pdf extension. Because it is named 'sample.py' you can get rst2pdf to import it by putting '-e sample' on the rst2pdf command line. An extension is called after the command-line is parsed, and can monkey-patch any necessary changes into rst2pdf. An extension can live either in the extensions subdirectory, or anywhere on the python path. ''' ) def install(createpdf, options): """This function is called with an object with the createpdf module globals as attributes, and with the options from the command line parser. This function does not have to exist, but must have the correct call signature if it does. """ rst2pdf-0.102/rst2pdf/findfonts.py000077500000000000000000000320561463013543400170440ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms """ Scan a list of folders and find all .afm files, then create rst2pdf-ready font-aliases. """ import os import subprocess import sys from fnmatch import fnmatch from reportlab.lib.fonts import addMapping from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import ( FF_FORCEBOLD, FF_ITALIC, TTFError, TTFont, TTFontFile, ) from rst2pdf.log import log flist = [] afmList = [] pfbList = {} ttfList = [] # Aliases defined by GhostScript, so if you use Palatino or whatever you # may get **something**. They are family name aliases. Alias = { "itc bookman": "urw bookman l", "itc avant garde gothic": "urw gothic l", "palatino": "urw palladio l", "new century schoolbook": "century schoolbook l", "itc zapf chancery": "urw chancery l", } # Standard PDF fonts, so no need to embed them Ignored = ["times", "itc zapf dingbats", "symbol", "helvetica", "courier"] fonts = {} families = {} fontMappings = {} def make_string(b): if isinstance(b, bytes): return b.decode('utf-8') return b def loadFonts(): """ Search the system and build lists of available fonts. """ if not any([afmList, pfbList, ttfList]): # FIXME: When we drop support por py2, use recursive globs for folder in flist: for root, _, files in os.walk(folder): for f in files: if fnmatch(f, "*.ttf") or fnmatch(f, "*.ttc"): ttfList.append(os.path.join(root, f)) elif fnmatch(f, "*.afm"): afmList.append(os.path.join(root, f)) elif fnmatch(f, "*.pfb"): pfbList[f[:-4]] = os.path.join(root, f) for ttf in ttfList: try: font = TTFontFile(ttf) except TTFError: log.warning("Error processing %s", ttf) continue family = make_string(font.familyName.lower()) fontName = make_string(font.name).lower() baseName = os.path.basename(ttf)[:-4] fullName = make_string(font.fullName).lower() for k in (fontName, fullName, fullName.replace("italic", "oblique")): fonts[k] = (ttf, ttf, family) bold = FF_FORCEBOLD == FF_FORCEBOLD & font.flags italic = FF_ITALIC == FF_ITALIC & font.flags # And we can try to build/fill the family mapping if family not in families: families[family] = [fontName, fontName, fontName, fontName] if bold and italic: families[family][3] = fontName elif bold: families[family][1] = fontName elif italic: families[family][2] = fontName # FIXME: what happens if there are Demi and Medium # weights? We get a random one. else: families[family][0] = fontName # Now we have full afm and pbf lists, process the # afm list to figure out family name, weight and if # it's italic or not, as well as where the # matching pfb file is for afm in afmList: family = None fontName = None italic = False bold = False for line in open(afm, "r"): line = line.strip() if line.startswith("StartCharMetrics"): break elif line.startswith("FamilyName"): family = line.split(" ", 1)[1].lower() elif line.startswith("FontName"): fontName = line.split(" ")[1] elif line.startswith("FullName"): fullName = line.split(" ", 1)[1] elif line.startswith("Weight"): bold = line.split(" ")[1] == "Bold" elif line.startswith("ItalicAngle"): italic = line.split(" ")[1] != "0.0" baseName = os.path.basename(afm)[:-4] if family in Ignored or family in Alias: continue if baseName not in pfbList: log.info("afm file without matching pfb file: %s" % baseName) continue # So now we have a font we know we can embed. for n in ( fontName.lower(), fullName.lower(), fullName.lower().replace("italic", "oblique"), ): fonts[n] = (afm, pfbList[baseName], family) # And we can try to build/fill the family mapping if family not in families: families[family] = [fontName, fontName, fontName, fontName] if bold and italic: families[family][3] = fontName elif bold: families[family][1] = fontName elif italic: families[family][2] = fontName # FIXME: what happens if there are Demi and Medium # weights? We get a random one. else: families[family][0] = fontName def findFont(fname): loadFonts() # So now we are sure we know the families and font # names. Well, return some data! fname = fname.lower() if fname in fonts: font = fonts[fname.lower()] else: if fname in Alias: fname = Alias[fname] if fname in families: font = fonts[families[fname][0].lower()] else: return None return font def findTTFont(fname): def get_family(query): data = make_string(subprocess.check_output(["fc-match", query])) for line in data.splitlines(): line = line.strip() if not line: continue family = line.split('"')[1].replace('"', "") if family: return family return None def get_fname(query): data = make_string(subprocess.check_output(["fc-match", "-v", query])) for line in data.splitlines(): line = line.strip() if line.startswith("file: "): return line.split('"')[1] return None def get_variants(family): variants = [ get_fname(family + ":style=Roman"), get_fname(family + ":style=Bold"), get_fname(family + ":style=Oblique"), get_fname(family + ":style=Bold Oblique"), ] if variants[2] == variants[0]: variants[2] = get_fname(family + ":style=Italic") if variants[3] == variants[0]: variants[3] = get_fname(family + ":style=Bold Italic") if variants[0].endswith(".pfb") or variants[0].endswith(".gz"): return None return variants if os.name != "nt": family = get_family(fname) if not family: log.error("Unknown font: %s", fname) return None return get_variants(family) else: # lookup required font in registry lookup, alternative approach # is to let loadFont() traverse windows font directory or use # ctypes with EnumFontFamiliesEx def get_nt_fname(ftname): import winreg as _w fontkey = _w.OpenKey( _w.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", ) fontname = ftname + " (TrueType)" try: fname = _w.QueryValueEx(fontkey, fontname)[0] if os.path.isabs(fname): fontkey.close() return fname fontdir = os.environ.get("SystemRoot", "C:\\Windows") fontdir += "\\Fonts" fontkey.Close() return fontdir + "\\" + fname except WindowsError: fontkey.Close() return None family, pos = guessFont(fname) fontfile = get_nt_fname(fname) if not fontfile: if pos == 0: fontfile = get_nt_fname(family) elif pos == 1: fontfile = get_nt_fname(family + " Bold") elif pos == 2: fontfile = get_nt_fname(family + " Italic") or get_nt_fname( family + " Oblique" ) else: fontfile = get_nt_fname(family + " Bold Italic") or get_nt_fname( family + " Bold Oblique" ) if not fontfile: log.error("Unknown font: %s", fname) return None family, pos = guessFont(fname) variants = [ get_nt_fname(family) or fontfile, get_nt_fname(family + " Bold") or fontfile, get_nt_fname(family + " Italic") or get_nt_fname(family + " Oblique") or fontfile, get_nt_fname(family + " Bold Italic") or get_nt_fname(family + " Bold Oblique") or fontfile, ] return variants def autoEmbed(fname): """Given a font name, does a best-effort of embedding said font and its variants. Returns a list of the font names it registered with ReportLab. """ log.info("Trying to embed %s" % fname) fontList = [] variants = [] f = findFont(fname) if f: # We have this font located if f[0].lower().endswith(".afm"): # Type 1 font family = families[f[2]] # Register the whole family of faces faces = [ pdfmetrics.EmbeddedType1Face(*fonts[fn.lower()][:2]) for fn in family ] for face in faces: pdfmetrics.registerTypeFace(face) for face, name in zip(faces, family): fontList.append(name) font = pdfmetrics.Font(face, name, "WinAnsiEncoding") log.info("Registering font: %s from %s" % (name, face.getFontFiles())) pdfmetrics.registerFont(font) # Map the variants regular, italic, bold, bolditalic = family for n in fname, regular: addMapping(n, 0, 0, regular) addMapping(n, 0, 1, italic) addMapping(n, 1, 0, bold) addMapping(n, 1, 1, bolditalic) log.info("Embedding as %s" % fontList) return fontList else: # A TTF font variants = [fonts[x.lower()][0] for x in families[f[2]]] if not variants: # Try fc-match variants = findTTFont(fname) if variants: vname = os.path.basename(variants[0])[:-4] if vname != fname: log.warn( "Could not find font '%s'. Substituting with %s." % (fname, vname) ) # It is a TT Font and we found it using fc-match (or found *something*) if variants: for variant in variants: vname = os.path.basename(variant)[:-4] try: if vname not in pdfmetrics._fonts: _font = TTFont(vname, variant) log.info("Registering font: %s from %s" % (vname, variant)) pdfmetrics.registerFont(_font) except TTFError: log.error("Error registering font: %s from %s" % (vname, variant)) else: fontList.append(vname) regular, bold, italic, bolditalic = [ os.path.basename(variant)[:-4] for variant in variants ] addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) log.info("Embedding via findTTFont as %s" % fontList) return fontList def guessFont(fname): """Given a font name like "Tahoma-BoldOblique", "Bitstream Charter Italic" or "Perpetua Bold Italic" guess what it means. Returns (family, x) where x is 0: regular 1: bold 2: italic 3: bolditalic """ italic = 0 bold = 0 if "-" not in fname: sfx = { "Bold": 1, "Bold Italic": 3, "Bold Oblique": 3, "Italic": 2, "Oblique": 2, } for key in sfx: if fname.endswith(" " + key): return fname.rpartition(key)[0], sfx[key] return fname, 0 else: family, mod = fname.rsplit("-", 1) mod = mod.lower() if "oblique" in mod or "italic" in mod: italic = 1 if "bold" in mod: bold = 1 if bold + italic == 0: # Not really a modifier return fname, 0 return family, bold + 2 * italic def main(): global flist if len(sys.argv) != 2: print("Usage: findfonts.py fontName") sys.exit(1) if os.name == "nt": flist = [".", os.environ.get("SystemRoot", "C:\\Windows") + "\\Fonts"] else: flist = [".", "/usr/share/fonts", "/usr/share/texmf-dist/fonts"] fname = make_string(sys.argv[1]) fn, _ = guessFont(fname) f = findFont(fn) if not f: f = findTTFont(fn) if f: print(f) else: print("Unknown font %s" % fname) if __name__ == "__main__": main() rst2pdf-0.102/rst2pdf/flowables.py000066400000000000000000001225501463013543400170240ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms __docformat__ = 'reStructuredText' from copy import copy import re import sys from xml.sax.saxutils import unescape from reportlab.lib.enums import TA_CENTER, TA_RIGHT from reportlab.lib.styles import ParagraphStyle from reportlab.lib.units import cm from reportlab.platypus.doctemplate import FrameActionFlowable, FrameBreak, Indenter from reportlab.platypus.flowables import ( _listWrapOn, _FUZZ, Flowable, NullDraw, PageBreak, Spacer, ) from reportlab.platypus.frames import Frame from reportlab.platypus.paragraph import Paragraph from reportlab.platypus.tables import Table, TableStyle from reportlab.platypus.tableofcontents import TableOfContents from reportlab.platypus.xpreformatted import XPreformatted from . import styles from .log import log class XXPreformatted(XPreformatted): """An extended XPreformattedFit""" def __init__(self, *args, **kwargs): XPreformatted.__init__(self, *args, **kwargs) def split(self, aW, aH): # Figure out a nice range of splits # # Assume we would prefer 5 lines (at least) on # a splitted flowable before a break, and 4 on # the last flowable after a break. # So, the minimum wrap height for a fragment # will be 5*leading rW, rH = self.wrap(aW, aH) if rH > aH: minH1 = getattr(self.style, 'allowOrphans', 5) * self.style.leading minH2 = getattr(self.style, 'allowWidows', 4) * self.style.leading # If there's no way to fid a decent fragment, # refuse to split if aH < minH1: return [] # Now, don't split too close to the end either pw, ph = self.wrap(aW, aH) if ph - aH < minH2: aH = ph - minH2 return XPreformatted.split(self, aW, aH) class MyIndenter(Indenter): """An indenter that has a width, because otherwise you get crashes if added inside tables""" width = 0 height = 0 def draw(self): pass class TocEntry(NullDraw): """A flowable that adds a TOC entry but draws nothing""" def __init__(self, level, label): self.level = level self.label = label self.width = 0 self.height = 0 self.keepWithNext = True def draw(self): # Add outline entry self.canv.bookmarkHorizontal(self.label, 0, 0 + self.height) self.canv.addOutlineEntry( self.label, self.label, max(0, int(self.level)), False ) class Heading(Paragraph): """A paragraph that also adds an outline entry in the PDF TOC.""" def __init__( self, text, style, bulletText=None, caseSensitive=1, level=0, snum=None, parent_id=None, node=None, section_header_depth=2, toc_depth=9999, ): # Issue 114: need to convert "&" to "&" and such. # Issue 140: need to make it plain text self.stext = re.sub(r'<[^>]*?>', '', unescape(text)) self.stext = self.stext.strip() self.level = int(level) self.snum = snum self.parent_id = parent_id self.node = node self.section_header_depth = section_header_depth self.toc_depth = toc_depth Paragraph.__init__(self, text, style, bulletText) def draw(self): # Add outline entry self.canv.bookmarkHorizontal(self.parent_id, 0, 0 + self.height) # self.section_header_depth is for Issue 391 if self.canv.firstSect and self.level < self.section_header_depth: self.canv.sectName = self.stext self.canv.firstSect = False if self.snum is not None: self.canv.sectNum = self.snum else: self.canv.sectNum = "" # Close entry if it's below the toc depth # (we add 1 to self.level as it's zero-indexed, but toc_depth is one-indexed.) closed = None if (self.level + 1) >= self.toc_depth: closed = True self.canv.addOutlineEntry(self.stext, self.parent_id, int(self.level), closed) Paragraph.draw(self) class Separation(Flowable): """A simple
-like flowable""" def __init__(self, style=None): self.style = style def wrap(self, w, h): self.w = w return w, 1 * cm def draw(self): if self.style is not None: self.canv.setStrokeColor(self.style.textColor) self.canv.line(0, 0.5 * cm, self.w, 0.5 * cm) class Reference(Flowable): """A flowable to insert an anchor without taking space""" def __init__(self, refid): self.refid = refid self.keepWithNext = True Flowable.__init__(self) def wrap(self, w, h): """This takes no space""" return 0, 0 def draw(self): self.canv.bookmarkPage(self.refid) def repr(self): return "Reference: %s" % self.refid def __str__(self): return "Reference: %s" % self.refid class OddEven(Flowable): """This flowable takes two lists of flowables as arguments, odd and even. If will draw the "odd" list when drawn in odd pages and the "even" list on even pages. wrap() will always return a size large enough for both lists, and this flowable **cannot** be split, so use with care. """ def __init__(self, odd, even, style=None): self.odd = DelayedTable([[odd]], ['100%'], style) self.even = DelayedTable([[even]], ['100%'], style) def wrap(self, w, h): """Return a box large enough for both odd and even""" w1, h1 = self.odd.wrap(w, h) w2, h2 = self.even.wrap(w, h) return max(w1, w2), max(h1, h2) def drawOn(self, canvas, x, y, _sW=0): if canvas._pagenum % 2 == 0: self.even.drawOn(canvas, x, y, _sW) else: self.odd.drawOn(canvas, x, y, _sW) def split(self): """Makes no sense to split this...""" return [] class DelayedTable(Table): """A flowable that inserts a table for which it has the data. Needed so column widths can be determined after we know on what frame the table will be inserted, thus making the overal table width correct. """ def __init__(self, data, colWidths, style=None, repeatrows=False, splitByRow=True): self.data = data self._colWidths = colWidths if style is None: style = TableStyle( [ ('LEFTPADDING', (0, 0), (-1, -1), 0), ('RIGHTPADDING', (0, 0), (-1, -1), 0), ('TOPPADDING', (0, 0), (-1, -1), 0), ('BOTTOMPADDING', (0, 0), (-1, -1), 0), ] ) self.style = style self.t = None self.repeatrows = repeatrows self.hAlign = TA_CENTER self.splitByRow = splitByRow def wrap(self, w, h): # Create the table, with the widths from colWidths reinterpreted # if needed as percentages of frame/cell/whatever width w is. # _tw = w/sum(self.colWidths) def adjust(*args, **kwargs): kwargs['total'] = w return styles.adjustUnits(*args, **kwargs) # adjust=functools.partial(styles.adjustUnits, total=w) self.colWidths = [adjust(x) for x in self._colWidths] # colWidths = [_w * _tw for _w in self.colWidths] self.t = Table( self.data, colWidths=self.colWidths, style=self.style, repeatRows=self.repeatrows, splitByRow=True, ) self._set_max_page_height_on_cell_flowables(h) # splitByRow=self.splitByRow) self.t.hAlign = self.hAlign return self.t.wrap(w, h) def _set_max_page_height_on_cell_flowables(self, height): """Iterate over all cells in the table and set the maximum height onto the flowable. This is useful to the flowable if its data cannot be rendered over a page boundary (e.g. an image) as it can then resize itself to a valid height in its wrap() method. """ def set_max_page_height_on_flowable(flowable, cell_style): if hasattr(flowable, 'max_page_height'): # Subtract padding from h only if it is a positive value top_padding = cell_style.topPadding if cell_style.topPadding > 0 else 0 bottom_padding = ( cell_style.topPadding if cell_style.bottomPadding > 0 else 0 ) h = abs(height - top_padding - bottom_padding) - _FUZZ flowable.max_page_height = h for row_index, row in enumerate(self.data): for col_index, columns in enumerate(row): # columns is either a list or a cell (for a single cell table) if isinstance(columns, list): for cell in columns: set_max_page_height_on_flowable( cell, self.t._cellStyles[row_index][col_index] ) else: set_max_page_height_on_flowable( columns, self.t._cellStyles[row_index][col_index] ) def split(self, w, h): if self.splitByRow: if not self.t: self.wrap(w, h) return self.t.split(w, h) else: return [] def drawOn(self, canvas, x, y, _sW=0): self.t.drawOn(canvas, x, y, _sW) def identity(self, maxLen=None): return ( "<%s at %s%s%s> containing: %s" % ( self.__class__.__name__, hex(id(self)), self._frameName(), getattr(self, 'name', '') and (' name="%s"' % getattr(self, 'name', '')) or '', repr(self.data[0]), )[:180] ) def tablepadding(padding): if not isinstance(padding, (list, tuple)): padding = [padding] * 4 return ( padding, ('TOPPADDING', [0, 0], [-1, -1], padding[0]), ('RIGHTPADDING', [-1, 0], [-1, -1], padding[1]), ('BOTTOMPADDING', [0, 0], [-1, -1], padding[2]), ('LEFTPADDING', [1, 0], [1, -1], padding[3]), ) class SplitTable(DelayedTable): def __init__(self, data, colWidths, style, padding=3): if len(data) != 1 or len(data[0]) != 2: log.error('SplitTable can only be 1 row and two columns!') sys.exit(1) DelayedTable.__init__(self, data, colWidths, style) self.padding, p1, p2, p3, p4 = tablepadding(padding) self.style._cmds.insert(0, p1) self.style._cmds.insert(0, p2) self.style._cmds.insert(0, p3) self.style._cmds.insert(0, p4) def identity(self, maxLen=None): return "<%s at %s%s%s> containing: %s" % ( self.__class__.__name__, hex(id(self)), self._frameName(), getattr(self, 'name', '') and (' name="%s"' % getattr(self, 'name', '')) or '', repr(self.data[0][1])[:180], ) def split(self, w, h): _w, _h = self.wrap(w, h) if _h > h: # Can't split! # The right column data mandates the split # Find which flowable exceeds the available height dw = self.colWidths[0] + self.padding[1] + self.padding[3] dh = self.padding[0] + self.padding[2] bullet = self.data[0][0] text = self.data[0][1] for l in range(0, len(text)): _, fh = _listWrapOn(text[: l + 1], w - dw, None) if fh + dh > h: # The lth flowable is the guilty one # split it _, lh = _listWrapOn(text[:l], w - dw, None) # Workaround for Issue 180 text[l].wrap(w - dw, h - lh - dh) l2 = text[l].split(w - dw, h - lh - dh) if l2 == []: # Not splittable, push some to next page if l == 0: # Can't fit anything, push all to next page return l2 # We reduce the number of items we keep on the # page for two reasons: # 1) If an item is associated with the following # item (getKeepWithNext() == True), we have # to back up to a previous one. # 2) If we miscalculated the size required on # the first page (I dunno why, probably not # counting borders properly, but we do # miscalculate occasionally). Seems to # have to do with nested tables, so it might # be the extra space on the border on the # inner table. while l > 0: if not text[l - 1].getKeepWithNext(): first_t = Table( [[bullet, text[:l]]], colWidths=self.colWidths, style=self.style, ) _w, _h = first_t.wrap(w, h) if _h <= h: break l -= 1 if l > 0: # Workaround for Issue 180 with wordaxe: # if wordaxe is not None: # l3=[Table([ # [bullet, # text[:l]] # ], # colWidths=self.colWidths, # style=self.style), # Table([['',text[l:]]], # colWidths=self.colWidths, # style=self.style)] # else: l3 = [ first_t, SplitTable( [['', text[l:]]], colWidths=self.colWidths, style=self.style, padding=self.padding, ), ] else: # Everything flows l3 = [] else: l3 = [ Table( [[bullet, text[:l] + [l2[0]]]], colWidths=self.colWidths, rowHeights=[h], style=self.style, ) ] if l2[1:] + text[l + 1 :]: l3.append( SplitTable( [['', l2[1:] + text[l + 1 :]]], colWidths=self.colWidths, style=self.style, padding=self.padding, ) ) return l3 log.debug("Can't split splittable") return self.t.split(w, h) else: return DelayedTable.split(self, w, h) class MySpacer(Spacer): def wrap(self, aW, aH): w, h = Spacer.wrap(self, aW, aH) self.height = min(aH, h) return w, self.height class MyPageBreak(FrameActionFlowable): def __init__(self, args=None, templateName=None, breakTo='any'): """templateName switches the page template starting in the next page. breakTo can be 'any' 'even' or 'odd'. 'even' will break one page if the current page is odd or two pages if it's even. That way the next flowable will be in an even page. 'odd' is the opposite of 'even' 'any' is the default, and means it will always break only one page. """ self.templateName = templateName self.breakTo = breakTo self.forced = False self.extraContent = [] self.background = None self.background_fit_mode = None if args: # args is a set of key=value pairs, with the exception of the first one # which may be the tempate name for k, arg in enumerate(args): parts = arg.split("=", 2) if parts[0] == arg: if k == 0: self.templateName = arg else: # If we recognised the key, then set the appropriate property to the value # for use in SetNextTemplate() key, value = parts key = key.lower() if key == 'background': self.background = value.strip('"\'') elif key == 'fit-background-mode': self.background_fit_mode = value elif key == 'template' or key == 'templatename': self.templateName = value def frameAction(self, frame): frame._generated_content = [] if self.breakTo == 'any': # Break only once. None if at top of page if not frame._atTop: frame._generated_content.append( SetNextTemplate( self.templateName, self.background, self.background_fit_mode ) ) frame._generated_content.append(PageBreak()) elif self.breakTo == 'odd': # Break once if on even page, twice # on odd page, none if on top of odd page if frame._pagenum % 2: # odd pageNum if not frame._atTop: # Blank pages get no heading or footer frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(SetNextTemplate('emptyPage')) frame._generated_content.append(PageBreak()) frame._generated_content.append(ResetNextTemplate()) frame._generated_content.append(PageBreak()) else: # even frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(PageBreak()) elif self.breakTo == 'even': # Break once if on odd page, twice # on even page, none if on top of even page if frame._pagenum % 2: # odd pageNum frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(PageBreak()) else: # even if not frame._atTop: # Blank pages get no heading or footer frame._generated_content.append(SetNextTemplate(self.templateName)) frame._generated_content.append(SetNextTemplate('emptyPage')) frame._generated_content.append(PageBreak()) frame._generated_content.append(ResetNextTemplate()) frame._generated_content.append(PageBreak()) class SetNextTemplate(Flowable): """Set canv.templateName when drawing. rst2pdf uses that to switch page templates. """ def __init__(self, templateName=None, background=None, background_fit_mode=None): self.templateName = templateName self.background = background self.background_fit_mode = background_fit_mode Flowable.__init__(self) def draw(self): self.canv.background = self.background self.canv.background_fit_mode = self.background_fit_mode if self.templateName: try: self.canv.oldTemplateName = self.canv.templateName except Exception: self.canv.oldTemplateName = 'oneColumn' self.canv.templateName = self.templateName class ResetNextTemplate(Flowable): """Go back to the previous template. rst2pdf uses that to switch page templates back when temporarily it needed to switch to another template. For example, after a OddPageBreak, there can be a totally blank page. Those have to use coverPage as a template, because they must not have headers or footers. And then we need to switch back to whatever was used. """ def __init__(self): Flowable.__init__(self) def draw(self): self.canv.templateName, self.canv.oldTemplateName = ( self.canv.oldTemplateName, self.canv.templateName, ) self.canv.background = None def wrap(self, aW, aH): return 0, 0 class TextAnnotation(Flowable): """Add text annotation flowable""" def __init__(self, *args): self.annotationText = "" self.position = [-1, -1, -1, -1] if len(args) >= 1: self.annotationText = args[0].lstrip('"').rstrip('"') if len(args) >= 5: self.position = args[1:] def wrap(self, w, h): return 0, 0 def draw(self): # Format of Reportlab's textAnnotation(): # textAnnotation("Your content", Rect=[x_begin, y_begin, x_end, y_end], relative=1) self.canv.textAnnotation(self.annotationText, self.position, 1) class Transition(Flowable): """Wrap canvas.setPageTransition. Sets the transition effect from the current page to the next. """ PageTransitionEffects = dict( Split=['direction', 'motion'], Blinds=['dimension'], Box=['motion'], Wipe=['direction'], Dissolve=[], Glitter=['direction'], ) def __init__(self, *args): if len(args) < 1: args = [None, 1] # No transition # See if we got a valid transition effect name if args[0] not in self.PageTransitionEffects: log.error('Unknown transition effect name: %s' % args[0]) args[0] = None elif len(args) == 1: args.append(1) # FIXME: validate more self.args = args def wrap(self, aw, ah): return 0, 0 def draw(self): kwargs = dict( effectname=None, duration=1, direction=0, dimension='H', motion='I' ) ceff = ['effectname', 'duration'] + self.PageTransitionEffects[self.args[0]] for argname, argvalue in zip(ceff, self.args): kwargs[argname] = argvalue kwargs['duration'] = int(kwargs['duration']) kwargs['direction'] = int(kwargs['direction']) self.canv.setPageTransition(**kwargs) class SmartFrame(Frame): """A (Hopefully) smarter frame object. This frame object knows how to handle a two-pass layout procedure (someday). """ def __init__( self, container, x1, y1, width, height, leftPadding=6, bottomPadding=6, rightPadding=6, topPadding=6, id=None, showBoundary=0, overlapAttachedSpace=None, _debug=None, ): self.container = container self.onSidebar = False self.__s = '[%s, %s, %s, %s, %s, %s, %s, %s,]' % ( x1, y1, width, height, leftPadding, bottomPadding, rightPadding, topPadding, ) Frame.__init__( self, x1, y1, width, height, leftPadding, bottomPadding, rightPadding, topPadding, id, showBoundary, overlapAttachedSpace, _debug, ) def add(self, flowable, canv, trySplit=0): flowable._atTop = self._atTop return Frame.add(self, flowable, canv, trySplit) def __repr__(self): return self.__s def __deepcopy__(self, *whatever): return copy(self) class FrameCutter(FrameActionFlowable): def __init__(self, dx, width, flowable, padding, lpad, floatLeft=True): self.width = width self.dx = dx self.f = flowable self.padding = padding self.lpad = lpad self.floatLeft = floatLeft def frameAction(self, frame): idx = frame.container.frames.index(frame) if self.floatLeft: # Don't bother inserting a silly thin frame if self.width - self.padding > 30: f1 = SmartFrame( frame.container, frame._x1 + self.dx - 2 * self.padding, frame._y2 - self.f.height - 3 * self.padding, self.width + 2 * self.padding, self.f.height + 3 * self.padding, bottomPadding=0, topPadding=0, leftPadding=self.lpad, ) f1._atTop = frame._atTop # This is a frame next to a sidebar. f1.onSidebar = True frame.container.frames.insert(idx + 1, f1) # Don't add silly thin frame if frame._height - self.f.height - 2 * self.padding > 30: frame.container.frames.insert( idx + 2, SmartFrame( frame.container, frame._x1, frame._y1p, self.width + self.dx, frame._height - self.f.height - 3 * self.padding, topPadding=0, ), ) else: # Don't bother inserting a silly thin frame if self.width - self.padding > 30: f1 = SmartFrame( frame.container, frame._x1 - self.width, frame._y2 - self.f.height - 2 * self.padding, self.width, self.f.height + 2 * self.padding, bottomPadding=0, topPadding=0, rightPadding=self.lpad, ) f1._atTop = frame._atTop # This is a frame next to a sidebar. f1.onSidebar = True frame.container.frames.insert(idx + 1, f1) if frame._height - self.f.height - 2 * self.padding > 30: frame.container.frames.insert( idx + 2, SmartFrame( frame.container, frame._x1 - self.width, frame._y1p, self.width + self.dx, frame._height - self.f.height - 2 * self.padding, topPadding=0, ), ) class Sidebar(FrameActionFlowable): def __init__(self, flowables, style): self.style = style self.width = self.style.width self.flowables = flowables def frameAction(self, frame): if self.style.float not in ('left', 'right'): return if frame.onSidebar: # We are still on the frame next to a sidebar! frame._generated_content = [FrameBreak(), self] else: w = frame.container.styles.adjustUnits(self.width, frame.width) idx = frame.container.frames.index(frame) padding = self.style.borderPadding width = self.style.width self.style.padding = frame.container.styles.adjustUnits( str(padding), frame.width ) self.style.width = frame.container.styles.adjustUnits( str(width), frame.width ) self.kif = BoxedContainer(self.flowables, self.style) if self.style.float == 'left': self.style.lpad = frame.leftPadding f1 = SmartFrame( frame.container, frame._x1, frame._y1p, w - 2 * self.style.padding, frame._y - frame._y1p, leftPadding=self.style.lpad, rightPadding=0, bottomPadding=0, topPadding=0, ) f1._atTop = frame._atTop frame.container.frames.insert(idx + 1, f1) frame._generated_content = [ FrameBreak(), self.kif, FrameCutter( w, frame.width - w, self.kif, padding, self.style.lpad, True, ), FrameBreak(), ] elif self.style.float == 'right': self.style.lpad = frame.rightPadding frame.container.frames.insert( idx + 1, SmartFrame( frame.container, frame._x1 + frame.width - self.style.width, frame._y1p, w, frame._y - frame._y1p, rightPadding=self.style.lpad, leftPadding=0, bottomPadding=0, topPadding=0, ), ) frame._generated_content = [ FrameBreak(), self.kif, FrameCutter( w, frame.width - w, self.kif, padding, self.style.lpad, False, ), FrameBreak(), ] class BoundByWidth(Flowable): """Limit a list of flowables by width. This still lets the flowables break over pages and frames. """ def __init__(self, maxWidth, content=[], style=None, mode=None, scale=None): self.maxWidth = maxWidth self.content = content self.style = style self.mode = mode self.pad = None self.scale = scale Flowable.__init__(self) def border_padding(self, useWidth, additional): sdict = self.style sdict = sdict.__dict__ or {} bp = sdict.get("borderPadding", 0) if useWidth: additional += sdict.get("borderWidth", 0) if not isinstance(bp, list): bp = [bp] * 4 return [x + additional for x in bp] def identity(self, maxLen=None): return "<%s at %s%s%s> containing: %s" % ( self.__class__.__name__, hex(id(self)), self._frameName(), getattr(self, 'name', '') and (' name="%s"' % getattr(self, 'name', '')) or '', repr([c.identity() for c in self.content])[:80], ) def wrap(self, availWidth, availHeight): """If we need more width than we have, complain, keep a scale""" self.pad = self.border_padding(True, 0.1) maxWidth = float( min( styles.adjustUnits(self.maxWidth, availWidth) or availWidth, availWidth, ) ) self.maxWidth = maxWidth maxWidth -= self.pad[1] + self.pad[3] self.width, self.height = _listWrapOn( self.content, maxWidth, None, fakeWidth=False ) if self.width > maxWidth: if self.mode == 'error': log.error( "BoundByWidth too wide to fit in frame (%s > %s): %s", self.width, maxWidth, self.identity(), ) sys.exit(1) if self.mode != 'shrink': self.scale = 1.0 log.warning( "BoundByWidth too wide to fit in frame (%s > %s): %s", self.width, maxWidth, self.identity(), ) if self.mode == 'shrink' and not self.scale: self.scale = (maxWidth + self.pad[1] + self.pad[3]) / ( self.width + self.pad[1] + self.pad[3] ) else: self.scale = 1.0 self.height *= self.scale self.width *= self.scale return ( self.width, self.height + (self.pad[0] + self.pad[2]) * self.scale, ) def split(self, availWidth, availHeight): if not self.pad: self.wrap(availWidth, availHeight) content = self.content if len(self.content) == 1: # We need to split the only element we have content = content[0].split( availWidth - (self.pad[1] + self.pad[3]), availHeight - (self.pad[0] + self.pad[2]), ) result = [ BoundByWidth(self.maxWidth, [f], self.style, self.mode, self.scale) for f in content ] return result def draw(self): """we simulate being added to a frame""" canv = self.canv canv.saveState() x = canv._x y = canv._y _sW = 0 scale = self.scale content = None # , canv, x, y, _sW=0, scale=1.0, content=None, aW=None): pS = 0 aW = self.width aW = scale * (aW + _sW) if content is None: content = self.content y += (self.height + self.pad[2]) / scale x += self.pad[3] for c in content: w, h = c.wrapOn(canv, aW, 0xFFFFFFF) if (w < _FUZZ or h < _FUZZ) and not getattr(c, '_ZEROSIZE', None): continue if c is not content[0]: h += max(c.getSpaceBefore() - pS, 0) y -= h canv.saveState() if self.mode == 'shrink': canv.scale(scale, scale) elif self.mode == 'truncate': p = canv.beginPath() p.rect( x - self.pad[3], y - self.pad[2], self.maxWidth, self.height + self.pad[0] + self.pad[2], ) canv.clipPath(p, stroke=0) c.drawOn(canv, x, y, _sW=aW - w) canv.restoreState() if c is not content[-1]: pS = c.getSpaceAfter() y -= pS canv.restoreState() class BoxedContainer(BoundByWidth): def __init__(self, content, style, mode='shrink'): try: w = style.width except AttributeError: w = '100%' BoundByWidth.__init__(self, w, content, mode=mode, style=None) self.style = style self.mode = mode def identity(self, maxLen=None): return repr( ['BoxedContainer containing: ', [c.identity() for c in self.content]] )[:80] def draw(self): canv = self.canv canv.saveState() x = canv._x y = canv._y lw = 0 if self.style and self.style.borderWidth > 0: lw = self.style.borderWidth canv.setLineWidth(self.style.borderWidth) if self.style.borderColor: # This could be None :-( canv.setStrokeColor(self.style.borderColor) stroke = 1 else: stroke = 0 else: stroke = 0 if self.style and self.style.backColor: canv.setFillColor(self.style.backColor) fill = 1 else: fill = 0 padding = self.border_padding(False, lw) xpadding = padding[1] + padding[3] ypadding = padding[0] + padding[2] p = canv.beginPath() p.rect(x, y, self.width + xpadding, self.height + ypadding) canv.drawPath(p, stroke=stroke, fill=fill) canv.restoreState() BoundByWidth.draw(self) def split(self, availWidth, availHeight): self.wrap(availWidth, availHeight) padding = (self.pad[1] + self.pad[3]) * self.scale if self.height + padding <= availHeight: return [self] else: # Try to figure out how many elements # we can put in the available space candidate = None remainder = None for p in range(1, len(self.content)): b = BoxedContainer(self.content[:p], self.style, self.mode) w, h = b.wrap(availWidth, availHeight) if h < availHeight: candidate = b if self.content[p:]: remainder = BoxedContainer( self.content[p:], self.style, self.mode ) else: break if not candidate or not remainder: # Nothing fits, break page return [] if not remainder: # Everything fits? return [self] return [candidate, remainder] class MyTableOfContents(TableOfContents): """ Subclass of reportlab.platypus.tableofcontents.TableOfContents which supports hyperlinks to corresponding sections. """ def __init__(self, *args, **kwargs): # The parent argument is to define the locality of # the TOC. If it's none, it's a global TOC and # any heading it's notified about is accepted. # If it's a node, then the heading needs to be "inside" # that node. This can be figured out because # the heading flowable keeps a reference to the title # node it was creatd from. # # Yes, this is gross. self.parent = kwargs.pop('parent') TableOfContents.__init__(self, *args, **kwargs) # reference ids for which this TOC should be notified self.refids = [] # revese lookup table from (level, text) to refid self.refid_lut = {} self.linkColor = "#0000ff" def notify(self, kind, stuff): # stuff includes (level, text, pagenum, label) level, text, pageNum, label, node = stuff rlabel = '-'.join(label.split('-')[:-1]) def islocal(_node): """See if this node is "local enough" for this TOC. This is for Issue 196""" if self.parent is None: return True while _node.parent: if _node.parent == self.parent: return True _node = _node.parent return False if rlabel in self.refids and islocal(node): self.addEntry(level, text, pageNum) self.refid_lut[(level, text, pageNum)] = label def wrap(self, availWidth, availHeight): """Adds hyperlink to toc entry.""" widths = (availWidth - self.rightColumnWidth, self.rightColumnWidth) # makes an internal table which does all the work. # we draw the LAST RUN's entries! If there are # none, we make some dummy data to keep the table # from complaining if len(self._lastEntries) == 0: _tempEntries = [(0, 'Placeholder for table of contents', 0, None)] else: _tempEntries = self._lastEntries if _tempEntries: base_level = _tempEntries[0][0] else: base_level = 0 tableData = [] for entry in _tempEntries: level, text, pageNum = entry[:3] left_col_level = level - base_level leftColStyle = self.getLevelStyle(left_col_level) label = self.refid_lut.get((level, text, pageNum), None) if label: pre = u'' % (label, self.linkColor) post = u'' if isinstance(text, bytes): text = text.decode('utf-8') text = pre + text + post else: pre = '' post = '' # right col style is right aligned rightColStyle = ParagraphStyle( name='leftColLevel%d' % left_col_level, parent=leftColStyle, leftIndent=0, alignment=TA_RIGHT, ) leftPara = Paragraph(text, leftColStyle) rightPara = Paragraph(pre + str(pageNum) + post, rightColStyle) tableData.append([leftPara, rightPara]) self._table = Table(tableData, colWidths=widths, style=self.tableStyle) self.width, self.height = self._table.wrapOn(self.canv, availWidth, availHeight) return self.width, self.height def split(self, aW, aH): # Make sure _table exists before splitting. # This was only triggered in rare cases using sphinx. if not self._table: self.wrap(aW, aH) return TableOfContents.split(self, aW, aH) def isSatisfied(self): if self._entries == self._lastEntries: log.debug('Table Of Contents is stable') return True else: if len(self._entries) != len(self._lastEntries): log.info( 'Number of items in TOC changed ' 'from %d to %d, not satisfied' % (len(self._lastEntries), len(self._entries)) ) return False log.info('TOC entries that moved in this pass:') for i in range(len(self._entries)): if self._entries[i] != self._lastEntries[i]: log.info(str(self._entries[i])) log.info(str(self._lastEntries[i])) return False rst2pdf-0.102/rst2pdf/genelements.py000066400000000000000000001171611463013543400173560ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms # Some fragments of code are copied from Reportlab under this license: # ##################################################################################### # # Copyright (c) 2000-2008, ReportLab Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # * Neither the name of the company nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE OFFICERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # ##################################################################################### from copy import copy import docutils.nodes import reportlab from reportlab.platypus import Paragraph, TableStyle from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT from .basenodehandler import NodeHandler from .directives.aafigure import Aanode from .directives.oddeven import OddEvenNode from .flowables import ( Table, DelayedTable, SplitTable, Heading, MyTableOfContents, MySpacer, Separation, BoxedContainer, MyPageBreak, tablepadding, OddEven, XPreformatted, ) from .math_flowable import Math from .utils import parseRaw, parseHTML class TocBuilderVisitor(docutils.nodes.SparseNodeVisitor): def __init__(self, document): docutils.nodes.SparseNodeVisitor.__init__(self, document) self.toc = None # For some reason, when called via sphinx, # .. contents:: ends up trying to call # visitor.document.reporter.debug # so we need a valid document here. self.document = docutils.utils.new_document('') def visit_reference(self, node): refid = node.attributes.get('refid') if refid: self.toc.refids.append(refid) class HandleDocument(NodeHandler, docutils.nodes.document): pass class HandleTable(NodeHandler, docutils.nodes.table): def gather_elements(self, client, node, style): if node['classes']: style = client.styles.combinedStyle(['table'] + node['classes']) else: style = client.styles['table'] return ( [MySpacer(0, client.styles['table'].spaceBefore)] + client.gather_elements(node, style=style) + [MySpacer(0, client.styles['table'].spaceAfter)] ) class HandleTGroup(NodeHandler, docutils.nodes.tgroup): def gather_elements(self, client, node, style): # Take the style from the parent "table" node # because sometimes it's not passed down. if node.parent['classes']: style = client.styles.combinedStyle(['table'] + node.parent['classes']) else: style = client.styles['table'] rows = [] colWidths = [] hasHead = False headRows = 0 for n in node.children: if isinstance(n, docutils.nodes.thead): hasHead = True for row in n.children: r = [] for cell in row.children: r.append(cell) rows.append(r) headRows = len(rows) elif isinstance(n, docutils.nodes.tbody): for row in n.children: r = [] for cell in row.children: r.append(cell) rows.append(r) elif isinstance(n, docutils.nodes.colspec): colWidths.append(int(n['colwidth'])) # colWidths are in no specific unit, really. Maybe ems. tot = sum(colWidths) adjustedWidths = [] for x in colWidths: # Convert them to % w = 100 * x / tot # Limit minimum width of a column as narrow columns cause strange "huge height" from reportlab if the cell # padding is larger than the calculated width. Hack for #967 if w < 4: w = 4 adjustedWidths.append("%s%%" % w) colWidths = adjustedWidths if 'colWidths' in style.__dict__: colWidths[: len(style.colWidths)] = style.colWidths spans = client.filltable(rows) data = [] rowids = range(0, len(rows)) for row, i in zip(rows, rowids): r = [] j = 0 for cell in row: if isinstance(cell, str): r.append("") else: if i < headRows: st = client.styles['table-heading'] else: st = client.styles['table-body'] ell = client.gather_elements(cell, style=st) r.append(ell) j += 1 data.append(r) st = TableStyle(spans) if 'commands' in style.__dict__: for cmd in style.commands: st.add(*cmd) else: # Only use the commands from "table" if the # specified class has no commands. for cmd in client.styles['table'].commands: st.add(*cmd) if hasHead: for cmd in client.styles.tstyleHead(headRows): st.add(*cmd) rtr = client.repeat_table_rows t = DelayedTable(data, colWidths, st, rtr) if style.alignment == TA_LEFT: t.hAlign = 'LEFT' elif style.alignment == TA_CENTER: t.hAlign = 'CENTER' elif style.alignment == TA_RIGHT: t.hAlign = 'RIGHT' return [t] class HandleParagraph(NodeHandler, docutils.nodes.paragraph): def gather_elements(self, client, node, style): return [Paragraph(client.gen_pdftext(node), style)] def get_pre_post(self, client, node, replaceEnt): pre = '' targets = set(node.get('ids', []) + client.pending_targets) client.pending_targets = [] for _id in targets: if _id not in client.targets: pre += '' % (_id) client.targets.append(_id) return pre, '\n' class HandleTitle(HandleParagraph, docutils.nodes.title): def gather_elements(self, client, node, style): # Special cases: (Not sure this is right ;-) if isinstance(node.parent, docutils.nodes.document): # The visible output is done by the cover template node.elements = [] client.doc_title = node.rawsource client.doc_title_clean = node.astext().strip() elif isinstance(node.parent, docutils.nodes.topic): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['topic-title']) ] elif isinstance(node.parent, docutils.nodes.Admonition): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['admonition-title']) ] elif isinstance(node.parent, docutils.nodes.table): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['table-title']) ] elif isinstance(node.parent, docutils.nodes.sidebar): node.elements = [ Paragraph(client.gen_pdftext(node), client.styles['sidebar-title']) ] else: # Section/Subsection/etc. text = client.gen_pdftext(node) maxdepth = 6 # The parent ID is the refid + an ID to make it unique for Sphinx parent_id = ( (node.parent.get('ids', [None]) or [None])[0] + u'-' + str(id(node)) ) node.elements = [ Heading( text, client.styles['heading%d' % min(client.depth, maxdepth)], level=client.depth - 1, parent_id=parent_id, node=node, section_header_depth=client.section_header_depth, toc_depth=client.toc_depth, ) ] if client.depth <= client.breaklevel: node.elements.insert(0, MyPageBreak(breakTo=client.breakside)) return node.elements class HandleSubTitle(HandleParagraph, docutils.nodes.subtitle): def gather_elements(self, client, node, style): if isinstance(node.parent, docutils.nodes.sidebar): elements = [ Paragraph(client.gen_pdftext(node), client.styles['sidebar-subtitle']) ] elif isinstance(node.parent, docutils.nodes.document): # elements = [Paragraph(client.gen_pdftext(node), # client.styles['subtitle'])] # The visible output is now done by the cover template elements = [] # FIXME: looks like subtitles don't have a rawsource like # titles do. # That means that literals and italics etc in subtitles won't # work. client.doc_subtitle = getattr(node, 'rawtext', node.astext()).strip() else: elements = [ Paragraph( client.gen_pdftext(node), client.styles['%s-subtitle' % node.parent.tagname], ) ] return elements class HandleDocInfo(NodeHandler, docutils.nodes.docinfo): # A docinfo usually contains several fields. # We'll render it as a series of elements, one field each. pass class HandleField(NodeHandler, docutils.nodes.field): def gather_elements(self, client, node, style): # A field has two child elements, a field_name and a field_body. # We render as a two-column table, left-column is right-aligned, # bold, and much smaller fn = Paragraph( client.gather_pdftext(node.children[0]) + ":", style=client.styles['fieldname'], ) fb = client.gen_elements(node.children[1], style=client.styles['fieldvalue']) t_style = TableStyle(client.styles['field-list'].commands) return [ DelayedTable( [[fn, fb]], colWidths=client.styles['field-list'].colWidths, style=t_style, ) ] class HandleDecoration(NodeHandler, docutils.nodes.decoration): pass class HandleHeader(NodeHandler, docutils.nodes.header): stylename = 'header' def gather_elements(self, client, node, style): client.decoration[self.stylename] = client.gather_elements( node, style=client.styles[self.stylename] ) return [] class HandleFooter(HandleHeader, docutils.nodes.footer): stylename = 'footer' class HandleAuthor(NodeHandler, docutils.nodes.author): def gather_elements(self, client, node, style): if isinstance(node.parent, docutils.nodes.authors): # Is only one of multiple authors. Return a paragraph node.elements = [Paragraph(client.gather_pdftext(node), style=style)] if client.doc_author: client.doc_author += ( client.author_separator(style=style) + node.astext().strip() ) else: client.doc_author = node.astext().strip() else: # A single author: works like a field fb = client.gather_pdftext(node) t_style = TableStyle(client.styles['field-list'].commands) colWidths = [ client.styles.adjustUnits(x) for x in client.styles['field-list'].colWidths ] node.elements = [ Table( [ [ Paragraph( client.text_for_label("author", style) + ":", style=client.styles['fieldname'], ), Paragraph(fb, style), ] ], style=t_style, colWidths=colWidths, ) ] client.doc_author = node.astext().strip() return node.elements class HandleAuthors(NodeHandler, docutils.nodes.authors): def gather_elements(self, client, node, style): # Multiple authors. Create a two-column table. # Author references on the right. t_style = TableStyle(client.styles['field-list'].commands) colWidths = client.styles['field-list'].colWidths td = [ [ Paragraph( client.text_for_label("authors", style) + ":", style=client.styles['fieldname'], ), client.gather_elements(node, style=style), ] ] return [DelayedTable(td, colWidths=colWidths, style=t_style)] class HandleFList(NodeHandler): adjustwidths = False TableType = DelayedTable def gather_elements(self, client, node, style): fb = client.gather_pdftext(node) t_style = TableStyle(client.styles['field-list'].commands) colWidths = client.styles['field-list'].colWidths if self.adjustwidths: colWidths = [client.styles.adjustUnits(x) for x in colWidths] label = client.text_for_label(self.labeltext, style) + ":" t = self.TableType( [ [ Paragraph(label, style=client.styles['fieldname']), Paragraph(fb, style), ] ], style=t_style, colWidths=colWidths, ) return [t] class HandleOrganization(HandleFList, docutils.nodes.organization): labeltext = "organization" class HandleContact(HandleFList, docutils.nodes.contact): labeltext = "contact" class HandleAddress(HandleFList, docutils.nodes.address): labeltext = "address" def gather_elements(self, client, node, style): fb = client.gather_pdftext(node) t_style = TableStyle(client.styles['field-list'].commands) colWidths = client.styles['field-list'].colWidths if self.adjustwidths: colWidths = [client.styles.adjustUnits(x) for x in colWidths] label = client.text_for_label(self.labeltext, style) + ":" t = self.TableType( [ [ Paragraph(label, style=client.styles['fieldname']), XPreformatted(fb, style), ] ], style=t_style, colWidths=colWidths, ) return [t] class HandleVersion(HandleFList, docutils.nodes.version): labeltext = "version" class HandleRevision(HandleFList, docutils.nodes.revision): labeltext = "revision" adjustwidths = True TableType = Table class HandleStatus(HandleFList, docutils.nodes.status): labeltext = "status" class HandleDate(HandleFList, docutils.nodes.date): labeltext = "date" class HandleCopyright(HandleFList, docutils.nodes.copyright): labeltext = "copyright" class HandleTopic(NodeHandler, docutils.nodes.topic): def gather_elements(self, client, node, style): # toc node_classes = node.attributes.get('classes', []) cstyles = client.styles if 'contents' in node_classes: toc_visitor = TocBuilderVisitor(node.document) if 'local' in node_classes: toc_visitor.toc = MyTableOfContents(parent=node.parent) else: toc_visitor.toc = MyTableOfContents(parent=None) toc_visitor.toc.linkColor = cstyles.tocColor or cstyles.linkColor node.walk(toc_visitor) toc = toc_visitor.toc toc.levelStyles = [cstyles['toc%d' % l] for l in range(1, 15)] for s in toc.levelStyles: # FIXME: awful slimy hack! s.__class__ = reportlab.lib.styles.ParagraphStyle if 'local' in node_classes: node.elements = [toc] else: node.elements = [ Paragraph( client.gen_pdftext(node.children[0]), cstyles['heading1'], ), toc, ] else: node.elements = client.gather_elements(node, style=style) return node.elements class HandleFieldBody(NodeHandler, docutils.nodes.field_body): pass class HandleSection(NodeHandler, docutils.nodes.section): def gather_elements(self, client, node, style): # XXX: should style be passed down here? client.depth += 1 elements = client.gather_elements(node) client.depth -= 1 return elements class HandleBulletList(NodeHandler, docutils.nodes.bullet_list): def gather_elements(self, client, node, style): if node['classes']: style = client.styles[node['classes'][0]] else: style = client.styles["bullet-list"] node.elements = client.gather_elements(node, style=style) # Here we need to separate the list from the previous element. # Calculate by how much: sb = style.spaceBefore # list separation sa = style.spaceAfter # list separation node.elements.insert(0, MySpacer(0, sb)) node.elements.append(MySpacer(0, sa)) return node.elements class HandleDefOrOptList( NodeHandler, docutils.nodes.definition_list, docutils.nodes.option_list ): pass class HandleFieldList(NodeHandler, docutils.nodes.field_list): def gather_elements(self, client, node, style): return [ MySpacer(0, client.styles['field-list'].spaceBefore) ] + client.gather_elements(node, style=style) class HandleEnumeratedList(NodeHandler, docutils.nodes.enumerated_list): def gather_elements(self, client, node, style): if node['classes']: style = client.styles[node['classes'][0]] else: style = client.styles["item-list"] node.elements = client.gather_elements(node, style=style) # Here we need to separate the list from the previous element. # Calculate by how much: sb = style.spaceBefore # list separation sa = style.spaceAfter # list separation node.elements.insert(0, MySpacer(0, sb)) node.elements.append(MySpacer(0, sa)) return node.elements class HandleDefinition(NodeHandler, docutils.nodes.definition): def gather_elements(self, client, node, style): return client.gather_elements(node, style=style) class HandleOptionListItem(NodeHandler, docutils.nodes.option_list_item): def gather_elements(self, client, node, style): optext = ', '.join( [client.gather_pdftext(child) for child in node.children[0].children] ) desc = client.gather_elements(node.children[1], style) t_style = TableStyle(client.styles['option-list'].commands) colWidths = client.styles['option-list'].colWidths node.elements = [ DelayedTable( [[client.PreformattedFit(optext, client.styles["literal"]), desc]], colWidths=colWidths, style=t_style, ) ] return node.elements class HandleDefListItem(NodeHandler, docutils.nodes.definition_list_item): def gather_elements(self, client, node, style): # I need to catch the classifiers here tt = [] dt = [] ids = [] for n in node.children: if isinstance(n, docutils.nodes.term): for i in n['ids']: # Used by sphinx glossary lists if i not in client.targets: ids.append('' % i) client.targets.append(i) o, c = client.styleToTags("definition-list-term") tt.append(o + client.gather_pdftext(n) + c) elif isinstance(n, docutils.nodes.classifier): o, c = client.styleToTags("definition-list-classifier") tt.append(o + client.gather_pdftext(n) + c) else: dt.extend(client.gen_elements(n, style)) # FIXME: make this configurable from the stylesheet t_style = TableStyle(client.styles['definition'].commands) cw = getattr(client.styles['definition'], 'colWidths', []) if client.splittables: node.elements = [ Paragraph( ''.join(ids) + ' : '.join(tt), client.styles['definition-list-term'], ), SplitTable([['', dt]], colWidths=cw, style=t_style), ] else: node.elements = [ Paragraph( ''.join(ids) + ' : '.join(tt), client.styles['definition-list-term'], ), DelayedTable([['', dt]], colWidths=[10, None], style=t_style), ] return node.elements class HandleListItem(NodeHandler, docutils.nodes.list_item): def gather_elements(self, client, node, style): b, t = client.bullet_for_node(node) bStyle = copy(style) bStyle.alignment = 2 # FIXME: use different unicode bullets depending on b if b and b in "*+-": b = getattr(bStyle, 'bulletText', u'\u2022') # The style has information about the bullet: # # bulletFontSize # bulletFont # This is so the baselines of the bullet and the text align extra_space = bStyle.bulletFontSize - bStyle.fontSize bStyle.fontSize = bStyle.bulletFontSize bStyle.fontName = bStyle.bulletFontName if t == 'bullet': item_st = client.styles['bullet-list-item'] else: item_st = client.styles['item-list-item'] el = client.gather_elements(node, item_st) # FIXME: this is really really not good code if not el: el = [Paragraph(u"\xa0", item_st)] idx = node.parent.children.index(node) if idx == 0: # The first item in the list, so doesn't need # separation (it's provided by the list itself) sb = 0 else: # Not the first item, so need to separate from # previous item. Account for space provided by # the item's content, too. sb = item_st.spaceBefore - item_st.spaceAfter bStyle.spaceBefore = 0 t_style = TableStyle(style.commands) # The -3 here is to compensate for padding, 0 doesn't work :-( t_style._cmds.extend([["BOTTOMPADDING", [0, 0], [-1, -1], -3]]) if extra_space > 0: # The bullet is larger, move down the item text sb += extra_space colWidths = getattr(style, 'colWidths', []) while len(colWidths) < 2: colWidths.append(client.styles['item_list'].colWidths[len(colWidths)]) if client.splittables: node.elements = [ MySpacer(0, sb), SplitTable( [[Paragraph(b, style=bStyle), el]], colWidths=colWidths, style=t_style, ), ] else: node.elements = [ MySpacer(0, sb), DelayedTable( [[Paragraph(b, style=bStyle), el]], colWidths=colWidths, style=t_style, ), ] return node.elements class HandleTransition(NodeHandler, docutils.nodes.transition): def gather_elements(self, client, node, style): return [Separation(style=client.styles['separation'])] class HandleBlockQuote(NodeHandler, docutils.nodes.block_quote): def gather_elements(self, client, node, style): # This should work, but doesn't look good inside of # table cells (see Issue 173) # node.elements = [MyIndenter(left=client.styles['blockquote'].leftIndent)]\ # + client.gather_elements( node, style) + \ # [MyIndenter(left=-client.styles['blockquote'].leftIndent)] # Workaround for Issue 173 using tables leftIndent = client.styles['blockquote'].leftIndent rightIndent = client.styles['blockquote'].rightIndent spaceBefore = client.styles['blockquote'].spaceBefore spaceAfter = client.styles['blockquote'].spaceAfter s = copy(client.styles['blockquote']) s.leftIndent = style.leftIndent data = [['', client.gather_elements(node, s)]] if client.splittables: node.elements = [ MySpacer(0, spaceBefore), SplitTable( data, colWidths=[leftIndent, None], style=TableStyle( [ ["TOPPADDING", [0, 0], [-1, -1], 0], ["LEFTPADDING", [0, 0], [-1, -1], 0], ["RIGHTPADDING", [0, 0], [-1, -1], rightIndent], ["BOTTOMPADDING", [0, 0], [-1, -1], 0], ] ), ), MySpacer(0, spaceAfter), ] else: node.elements = [ MySpacer(0, spaceBefore), DelayedTable( data, colWidths=[leftIndent, None], style=TableStyle( [ ["TOPPADDING", [0, 0], [-1, -1], 0], ["LEFTPADDING", [0, 0], [-1, -1], 0], ["RIGHTPADDING", [0, 0], [-1, -1], rightIndent], ["BOTTOMPADDING", [0, 0], [-1, -1], 0], ] ), ), MySpacer(0, spaceAfter), ] return node.elements class HandleAttribution(NodeHandler, docutils.nodes.attribution): def gather_elements(self, client, node, style): return [Paragraph(client.gather_pdftext(node), client.styles['attribution'])] class HandleComment(NodeHandler, docutils.nodes.comment): def gather_elements(self, client, node, style): # Class that generates no output return [] class HandleLineBlock(NodeHandler, docutils.nodes.line_block): def gather_elements(self, client, node, style): if isinstance(node.parent, docutils.nodes.line_block): qstyle = copy(style) qstyle.leftIndent += client.styles.adjustUnits("1.5em") else: qstyle = copy(client.styles['lineblock']) # Fix Issue 225: no space betwen line in a lineblock, but keep # space before the lineblock itself # Fix Issue 482: nested lineblocks don't need spacing before/after if not isinstance(node.parent, docutils.nodes.line_block): return ( [MySpacer(0, client.styles['lineblock'].spaceBefore)] + client.gather_elements(node, style=qstyle) + [MySpacer(0, client.styles['lineblock'].spaceAfter)] ) else: return client.gather_elements(node, style=qstyle) class HandleLine(NodeHandler, docutils.nodes.line): def gather_elements(self, client, node, style): # line nodes have no classes, they have to inherit from the outermost lineblock (sigh) # For more info see Issue 471 and its test case. parent = node while isinstance( parent.parent, (docutils.nodes.line, docutils.nodes.line_block) ): parent = parent.parent p_class = (parent.get('classes') or ['line'])[0] qstyle = copy(client.styles[p_class]) # Indent .5em per indent unit i = node.__dict__.get('indent', 0) # qstyle = copy(client.styles['line']) qstyle.leftIndent += client.styles.adjustUnits("0.5em") * i text = client.gather_pdftext(node) if not text: # empty line text = u"\xa0" return [Paragraph(text, style=qstyle)] class HandleLiteralBlock( NodeHandler, docutils.nodes.literal_block, docutils.nodes.doctest_block ): def gather_elements(self, client, node, style): if node['classes']: style = client.styles.combinedStyle(['code'] + node['classes']) else: style = client.styles['code'] return [ client.PreformattedFit(client.gather_pdftext(node, replaceEnt=True), style) ] class HandleFigure(NodeHandler, docutils.nodes.figure): def gather_elements(self, client, node, style): # Either use the figure style or the class # selected by the user st_name = 'figure' if node.get('classes'): st_name = node.get('classes')[0] style = client.styles[st_name] cmd = getattr(style, 'commands', []) w = node.get('width', client.styles['figure'].colWidths[0]) cw = [w] sub_elems = client.gather_elements(node, style=None) t_style = TableStyle(cmd) table = DelayedTable([[e] for e in sub_elems], colWidths=cw, style=t_style) table.hAlign = node.get('align', 'CENTER').upper() return [ MySpacer(0, style.spaceBefore), table, MySpacer(0, style.spaceAfter), ] class HandleCaption(NodeHandler, docutils.nodes.caption): def gather_elements(self, client, node, style): return [ Paragraph( client.gather_pdftext(node), style=client.styles['figure-caption'], ) ] class HandleLegend(NodeHandler, docutils.nodes.legend): def gather_elements(self, client, node, style): return client.gather_elements(node, style=client.styles['figure-legend']) class HandleSidebar(NodeHandler, docutils.nodes.sidebar): def gather_elements(self, client, node, style): return [ BoxedContainer( client.gather_elements(node, style=None), client.styles['sidebar'], ) ] class HandleRubric(NodeHandler, docutils.nodes.rubric): def gather_elements(self, client, node, style): # Sphinx uses a rubric as footnote container if ( self.sphinxmode and len(node.children) == 1 and node.children[0].astext() == 'Footnotes' ): return [] else: return [Paragraph(client.gather_pdftext(node), client.styles['rubric'])] class HandleCompound(NodeHandler, docutils.nodes.compound): # FIXME think if this is even implementable pass class HandleContainer(NodeHandler, docutils.nodes.container): def getelements(self, client, node, style): parent = node.parent if not isinstance(parent, (docutils.nodes.header, docutils.nodes.footer)): return NodeHandler.getelements(self, client, node, style) return self.gather_elements(client, node, style) class HandleSubstitutionDefinition(NodeHandler, docutils.nodes.substitution_definition): def gather_elements(self, client, node, style): return [] class HandleTBody(NodeHandler, docutils.nodes.tbody): def gather_elements(self, client, node, style): rows = [client.gen_elements(n) for n in node.children] t = [] for r in rows: if not r: continue t.append(r) t_style = TableStyle(client.styles['table'].commands) colWidths = client.styles['table'].colWidths return [DelayedTable(t, colWidths=colWidths, style=t_style)] class HandleFootnote(NodeHandler, docutils.nodes.footnote, docutils.nodes.citation): def gather_elements(self, client, node, style): # It seems a footnote contains a label and a series of elements ltext = client.gather_pdftext(node.children[0]) label = None ids = '' for i in node.get('ids', []): ids += '' % (i) client.targets.extend(node.get('ids', [ltext])) if len(node['backrefs']) > 1 and client.footnote_backlinks: backrefs = [] i = 1 for r in node['backrefs']: backrefs.append( '%d' % (r, client.styles.linkColor, i) ) i += 1 backrefs = '(%s)' % ', '.join(backrefs) if ltext not in client.targets: label = Paragraph( ids + '%s' % (ltext + backrefs), client.styles["endnote"] ) client.targets.append(ltext) elif len(node['backrefs']) == 1 and client.footnote_backlinks: if ltext not in client.targets: label = Paragraph( ids + '%s' % (node['backrefs'][0], client.styles.linkColor, ltext), client.styles["endnote"], ) client.targets.append(ltext) else: if ltext not in client.targets: label = Paragraph(ids + ltext, client.styles["endnote"]) client.targets.append(ltext) if not label: label = Paragraph(ids + ltext, client.styles["endnote"]) contents = client.gather_elements(node, client.styles["endnote"])[1:] if client.inline_footnotes: st = client.styles['endnote'] t_style = TableStyle(st.commands) colWidths = client.styles['endnote'].colWidths node.elements = [ MySpacer(0, st.spaceBefore), DelayedTable([[label, contents]], colWidths=colWidths, style=t_style), MySpacer(0, st.spaceAfter), ] if client.real_footnotes: client.mustMultiBuild = True for e in node.elements: e.isFootnote = True else: client.decoration['endnotes'].append([label, contents]) node.elements = [] return node.elements class HandleLabel(NodeHandler, docutils.nodes.label): def gather_elements(self, client, node, style): return [Paragraph(client.gather_pdftext(node), style)] class HandleEntry(NodeHandler, docutils.nodes.entry): pass class HandleRaw(NodeHandler, docutils.nodes.raw): def gather_elements(self, client, node, style): # Not really raw, but what the heck if node.get('format', 'NONE').lower() == 'pdf': return parseRaw(str(node.astext()), node) elif client.raw_html and node.get('format', 'NONE').lower() == 'html': x = parseHTML(str(node.astext()), node) return x else: return [] class HandleOddEven(NodeHandler, OddEvenNode): def gather_elements(self, client, node, style): odd = [] even = [] if node.children: if isinstance(node.children[0], docutils.nodes.paragraph): if node.children[0].get('classes'): s = client.styles[node.children[0].get('classes')[0]] else: s = style odd = [Paragraph(client.gather_pdftext(node.children[0]), s)] else: # A compound element odd = client.gather_elements(node.children[0]) if len(node.children) > 1: if isinstance(node.children[1], docutils.nodes.paragraph): if node.children[1].get('classes'): s = client.styles[node.children[1].get('classes')[0]] else: s = style even = [Paragraph(client.gather_pdftext(node.children[1]), s)] else: even = client.gather_elements(node.children[1]) return [OddEven(odd=odd, even=even)] class HandleAanode(NodeHandler, Aanode): def gather_elements(self, client, node, style): style_options = { 'font': client.styles['aafigure'].fontName, } return [node.gen_flowable(style_options)] class HandleAdmonition( NodeHandler, docutils.nodes.attention, docutils.nodes.caution, docutils.nodes.danger, docutils.nodes.error, docutils.nodes.hint, docutils.nodes.important, docutils.nodes.note, docutils.nodes.tip, docutils.nodes.warning, docutils.nodes.Admonition, ): def gather_elements(self, client, node, style): if node.children and isinstance(node.children[0], docutils.nodes.title): title = [] else: title = [ Paragraph( client.text_for_label(node.tagname, style), style=client.styles['%s-heading' % node.tagname], ) ] rows = title + client.gather_elements(node, style=style) st = client.styles[node.tagname] if 'commands' in dir(st): t_style = TableStyle(st.commands) else: t_style = TableStyle() t_style.add("ROWBACKGROUNDS", [0, 0], [-1, -1], [st.backColor]) t_style.add("BOX", [0, 0], [-1, -1], st.borderWidth, st.borderColor) if client.splittables: node.elements = [ MySpacer(0, st.spaceBefore), SplitTable( [['', rows]], colWidths=[0, None], style=t_style, padding=st.borderPadding, ), MySpacer(0, st.spaceAfter), ] else: padding, p1, p2, p3, p4 = tablepadding(padding=st.borderPadding) t_style.add(*p1) t_style.add(*p2) t_style.add(*p3) t_style.add(*p4) node.elements = [ MySpacer(0, st.spaceBefore), DelayedTable([['', rows]], colWidths=[0, None], style=t_style), MySpacer(0, st.spaceAfter), ] return node.elements class HandleMath(NodeHandler, docutils.nodes.math_block, docutils.nodes.math): def gather_elements(self, client, node, style): label = node.attributes.get('label') return [ Math( node.astext(), label, style, ) ] def get_text(self, client, node, replaceEnt): """Generate an image of the math equation for the inline role usage""" # get style for current node style = client.styles.styleForNode(node) label = node.attributes.get('label') mf = Math(node.astext(), label, style) mf.fontsize = style.fontSize * 0.95 w, h = mf.wrap(0, 0) descent = mf.descent() img = mf.genImage() client.to_unlink.append(img) return '' % ( img, w, h, -descent, ) rst2pdf-0.102/rst2pdf/genpdftext.py000066400000000000000000000212621463013543400172140ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms import os from urllib.parse import urljoin, urlparse from xml.sax.saxutils import escape import docutils.nodes from reportlab.platypus.paragraph import Paragraph from .basenodehandler import NodeHandler from .image import MyImage, missing class FontHandler(NodeHandler): def get_pre_post(self, client, node, replaceEnt): return self.get_font_prefix(client, node, replaceEnt), '
' def get_font_prefix(self, client, node, replaceEnt): return client.styleToFont(self.fontstyle) class HandleText(NodeHandler, docutils.nodes.Text): def gather_elements(self, client, node, style): return [Paragraph(client.gather_pdftext(node), style)] def get_text(self, client, node, replaceEnt): text = node.astext() if replaceEnt: text = escape(text) return text class HandleStrong(NodeHandler, docutils.nodes.strong): pre = "" post = "" class HandleEmphasis(NodeHandler, docutils.nodes.emphasis): pre = "" post = "" class HandleLiteral(NodeHandler, docutils.nodes.literal): def get_pre_post(self, client, node, replaceEnt): if node['classes']: pre = client.styleToFont(node['classes'][0]) else: pre = client.styleToFont('literal') post = "
" if not client.styles['literal'].hyphenation: pre = '' + pre post += '' return pre, post def get_text(self, client, node, replaceEnt): text = node.astext() text = escape(node.astext()) text = text.replace(' ', ' ') return text class HandleSuper(NodeHandler, docutils.nodes.superscript): pre = '' post = "" class HandleSub(NodeHandler, docutils.nodes.subscript): pre = '' post = "" class HandleTitleReference(FontHandler, docutils.nodes.title_reference): fontstyle = 'title_reference' class HandleReference(NodeHandler, docutils.nodes.reference): def get_pre_post(self, client, node, replaceEnt): pre, post = '', '' uri = node.get('refuri') if uri: # Issue 366: links to "#" make no sense in a PDF if uri == "#": return "", "" if uri.startswith('#'): pass elif client.baseurl: # Need to join the uri with the base url uri = urljoin(client.baseurl, uri) if urlparse(uri)[0] and client.inlinelinks: # external inline reference if uri in [node.astext(), "mailto:" + node.astext()]: # No point on repeating it post = u'' elif uri.startswith('mailto:'): # No point on showing "mailto:" post = u' (%s)' % uri[7:] else: post = u' (%s)' % uri else: # A plain old link pre += u'' % ( uri, client.styles.linkColor, ) post = '' + post else: uri = node.get('refid') if uri: pre += u'' % ( uri, client.styles.linkColor, ) post = '' + post return pre, post class HandleOptions( HandleText, docutils.nodes.option_string, docutils.nodes.option_argument ): pass class HandleSysMessage( HandleText, docutils.nodes.system_message, docutils.nodes.problematic ): pre = '' post = "" def gather_elements(self, client, node, style): # FIXME show the error in the document, red, whatever # log.warning("Problematic node %s", node.astext()) return [] class HandleGenerated(HandleText, docutils.nodes.generated): pass # def get_text(self, client, node, replaceEnt): # if 'sectnum' in node['classes']: # # This is the child of a title with a section number # # Send the section number up to the title node # node.parent['_sectnum'] = node.astext() # return node.astext() class HandleImage(NodeHandler, docutils.nodes.image): def gather_elements(self, client, node, style): # FIXME: handle alt target = None if isinstance(node.parent, docutils.nodes.reference): target = node.parent.get('refuri', None) st_name = 'image' if node.get('classes'): st_name = node.get('classes')[0] style = client.styles[st_name] uri = str(node.get("uri")) if uri.split("://")[0].lower() not in ('http', 'ftp', 'https'): imgname = os.path.join(client.basedir, uri) else: imgname = uri try: w, h, kind = MyImage.size_for_node(node, client=client) except ValueError: # Broken image, return arbitrary stuff imgname = missing w, h, kind = 100, 100, 'direct' node.elements = [ MyImage( filename=imgname, height=h, width=w, kind=kind, client=client, target=target, ) ] alignment = node.get('align', '').upper() if not alignment: # There is no JUSTIFY for flowables, of course, so 4:LEFT alignment = {0: 'LEFT', 1: 'CENTER', 2: 'RIGHT', 4: 'LEFT'}[style.alignment] if not alignment: alignment = 'CENTER' node.elements[0].image.hAlign = alignment node.elements[0].spaceBefore = style.spaceBefore node.elements[0].spaceAfter = style.spaceAfter # Image flowables don't support valign (makes no sense for them?) # elif alignment in ('TOP','MIDDLE','BOTTOM'): # i.vAlign = alignment return node.elements def get_text(self, client, node, replaceEnt): # First see if the image file exists, or else, # use image-missing.png imgname = os.path.join(client.basedir, str(node.get("uri"))) try: w, h, kind = MyImage.size_for_node(node, client=client) except ValueError: # Broken image, return arbitrary stuff imgname = missing w, h, kind = 100, 100, 'direct' alignment = node.get('align', 'CENTER').lower() if alignment in ('top', 'middle', 'bottom'): align = 'valign="%s"' % alignment else: align = '' # TODO: inline images don't support SVG, vectors and PDF, # which may be surprising. So, work on converting them # previous to passing to reportlab. # Try to rasterize using the backend w, h, kind = MyImage.size_for_node(node, client=client) uri = MyImage.raster(imgname, client) return '' % (uri, w, h, align) class HandleFootRef( NodeHandler, docutils.nodes.footnote_reference, docutils.nodes.citation_reference, ): def get_text(self, client, node, replaceEnt): # TODO: when used in Sphinx, all footnotes are autonumbered anchors = '' for i in node.get('ids'): if i not in client.targets: anchors += '' % i client.targets.append(i) return u'%s%s' % ( anchors, '#' + node.get('refid', node.astext()), client.styles.linkColor, node.astext(), ) class HandleTarget(NodeHandler, docutils.nodes.target): def gather_elements(self, client, node, style): if 'refid' in node: client.pending_targets.append(node['refid']) return client.gather_elements(node, style) def get_text(self, client, node, replaceEnt): text = client.gather_pdftext(node) if replaceEnt: text = escape(text) return text def get_pre_post(self, client, node, replaceEnt): pre = '' if node['ids']: if node['ids'][0] not in client.targets: pre = u'' % node['ids'][0] client.targets.append(node['ids'][0]) else: name = node['names'][0] if name: pre = '' % name client.targets.append(name) return pre, '' class HandleInline(NodeHandler, docutils.nodes.inline): def get_pre_post(self, client, node, replaceEnt): if node['classes'] and node['classes'][0]: r = client.styleToTags(node['classes'][0]) if r: return r return '', '' rst2pdf-0.102/rst2pdf/image.py000066400000000000000000000363021463013543400161270ustar00rootroot00000000000000# -*- coding: utf-8 -*- from copy import copy import glob import os from os.path import abspath, dirname import sys from urllib.request import urlretrieve from PIL import Image as PILImage from reportlab.platypus.flowables import Image, Flowable from reportlab.lib.units import cm, inch from .log import log, nodeid try: from .svgimage import SVGImage except ImportError: # svglib may optionally not be installed, which causes this error SVGImage = None # find base path if hasattr(sys, 'frozen'): PATH = abspath(dirname(sys.executable)) else: PATH = abspath(dirname(__file__)) missing = os.path.join(PATH, 'images', 'image-missing.jpg') def defaultimage( filename, width=None, height=None, kind='direct', mask='auto', lazy=1, srcinfo=None, ): """Get default image backend. We have multiple image backends, including the stock ReportLab one. This wrapper around the ReportLab one allows us to pass the client ``RstToPdf`` object and the URI into all our backends, which they can use (or not) as necessary. """ return Image(filename, width, height, kind, mask, lazy) class MyImage(Flowable): """A Image subclass that can: 1. Take a ``percentage_of_container`` kind, which resizes it on ``wrap(`` to use a percentage of the container's width. 2. Take vector formats and instantiates the right "backend" flowable. """ warned = False @classmethod def support_warning(cls): if cls.warned or PILImage: return cls.warned = True log.warning( 'Support for images other than JPG is now limited. Please install ' 'Pillow.' ) @staticmethod def split_uri(uri): """Split provided URI. A really minimalistic split -- doesn't cope with http:, etc. HOWEVER, it tries to do so in a fashion that allows a clueless user to have ``#`` inside his filename without screwing anything up. """ basename, extra = os.path.splitext(uri) extra = extra.split('#', 1) + [''] fname = basename + extra[0] extension = extra[0][1:].lower() options = extra[1] return fname, extension, options def __init__( self, filename, width=None, height=None, kind='direct', mask='auto', lazy=1, client=None, target=None, ): # Client is mandatory. Perhaps move it farther up if we refactor assert client is not None self.__kind = kind # Maximum page height is used when resizing in wrap() as we can't render an image across a page boundary self.max_page_height = 999999 if filename.split("://")[0].lower() in ('http', 'ftp', 'https'): try: filename2, _ = urlretrieve(filename) if filename != filename2: client.to_unlink.append(filename2) filename = filename2 except IOError: filename = missing self.filename, self._backend = self.get_backend(filename, client) srcinfo = client, self.filename if kind == 'percentage_of_container': self.image = self._backend( self.filename, width, height, 'direct', mask, lazy, srcinfo ) self.image.drawWidth = width self.image.drawHeight = height self.__width = width self.__height = height else: self.image = self._backend( self.filename, width, height, kind, mask, lazy, srcinfo ) self.__ratio = float(self.image.imageWidth) / self.image.imageHeight self.__wrappedonce = False self.target = target @classmethod def raster(self, filename, client): """Convert image to raster image. Takes a filename and converts it to a raster image reportlab can process. """ if not os.path.exists(filename): log.error('Missing image file: %s', filename) return missing try: # First try to rasterize using the suggested backend backend = self.get_backend(filename, client)[1] return backend.raster(filename, client) except Exception: pass # Last resort: try everything if PILImage: # See if pil can process it try: PILImage.open(filename) return filename except Exception: # Can't read it pass # PIL can't, so we can't self.support_warning() log.error('Could not load image: %s', filename) return missing @classmethod def get_backend(self, uri, client): """Get backend for an image. Given the filename of an image, returns ``(fname, backend)``, where ``fname`` is the filename to be used (could be the same as filename, or something different if the image had to be converted or is missing), and ``backend`` is an ``Image`` class that can handle ``fname``. If ``uri`` ends with '.*' then the returned filename will be the best quality supported at the moment. That means: SVG > PNG > JPG > GIF """ backend = defaultimage # Extract all the information from the URI filename, extension, options = self.split_uri(uri) if '*' in filename: preferred = ['gif', 'jpg', 'png', 'svg'] # Find out what images are available available = glob.glob(filename) cfn = available[0] cv = -10 for fn in available: ext = fn.split('.')[-1] if ext in preferred: v = preferred.index(ext) else: v = -1 if v > cv: cv = v cfn = fn # cfn should have our favourite type of those available filename = cfn extension = cfn.split('.')[-1] uri = filename # If the image doesn't exist, we use a 'missing' image if not os.path.exists(filename): log.error('Missing image file: %s', filename) filename = missing return filename, backend if extension in ['svg', 'svgz']: if SVGImage is not None: log.info('Backend for %s is SVGImage', filename) backend = SVGImage else: log.error('SVG image support requires svglib: %s', filename) filename = missing elif extension in ['pdf']: log.error("PDF images are not supported") filename = missing elif extension != 'jpg' and not PILImage: # No way to make this work log.error( '%s image support requires Pillow: %s', extension.upper(), filename, ) filename = missing return filename, backend @classmethod def size_for_node(self, node, client): """Get size for image node. Given a docutils image node, returns the size the image should have in the PDF document, and what "kind" of size that is. That involves lots of guesswork. """ uri = str(node.get('uri')) if uri.split('://')[0].lower() not in ('http', 'ftp', 'https'): uri = os.path.join(client.basedir, uri) else: uri, _ = urlretrieve(uri) client.to_unlink.append(uri) srcinfo = client, uri # Extract all the information from the URI imgname, extension, options = self.split_uri(uri) if not os.path.isfile(imgname): imgname = missing scale = float(node.get('scale', 100)) / 100 # Figuring out the size to display of an image is ... annoying. # If the user provides a size with a unit, it's simple, adjustUnits # will return it in points and we're done. # However, often the unit wil be "%" (specially if it's meant for # HTML originally. In which case, we will use a percentage of # the containing frame. # Find the image size in pixels: kind = 'direct' xdpi, ydpi = client.styles.def_dpi, client.styles.def_dpi extension = imgname.split('.')[-1].lower() if extension in ['svg', 'svgz']: if not SVGImage: raise RuntimeError( 'Documentation uses SVG image but svglib is not installed.' ) iw, ih = SVGImage(imgname, srcinfo=srcinfo).wrap(0, 0) # These are in pt, so convert to px iw = iw * xdpi / 72 ih = ih * ydpi / 72 else: keeptrying = True if PILImage: try: img = PILImage.open(imgname) img.load() iw, ih = img.size xdpi, ydpi = img.info.get('dpi', (xdpi, ydpi)) keeptrying = False except IOError: # PIL throws this when it's a broken/unknown image pass if keeptrying: if extension not in ['jpg', 'jpeg']: log.error( "The image (%s, %s) is broken or in an unknown format", imgname, nodeid(node), ) raise ValueError else: # Can be handled by reportlab log.warning( "Can't figure out size of the image (%s, %s). Install PIL for better results.", imgname, nodeid(node), ) iw = 1000 ih = 1000 # Try to get the print resolution from the image itself via PIL. # If it fails, assume a DPI of 300, which is pretty much made up, # and then a 100% size would be iw*inch/300, so we pass # that as the second parameter to adjustUnits # # Some say the default DPI should be 72. That would mean # the largest printable image in A4 paper would be something # like 480x640. That would be awful. # w = node.get('width') h = node.get('height') if h is None and w is None: # Nothing specified # Guess from iw, ih log.debug( "Using image %s without specifying size." "Calculating based on image size at %ddpi [%s]", imgname, xdpi, nodeid(node), ) w = iw * inch / xdpi h = ih * inch / ydpi elif w is not None: # Node specifies only w # In this particular case, we want the default unit # to be pixels so we work like rst2html if w[-1] == '%': kind = 'percentage_of_container' w = int(w[:-1]) else: # This uses default DPI setting because we # are not using the image's "natural size" # this is what LaTeX does, according to the # docutils mailing list discussion w = client.styles.adjustUnits(w, client.styles.tw, default_unit='px') if h is None: # h is set from w with right aspect ratio h = w * ih / iw else: h = client.styles.adjustUnits(h, ih * inch / ydpi, default_unit='px') elif h is not None and w is None: if h[-1] != '%': h = client.styles.adjustUnits(h, ih * inch / ydpi, default_unit='px') # w is set from h with right aspect ratio w = h * iw / ih else: log.error( 'Setting height as a percentage does **not** work. ' 'ignoring height parameter [%s]', nodeid(node), ) # Set both from image data w = iw * inch / xdpi h = ih * inch / ydpi # Apply scale factor w = w * scale h = h * scale # And now we have this probably completely bogus size! log.info( 'Image %s size calculated: %fcm by %fcm [%s]', imgname, w / cm, h / cm, nodeid(node), ) return w, h, kind def _restrictSize(self, aW, aH): return self.image._restrictSize(aW, aH) def _unRestrictSize(self, aW, aH): return self.image._unRestrictSize(aW, aH) def __deepcopy__(self, *whatever): # ImageCore class is not deep copyable. Stop the copy at this # class. If you remove this, re-test for issue #126. return copy(self) def wrap(self, availWidth, availHeight): if self.max_page_height < availHeight: # We can't render an image across a page boundary, so this is the tallest we can be availHeight = self.max_page_height if self.__kind == 'percentage_of_container': w, h = self.__width, self.__height if not w: log.warning( 'Scaling image as % of container with w unset. ' 'This should not happen, setting to 100' ) w = 100 scale = w / 100.0 w = availWidth * scale h = w / self.__ratio self.image.drawWidth, self.image.drawHeight = w, h return w, h else: if self.image.drawHeight > availHeight: if not getattr(self, '_atTop', True): return self.image.wrap(availWidth, availHeight) else: # It's the first thing in the frame, probably # Wrapping it will not make it work, so we # adjust by height # FIXME get rst file info (line number) # here for better error message log.warning( 'Image %s is too tall for the frame, rescaling', self.filename ) self.image.drawHeight = availHeight self.image.drawWidth = availHeight * self.__ratio elif self.image.drawWidth > availWidth: log.warning( 'Image %s is too wide for the frame, rescaling', self.filename ) self.image.drawWidth = availWidth self.image.drawHeight = availWidth / self.__ratio return self.image.wrap(availWidth, availHeight) def drawOn(self, canv, x, y, _sW=0): if self.target: offset = 0 if self.image.hAlign == 'CENTER': offset = _sW / 2.0 elif self.image.hAlign == 'RIGHT': offset = _sW canv.linkURL( self.target, ( x + offset, y, x + offset + self.image.drawWidth, y + self.image.drawHeight, ), relative=True, # thickness = 3, ) return self.image.drawOn(canv, x, y, _sW) rst2pdf-0.102/rst2pdf/images/000077500000000000000000000000001463013543400157345ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/images/image-missing.jpg000066400000000000000000000117551463013543400212000ustar00rootroot00000000000000ÿØÿàJFIFvvÿÛC       ÿÛC ÿÀ€€"ÿÄ  ÿÄQ  !18AQwµ "2Waq¦±Ô#$3BRTXr’–¡Ós‘“bcÑð4CDƒ¢²ÁáÿÄÿÄ7 !1Aq"2Qa‘Áð$Rr¡b‚Ñ#±áÿÚ ?•8ŒÈe ûÃG«à^Ž®R¤æè’Õ»¥ÖÙŸqÙ¶â¥äÛ%l§‚l¼^BÕÂ)Ô4¦ƒ‹“øÍ,xÓã'HX¿[Wº§g?FhþÉ º§g?FhþÉ—==>™ù”¢uô¥.¬ †¦v¡ôéê«üà±UÝÔ};–”Õ9ÊsͲ3Ž´6r–ÒBOš,%±ÿ°öy©–¤ÕyÐA=°Û-Ô˜O:Z'UáÌ”hÇÝš_V}:b±kãUÂ…0‚´7Uu­9PNÏõ¶4}—ˆWV¡R¢×’šý”çjÔåžÕ}czR*¥96ÌÑbÌ˸{Ê´.õÝÞ¹II`¸¼'™]˜­hç×1À ¸¾”qûHª‘,ÇhMÖ-j«næui]ë,oBÒv¥C˜Žc¸ƒ""÷ö­vÙ¹šÄ<<˜í[Ž]ASRÈV£5¦†ÒË láwê9–yœŽy‚$q‚…$×Etž:Úö-§rZ9•›fc(ÙÉÎrбöpüޱæ7pPœÅ—NDyr]Æ—Õ§éu,mÑp pÁÀ…°õ 9´{â÷„;Tú|â=Ê.†ßDî4ø7Ò½Ö,A)ÀÖhÆŸú@·ºÅˆ%8"P5šXñ§ÆN.±~ N³K4øÉÒÃÖ/ÁÌ'áO^¸C$‚£¸ áï„»öÕë‹Z£¯L™{æ4£ùAap>“·Ó—æ9·l­ýz=”Ës«hx+¨;¬Öû ‚±åXÅ"µ‹—½+è30ÝE&j³2τ̊NZ ò)Åw¾A·hÎ<µZ´ã÷ÅóT}·&®‰æµÉÌ”0 ÒG˜#£;Öû5[¾ú¼æPê* RšQ e ÈyÔò³óD]ƒ–Í–»BMx6ÔõÚ®HÑ>ÀÛIŒhoÞúî ¸ŸâÞ¥×8g†VÖT 1‰V¥ZKiKiÈ$OþòïUPŸ“¥J9;:ê[i°I$ÇÚ…BR•(äìë©m¶ÒI$Ç cn’Tú‘y2N&bšÒ”‰Yp®öyÁò•þÿ¼ìð|)ÄÄ)8{o°ÝýWá¸dÞ74 ÀÎq¹×]äøêV7J]›½©[5Išum%Ë9¨üÛ{ŽGz[;µ·«“½Ú®n”rN—(Í2—,†%Ù 4ØØ?Ìùw˜·¬\ukš¬äôëÎMNͯfI;€ƒ˜Fc ð®çÇKV¥°ë¬Ñ¥\à«•¦w+,­ÅdýÍÉg&´YÓ1'£Õ¢®:¡ëR¯XD®TÃ6fÑw³§w×––¾d'ê“T¹GTµÊ¤+…á%•ªrŽ$o=±û;Å ¶B(÷ËÎ%¬ûÖêlê‡ÂGø”º|»¢ÃLœµðfFÀ™·¥[••}ÚJõÕJakÌš•’™Ï=§2NÒc@á¦%Ñç1É“¡ªuÇi×D›†uÔ†’0¡.âœÊŠT sRŠI QÃnJh5æ¤÷‡X]KR÷ÀÌX4H°XC\×ØÞ…• ×JÕ ÛM¢/¾hÓ’’Â3‡%=ðÛË´‡DÅ2UïžÒOå‰1ç‰Z¤ÙhÆŸú@·ºÅˆ%8͸ÓàßH÷X±§J³K4øÉÒÃÖ/Á)ÀÖicÆŸ:@¸zÅø"#‡‡ÂûjõÅ­UŽ™2ÏÎiCò‹ÇGÂûjõÂ’RFÂ2‚ƒ||ÛgîyiYɹ2ÕÉR.!)'V—ÐHݵ.#¯ûX‹N¥Ï]ôjÅA´“-[l-Y)aæR‡çÉläy‰ñá; ˜;7CÄ¥\’²¹H]m6ÒbjL–¹ ÉR•±Î#–­Š÷hÓÝeuyê{Í0äšÄ©)\䣊 \±WÈé>b¡ÇÇ8\ñsÁ àëÍ•ñ/!ñ†[dcÏæŽ´GÅv—z`LâÌ勇õG%íyw/?R—^K¨¬•/.¡þï‘n þÙás+·ýÑS}©—ÖÉ-´„³­ªÀLyd¿3U™md ¦i=êòP„ôctà&ÜØÍsþïPxYj|«ºÝe±²_çJË+rž ÷ËÚ) Lhóx¼Ðk5: ͵;Õ‘‡a˜³\”NP¾›úNwPõØS°³ñÚârܦÏ.VŽÒ¸ÕZ^]¶ø4œµ¥XZSµÒ<5fBå$)8W…v¶ZÒVűKfR^Q ÚRÚwsíÞI9’NÒI'2aaNÚ¸OjÉZö½-‰9i6ƒiKiÝÏ·y$æI;I$œÉ‡b¦*ZXOiOÝ7M^^JVI•8µ¸¼¼À ä“m$€&'~…JÕÛÉõ`¾jÍžo5ΘŽey¬ ÂÃSþ´Éâ~ÉÅß(äí±i6òTäºæjïv¡,°¦“Ÿ6k˜y4qFŽTg꘣k°Ã qO\”íP‘™!•©õŸ0K`˜ÌéŠÕŒU½*—mU·X™¬7/&³šä©è9´Ò‡#‹Q.,r$o~ÇÎMVq0\óR ÈZ8Êœ#bªO„O/ÈJ•ÃÌb>bþ£ˆÖ• ¹=åY-–9[)|ÍžàãN×Vß‘à¥"ŽÏkÒåYË-F’?(¼âÌ>”€v”=¹€¥¥ ï DÅQˆn4NãOƒ} [ÝbÄœ f‰Üiðo¤ {¬X‚S‚%Y¥|déáëà”àk4±ãOŒ \=büã£ßÜûg×@Ž~síŸ\=µ¾=àÅì)ëR´ÒÁu̼ҵ]eÔd8…r)*@ó¹ŒÄD>*a ×c]ÓVÝÅ X¯2V¤äÞ£U†Sÿ/ÈW–EÆÖIÌŒÁ‰Åã[c6ØXÙA]줶öJ²òImÖ]O‚ãn$…!cç$ƒ´ÄˆÖbXk'ÙPhñ¡ò=ž‚–e<Ù3•æ}ã9ÐέóªèS2MHMÉÇiµýí¹î „ #å' BNÑ®3 ‚;“Fm'hV­O´½kÒY”oƒI’©)Ä„[ ÍDæu‰Q$’IÌljÅ}qZ×›zb--{SP3iS¥U@ݪ^J /ä>S‰AäÌï%ý‡Þl͹'?fÞ”—P½MGèjš@ÿ«.¥%C<ö™d|‘… ÁÞã kÙ´x¡É??’óô6ÄÄ&Ÿ aÀ.èÄ-8 &]Ö¨3¶êŠ›V£«sY Ëfmð`¼QÂ8·w~&W?k]w+µù¦]+‘e,)òJ;”Ó•8à€ã„‘™ÈEúpìva¹iKnâ‚ClPœ–IÏw¾¾R„íËiØ#na~ƒØ¥q̳1_–•²éʸ©yŽÝª¬|ÞH ±³•´¬òf7ÇcÝŒâ¿ãsK[¾Û#¾¦§‚ðÁ…ìÿ&üÌÆf(Ò´ò²çü6Â˶û¼Y¡ÑeW5pL­.8µ ¸Ý)µœÌÌÉÝÂe™CDë(í9ÇXQAÁ[FÕ¢¶¬ÚF³Î¸­guGYn-\ªR‰Q<çfC!œ8ÂL=À;hS­êkL$(ºóÊQ[:|'Z³RÔyT¢NÀ7„â ªn–(ô¹éÕóKË­ÏP‰6†3eÍ^u>C±UY³6Ìæ‰·˜c¢ßíl=ýè©/>ÚBÝu(BTµ)Y¼“È#Á;P¯4×lTÚD‚2Ì6µ…9ü†Áÿ3Ÿ’#g²#§$Üêj…µÅj©k–£,æ@ Ê’mCy;#vÔo×h¢KtNãOƒ} [ÝbÄœC_bSCúííˆòzL_–Þ¥™kðÊ·8„Õ+ <^m§WÌ¿¾«…3(gQJ-:”L¤(Í,xÓã'HX¿§Y¥|déáëàˆÜøç>ÑõÅDCñËûf*#t=0ñºÐñºœP•U$yâÕú%&ckÔöç@‹Á¾>«Á0EˆU"“* fžÂ<Èa4âPHhËN+aŒúòµþ!©ê“²Ysï“ólˤ}µ„ÿî6]Ñs3Mam¶àÖËiÎ5¹qµÝb«1ñT¶Ô´gÊêJÖ>|£‡4ãì€ËØ«ŸÃ<%¨³;u«Y™êŠrqšO!Jw…¾9¶¥ÂÌX"gdNØÌMá6U³ºç[Õ¨Ï2¼ÿe2±à‚7>¤œ¨IÖØJc“tÐzõÓõ\ôó³”\<¢Ì¤\Hás £%(T W2¤¨¢ YJ‚ÖTÓNù ô_ÅM21QËnÛyäJ¡Ñ=sÜóÉ[ÌÓ™qd—\$‚óî¾ ­`§IJ㈠Ì*Ã;WðâÜÂÛ*Sµè¶Í=ª|¶³m¡Çµ~û¼…<êÊœqa#]Å­Df£Wvfáe›IÃì>·¥(võ\KHÈ˨Ò3$’I*ZÔ¢¥­j%kZ”¥)DŸA (Í,xÓã'HX¿§íÙìtâä¾.\xå¶TÝ×l]s «Ô锄®b£M¨º´&càêZž™CÏ8§ÁdYÔ© ¶ÒT²)x[NðË<²*'tTKneà+ù@Üû“´§ú´â¯àÚèÂ÷'iOõiÅ_ÁµÑ‚"H^^þPð•eàŸåiîNÒŸêÓŠ¿ƒj?£ Ü¥?Õ§ÔF‰<žãT©@×û“´§ú´â¯àÚèÂ÷'iOõiÅ_ÁµÑ‚"AšeÕõµ01©JL¥—[%IR”R@HÉ<Ð;žäí)þ­8«ø6£ú0½ÉÚSýZqWðmGô`‹²tÝì…´§jXQ£í`+Ykb©sK/09Üš†óÈ^ÈÌä± tÐzõÓõ\ôó³”\<¢Ì¤\Hás £%(T W2¤¨¢ YJ‚ÖTÓNïMû˜{Wh÷æ“ßÝ{1³Š·2SXª'Q·mÔ·þÆÊõÔ—–™”––ßÑR]D¿ZÖ«cP¥mk*Ù¥[ôY-~Ö§Rä›”•c]jZõl% ÖZÔ£Ú¥v“V¶fáe›IÃì>·¥(võ\KHÈ˨Ò3$’I*ZÔ¢¥­j%kZ”¥)DŸA (P¡AÿÙrst2pdf-0.102/rst2pdf/images/image-missing.png000066400000000000000000000257341463013543400212060ustar00rootroot00000000000000‰PNG  IHDR€€Ã>aËsRGB®ÎébKGDÿÿÿ ½§“ pHYs.#.#x¥?vtIMEÙ,+˜¨™L IDATxÚíywy÷?}Ì}íÎÞ«såK>äÛ`lcb'¤Þ@¥*DðR¼Ä@À¤c ”£8Æ8ØTb¿ TÀDø-cXÂȇ¬Ó–eY–¬cW{Î=ÝÓ÷ûÇtzfgwgW»ÒJvWuuOïÌNO¿Ï÷y~Ïó;Çqx{{ënâÛà­½Ésý  B㥷çqÝê¤Û™£” ³ýœ |ãþ6Nÿ>["ÌŠ.ø" 5›ÿ6!ØêÝ×6`ù³!AËð/ß.ûHð6èÇø&`øvs6$˜M ¸Â@ˆÁ”àímaàY¼¨€ÒÄ%Ì|~_t ’@ÜG‚F¼M†…õû¶ü€{Ýr@AhEŽE@›ã8¼Ë‰ÛAøc¨¸Gs!šþ èZ~ `|b‚JE£Ú0Ü«ÿëúäL¯¡±Å9¹Úâßêodê¨Uf| _zl ÎAdY&‹áb ¹˜È³uÅòîÕ†4­ø3aò³›=Žø9Þ"àÂìÍyäºÿi™5#5 Æ4ä‘ÀkÖ}çü¨@ëV/Lì|¨A‹€ su~È!ùð˜õ—ÉǨ\M èX%¿þõ|?“µ· º0Ï@ÏÅL…Ãñ$ÍÀo]òçfõS<#ðÇèûçâ÷¢4ßÿSž¥µO•žü…²ú¹?+5˜K`¸n`öØ8ÇEÁŸ ¸-Yý,ž+ð³}>ÜÀ±ÐÂ9Î 0plĘO70¾.€ lö‹†ó­Çø9>[E8~nàD`q,À·ú|ùû·´ XP«?5˜-èÇ¢ §® hsŽàŸ`70¿/ÌÞZÞvSº…yû¹ß*èÇê„S‰­Êü\=óüÜÀl]ÀÉR ?..`¾%_˜'àçtans*º€Ùƒ¿PV?oÀÏðž`°ÀàÏ'ð³ôý³õùoA0=øMlAò…éÀh`aŽÖÞ*è±ZÍ©@€cÿX¬þ¸ßj|p’ˆò‚ƒÜ@ËÀ·bÅî{fëóßò.`®@·*ù³µzïÌqœÚuǶ«uSA¨¥VA8~n`®®`ôÊ'5ø3ï88Ž»ÛÞѶk×½{Q’Ik×ðŽs|!”aãù„¿’/U€- Ƕ1M˲0L³vn[¦ibÛ6¶mWE$IB–¤êQ–‘$‰@ €$ËȲŒ(Š5b,¨"œÌ.`¾ÀŸ­Õ{ÖmY–ibš¦Q©TP+*• †®WÿnYUðMgbQ F ªÖï  …ˆF£„ÃaB¡@ J W)Q<¾V½s9ÈÇüùvð¦i¢ë:UEUUÊå2ªª¢V*è{÷"mÞL¸T"M&‰õö ´t)R4Š Š(ƒƒ”öï§42‚R,¢dÎ=yåJ¢ÑhmÅã„Ãa¡’$!ŠâÌàÍ—2,@ÓQ>ÙÀ÷^Û¶iY躎R.S(( ”ËeÌmÛ^xè¤ÛÚõõìë#ÐÑA¨»›`o/N4ZIi„R)’çŸOlåJÒÙ,F&SÝÇÇ)lÛFÆ0^½šÀš5Ä ‰Éd’h4J(ª¹ˆYµNÕfà1ߢ՛–…a”ËeŠ…¹\ŽâÈöƒ"?ý4BÈÊ•„ûû‰¿óDÏ=9E EѲ°ŠElMC*ccè¡ÈrÕ•„ÃX©–¦I&éÃØ°eýzò+VÿàIvw“J¥HµµU‰ "ËòI7 rþc€9ÛÊ{lÛÆ0ME¡P(ËfÉOL`=ôÒ/‰\,"§Rt¬ý’—¾ƒXO( ÆÄæø8¦ëCýc&½–Bãu$‰HW²eè¥Êž=”~˜À#`<ò™?ÿsÊú¥R‰öööš"]’5“ïÅHŽ–æÁR@Ð t9ŽsÿD&³`à׆B¹r_,•Èf2d2ÔGAúÉO`t9£ÿÆ¿%uÞHåz±TS¦Úoô5ýf{=NC4ÊØocâ§?ÓÆéëÃùÈGˆÜpétšŽŽ‰¡pY’¼`0ˆ ŒÃî1Ouİé8Ž}Ü0S´?Wð7º×t\.ÇÄø8Ùƒ±¿õ-„]»B2=ýk:ßu%Ë8šÑ²•Ïåz0•„x”Ü3Ï0òàOp,çüó‘o¹…ôòåt»®!×Z o Ì¥©×ø¦e¡ª*¹\Žñ±1r۷÷¾…0>FÇûo ûOþÙ°ÊjõSÇ`å-_ÇAŠÇ"AöÞñmœCCÐÓ ·ÞJûùçÓÝÝM›Ȳ|4©4Ï[ Út=&œDÐlÀW…L&ÃøØùLJï~Á¬°äÓŸ íìs±s †C `Ú8‚ã€à88Ž…Q.áØ6b8‚â ‚cãØ L« v®€Y9ýæ¯2òÿÖ“ÿõã8_ü"_øÖõ×W³@,C–eë¶0AàlÁoB˶©T*d3FGF(Þ?ÎOгâK_$–èÄÌ•«yü)%ÛÇ¡RÌ{e7Ú‘˜ùv©Œ]*!XNµ €qâ1ý=„z—_±Œpº ÛžBLã7éxÏ{Ižw‡ïºó¶ÛÈ8€½v-¢(Ö”àÔ/Íì)À×4\6ËØØ…üë'^ÞÏŠ?I@0ËZ5à³rŽ`£³LlÛŽº/ÖàŽéàXNõ;D!‘@H&Á¶qÆÇ«ÿ¯œÃÍ¡‰¯Q”DÄtŠÈYgÓváÄ@±¾¨ä~¯rx!dù?ÜÌÞ\?z€œ("®][KE"¤ãž¸DÐHpy/+>ó¿‘Ê6¶-4—fl ½Èè–M”žßŽS6Àr;;ᢋ.¿aåJ¤ŽDY®¦Ýæ¥=1uø0 !<ˆýì³XÃY̱M·l&töi¤/}'Pœ&ªSTÑ-‹å_ú×Ýõ£‘]¾ù†j‰¢p8ܼ‰xÒ'‚æö¤œ>T›zÅ"ãããdvîĸë.¤d˜¥ûK„¢‰m “}<–Saì•Í~¿;SABzÏ{ß÷>äÕ« ƒ„B¡ZNß³L¯•aöô`y&º®£ë:êÚµO>‰ýØc8o¼²y7•½o»ìÚÎ8Á©w9VAAr",ûüßràŽ»1‰þþºï …B Ú281 0ðS¦‚€i¨ŠÂÄăƒhßúX–®ý(!'ŒmVƒ¹z8fžÁ'§òÊ~äË.CþèG‰ ‹ÅˆÅbDc1"á0@ š ôUö¼±åV E!›Í2zýõŒ_tâ›o¿çìlžÒÖ­„{zE;qœÉ¢-HÅXú>Æ¡ïßOåß`ìž{ƒƒÁZ•±Y°<›m¾&ù^ø Y€Ø|Û¶1tB¡@&›¥üÍobMŒ²ôà ïÀÔìÉQ¹h£†~ü1*oN vtüˆ¬YC[[Éd’D"A8!Ô¤Øk–5&Š<„ÃaŠÅb°§žÂ.ä»bt\÷Èá4¶iOÙJ¨Lä‰,í ù‡W’ýõ³”¿ùM2wÝÕ¼v0O-¯EÓ hìf¯-Ó¤\.“Éf)>ñÆ+/ÓyíÅ$Vž†­ŽUÿÀ‹Òð>†}cL!pÖjB7ßLª¿Ÿt:M{{{­”[«ÚÁ´mrQk$¨T*†Aäþû±ŸÛ„Ü› ý®AwâÖÑàsŠÜAùà(W^C~ç+;wâ bögµtq0\.@\ëŸ-øŽm£ë:…b‘B>OåÇ?FL†h¿p NÉÁ6«u~ÛíÐa[&JaˆáÇŸ@-üƒëˆ­[G÷ÀK–,¡¯¯¶övâñx}ý~ ð½k¦K‰‰ ÆÇÇ)ßqæï6"÷'è¸î=ÈÁŽ*øV“½îþ,lÓ¢°û Ëþê/q"ê~@>—£X,¢iZ-OpJ éX¾)^OJ ;†aP*—Ée³”ÿç0G†é¼úb$1ŽmÚuà[–‰ne9òôSh#*ÁkßK쳟¥»§‡¾¾>:::ˆÅã„Ü¢Œîtà;î=‹EÆÆÆ!³núï6"-IÐõÞ«‘¥‚aƒeá˜&Žw?þ{k87+:’£ý`¤ðÐCd³YÊå2†a°ë˜h1l¦¶gý…Ålåç?'Ð#qæ™Øª3ÉÒAaô¹gPdN?ƒØç>GWW===µôkÀM¿Nç/=BøÁgdd„ò¿ÿ;òÐ ‰5ËéïU…è6˜&XV•îî·~Ç2ë‰`šd^}“Îk®BˆI¨?û…L†B¡°hT@\¿?24&}, EU) x«T ó=—"èl«Áúì]äw†D;±[n!ÝÑAWWÉTjr²eÉoxxóg?££½î+ϣ㒠Ø lÍ×ê=ëÇr¯¹÷gY&NHÁÍ:RXšŽ©@âò5˜Å<…þB¡€ªªX–5%1§sY‹7hfíÓT·;—ª(Õn\7ìŽë_‚]a²¼:²;v¡+6±Ï|†¶¥Kéìì$™J…ê"k¡Iý½1òoß~è!:{{ö…‘e©À©X®µû?lä"¹—·b;Ê$—ݵôW $e”§ŸFQE©`&°›‘b¾ˆ1¿i©Y¶ã »={Ê»w£;sh¶e7H¿NîànÔá¡5kˆ_vétš¶öv"n¤?“äû‰×¾óðÃô¶ )eaAÈP•ýFà}.ÓÇBˆ¨ävlEÝ7†–ÄvêBÓ0‘CI¢§÷£QÞµ EQÐuý„»gjû뚆¢(¨¿ý-BP$Ú—ÆÖ…ÉÖOžÌË{14ˆüã´µµÑžNmýf•É™À~ýk–®9)ZÁÜ¿FLÐmð‚i"ø¬_°,p,ä„NnÇVНO M”Cƒ²6éþ‹ûé¼ôBÄ @ù©§P…J¥rj`.dpË4QU•Ц¡nÝŠœ L´aéõÁŸãF¡ŽWˆ^qñ³Î"™JóÕÛ[)K7 ø¤'ŸdÅ;.E äQ_Ù†3d è6Ž ¾`š5p|à;¶I Ævn%ûÚÒÀéVŸ:\D/à8õn 88JtÉRĘŒòÒKÕ^˪Šiš'´5 .ˆô7 …ɹ̪ÿWU”Ç© [Ù…è„°ŒzëAÒ)bª6‘ë®#“L$ùüþ\ÀŸzŠw_ Reóï±–A«Ê¾è“~Ïò½£c›„—Ù¾•Ì®qä«0n¼ëÒKÑKÚ‘#7PÑC)¤tíÐ!”C‡PUõ„7ç¿45U{ß™ûÀЦQ~ê)Y ÞŸÆT™Ü®¦Dy(‘(Ñw¼ƒ¸Û7ß“þ9ÿôÓ¬ºæj0)=ó¬}%ÍFð¬Þ¼!ð›ð@ŒÁ­/2þòÁÓ‰}íkÄÓi‚W_#PGˈ²2)I¤Ž•H®À–¡ðä“hšvÂ`AÊÁB dðúõ›†>4A9ÂÒlûh™Ul´Ò8ZÎ |ö„Ãab±˜×nNà;?ÎÀ5Wc)oRzêQì}EDÝ7÷ž/¯/:¶k)¶ÑÓÛØ÷ü&ÆvŽ8îÛn#‘N#Š"…BóÜs1ö½Œ­«Ø–\÷[rû“\5À‘À.Œ¡!tw´Rõw '/„947ÿoYf6‹–Ë´ÁWf•Bj&‡¦Z´]zim˜–?¿?ðÍGaà—c–÷¡lø Öž"‚|ÁßÁÄ©ö‚Ñs:سéYFwŽ8¾uëèìë#Nã8¢(R¼ôR”Ww`e¢XVµ>ˆÅH­\E šA‰˜™L­úxJ(ÀŒÒߤàÓ3 Ä€ˆ#ŠØ¦UW]C¦¦cYÁU«º0{×´¾¶~=Ë.<»rí¹ X¯æÌ*ØÞÔÚþªžw]ˆ ¯éâÕg72¼c”ÈŠUô¯[GW?===$‰Z?†àÒ¥X–YÑD‹@*…]g&Ã"F¡Puƒ®œ(70ïB¦ËüÕÈàë€á8F¹ŒØ¤£káx ÚTTG–‘ÓéZ‡Ž™À/•J5ðó?þ1]Ë– :G¶¿‚½+¨95É÷û~ÇqªþÞq´%Ïïdצ Ú6FdÙË}à§Ói"‘HõAºÃÈÃK–`# +¯?ö+2•º%¼lÓF hcåZo¤SBf;OŸ7²×Ö4ôJ9žÄÖ«Ù¿š5:‚c`V äX¬æ÷§j÷7üÞ{iëê #ïÙ ¯jàûbrÜïóÜ@°«qM;7ýŽƒ[Æ/`åwÐÙ×GOOµ–ˆ7Ï€$I²Œbê6ˆX[ÌÇËú[¦ƒ‘0* ¶[:5b€YÄu?W’°Dz(ç²år(„à8H€m8¢€aÔøiüý·ÝF, ¼L vhá•‚v”\~é÷ûÿà’^8'ŶMÙÿÒ(±%+Yå‚ßÛÛK:®k†6n–ãàˆ"² Ô`{¿[°êk2˜3¹g±Î ´H†ºÄ;ã†(ˈ‘šj —÷3òZ±Úƒ6!‰Ðã$ƒ"ºRÂ(—›Êe3ð_½ùf »^¦ãº³i›Pw+†ˆ$‹ ËÕé`d!Y>Ú3Ik©ÃöçÇ/ë_Áißþ6}}ôõõÑÞÞÞ|¯_¡mšèªŠJ`kvÝk X–ƒ#ºÁl«ÝÄŠèÍÀù+_aâ¥é?7Å™ óW[±ÊVÝêÖþöDWšÅ€ˆy~Š×%}Û«à¯þÎwèèí|/˜3 õÈ ’Ðt«nYuB"zÆAL$Ž>ƒ™æ:YjS‘AhBïÇK¢ˆ˜H Vl¤°Œ Ô¯‚hM"Q ),¡>Œ®ë†Q›Æþί|…±—^dÉšç$„¶\ð½]nv±.H±; °w{žpÿrÎn|Ïú èÞÏîÝ †DìŠUçDQ@ Š˜šœLÖà”n4SAÝ›r[Æ! ) "Äj)Ö#@ÙBBI™ÒþýhšV›Ê0 2™ ###ìøò—Û²™åkR¬N_ÊAÙ¨_¤ž\Õ Ÿˆqa»d‘×¶d‰õ.å\×ç÷ööξçûu]§R©yþyÂíAŽƒY¶ê¬_ÈAM³‰¶µÕ&¤:‘.`A¨7¥õ7Y&@S, Ò¬{h¶aƒbK‡ß³‡âð0¹\®:pct”ááa¶}ùËÙº™e¶qN[ÀÖBøM÷ ˆuQ;Û"»·f‰ô,å¼ï|‡Î%KZßN×õj/Ÿ|žì¾}$ºÃØyǰë~K´-ˆhªEd` iRë¤$Àl­@rå/ Ññ‡ˆaB1¯‘êOZýЯî cÙ‡|‘‘:Ä‘#GØö¥/qdëf.hçœdá¥,:k÷/t\“ÿ ˆqI;[ƒ"»¶d w-aÍw¾CW àû›lÞ‚R©Äèca9é® Æ¨>Éÿ'ºC”ó¦Ý7Ü@8žó ‘ÅÙ%¬Eë÷:k"‘ñÎN’K–Õ‰v‡%¡îÁ•‡*¤"‰®0ƒ72::ÊÐÐ;¾úU†¶oá´‹Ú9§­ ¾Ðüf–¯_ÚÁÖ ÄŽÍÂ]K¸à®»èžüƶº'ý¥R‰R©ÄУK‰$´ŒVüI‘®0¹QIJeD;;ë†;¾MgÚç3'0˜…õ{óóʲLĽÓ~ÑEdÇ4ÄD´­Þ XªcÝ+£” ò¿ûoÞ~;C;¶rÆÅíœÝÀ~1ƒS0êZ¢Ï÷×ÿŽ^ l{a‚h×.jüÆÍG˜Ïç9òÄL¼¹ŸÞÓâ㬊U×¢ ·‚"… öK.! Õ`6ð¿wÑ)@«Ö4 (ÕfãìyßûP“bÑ$Õ©{xåeú;Ã$ºB¼ùÀŒ¾ú2g^œfu*„õ|üf²_…‡DôË;ÙØò‘Î~.ž#øžôçr9òù<»ï½—¶Þýéå=źû€d_„bÉ ¢ZôüÑ‹Åêz4ÍD‚fïYÔÍÀ鬿öån ‹ÅH­ZE¼£ƒ‘¡2ñ¥Áúœ@e\#0ªrúymX‚ÅêKÒœÝÄx~Ûgù{!íŠN6D^|~‚HG?—þë¿N þTéYÛÀ¢P(011Á>HabŒg%+èE³^þƒ"±þcƒ*±®.+V‰D¼9~Zt:R, ˜­õˆnà á^zÝu TQHŸŸDœü®}1™‹®éáìöúsؽN)š’ $a\ÑÉ ²ÈóÏM÷qY àOÕæ×u|>ÏØØƒ›7³ó‡?¤kEŒžh€âëÅÆeÕIŸž lÃèa•%×_O,#‰ÌÉÿ/ZÌÖú=2H’D$!™LrÚ_ÿ5¡X’=¯Iœ‘"•ë>g–Mì×ò Èê¦q̼^W4!’0®ìäÅ Èó›Æˆ¤û¸â»ß3øš¦ÕÀÞ·M·ÜB¼]âüsÛ±wç°U«îž1™øiqöï)Œ§Xù‘H$ˆF£H’ÔXo&s¯R¸ÀŸf`³ÏxS§¤R)≫?üaŽ,“QMºÎIN"Pq_™Ü3#.øÍ€¯‡$Œww³Y–øý³cDÚzx×À÷R½žÏadx˜goº ËQ¹ø$•(ï/O"zç9)2ŠÍða…3>ò‘Ú\ÃÞ$3Þìº÷ú¤jN¹’‡Ï ´µµ±üýï§­»—×vå ¯ŒjÕ}Þ±¬²9ó}„$ì«»ÙxöÙQ¢m=\uÏ=³ßKózÃÆ9Âá={xêŸ ;2ÈÅWtÒ[0(îÌ!4g¨#D`YŒ×wçIöô±ôÿ˜”;†Ñ“ÿé,}*e8y\À Öï/ …ÃáÚ¬ç|üã *ž¨Ð{Y)(Îjµl!,ÁÕÝl<³q”p²‹«î¾»®×tà{Û0 TU%ŸÏ322Âàà {7làѵkQŠ£¼ëÚN— /Œc[õw(…DzÞÑÁ¡q‘!…³Ö®­Í2îÍÔ̪§Ûýï]|SÄ´:òãöñxœt:ÍÒ«®bÙšóyqÓ+$®ï§ï²NF~?^k¿<7_º¦‡í‘§Ÿ&–èäŠùRÕ¤ÉdM~=õGâ^W5Ã0j¾\.G>›eç}÷±ãç?§­+À»/ï¡/£Qx~Ûmó×z‹Ý—u2& l}aœ%ç_@ß•W’J¥ê|ÿl:þÎ0¾Ï9ÓìÇ·ÜJð7•+ð«€¢(\ñÿÈ£Ÿü$Ÿå†ëúè<¿ì¶LSàøk{Ù) <õô0±xg}å+ؾ^Ä^Ï¢Æ:¼’(ͯX*•(‹ì]¿ž­ÿõ_(å+ÏHð®óÚIï+’ßš©Y¾ÿ~Òç·¡ôDxîÉa¢É.þú×ioo'•JMÛô›Ž µèçj%GÐè dY&‹ÑÙÙ‰®ë\³nÜx#_˜àºwu’*”÷§$Aüê8C!ö½œC7d]gdýzÂú§’IA P(ÔŠ0 ¼ÎÞR3š¦QæÀ#ppÓ&¿¾‡e1ÞsõV†DÄm”ö›šZò´8¬ncÓ¦1tMâªþí¤ÓéI‘+À7³þùLË'Êâ§by("™Lbº =½çæ›yôë_ç¹—s\sy'Q ´§€ÓDÿŠÏ+ôŸ)sÙ).:3Éö7 ì}q¯mØÀY_LzÕ*¢==D{{I,_N´§€Êø8¥Ã‡)£ƒaH$¨äFéYã¢s9Äöæ)¿’GU­:à½óÄI—v°aG†áÃ*×Þz+]§Fgg'‰D¢.ðkb+ 0UŸÈÅ£³°øfç~W`š&Ö•Wò®}Œßþßû+/ï¢+ ûRÇvê`æ Š/NØ™c`U‚«SŒ­nçr)‚I™p"@<")ˆããD’I‚==Tâ1”®6J½)¬Òa‚ÊARá1"e…о2•­”‚ÕÌÑŠ§ÑÎJ±qg†Ý¯xçG?Æ’Ë/§³³³Nú›?h¿YùýãçæÈR/9ÔÞÞ^}`õW I÷¹8pàÀ¨ ¸T\ŽÚÕÕZ3aá`ªóY(€?òõrñ.û™˜˜àÐ /°ñž{>ÂYg&y÷ŬH„•Ð÷—°‡ÍšÔ!´¨í! ©?J` †º,ΛšÍï¶L°wo%ýK¸ìSŸ¢ç‚ H§Ó¤Ói‰Dmîß\|™Y–I&“D"Ñê´¸º^ÿ7¿ùͯ¾þõ¯ÿȹÀg]ðK® 0ZõýÇÇ(ÿÍ®û²ªª”J¥ÚÒ±Š¢Pe÷úõì}î9 !ˆ½=Iº:t¦c´§Â¤’aRñ²@·$JŠI¡¨‘ÍUÈL”(SÈI§R \vg¼ÿýÄ»ºˆD"$Ü’®7Uß×{*åæÍttÅrËö¯nnã86ííít¹ÿßðY¼wܱcÇsŸúÔ§þÝÜoù%ª«„³‘þC€iÈÐ øÓUí*• Š;ãh¹\®Íç‹ì}ì12o¼Z(`ª*Ø6r @$¯¶ÏM³ºº8 ƒHÑ(í«V±ê}ï#ìvZD"D"¢Ñ(‘H¤6S‰à[v¦6ó™Ï|·R©ä]‹Ï×çøóZ 8>Ý „iGÞr,‘H„x<^óÞûwÿÌðÞÿðà?6Î3Ë_ða!;…Òâl! ¨ ­–X›ßê¹ã88öQs4È´H¥R“ÀŸNú5M³üãÿç/ùËm>ËÏùÀ׿üy#ÀâYqö¤™ÍêY–…áš½½½µØa¦€O×u~õ«_=xß}÷=ÛDöø–3ƒDÞÞ¦-ÇÎìû«s •«–ûïéé© &™ÉúŸy晇ï¼óÎÇÜ@/ß|c>-apŒ2-œÀ q*¿?3!œZ§Fà­­­VÁ›iߺuë†[o½õ¿]ð=Ù÷·õ=ðç}FIñ­jñ­ Æœ üÆ÷Íë[f5ë×ßß?£ÕëºÎ«¯¾ºù¦›nºÏ~c¢Ç\(ð–‚pR£U˯Ï8X¶e»³Û6Ë—/Ÿü-[¶løô§?}·eYù†Dßò­…ÿø)À16ê33õÇ›ŽNÍúl§º¼i˜†AWW¢(N+ûÏ<ó̯þîïþî^˲r¾ü~£ìS–oqåN’p:Ðð落¦…a˜¬ZÕ7¥ÕW*ûá‡~ðŽ;îx´‰ìÏk–oÑ@8ÉÉм¥€OÜJ iȤR©¦V¯ªªùÀü‡ÛÔkæó=ðÍãþÛ ÐB.`êòhw.¯ùg[6]]]M3|¥RIýÞ÷¾w÷C=´µübƒì7ðß’hVä™mpXO/ûgá86mmm“ÀÏårùuëÖÝùôÓO¿Ö$½;Éç;Çqþø·`žÔöíÚ8†Æ’î-·Üò/Û¶m;Ð|’縃¿ ÞBà{Doí Ïú>|àóŸÿü8Ò û¥&¾²lÈ‚Ày‹Às+áp¸.ó·wïÞ]7Þxã]™Lf‚£¹ýÍ ;'l͘·]À<€ïõ&ò¬Û¶mÏ}ö³Ÿý·Ÿ|¯™ç•t-çD®3‹DÐ1ÍBq*Ýìµ(еž¼O<ñÄúO~ò“ß«T*¾OSŸ¢ÁK*Àlž¹ æäÏyàKT*Et]wxà{ï¾ûîßúÚöÍ:pÎk=ÿD eXìñ@#ÐÓ5v5sjC¶t]·×­[÷Ï¿øÅ/¶3¹œÛØÌ[4àÏ•ƒh‘$ ˲Né¼ÿèߋŢ~ã7~õ¹çž{³Áê=ɯ•søs!€¾éþ( ¨­œy2ûó¹lÛ·oõCúÐ]ûöíuA/4{'´ßÒshqd@ux}ˆm@‡{Œ¹×%æ·ࢠ!Ü£gºkå%×â=É÷"}Ïò%ø³UÇe²áÊZѽV‚Lrª 6%‘ ²ê‚^öEùšÏßÛ‹ùµDÇqA<ù7ÜŠ{^†ºUÙNù†„/þ1\TÜÝKî,ªH!÷¼âþfs.œÊh$é;Ú' ø-Ç ±@ãJ,SY¾p Þl³}FQ7ÔÉþ¬ à#AãoÔ¿ŸuYÑ“ ø9 §¢ÅÏZNFà™oo§Æöÿó}›‹?IEND®B`‚rst2pdf-0.102/rst2pdf/languages.py000066400000000000000000000027741463013543400170210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms from docutils.languages import get_language as get_language from .log import log def get_language_silent(lang): """Docutils get_language() with patches for older versions.""" try: return get_language(lang) except TypeError as err: # Docutils 0.8.1 if 'get_language() takes exactly 2 arguments' in str(err): class SilentReporter(object): def warning(self, msg): pass return get_language(lang, SilentReporter()) raise # re-raise any other TypeError except ImportError: # Docutils < 0.8 return get_language('en') def get_language_available(lang): """Docutils get_language() also returning the available language.""" module = get_language_silent(lang) docutils_lang = module.__name__.rsplit('.', 1)[-1] if docutils_lang == 'en' and docutils_lang != lang and '_' in lang: module = get_language_silent(lang.split('_', 1)[0]) docutils_lang = module.__name__.rsplit('.', 1)[-1] if docutils_lang != lang: warn = ( docutils_lang.split('_', 1)[0] == lang.split('_', 1)[0] and log.info or log.warning ) warn( "Language '%s' not supported by Docutils," " using '%s' instead." % (lang, docutils_lang) ) if docutils_lang == 'en' and lang.split('_', 1)[0] != 'en': lang = 'en_US' return lang, docutils_lang, module rst2pdf-0.102/rst2pdf/log.py000066400000000000000000000013141463013543400156210ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms import logging log = logging.getLogger('rst2pdf') _fmt = logging.Formatter('[%(levelname)s] %(filename)s:%(lineno)d %(message)s') _hdlr = logging.StreamHandler() _hdlr.setFormatter(_fmt) log.addHandler(_hdlr) log.setLevel(logging.WARNING) def nodeid(node): """Given a node, tries to return a way to see where it was in the source text""" fname = 'UNKNOWN' line = 'UNKNOWN' try: if node.line: line = str(node.line) except Exception: pass try: if node.source: fname = str(node.source) except Exception: pass return 'near line %s in file %s' % (line, fname) rst2pdf-0.102/rst2pdf/math_flowable.py000066400000000000000000000147051463013543400176540ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms import os import re import tempfile from reportlab.platypus.flowables import Flowable from reportlab.platypus import SimpleDocTemplate from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont from .log import log try: from matplotlib import mathtext from matplotlib.font_manager import FontProperties from matplotlib.colors import to_rgb HAS_MATPLOTLIB = True except ImportError: HAS_MATPLOTLIB = False fonts = {} def enclose(s): """Enclose the string in $...$ if needed""" if not re.match(r'.*\$.+\$.*', s, re.MULTILINE | re.DOTALL): s = u"$%s$" % s return s class Math(Flowable): def __init__(self, s, label=None, style=None): Flowable.__init__(self) self.s = s.strip() self.label = label self.fontsize = 10 self.color = (0, 0, 0) self.hAlign = 'LEFT' if style: self.style = style self.fontsize = style.fontSize self.color = style.textColor.rgb() self.hAlign = style.alignment if HAS_MATPLOTLIB: self.parser = mathtext.MathTextParser("Path") else: log.error( "Math support not available," " some parts of this document will be rendered incorrectly." " Install matplotlib." ) if "\n" in s: log.error("rst2pdf's math directive does not support multiple lines'") def wrap(self, aW, aH): if HAS_MATPLOTLIB: try: (width, height, descent, _, _,) = self.parser.parse( enclose(self.s), 72, prop=FontProperties(size=self.fontsize) ) return width, height + descent except Exception as e: log.error(f"Math error in wrap: {e}") pass return 10, 10 def drawOn(self, canv, x, y, _sW=0): if _sW and hasattr(self, 'hAlign'): from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY a = self.hAlign if a in ('CENTER', 'CENTRE', TA_CENTER): x = x + 0.5 * _sW elif a in ('RIGHT', TA_RIGHT): x = x + _sW elif a not in ('LEFT', TA_LEFT, TA_JUSTIFY): raise ValueError("Bad hAlign value " + str(a)) height = 0 if HAS_MATPLOTLIB: global fonts canv.saveState() try: (width, height, descent, glyphs, rects,) = self.parser.parse( enclose(self.s), 72, prop=FontProperties(size=self.fontsize) ) canv.translate(x, y + descent) for font, fontsize, num, ox, oy in glyphs: fontname = font.fname if fontname not in fonts: fonts[fontname] = fontname pdfmetrics.registerFont(TTFont(fontname, fontname)) canv.setFont(fontname, fontsize) rgb_color = to_rgb(self.color) canv.setFillColorRGB(rgb_color[0], rgb_color[1], rgb_color[2]) canv.drawString(ox, oy, chr(num)) canv.setLineWidth(0) canv.setDash([]) for ox, oy, width, height in rects: canv.rect(ox, oy + height, width, height, fill=1) except Exception as e: log.error(f"Math error: {e}") log.exception("Math error!") canv.translate(x, y) rgb_color = to_rgb(self.color) canv.setFillColorRGB(rgb_color[0], rgb_color[1], rgb_color[2]) canv.drawString(0, 0, self.s) canv.restoreState() else: canv.saveState() canv.translate(x, y) canv.drawString(x, y, self.s) canv.restoreState() if self.label: log.info('Drawing equation-%s' % self.label) canv.bookmarkHorizontal('equation-%s' % self.label, 0, height) def descent(self): """Return the descent of this flowable, useful to align it when used inline.""" if HAS_MATPLOTLIB: width, height, descent, glyphs, rects = self.parser.parse( enclose(self.s), 72, prop=FontProperties(size=self.fontsize) ) return descent return 0 def genImage(self): """Create a PNG from the contents of this flowable. Required so we can put inline math in paragraphs. Returns the file name. The file is caller's responsibility. """ dpi = 72 scale = 72 try: import Image import ImageFont import ImageDraw except ImportError: from PIL import ( Image, ImageFont, ImageDraw, ) if not HAS_MATPLOTLIB: img = Image.new('RGBA', (120, 120), (255, 255, 255, 0)) else: (width, height, descent, glyphs, rects,) = self.parser.parse( enclose(self.s), dpi, prop=FontProperties(size=self.fontsize) ) img = Image.new( 'RGBA', (int(width * scale), int((height + descent) * scale)), (255, 255, 255, 0), ) draw = ImageDraw.Draw(img) for font, fontsize, num, ox, oy in glyphs: fontname = font.fname image_font = ImageFont.truetype(fontname, int(fontsize * scale)) fc = to_rgb(self.color) rgb_color = (int(fc[0] * 255), int(fc[1] * 255), int(fc[2] * 255)) draw.text( (ox * scale, (height + 1 - oy - fontsize) * scale), chr(num), font=image_font, fill=rgb_color, ) for ox, oy, w, h in rects: x1 = ox * scale x2 = x1 + w * scale y1 = (height - 1 - oy) * scale y2 = y1 + (h * scale) draw.rectangle([x1, y1, x2, y2], (0, 0, 0)) fh, fn = tempfile.mkstemp(suffix=".png") os.close(fh) img.save(fn) return fn if __name__ == "__main__": doc = SimpleDocTemplate("mathtest.pdf") Story = [ Math(r'\mathcal{R}\prod_{i=\alpha\mathcal{B}}' r'^\infty a_i\sin(2 \pi f x_i)') ] doc.build(Story) rst2pdf-0.102/rst2pdf/nodehandlers.py000066400000000000000000000005571463013543400175160ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms # Import all node handler modules here. # The act of importing them wires them in. from . import genelements # noqa from . import genpdftext # noqa # sphinxnodes needs these from .genpdftext import NodeHandler, FontHandler, HandleEmphasis # noqa # createpdf needs this nodehandlers = NodeHandler() rst2pdf-0.102/rst2pdf/pdfbuilder.py000066400000000000000000001146171463013543400171730ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ Sphinx rst2pdf builder extension ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Usage: 1. In conf.py add 'rst2pdf.pdfbuilder' element to 'extensions' list: extensions = ['rst2pdf.pdfbuilder'] 2. Modify your Makefile or run it with: $ sphinx-build -d_build/doctrees -bpdf . _build/pdf :copyright: Copyright 2009 Roberto Alsina, Wojtek Walczak :license: BSD, see LICENSE for details. """ from copy import copy from io import BytesIO import logging import os import os.path import re import sys import time from urllib.parse import urlunparse from docutils import writers from docutils import nodes from docutils.transforms.parts import Contents from docutils.io import FileOutput import docutils.core import jinja2 from pygments.lexers import guess_lexer import sphinx from sphinx import addnodes from sphinx.builders import Builder from sphinx.environment.adapters.indexentries import IndexEntries from sphinx.locale import _ from sphinx.transforms import SphinxTransform from sphinx.util.console import darkgreen, red # type: ignore from sphinx.util import SEP import rst2pdf from rst2pdf import createpdf from rst2pdf.directives import code_block from rst2pdf.log import log from rst2pdf.languages import get_language_available if sphinx.__version__ >= '2.1': from sphinx.errors import NoUri else: from sphinx.environment import NoUri class PDFBuilder(Builder): name = 'pdf' out_suffix = '.pdf' supported_image_types = ['image/svg+xml', 'image/png', 'image/gif', 'image/jpeg'] def init(self): self.docnames = [] self.document_data = [] self.sphinx_logger = sphinx.util.logging.getLogger(__name__) def write(self, *ignored): self.init_document_data() if self.config.pdf_verbosity > 1: log.setLevel(logging.DEBUG) elif self.config.pdf_verbosity > 0: log.setLevel(logging.INFO) for entry in self.document_data: try: docname, targetname, title, author = entry[:4] # Custom options per document if len(entry) > 4 and isinstance(entry[4], dict): opts = entry[4] else: opts = {} self.sphinx_logger.info("processing " + targetname + "... ") self.opts = opts class dummy: extensions = self.config.pdf_extensions createpdf.add_extensions(dummy()) self.page_template = opts.get( 'pdf_page_template', self.config.pdf_page_template ) docwriter = PDFWriter( self, stylesheets=opts.get( 'pdf_stylesheets', self.config.pdf_stylesheets ), language=opts.get('pdf_language', self.config.pdf_language), breaklevel=opts.get('pdf_break_level', self.config.pdf_break_level), breakside=opts.get('pdf_breakside', self.config.pdf_breakside), fontpath=opts.get('pdf_font_path', self.config.pdf_font_path), fitmode=opts.get('pdf_fit_mode', self.config.pdf_fit_mode), compressed=opts.get('pdf_compressed', self.config.pdf_compressed), inline_footnotes=opts.get( 'pdf_inline_footnotes', self.config.pdf_inline_footnotes ), splittables=opts.get( 'pdf_splittables', self.config.pdf_splittables ), repeat_table_rows=opts.get( 'pdf_repeat_table_rows', self.config.pdf_repeat_table_rows ), default_dpi=opts.get( 'pdf_default_dpi', self.config.pdf_default_dpi ), page_template=self.page_template, invariant=opts.get('pdf_invariant', self.config.pdf_invariant), real_footnotes=opts.get( 'pdf_real_footnotes', self.config.pdf_real_footnotes ), use_toc=opts.get('pdf_use_toc', self.config.pdf_use_toc), toc_depth=opts.get('pdf_toc_depth', self.config.pdf_toc_depth), use_coverpage=opts.get( 'pdf_use_coverpage', self.config.pdf_use_coverpage ), use_numbered_links=opts.get( 'pdf_use_numbered_links', self.config.pdf_use_numbered_links ), fit_background_mode=opts.get( 'pdf_fit_background_mode', self.config.pdf_fit_background_mode ), baseurl=opts.get('pdf_baseurl', self.config.pdf_baseurl), section_header_depth=opts.get( 'section_header_depth', self.config.section_header_depth ), smartquotes=str( opts.get('pdf_smartquotes', self.config.pdf_smartquotes) ), srcdir=self.srcdir, style_path=opts.get('pdf_style_path', self.config.pdf_style_path), config=self.config, ) tgt_file = os.path.join(self.outdir, targetname + self.out_suffix) destination = FileOutput( destination=open(tgt_file, 'wb'), encoding='utf-8' ) doctree = self.assemble_doctree( docname, title, author, appendices=opts.get('pdf_appendices', self.config.pdf_appendices) or [], ) doctree.settings.author = author doctree.settings.title = title self.sphinx_logger.info("done") self.sphinx_logger.info("writing " + targetname + "... ") docwriter.write(doctree, destination) self.sphinx_logger.info("done") except Exception: log.exception('Failed to build doc') self.sphinx_logger.info(red("FAILED")) def init_document_data(self): preliminary_document_data = map(list, self.config.pdf_documents) if not preliminary_document_data: self.sphinx_logger.warning( 'no "pdf_documents" config value found; no documents ' 'will be written' ) return # assign subdirs to titles self.titles = [] for entry in preliminary_document_data: docname = entry[0] if docname not in self.env.all_docs: self.sphinx_logger.warning( '"pdf_documents" config value references unknown ' 'document %s' % docname ) continue self.document_data.append(entry) if docname.endswith(SEP + 'index'): docname = docname[:-5] self.titles.append((docname, entry[2])) def assemble_doctree(self, docname, title, author, appendices): # FIXME: use the new inline_all_trees from Sphinx. # check how the LaTeX builder does it. self.docnames = set([docname]) self.sphinx_logger.info(darkgreen(docname) + " ") def process_tree(docname, tree): tree = tree.deepcopy() for toctreenode in tree.traverse(addnodes.toctree): newnodes = [] includefiles = map(str, toctreenode['includefiles']) for includefile in includefiles: try: self.sphinx_logger.info(darkgreen(includefile) + " ") subtree = process_tree( includefile, self.env.get_doctree(includefile) ) self.docnames.add(includefile) except Exception: self.sphinx_logger.warning( '%s: toctree contains ref to nonexisting file %r' % (docname, includefile) ) else: sof = addnodes.start_of_file(docname=includefile) sof.children = subtree.children newnodes.append(sof) toctreenode.parent.replace(toctreenode, newnodes) return tree tree = self.env.get_doctree(docname) tree = process_tree(docname, tree) self.docutils_languages = {} if self.config.language: self.docutils_languages[self.config.language] = get_language_available( self.config.language )[2] if self.opts.get('pdf_use_index', self.config.pdf_use_index): # Add index at the end of the document # This is a hack. create_index creates an index from # ALL the documents data, not just this one. # So, we preserve a copy, use just what we need, then # restore it. if hasattr(self.env, 'domains') and "index" in self.env.domains: # Sphinx 2.4.0+ stores the index entries in self.env.domains["index"] t = copy(self.env.domains["index"].data['entries']) try: self.env.domains["index"].data["entries"] = { docname: self.env.domains["index"].data['entries'][ docname + '-gen' ] } except KeyError: self.env.domains["index"].data["entries"] = {} for dname in self.docnames: self.env.domains["index"].data["entries"][dname] = t.get( dname, [] ) genindex = IndexEntries(self.env).create_index(self) self.env.domains["index"].data['entries'] = t elif hasattr(self.env, 'indexentries'): # Sphinx 2.3.1 or lower stores the index entries in self.env.indexentries t = copy(self.env.indexentries) try: self.env.indexentries = { docname: self.env.indexentries[docname + '-gen'] } except KeyError: self.env.indexentries = {} for dname in self.docnames: self.env.indexentries[dname] = t.get(dname, []) genindex = IndexEntries(self.env).create_index(self) self.env.indexentries = t # EOH (End Of Hack) if genindex: # No point in creating empty indexes index_nodes = genindex_nodes(genindex) tree.append(nodes.raw(text='OddPageBreak twoColumn', format='pdf')) tree.append(index_nodes) # This is stolen from the HTML builder's prepare_writing function self.domain_indices = [] # html_domain_indices can be False/True or a list of index names indices_config = self.config.pdf_domain_indices if indices_config and hasattr(self.env, 'domains'): for domain in self.env.domains.values(): for indexcls in domain.indices: indexname = '%s-%s' % (domain.name, indexcls.name) if isinstance(indices_config, list): if indexname not in indices_config: continue # deprecated config value if indexname == 'py-modindex' and not self.config.pdf_use_modindex: continue content, collapse = indexcls(domain).generate() if content: self.domain_indices.append( (indexname, indexcls, content, collapse) ) # self.domain_indices contains a list of indices to generate, like # this: # [('py-modindex', # , # [(u'p', [[u'parrot', 0, 'test', u'module-parrot', 'Unix, Windows', # '', 'Analyze and reanimate dead parrots.']])], True)] # Now this in the HTML builder is passed onto write_domain_indices. # We handle it right here for indexname, indexcls, content, collapse in self.domain_indices: # In HTML this is handled with a Jinja template, domainindex.html # We have to generate docutils stuff right here in the same way. self.sphinx_logger.info(' ' + indexname) output = ['DUMMY', '=====', '', '.. _modindex:\n\n'] t = indexcls.localname t += '\n' + '=' * len(t) + '\n' output.append(t) for letter, entries in content: output.append('.. cssclass:: heading4\n\n%s\n\n' % letter) for ( name, grouptype, page, anchor, extra, qualifier, description, ) in entries: if qualifier: q = '[%s]' % qualifier else: q = '' if extra: e = '(%s)' % extra else: e = '' output.append('`%s <#%s>`_ %s %s' % (name, anchor, e, q)) output.append(' %s' % description) output.append('') dt = docutils.core.publish_doctree('\n'.join(output))[1:] dt.insert(0, nodes.raw(text='OddPageBreak twoColumn', format='pdf')) tree.extend(dt) if appendices: tree.append( nodes.raw(text='OddPageBreak %s' % self.page_template, format='pdf') ) self.sphinx_logger.info('') self.sphinx_logger.info('adding appendixes...') for docname in appendices: self.sphinx_logger.info(darkgreen(docname) + " ") appendix = self.env.get_doctree(docname) appendix['docname'] = docname tree.append(appendix) self.sphinx_logger.info('done') # Replace Sphinx's HighlightLanguageTransform with our own for sphinx version between 1.8.0 & less than 2.0.0 as # Sphinx's HighlightLanguageTransform breaks linenothreshold setting in the highlight directive (See issue #721) # This code can be removed when we drop support for Python 2 if sphinx.__version__ > '1.7.9' and sphinx.__version__ < '2.0.0': for i in range(len(self.env.app.registry.post_transforms)): if ( self.env.app.registry.post_transforms[i].__name__ == 'HighlightLanguageTransform' ): self.env.app.registry.post_transforms[ i ] = HighlightLanguageTransform break self.sphinx_logger.info("resolving references...") self.env.resolve_references(tree, docname, self) for pendingnode in tree.traverse(addnodes.pending_xref): # This needs work, need to keep track of all targets # so I don't replace and create hanging refs, which # crash if ( pendingnode.get('reftarget', None) == 'genindex' and self.config.pdf_use_index ): pendingnode.replace_self( nodes.reference( text=pendingnode.astext(), refuri=pendingnode['reftarget'] ) ) # FIXME: probably need to handle dangling links to domain-specific indexes else: # FIXME: This is from the LaTeX builder and I still don't understand it # well, and doesn't seem to work # resolve :ref:s to distant tex files -- we can't add a cross-reference, # but append the document name docname = pendingnode['refdocname'] sectname = pendingnode['refsectname'] newnodes = [nodes.emphasis(sectname, sectname)] for subdir, title in self.titles: if docname.startswith(subdir): newnodes.append(nodes.Text(_(' (in '), _(' (in '))) newnodes.append(nodes.emphasis(title, title)) newnodes.append(nodes.Text(')', ')')) break else: pass pendingnode.replace_self(newnodes) # else: # pass return tree def get_target_uri(self, docname, typ=None): # print 'GTU',docname,typ # FIXME: production lists are not supported yet! if typ == 'token': # token references are always inside production lists and must be # replaced by \token{} in LaTeX return '@token' if docname not in self.docnames: # It can be a 'main' document: for doc in self.document_data: if doc[0] == docname: return "pdf:" + doc[1] + '.pdf' # It can be in some other document's toctree for indexname, toctree in self.env.toctree_includes.items(): if docname in toctree: for doc in self.document_data: if doc[0] == indexname: return "pdf:" + doc[1] + '.pdf' # No idea raise NoUri else: # Local link return "" def get_relative_uri(self, from_, to, typ=None): # ignore source path return self.get_target_uri(to, typ) def get_outdated_docs(self): for docname in self.env.found_docs: if docname not in self.env.all_docs: yield docname continue targetname = os.path.join(self.outdir, docname + self.out_suffix) try: targetmtime = os.path.getmtime(targetname) except Exception: targetmtime = 0 try: srcmtime = os.path.getmtime(self.env.doc2path(docname)) if srcmtime > targetmtime: yield docname except EnvironmentError: # source doesn't exist anymore pass def genindex_nodes(genindexentries): indexlabel = _('Index') indexunder = '=' * len(indexlabel) output = ['DUMMY', '=====', '.. _genindex:\n\n', indexlabel, indexunder, ''] for key, entries in genindexentries: output.append('.. cssclass:: heading4\n\n%s\n\n' % key) # initial for entryname, entryvalue in entries: links, subitems = entryvalue[0:2] if links: output.append('`%s <#%s>`_' % (entryname, nodes.make_id(links[0][1]))) for i, link in enumerate(links[1:]): output[-1] += ' `[%s] <#%s>`_ ' % (i + 1, nodes.make_id(link[1])) output.append('') else: output.append(entryname) if subitems: for subentryname, subentrylinks in subitems: if subentrylinks: output.append( ' `%s <%s>`_' % (subentryname, subentrylinks[0]) ) for i, link in enumerate(subentrylinks[1:]): output[-1] += ' `[%s] <%s>`_ ' % (i + 1, link) output.append('') else: output.append(subentryname) output.append('') doctree = docutils.core.publish_doctree('\n'.join(output)) return doctree[1] class PDFContents(Contents): # Mostly copied from Docutils' Contents transformation def build_contents(self, node, level=0): level += 1 sections = [] # Replaced this with the for below to make it work for Sphinx # trees. # sections = [sect for sect in node if isinstance(sect, nodes.section)] for sect in node: if isinstance(sect, nodes.compound): for sect2 in sect: if isinstance(sect2, addnodes.start_of_file): for sect3 in sect2: if isinstance(sect3, nodes.section): sections.append(sect3) elif isinstance(sect, nodes.section): sections.append(sect) entries = [] # FIXME: depth should be taken from :maxdepth: (Issue 320) depth = self.toc_depth for section in sections: title = section[0] auto = title.get('auto') # May be set by SectNum. entrytext = self.copy_and_filter(title) reference = nodes.reference('', '', refid=section['ids'][0], *entrytext) ref_id = self.document.set_id(reference) entry = nodes.paragraph('', '', reference) item = nodes.list_item('', entry) if ( self.backlinks in ('entry', 'top') and title.next_node(nodes.reference) is None ): if self.backlinks == 'entry': title['refid'] = ref_id elif self.backlinks == 'top': title['refid'] = self.toc_id if level < depth: subsects = self.build_contents(section, level) item += subsects entries.append(item) if entries: contents = nodes.bullet_list('', *entries) if auto: contents['classes'].append('auto-toc') return contents else: return [] class PDFWriter(writers.Writer): def __init__( self, builder, stylesheets, language, breaklevel=0, breakside='any', fontpath=[], fitmode='shrink', compressed=False, inline_footnotes=False, splittables=True, srcdir='.', default_dpi=300, page_template='decoratedPage', invariant=False, real_footnotes=False, use_toc=True, use_coverpage=True, toc_depth=9999, use_numbered_links=False, fit_background_mode="scale", section_header_depth=2, baseurl=urlunparse(['file', os.getcwd() + os.sep, '', '', '', '']), style_path=None, repeat_table_rows=False, smartquotes='0', config={}, ): writers.Writer.__init__(self) self.builder = builder self.output = '' self.stylesheets = stylesheets self.__language = language self.breaklevel = int(breaklevel) self.breakside = breakside self.fontpath = fontpath self.fitmode = fitmode self.compressed = compressed self.inline_footnotes = inline_footnotes self.splittables = splittables self.highlightlang = builder.config.highlight_language self.srcdir = srcdir self.config = config self.default_dpi = default_dpi self.page_template = page_template self.invariant = invariant self.real_footnotes = real_footnotes self.use_toc = use_toc self.use_coverpage = use_coverpage self.toc_depth = toc_depth self.use_numbered_links = use_numbered_links self.fit_background_mode = fit_background_mode self.section_header_depth = section_header_depth self.repeat_table_rows = repeat_table_rows self.smartquotes = smartquotes self.baseurl = baseurl if hasattr(sys, 'frozen'): self.PATH = os.path.abspath(os.path.dirname(sys.executable)) else: self.PATH = os.path.abspath(os.path.dirname(__file__)) if style_path: self.style_path = style_path else: self.style_path = [self.srcdir] supported = 'pdf' config_section = 'pdf writer' config_section_dependencies = ('writers',) def translate(self): visitor = PDFTranslator(self.document, self.builder) self.document.walkabout(visitor) lang = self.config.language or 'en' langmod = get_language_available(lang)[2] self.docutils_languages = {lang: langmod} # Generate Contents topic manually if self.use_toc: contents = nodes.topic(classes=['contents']) contents += nodes.title('') contents[0] += nodes.Text(langmod.labels['contents']) contents['ids'] = ['Contents'] pending = nodes.topic() contents.append(pending) pending.details = {} self.document.insert( 0, nodes.raw(text='SetPageCounter 1 arabic', format='pdf') ) self.document.insert( 0, nodes.raw(text='OddPageBreak %s' % self.page_template, format='pdf') ) self.document.insert(0, contents) self.document.insert( 0, nodes.raw(text='SetPageCounter 1 lowerroman', format='pdf') ) contTrans = PDFContents(self.document) contTrans.toc_depth = self.toc_depth contTrans.startnode = pending contTrans.apply() if self.use_coverpage: # Generate cover page # FIXME: duplicate from createpdf, refactor! # Add the Sphinx template paths def add_template_path(path): return os.path.join(self.srcdir, path) jinja_env = jinja2.Environment( loader=jinja2.FileSystemLoader( [ self.srcdir, os.path.expanduser('~/.rst2pdf'), os.path.join(self.PATH, 'templates'), ] + list(map(add_template_path, self.config.templates_path)) ), autoescape=jinja2.select_autoescape(['html', 'xml']), ) try: template = jinja_env.get_template(self.config.pdf_cover_template) except jinja2.TemplateNotFound: log.error( "Can't find cover template %s, using default" % self.config.pdf_cover_template ) template = jinja_env.get_template('sphinxcover.tmpl') # This is what's used in the python docs because # Latex does a manual linebreak. This sucks. authors = self.document.settings.author.split('\\') # Honour the "today" config setting if self.config.today: date = self.config.today else: date = time.strftime(self.config.today_fmt or _('%B %d, %Y')) # Feed data to the template, get restructured text. cover_text = template.render( title=self.document.settings.title or visitor.elements['title'], subtitle='%s %s' % (self.config.subtitle_prefix, self.config.version), authors=authors, date=date, ) cover_tree = docutils.core.publish_doctree(cover_text) self.document.insert(0, cover_tree) sio = BytesIO() if self.invariant: createpdf.patch_PDFDate() createpdf.patch_digester() createpdf.RstToPdf( sphinx=True, stylesheets=self.stylesheets, language=self.__language, breaklevel=self.breaklevel, breakside=self.breakside, fit_mode=self.fitmode, font_path=self.fontpath, inline_footnotes=self.inline_footnotes, highlightlang=self.highlightlang, splittables=self.splittables, style_path=self.style_path, repeat_table_rows=self.repeat_table_rows, basedir=self.srcdir, def_dpi=self.default_dpi, real_footnotes=self.real_footnotes, numbered_links=self.use_numbered_links, background_fit_mode=self.fit_background_mode, baseurl=self.baseurl, section_header_depth=self.section_header_depth, toc_depth=self.toc_depth, smarty=self.smartquotes, ).createPdf(doctree=self.document, output=sio, compressed=self.compressed) self.output = sio.getvalue() def supports(self, format): """This writer supports all format-specific elements.""" return 1 class PDFTranslator(nodes.SparseNodeVisitor): def __init__(self, document, builder): nodes.NodeVisitor.__init__(self, document) self.builder = builder self.footnotestack = [] self.curfilestack = [] self.highlightlinenothreshold = 999999 self.top_sectionlevel = 1 self.footnotecounter = 1 self.curfile = None self.footnotedict = {} self.this_is_the_title = True self.in_title = 0 self.elements = { 'title': document.settings.title, } self.highlightlang = builder.config.highlight_language def visit_document(self, node): self.curfilestack.append(node.get('docname', '')) self.footnotestack.append('') def visit_start_of_file(self, node): self.curfilestack.append(node['docname']) self.footnotestack.append(node['docname']) def depart_start_of_file(self, node): self.footnotestack.pop() self.curfilestack.pop() def visit_highlightlang(self, node): self.highlightlang = node['lang'] self.highlightlinenothreshold = node['linenothreshold'] raise nodes.SkipNode def visit_versionmodified(self, node): replacement = nodes.paragraph() replacement.extend(node.children) node.parent.replace(node, replacement) def depart_versionmodified(self, node): pass def visit_literal_block(self, node): if 'code' in node['classes']: # Probably a processed code-block pass else: lang = lang_for_block( node.astext(), node.get('language', self.highlightlang) ) content = node.astext().splitlines() if len(content) > self.highlightlinenothreshold or node.get( 'linenos', False ): options = {'linenos': True} else: options = {} # FIXME: make tab width configurable content = [c.replace('\t', ' ') for c in content] replacement = nodes.literal_block() replacement.children = code_block.code_block_directive( name=None, arguments=[lang], options=options, content=content, lineno=False, content_offset=None, block_text=None, state=None, state_machine=None, ) node.parent.replace(node, replacement) def visit_footnote(self, node): node['backrefs'] = [ '%s_%s' % (self.footnotestack[-1], x) for x in node['backrefs'] ] node['ids'] = ['%s_%s' % (self.footnotestack[-1], x) for x in node['ids']] node.children[0][0] = nodes.Text(str(self.footnotecounter)) for id in node['backrefs']: try: fnr = self.footnotedict[id] except KeyError: pass else: fnr.children[0] = nodes.Text(str(self.footnotecounter)) self.footnotedict[node['ids'][0]] = node self.footnotecounter += 1 def visit_footnote_reference(self, node): node['ids'] = ['%s_%s' % (self.footnotestack[-1], x) for x in node['ids']] node['refid'] = '%s_%s' % (self.footnotestack[-1], node['refid']) self.footnotedict[node['ids'][0]] = node try: footnote = self.footnotedict[node['refid']] except KeyError: pass else: node.children[0] = nodes.Text(footnote.children[0][0]) def visit_desc_annotation(self, node): pass def depart_desc_annotation(self, node): pass # This is for graphviz support def visit_graphviz(self, node): # Not neat, but I need to send self to my handlers node['builder'] = self def visit_Aanode(self, node): pass def depart_Aanode(self, node): pass def visit_productionlist(self, node): replacement = nodes.literal_block(classes=["code"]) names = [] for production in node: names.append(production['tokenname']) maxlen = max(len(name) for name in names) for production in node: if production['tokenname']: lastname = production['tokenname'].ljust(maxlen) n = nodes.strong() n += nodes.Text(lastname) replacement += n replacement += nodes.Text(' ::= ') else: replacement += nodes.Text('%s ' % (' ' * len(lastname))) production.walkabout(self) replacement.children.extend(production.children) replacement += nodes.Text('\n') node.parent.replace(node, replacement) raise nodes.SkipNode def depart_productionlist(self, node): pass def visit_production(self, node): pass def depart_production(self, node): pass def visit_OddEvenNode(self, node): pass def depart_OddEvenNode(self, node): pass class HighlightLanguageTransform(SphinxTransform): """ This is a copy of Sphinx's HighlightLanguageTransform for use with Sphinx versions between 1.8.0 & less than 2.0.0 as the Sphinx version of this class breaks the linenothreshold setting in the highlight directive (See issue #721). This code can be removed when we drop support for Python 2 Apply highlight_language to all literal_block nodes. This refers both :confval:`highlight_language` setting and :rst:dir:`highlightlang` directive. After processing, this overridden transform DOES NOT REMOVE ``highlightlang`` node from doctree in order to allow pdfbuilder's visit_highlightlang to work as before. """ default_priority = 400 def apply(self): from sphinx.transforms.post_transforms.code import HighlightLanguageVisitor visitor = HighlightLanguageVisitor( self.document, self.config.highlight_language ) self.document.walkabout(visitor) # This is copied from sphinx.highlighting def lang_for_block(source, lang): if lang in ('py', 'python'): if source.startswith('>>>'): # interactive session return 'pycon' else: # maybe Python -- try parsing it if try_parse(source): return 'python' else: # Guess return lang_for_block(source, 'guess') elif lang in ('python3', 'py3') and source.startswith('>>>'): # for py3, recognize interactive sessions, but do not try parsing... return 'pycon3' elif lang == 'guess': try: # return 'python' lexer = guess_lexer(source) return lexer.aliases[0] except Exception: return None else: return lang def try_parse(src): # Make sure it ends in a newline src += '\n' # Replace "..." by a mark which is also a valid python expression # (Note, the highlighter gets the original source, this is only done # to allow "..." in code and still highlight it as Python code.) mark = "__highlighting__ellipsis__" src = src.replace("...", mark) # lines beginning with "..." are probably placeholders for suite src = re.sub(r"(?m)^(\s*)" + mark + "(.)", r"\1" + mark + r"# \2", src) if not isinstance(src, bytes): # Non-ASCII chars will only occur in string literals # and comments. If we wanted to give them to the parser # correctly, we'd have to find out the correct source # encoding. Since it may not even be given in a snippet, # just replace all non-ASCII characters. src = src.encode('ascii', 'replace') return True def setup(app): app.add_builder(PDFBuilder) # PDF options app.add_config_value('pdf_documents', [], None) app.add_config_value('pdf_stylesheets', ['sphinx'], None) app.add_config_value('pdf_style_path', None, None) app.add_config_value('pdf_compressed', False, None) app.add_config_value('pdf_font_path', [], None) app.add_config_value('pdf_language', 'en_US', None) app.add_config_value('pdf_fit_mode', '', None), app.add_config_value('pdf_break_level', 0, None) app.add_config_value('pdf_inline_footnotes', True, None) app.add_config_value('pdf_verbosity', 0, None) app.add_config_value('pdf_use_index', True, None) app.add_config_value('pdf_domain_indices', True, None) app.add_config_value('pdf_use_modindex', True, None) app.add_config_value('pdf_use_coverpage', True, None) app.add_config_value('pdf_cover_template', 'sphinxcover.tmpl', None) app.add_config_value('pdf_appendices', [], None) app.add_config_value('pdf_splittables', True, None) app.add_config_value('pdf_repeat_table_rows', False, None) app.add_config_value('pdf_breakside', 'odd', None) app.add_config_value('pdf_default_dpi', 300, None) app.add_config_value('pdf_extensions', [], None) app.add_config_value('pdf_page_template', 'decoratedPage', None) app.add_config_value('pdf_invariant', False, None) app.add_config_value('pdf_real_footnotes', False, None) app.add_config_value('pdf_use_toc', True, None) app.add_config_value('pdf_toc_depth', 9999, None) app.add_config_value('pdf_use_numbered_links', False, None) app.add_config_value('pdf_fit_background_mode', "scale", None) app.add_config_value('pdf_smartquotes', 0, None) app.add_config_value('section_header_depth', 2, None) app.add_config_value( 'pdf_baseurl', urlunparse(['file', os.getcwd() + os.sep, '', '', '', '']), None ) app.add_config_value('subtitle_prefix', 'version', None) project_doc = app.config.project + ' Documentation' app.config.pdf_documents.append( ( app.config.master_doc, app.config.project, project_doc, app.config.copyright, 'manual', ) ) return { 'version': rst2pdf.version, 'parallel_read_safe': True, 'parallel_write_safe': False, } rst2pdf-0.102/rst2pdf/pygments2style.py000066400000000000000000000050531463013543400200550ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms ''' Creates a rst2pdf stylesheet for each pygments style. ''' import os from dumpstyle import dumps from pygments.token import STANDARD_TYPES from pygments import styles as pstyles # First get a list of all possible classes classnames = set() for name in list(pstyles.get_all_styles()): css = os.popen('pygmentize -S %s -f html' % name, 'r').read() for line in css.splitlines(): line = line.strip() sname = "pygments-" + line.split(' ')[0][1:] classnames.add(sname) def css2rl(css): dstyles = {} # First create a dumb stylesheet for key in STANDARD_TYPES: dstyles["pygments-" + STANDARD_TYPES[key]] = {'parent': 'code'} seenclassnames = set() styles = [] for line in css.splitlines(): line = line.strip() sname = "pygments-" + line.split(' ')[0][1:] seenclassnames.add(sname) style = dstyles.get(sname, {'parent': 'code'}) options = line.split('{')[1].split('}')[0].split(';') for option in options: option = option.strip() option, argument = option.split(':') option = option.strip() argument = argument.strip() if option == 'color': style['textColor'] = argument.strip() if option == 'background-color': style['backColor'] = argument.strip() # These two can come in any order if option == 'font-weight' and argument == 'bold': if 'fontName' in style and style['fontName'] == 'fontMonoItalic': style['fontName'] = 'fontMonoBoldItalic' else: style['fontName'] = 'fontMonoBold' if option == 'font-style' and argument == 'italic': if 'fontName' in style and style['fontName'] == 'fontSansBold': style['fontName'] = 'fontMonoBoldItalic' else: style['fontName'] = 'fontMonoItalic' if style.get('textColor', None) is None: style['textColor'] = 'black' styles.append([sname, style]) # Now add default styles for all unseen class names for sname in classnames - seenclassnames: style = dstyles.get(sname, {'parent': 'code'}) style['textColor'] = 'black' styles.append([sname, style]) return dumps({'styles': styles}) for name in list(pstyles.get_all_styles()): css = os.popen('pygmentize -S %s -f html' % name, 'r').read() open(name + '.style', 'w').write(css2rl(css)) rst2pdf-0.102/rst2pdf/roles/000077500000000000000000000000001463013543400156135ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/roles/__init__.py000066400000000000000000000000001463013543400177120ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/roles/counter.py000066400000000000000000000014351463013543400176470ustar00rootroot00000000000000# -*- coding: utf-8 -*- from docutils.nodes import Text, target from docutils.parsers.rst import roles values = {} class CounterNode(Text): children = () def __init__(self, data, rawsource=''): if ':' in data: self.name, value = [s.lower() for s in data.split(':')][:2] self.value = int(value) else: self.name = data.lower() self.value = values.get(self.name, 1) values[self.name] = self.value + 1 def astext(self): return str(self.value) def counter_fn(name, rawtext, text, lineno, inliner, options={}, content=[]): n = CounterNode(text) s = '%s-%s' % (n.name, n.value) return [target(ids=[s]), n], [] counter_fn.content = True roles.register_canonical_role('counter', counter_fn) rst2pdf-0.102/rst2pdf/roles/counter_off.py000066400000000000000000000003651463013543400205020ustar00rootroot00000000000000# -*- coding: utf-8 -*- from docutils.parsers.rst import roles def counter_fn(name, rawtext, text, lineno, inliner, options={}, content=[]): return [], [] counter_fn.content = False roles.register_canonical_role('counter', counter_fn) rst2pdf-0.102/rst2pdf/roles/package.py000066400000000000000000000024351463013543400175640ustar00rootroot00000000000000# SPDX-License-Identifier: MIT from docutils import nodes from docutils.parsers.rst import roles import importlib_metadata import packaging.version def _get_version(package): """Get version from the usual methods.""" # TODO(stephenfin): Switch to 'importlib.metadata' once we drop support for # Python < 3.8 try: parsed_version = packaging.version.parse(importlib_metadata.version(package)) except importlib_metadata.PackageNotFoundError: return 'UNKNOWN', 'UNKNOWN' version = '.'.join(str(r) for r in parsed_version.release) if parsed_version.pre: revision = parsed_version.pre elif parsed_version.dev: revision = f'dev{parsed_version.dev}' elif parsed_version.is_postrelease: revision = f'post{parsed_version.post}' else: revision = 'final' return version, revision def version_fn(name, rawtext, text, lineno, inliner, options=None, content=None): version, _ = _get_version(text) return [nodes.Text(version)], [] def revision_fn(name, rawtext, text, lineno, inliner, options=None, content=None): _, revision = _get_version(text) return [nodes.Text(revision)], [] roles.register_canonical_role('package-version', version_fn) roles.register_canonical_role('package-revision', revision_fn) rst2pdf-0.102/rst2pdf/rson.py000066400000000000000000001014161463013543400160250ustar00rootroot00000000000000""" RSON -- readable serial object notation RSON is a superset of JSON with relaxed syntax for human readability. Simple usage example: import rson obj = rson.loads(source) Additional documentation available at: http://code.google.com/p/rson/ """ __version__ = '0.08' __author__ = 'Patrick Maupin ' __copyright__ = ''' Copyright (c) 2010, Patrick Maupin. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ''' import bisect import re import sys class RSONDecodeError(ValueError): pass class Tokenizer(list): """The RSON tokenizer uses re.split() to rip the source string apart into smaller strings which may or may not be true standalone tokens. Sufficient information is maintained to put Humpty-Dumpty back together when necessary. The tokens are kept in a reversed list. This makes retrieving the next token a low-cost pop() operation from the end of the list, and facilitates arbitrary lookahead operations. Each token is a tuple, containing the following elements: [0] Negative character offset of token within the source string. A negative offset is used so that the tokens are sorted properly for bisect() for special operations. [1] single-character string usually containing a character which represents the token type (often the entire token). [2] string containing entire token [3] string (possibly null) containing whitespace after token [4] Indentation value of line containing token (\n followed by 0 or more spaces) [5] Line number of token [6] Tokenizer object that the token belongs to (for error reporting) """ # Like Python, indentation is special. I originally planned on making # the space character the only valid indenter, but that got messy # when combined with the desire to be 100% JSON compatible, so, like # JSON, you can indent with any old whitespace, but if you mix and # match, you might be in trouble (like with Python). # # An indentation is always the preceding EOL plus optional spaces, # so we create a dummy EOL for the very start of the string. # Could also have an embedded comment indentation = r'\n[ \t\v\f]*(?:#.*)?' # RSON syntax delimiters are tokenized separately from everything else. delimiterset = set(' { } [ ] : = , '.split()) re_delimiterset = ''.join(delimiterset).replace(']', r'\]').replace('[', r'\[') # Create a RE pattern for the delimiters delimiter_pattern = '[%s]' % re_delimiterset # A regular quoted string must terminate before the end of the line, # and \ can be used as the internal escape character. quoted_string = r'"(?:[^"\n\\]|\\.)*(?:"|(?=\n))' # A triple-quoted string can contain any characters. The only escape # processing that is done on them is to allow a backslash in front of # another set of triple quotes. We only look for the start of one of # these suckers in the first pass, and then go find the real string # later. This keeps us from getting our knickers in a twist on # regular strings vs triple-quoted vs comments, etc. triple_quoted_string = '"""' # Any non-whitespace, non-delimiter, group of characters is in the "other" # category. This group can have embedded whitespace, but ends on a # non-whitespace character. other = r'[\S](?:[^%s\n]*[^%s\s])*' % (re_delimiterset, re_delimiterset) pattern = '(%s)' % '|'.join( [delimiter_pattern, triple_quoted_string, quoted_string, other, indentation] ) splitter = re.compile(pattern).split @classmethod def factory(cls): splitter = cls.splitter delimiterset = set(cls.delimiterset) | set('"') def newstring(source, client): self = cls() self.client = client # Deal with 8 bit bytes for now if isinstance(source, str): source = source.encode('utf-8') # Convert MS-DOS or Mac line endings to the one true way source = source.replace(b'\r\n', b'\n').replace(b'\r', b'\n') sourcelist = splitter(source.decode()) # Get the indentation at the start of the file indentation = '\n' + sourcelist[0] linenum = 1 # Set up to iterate over the source and add to the destination list sourceiter = iter(sourcelist) next_ = sourceiter.__next__ offset = 0 - len(next_()) # Strip comment from first line if len(sourcelist) > 1 and sourcelist[1].startswith('#'): i = 1 while len(sourcelist) > i and not sourcelist[i].startswith('\n'): i += 1 offset -= len(next_()) # Preallocate the list self.append(None) self *= len(sourcelist) // 2 + 1 index = 0 # Create all the tokens for token in sourceiter: whitespace = next_() t0 = token[0] if t0 not in delimiterset: if t0 == '\n': linenum += 1 indentation = token offset -= len(token) continue else: t0 = 'X' self[index] = ( offset, t0, token, whitespace, indentation, linenum, self, ) index += 1 offset -= len(token) + len(whitespace) # Add a sentinel self[index] = (offset, '@', '@', '', '', linenum + 1, self) self[index + 1 :] = [] # Put everything we need in the actual object instantiation self.reverse() self.source = source self.next = self.pop self.push = self.append return self return newstring def peek(self): return self[-1] def lookahead(self, index=0): return self[-1 - index] @staticmethod def sourceloc(token): """Return the source location for a given token""" lineno = token[5] colno = offset = -token[0] + 1 if lineno != 1: colno -= token[-1].source.rfind('\n', 0, offset) + 1 return offset, lineno, colno @classmethod def error(cls, s, token): """error performs generic error reporting for tokens""" offset, lineno, colno = cls.sourceloc(token) if token[1] == '@': loc = 'at end of string' else: text = token[2] loc = 'line %s, column %s, text %s' % (lineno, colno, repr(text[:20])) err = RSONDecodeError('%s: %s' % (s, loc)) err.pos = offset err.lineno = lineno err.colno = colno raise err def make_hashable(what): try: hash(what) return what except TypeError: if isinstance(what, dict): return tuple(sorted(make_hashable(x) for x in what.items())) return tuple(make_hashable(x) for x in what) class BaseObjects(object): # These hooks allow compatibility with simplejson object_hook = None object_pairs_hook = None array_hook = None # Stock object constructor does not cope with no keys disallow_missing_object_keys = True # Stock object constructor copes with multiple keys just fine disallow_multiple_object_keys = False # Default JSON requires string keys disallow_nonstring_keys = True class default_array(list): def __new__(self, startlist, token): return list(startlist) class default_object(dict): """By default, RSON objects are dictionaries that allow attribute access to their existing contents. """ def __getattr__(self, key): return self[key] def __setattr__(self, key, value): self[key] = value def append(self, itemlist): mydict = self value = itemlist.pop() itemlist = [make_hashable(x) for x in itemlist] lastkey = itemlist.pop() if itemlist: itemlist.reverse() while itemlist: key = itemlist.pop() subdict = mydict.get(key) if not isinstance(subdict, dict): subdict = mydict[key] = type(self)() mydict = subdict if isinstance(value, dict): oldvalue = mydict.get(lastkey) if isinstance(oldvalue, dict): oldvalue.update(value) return mydict[lastkey] = value def get_result(self, token): return self def object_type_factory(self): """This function returns constructors for RSON objects and arrays. It handles simplejson compatible hooks as well. """ object_hook = self.object_hook object_pairs_hook = self.object_pairs_hook if object_pairs_hook is not None: class build_object(list): def get_result(self, token): return object_pairs_hook([tuple(x) for x in self]) self.disallow_multiple_object_keys = True self.disallow_nonstring_keys = True elif object_hook is not None: mydict = dict class build_object(list): def get_result(self, token): return object_hook(mydict(self)) self.disallow_multiple_object_keys = True self.disallow_nonstring_keys = True else: build_object = self.default_object build_array = self.array_hook or self.default_array return build_object, build_array class Dispatcher(object): """Assumes that this is mixed-in to a class with an appropriate parser_factory() method. """ @classmethod def dispatcher_factory(cls): self = cls() parser_factory = self.parser_factory parsercache = {} cached = parsercache.get default_loads = parser_factory() def loads(s, **kw): if not kw: return default_loads(s) key = tuple(sorted(kw.items())) func = cached(key) if func is None: # Begin some real ugliness here -- just modify our instance to # have the correct user variables for the initialization functions. # Seems to speed up simplejson testcases a bit. self.__dict__ = dict((x, y) for (x, y) in key if y is not None) func = parsercache[key] = parser_factory() return func(s) return loads class QuotedToken(object): """Subclass or replace this if you don't like quoted string handling""" parse_encoded_chr = chr parse_quoted_str = staticmethod(lambda token, s, str=str: str(s)) parse_join_str = u''.join cachestrings = False quoted_splitter = re.compile(r'(\\u[0-9a-fA-F]{4}|\\.|")').split quoted_mapper = { '\\\\': '\\', r'\"': '"', r'\/': '/', r'\b': '\b', r'\f': '\f', r'\n': '\n', r'\r': '\r', r'\t': '\t', }.get def quoted_parse_factory(self): quoted_splitter = self.quoted_splitter quoted_mapper = self.quoted_mapper parse_quoted_str = self.parse_quoted_str parse_encoded_chr = self.parse_encoded_chr parse_join_str = self.parse_join_str cachestrings = self.cachestrings triplequoted = self.triplequoted allow_double = sys.maxunicode > 65535 def badstring(token, special): if token[2] != '"""' or triplequoted is None: token[-1].error( 'Invalid character in quoted string: %s' % repr(special), token ) result = parse_quoted_str(token, triplequoted(token)) if cachestrings: result = token[-1].stringcache(result, result) return result def parse(token, next_): s = token[2] if len(s) < 2 or not (s[0] == s[-1] == '"'): token[-1].error('No end quote on string', token) s = quoted_splitter(s[1:-1]) result = parse_quoted_str(token, s[0]) if len(s) > 1: result = [result] append = result.append s = iter(s) next_ = s.__next__ next_() for special in s: nonmatch = next_() remap = quoted_mapper(special) if remap is None: if len(special) == 6: uni = int(special[2:], 16) if 0xD800 <= uni <= 0xDBFF and allow_double: uni, nonmatch = parse_double_unicode( uni, nonmatch, next_, token ) remap = parse_encoded_chr(uni) else: return badstring(token, special) append(remap) append(parse_quoted_str(token, nonmatch)) result = parse_join_str(result) if cachestrings: result = token[-1].stringcache(result, result) return result def parse_double_unicode(uni, nonmatch, next_, token): """Munged version of UCS-4 code pair stuff from simplejson. """ ok = True try: uni2 = next_() nonmatch2 = next_() except Exception: ok = False ok = ok and not nonmatch and uni2.startswith(b'\\u') and len(uni2) == 6 if ok: nonmatch = uni2 uni = 0x10000 + (((uni - 0xD800) << 10) | (int(uni2[2:], 16) - 0xDC00)) return uni, nonmatch2 token[-1].error( 'Invalid second ch in double sequence: %s' % repr(nonmatch), token ) return parse @staticmethod def triplequoted(token): tokens = token[-1] source = tokens.source result = [] start = 3 - token[0] while 1: end = source.find('"""', start) if end < 0: tokens.error('Did not find end for triple-quoted string', token) if source[end - 1] != '\\': break result.append(source[start : end - 1]) result.append('"""') start = end + 3 result.append(source[start:end]) offset = bisect.bisect(tokens, (-end - 2,)) tokens[offset:] = [] return ''.join(result) class UnquotedToken(object): """Subclass or replace this if you don't like the unquoted token handling. This is designed to be a superset of JSON: - Integers allowed to be expressed in octal, binary, or hex as well as decimal. - Integers can have embedded underscores. - Non-match of a special token will just be wrapped as a unicode string. - Numbers can be preceded by '+' as well s '-' - Numbers can be left-zero-filled - If a decimal point is present, digits are required on either side, but not both sides """ use_decimal = False parse_int = staticmethod(lambda s: int(s.replace('_', ''), 0)) parse_float = float parse_unquoted_str = staticmethod(lambda token: str(token[2])) special_strings = dict(true=True, false=False, null=None) unquoted_pattern = r''' (?: true | false | null | # Special JSON names (?P [-+]? # Optional sign (?: 0[xX](_*[0-9a-fA-F]+)+ | # Hex integer 0[bB](_*[01]+)+ | # binary integer 0[oO](_*[0-7]+)+ | # Octal integer \d+(_*\d+)* | # Decimal integer (?P (?: \d+(\.\d*)? | # One or more digits, # optional frac \.\d+ # Leading decimal point ) (?:[eE][-+]?\d+)? # Optional exponent ) ) ) ) \Z # Match end of string ''' def unquoted_parse_factory(self): unquoted_match = re.compile(self.unquoted_pattern, re.VERBOSE).match parse_unquoted_str = self.parse_unquoted_str parse_float = self.parse_float parse_int = self.parse_int special = self.special_strings if self.use_decimal: from decimal import Decimal parse_float = Decimal def parse(token, next_): s = token[2] m = unquoted_match(s) if m is None: return parse_unquoted_str(token) if m.group('num') is None: return special[s] if m.group('float') is None: return parse_int(s.replace('_', '')) return parse_float(s) return parse class EqualToken(object): """Subclass or replace this if you don't like the = string handling""" encode_equals_str = None @staticmethod def parse_equals(stringlist, indent, token): """token probably not needed except maybe for error reporting. Replace this with something that does what you want. """ # Strip any trailing whitespace to the right stringlist = [x.rstrip() for x in stringlist] # Strip any embedded comments stringlist = [x for x in stringlist if x.startswith(indent) or not x] # Strip trailing whitespace down below while stringlist and not stringlist[-1]: stringlist.pop() # Special cases for single line if not stringlist: return '' if len(stringlist) == 1: return stringlist[0].strip() # Strip whitespace on first line if stringlist and not stringlist[0]: stringlist.pop(0) # Dedent all the strings to one past the equals dedent = len(indent) stringlist = [x[dedent:] for x in stringlist] # Figure out if should dedent one more if min((not x and 500 or len(x) - len(x.lstrip())) for x in stringlist): stringlist = [x[1:] for x in stringlist] # Give every line its own linefeed (keeps later parsing from # treating this as a number, for example) stringlist.append('') # Return all joined up as a single unicode string return '\n'.join(stringlist) def equal_parse_factory(self, read_unquoted): parse_equals = self.parse_equals encoder = self.encode_equals_str if encoder is None: encoder = read_unquoted def parse(firsttok, next_): tokens = firsttok[-1] indent, linenum = firsttok[4:6] token = next_() while token[5] == linenum: token = next_() while token[4] > indent: token = next_() tokens.push(token) # Get rid of \n, and indent one past = indent = indent[1:] + ' ' bigstring = tokens.source[-firsttok[0] + 1 : -token[0]] bigstring = bigstring.decode('utf-8') stringlist = bigstring.split('\n') stringlist[0] = indent + stringlist[0] token = list(firsttok) token[1:3] = '=', parse_equals(stringlist, indent, firsttok) return encoder(token, next) return parse class RsonParser(object): """Parser for RSON""" disallow_trailing_commas = True disallow_rson_sublists = False disallow_rson_subdicts = False @staticmethod def post_parse(tokens, value): return value def client_info(self, parse_locals): pass def parser_factory(self): Tokenizer = self.Tokenizer tokenizer = Tokenizer.factory() error = Tokenizer.error read_unquoted = self.unquoted_parse_factory() read_quoted = self.quoted_parse_factory() parse_equals = self.equal_parse_factory(read_unquoted) new_object, new_array = self.object_type_factory() disallow_trailing_commas = self.disallow_trailing_commas disallow_missing_object_keys = self.disallow_missing_object_keys key_handling = [ disallow_missing_object_keys, self.disallow_multiple_object_keys, ] disallow_nonstring_keys = self.disallow_nonstring_keys post_parse = self.post_parse def bad_array_element(token, next): error('Expected array element', token) def bad_dict_key(token, next): error('Expected dictionary key', token) def bad_dict_value(token, next): error('Expected dictionary value', token) def bad_top_value(token, next): error('Expected start of object', token) def bad_unindent(token, next): error('Unindent does not match any outer indentation level', token) def bad_indent(token, next): error('Unexpected indentation', token) def read_json_array(firsttok, next): result = new_array([], firsttok) append = result.append while 1: token = next() t0 = token[1] if t0 == ']': if result and disallow_trailing_commas: error('Unexpected trailing comma', token) break append(json_value_dispatch(t0, bad_array_element)(token, next)) delim = next() t0 = delim[1] if t0 == ',': continue if t0 != ']': if t0 == '@': error('Unterminated list (no matching "]")', firsttok) error('Expected "," or "]"', delim) break return result def read_json_dict(firsttok, next): result = new_object() append = result.append while 1: token = next() t0 = token[1] if t0 == '}': if result and disallow_trailing_commas: error('Unexpected trailing comma', token) break key = json_value_dispatch(t0, bad_dict_key)(token, next) if disallow_nonstring_keys and not isinstance(key, str): error('Non-string key %s not supported' % repr(key), token) token = next() t0 = token[1] if t0 != ':': error('Expected ":" after dict key %s' % repr(key), token) token = next() t0 = token[1] value = json_value_dispatch(t0, bad_dict_value)(token, next) append([key, value]) delim = next() t0 = delim[1] if t0 == ',': continue if t0 != '}': if t0 == '@': error('Unterminated dict (no matching "}")', firsttok) error('Expected "," or "}"', delim) break return result.get_result(firsttok) def read_rson_unquoted(firsttok, next): toklist = [] linenum = firsttok[5] while 1: token = next() if token[5] != linenum or token[1] in ':=': break toklist.append(token) firsttok[-1].push(token) if not toklist: return read_unquoted(firsttok, next) s = list(firsttok[2:4]) for tok in toklist: s.extend(tok[2:4]) result = list(firsttok) result[3] = s.pop() result[2] = ''.join(s) return read_unquoted(result, next) json_value_dispatch = { 'X': read_unquoted, '[': read_json_array, '{': read_json_dict, '"': read_quoted, }.get rson_value_dispatch = { 'X': read_rson_unquoted, '[': read_json_array, '{': read_json_dict, '"': read_quoted, '=': parse_equals, } if self.disallow_rson_sublists: rson_value_dispatch['['] = read_rson_unquoted if self.disallow_rson_subdicts: rson_value_dispatch['{'] = read_rson_unquoted rson_key_dispatch = rson_value_dispatch.copy() if disallow_missing_object_keys: del rson_key_dispatch['='] rson_value_dispatch = rson_value_dispatch.get rson_key_dispatch = rson_key_dispatch.get empty_object = new_object().get_result(None) empty_array = new_array([], None) empty_array_type = type(empty_array) empties = empty_object, empty_array def parse_recurse_array(stack, next, token, result): arrayindent, linenum = stack[-1][4:6] linenum -= not result while 1: thisindent, newlinenum = token[4:6] if thisindent != arrayindent: if thisindent < arrayindent: return result, token if result: stack.append(token) lastitem = result[-1] if lastitem == empty_array: result[-1], token = parse_recurse_array( stack, next, token, lastitem ) elif lastitem == empty_object: result[-1], token = parse_recurse_dict( stack, next, token, lastitem ) else: result = None if result: stack.pop() thisindent, newlinenum = token[4:6] if thisindent <= arrayindent: continue bad_unindent(token, next) bad_indent(token, next) if newlinenum <= linenum: if token[1] in '=:': error( 'Cannot mix list elements with dict (key/value) elements', token, ) error( 'Array elements must either be on separate lines or enclosed in []', token, ) linenum = newlinenum value = rson_value_dispatch(token[1], bad_top_value)(token, next) result.append(value) token = next() def parse_one_dict_entry(stack, next, token, entry, mydict): arrayindent, linenum = stack[-1][4:6] while token[1] == ':': tok1 = next() thisindent, newlinenum = tok1[4:6] if newlinenum == linenum: value = rson_value_dispatch(tok1[1], bad_top_value)(tok1, next) token = next() entry.append(value) continue if thisindent <= arrayindent: error('Expected indented line after ":"', token) token = tok1 if not entry: error('Expected key', token) thisindent, newlinenum = token[4:6] if newlinenum == linenum and token[1] == '=': value = rson_value_dispatch(token[1], bad_top_value)(token, next) entry.append(value) token = next() elif thisindent > arrayindent: stack.append(token) value, token = parse_recurse(stack, next) if entry[-1] in empties: if type(entry[-1]) is type(value): entry[-1] = value else: error( 'Cannot load %s into %s' % (type(value), type(entry[-1])), stack[-1], ) elif len(value) == 1 and type(value) is empty_array_type: entry.extend(value) else: entry.append(value) stack.pop() length = len(entry) if length != 2 and key_handling[length > 2]: if length < 2: error('Expected ":" or "=", or indented line', token) error( "rson client's object handlers do not support chained objects", token, ) if disallow_nonstring_keys: for key in entry[:-1]: if not isinstance(key, str): error('Non-string key %s not supported' % repr(key), token) mydict.append(entry) return token def parse_recurse_dict(stack, next, token, result): arrayindent = stack[-1][4] while 1: thisindent = token[4] if thisindent != arrayindent: if thisindent < arrayindent: return result.get_result(token), token bad_unindent(token, next) key = rson_key_dispatch(token[1], bad_top_value)(token, next) stack[-1] = token token = parse_one_dict_entry(stack, next, next(), [key], result) def parse_recurse(stack, next, tokens=None): """parse_recurse ALWAYS returns a list or a dict. (or the user variants thereof) It is up to the caller to determine that it was an array of length 1 and strip the contents out of the array. """ firsttok = stack[-1] value = rson_value_dispatch(firsttok[1], bad_top_value)(firsttok, next) # We return an array if the next value is on a new line and either # is at the same indentation, or the current value is an empty list token = next() if ( token[5] != firsttok[5] and (token[4] <= firsttok[4] or value in empties) and disallow_missing_object_keys ): result = new_array([value], firsttok) if tokens is not None: tokens.top_object = result return parse_recurse_array(stack, next, token, result) # Otherwise, return a dict result = new_object() if tokens is not None: tokens.top_object = result token = parse_one_dict_entry(stack, next, token, [value], result) return parse_recurse_dict(stack, next, token, result) def parse(source): tokens = tokenizer(source, None) tokens.stringcache = {}.setdefault tokens.client_info = client_info next = tokens.next value, token = parse_recurse([next()], next, tokens) if token[1] != '@': error('Unexpected additional data', token) # If it's a single item and we don't have a specialized # object builder, just strip the outer list. if ( len(value) == 1 and isinstance(value, list) and disallow_missing_object_keys ): value = value[0] return post_parse(tokens, value) client_info = self.client_info(locals()) return parse class RsonSystem( RsonParser, UnquotedToken, QuotedToken, EqualToken, Dispatcher, BaseObjects ): Tokenizer = Tokenizer loads = RsonSystem.dispatcher_factory() rst2pdf-0.102/rst2pdf/sectnumlinks.py000066400000000000000000000015551463013543400175660ustar00rootroot00000000000000import docutils class SectNumFolder(docutils.nodes.SparseNodeVisitor): def __init__(self, document): docutils.nodes.SparseNodeVisitor.__init__(self, document) self.sectnums = {} def visit_generated(self, node): for i in node.parent.parent['ids']: self.sectnums[i] = node.parent.astext().replace(u'\xa0\xa0\xa0', ' ') def unknown_visit(self, node): pass class SectRefExpander(docutils.nodes.SparseNodeVisitor): def __init__(self, document, sectnums): docutils.nodes.SparseNodeVisitor.__init__(self, document) self.sectnums = sectnums def visit_reference(self, node): if node.get('refid', None) in self.sectnums: node.children = [ docutils.nodes.Text('%s ' % self.sectnums[node.get('refid')]) ] def unknown_visit(self, node): pass rst2pdf-0.102/rst2pdf/sinker.py000066400000000000000000000017031463013543400163350ustar00rootroot00000000000000# -*- coding: utf-8 -*- from reportlab.platypus.flowables import _listWrapOn, _FUZZ, Flowable class Sinker(Flowable): """A flowable that always takes the rest of the frame. It then draws its contents (a list of sub-flowables) at the bottom of that space""" def __init__(self, content): self.content = content def wrap(self, aW, aH): self.width, self.height = _listWrapOn(self.content, aW, None) return self.width, aH def draw(self): canv = self.canv canv.saveState() x = canv._x y = canv._y y += self.height aW = self.width for c in self.content: w, h = c.wrapOn(canv, aW, 0xFFFFFFF) if (w < _FUZZ or h < _FUZZ) and not getattr(c, '_ZEROSIZE', None): continue y -= h canv.saveState() c.drawOn(canv, x, y, _sW=aW - w) canv.restoreState() canv.restoreState() rst2pdf-0.102/rst2pdf/sphinxnodes.py000066400000000000000000000167311463013543400174130ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms ''' This module contains sphinx-specific node handlers. An import of this module will apparently fail if sphinx.roles hasn't been imported. This module creates a sphinx-specific dispatch dictionary, which is kept separate from the regular one. When the SphinxHandler class is instantiated, the two dictionaries are combined into the instantiated object. ''' from copy import copy import docutils from reportlab.platypus import Paragraph, TableStyle import sphinx from .flowables import ( MySpacer, MyIndenter, DelayedTable, ) from .image import MyImage from .log import nodeid, log from .nodehandlers import NodeHandler, FontHandler, HandleEmphasis # ################# NodeHandler subclasses ################### class SphinxHandler(NodeHandler): sphinxmode = True dispatchdict = {} def __init__(self): """This is where the magic happens. Make a copy of the elements in the non-sphinx dispatch dictionary, setting sphinxmode on every element, and then overwrite that dictionary with any sphinx-specific handlers. """ mydict = {} for key, value in self._baseclass.dispatchdict.items(): value = copy(value) value.sphinxmode = True mydict[key] = value mydict.update(self.dispatchdict) self.dispatchdict = mydict class SphinxFont(SphinxHandler, FontHandler): pass class HandleSphinxDefaults( SphinxHandler, sphinx.addnodes.glossary, sphinx.addnodes.start_of_file, sphinx.addnodes.compact_paragraph, sphinx.addnodes.pending_xref, ): pass class SphinxListHandler(SphinxHandler): def get_text(self, client, node, replaceEnt): t = client.gather_pdftext(node) while t and t[0] in ', ': t = t[1:] return t class HandleSphinxDescAddname(SphinxFont, sphinx.addnodes.desc_addname): fontstyle = "descclassname" class HandleSphinxDescName(SphinxFont, sphinx.addnodes.desc_name): fontstyle = "descname" class HandleSphinxDescReturn(SphinxFont, sphinx.addnodes.desc_returns): def get_font_prefix(self, client, node, replaceEnt): return ' → ' + client.styleToFont("returns") class HandleSphinxDescType(SphinxFont, sphinx.addnodes.desc_type): fontstyle = "desctype" class HandleSphinxDescParamList(SphinxListHandler, sphinx.addnodes.desc_parameterlist): pre = ' (' post = ')' class HandleSphinxDescParam(SphinxFont, sphinx.addnodes.desc_parameter): fontstyle = "descparameter" def get_pre_post(self, client, node, replaceEnt): pre, post = FontHandler.get_pre_post(self, client, node, replaceEnt) if node.hasattr('noemph'): pre = ', ' + pre else: pre = ', ' + pre post += '' return pre, post class HandleSphinxDescOpt(SphinxListHandler, SphinxFont, sphinx.addnodes.desc_optional): fontstyle = "optional" def get_pre_post(self, client, node, replaceEnt): prepost = FontHandler.get_pre_post(self, client, node, replaceEnt) return '%s[%s, ' % prepost, '%s]%s' % prepost class HandleDescAnnotation( SphinxHandler, HandleEmphasis, sphinx.addnodes.desc_annotation ): pass class HandleSphinxIndex(SphinxHandler, sphinx.addnodes.index): def gather_elements(self, client, node, style): try: for entry in node['entries']: client.pending_targets.append(docutils.nodes.make_id(entry[2])) except IndexError: if node['entries']: log.error( "Can't process index entry: %s [%s]", node['entries'], nodeid(node), ) return [] # custom SPHINX nodes. # FIXME: make sure they are all here, and keep them all together class HandleSphinxCentered(SphinxHandler, sphinx.addnodes.centered): def gather_elements(self, client, node, style): return [Paragraph(client.gather_pdftext(node), client.styles['centered'])] class HandleSphinxDesc(SphinxHandler, sphinx.addnodes.desc): def gather_elements(self, client, node, style): # Most node['desctype'] do not have a style attached and the default of "normal" # is acceptable, so suppress the warning as it's irrelevant in this situation client.styles.suppress_undefined_style_warning = True st = client.styles[node['desctype']] client.styles.suppress_undefined_style_warning = False if st == client.styles['normal']: st = copy(client.styles['desc']) st.spaceBefore = 0 pre = [MySpacer(0, client.styles['desc'].spaceBefore)] return pre + client.gather_elements(node, st) class HandleSphinxDescSignature(SphinxHandler, sphinx.addnodes.desc_signature): def gather_elements(self, client, node, style): # Need to add ids as targets, found this when using one of the # django docs extensions targets = [i.replace(' ', '') for i in node['ids']] pre = '' for i in targets: if i not in client.targets: pre += '' % i client.targets.append(i) return [Paragraph(pre + client.gather_pdftext(node), style)] class HandleSphinxDescSignatureLine(SphinxHandler, sphinx.addnodes.desc_signature_line): def gather_elements(self, client, node, style): pass class HandleSphinxDescContent(SphinxHandler, sphinx.addnodes.desc_content): def gather_elements(self, client, node, style): return ( [MyIndenter(left=10)] + client.gather_elements(node, client.styles["definition"]) + [MyIndenter(left=-10)] ) class HandleHList(SphinxHandler, sphinx.addnodes.hlist): def gather_elements(self, client, node, style): # Each child is a hlistcol and represents a column. # Each grandchild is a bullet list that's the contents # of the column # Represent it as a N-column, 1-row table, each cell containing # a list. cells = [[client.gather_elements(child, style) for child in node.children]] t_style = TableStyle(client.styles['hlist'].commands) cw = 100.0 / len(node.children) return [ DelayedTable(cells, colWidths=['%s%%' % cw] * len(cells), style=t_style) ] class HandleHighlightLang(SphinxHandler, sphinx.addnodes.highlightlang): pass try: x = sphinx.ext.graphviz.graphviz class HandleSphinxGraphviz(SphinxHandler, sphinx.ext.graphviz.graphviz): def gather_elements(self, client, node, style): # Based on the graphviz extension try: # Use bitmap fname, outfn = sphinx.ext.graphviz.render_dot( node['builder'], node['code'], node['options'], 'png' ) if outfn: client.to_unlink.append(outfn) client.to_unlink.append(outfn + '.map') else: # Something went very wrong with graphviz, and # sphinx should have given an error already return [] except sphinx.ext.graphviz.GraphvizError as exc: log.error('dot code %r: ' % node['code'] + str(exc)) return [Paragraph(node['code'], client.styles['code'])] return [MyImage(filename=outfn, client=client)] except AttributeError: # Probably the graphviz extension is not enabled pass sphinxhandlers = SphinxHandler() rst2pdf-0.102/rst2pdf/style2yaml.py000077500000000000000000000035701463013543400171560ustar00rootroot00000000000000#!/usr/bin/env python3 # SPDX-License-Identifier: MIT """Convert older RSON stylesheets to YAML format Run the script with this list of filenames to convert. It outputs to stdout, or use the --save3 flag to have it create .yaml files """ import argparse import json import os import yaml from rst2pdf.dumpstyle import fixstyle from rst2pdf.rson import loads as rloads def main(): # set up the command, optional --save parameter, and a list of paths parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, ) parser.add_argument( '--save', action='store_true', help='Save .yaml version of the file (rather than output to stdout)', ) parser.add_argument( 'paths', metavar='PATH', nargs='+', help='An RSON-formatted file to convert.', ) args = parser.parse_args() # loop over the files for path in args.paths: # read rson from a file with open(path, 'rb') as fh: style_data = fixstyle(rloads(fh.read())) # output the style as json (already supported), then parse that json_style = json.dumps(style_data) reparsed_style = json.loads(json_style) yaml_style = yaml.dump(reparsed_style, default_flow_style=None) # output the yaml or save to a file if args.save: new_path = '.'.join((os.path.splitext(path)[0], 'yaml')) if os.path.exists(new_path): print("File " + new_path + " exists, cannot overwrite") else: print("Creating file " + new_path) with open(new_path, 'w') as file: file.write(yaml_style) else: print("# " + os.path.splitext(path)[0]) print("---") print(yaml_style) if __name__ == '__main__': main() rst2pdf-0.102/rst2pdf/styles.py000066400000000000000000001060601463013543400163670ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms from copy import copy import os import os.path import sys import re import docutils.nodes import reportlab import reportlab.lib.colors as colors from reportlab.lib.fonts import addMapping import reportlab.lib.pagesizes as pagesizes from reportlab.lib.styles import StyleSheet1, ParagraphStyle import reportlab.lib.units as units from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase import pdfmetrics import reportlab.rl_config import yaml from . import findfonts from .log import log from .rson import loads as rson_loads unit_separator = re.compile('(-?[0-9.]*)') class StyleSheet(object): """Class to handle a collection of stylesheets""" @staticmethod def stylepairs(data): """Allows pairs of style information to be expressed in canonical reportlab list of two-item list/tuple, or in a more human-readable dictionary. """ styles = data.get('styles', {}) try: stylenames = list(styles.keys()) except AttributeError: for style in styles: yield style return # Traditional reportlab styles are in ordered (key, value) # tuples. We also support dictionary lookup. This is not # necessarily ordered. # The only problem with dictionary lookup is that # we need to insure that parents are processed before # their children. This loop is a little ugly, but # gets the job done. while stylenames: name = stylenames.pop() parent = styles[name].get('parent') if parent not in stylenames: yield name, styles[name] continue names = [name] while parent in stylenames: stylenames.remove(parent) names.append(parent) parent = styles[names[-1]].get('parent') while names: name = names.pop() yield name, styles[name] def __init__( self, flist, font_path=None, style_path=None, def_dpi=300, record_dependencies=None, ): log.info('Using stylesheets: %s' % ','.join(flist)) self.suppress_undefined_style_warning = False # find base path if hasattr(sys, 'frozen'): self.PATH = os.path.abspath(os.path.dirname(sys.executable)) else: self.PATH = os.path.abspath(os.path.dirname(__file__)) # flist is a list of stylesheet filenames. # They will be loaded and merged in order. # but the two default stylesheets will always # be loaded first flist = [ os.path.join(self.PATH, 'styles', 'styles.yaml'), os.path.join(self.PATH, 'styles', 'default.yaml'), ] + flist self.def_dpi = def_dpi if font_path is None: font_path = [] font_path += ['.', os.path.join(self.PATH, 'fonts')] self.FontSearchPath = list(map(os.path.expanduser, font_path)) if style_path is None: style_path = [] style_path += [ '.', os.path.join(self.PATH, 'styles'), '~/.rst2pdf/styles', ] self.StyleSearchPath = list(map(os.path.expanduser, style_path)) # Remove duplicates but preserve order. Not very efficient, but these are short lists self.FontSearchPath = [ x for (i, x) in enumerate(self.FontSearchPath) if self.FontSearchPath.index(x) == i ] self.StyleSearchPath = [ x for (i, x) in enumerate(self.StyleSearchPath) if self.StyleSearchPath.index(x) == i ] log.info('FontPath:%s' % self.FontSearchPath) log.info('StylePath:%s' % self.StyleSearchPath) findfonts.flist = self.FontSearchPath # Page width, height self.pw = 0 self.ph = 0 # Page size [w,h] self.ps = None # Margins (top,bottom,left,right,gutter) self.tm = 0 self.bm = 0 self.lm = 0 self.rm = 0 self.gm = 0 # text width self.tw = 0 # Default emsize, later it will be the fontSize of the base style self.emsize = 10 self.languages = [] self.record_dependencies = record_dependencies ssdata = self.readSheets(flist) # Get pageSetup data from all stylessheets in order: self.ps = pagesizes.A4 self.page = {} for data, ssname in ssdata: page = data.get('pageSetup', {}) if page: self.page.update(page) pgs = page.get('size', None) if pgs: # A standard size pgs = pgs.upper() if pgs in pagesizes.__dict__: self.ps = list(pagesizes.__dict__[pgs]) self.psname = pgs if 'width' in self.page: del self.page['width'] if 'height' in self.page: del self.page['height'] elif pgs.endswith('-LANDSCAPE'): self.psname = pgs.split('-')[0] self.ps = list( pagesizes.landscape(pagesizes.__dict__[self.psname]) ) if 'width' in self.page: del self.page['width'] if 'height' in self.page: del self.page['height'] else: log.critical( 'Unknown page size %s in stylesheet %s' % (page['size'], ssname) ) continue else: # A custom size if 'size' in self.page: del self.page['size'] # The sizes are expressed in some unit. # For example, 2cm is 2 centimeters, and we need # to do 2*cm (cm comes from reportlab.lib.units) if 'width' in page: self.ps[0] = self.adjustUnits(page['width']) if 'height' in page: self.ps[1] = self.adjustUnits(page['height']) self.pw, self.ph = self.ps if 'margin-left' in page: self.lm = self.adjustUnits(page['margin-left']) if 'margin-right' in page: self.rm = self.adjustUnits(page['margin-right']) if 'margin-top' in page: self.tm = self.adjustUnits(page['margin-top']) if 'margin-bottom' in page: self.bm = self.adjustUnits(page['margin-bottom']) if 'margin-gutter' in page: self.gm = self.adjustUnits(page['margin-gutter']) if 'spacing-header' in page: self.ts = self.adjustUnits(page['spacing-header']) if 'spacing-footer' in page: self.bs = self.adjustUnits(page['spacing-footer']) if 'firstTemplate' in page: self.firstTemplate = page['firstTemplate'] # tw is the text width. # We need it to calculate header-footer height # and compress literal blocks. self.tw = self.pw - self.lm - self.rm - self.gm # Get page templates from all stylesheets self.pageTemplates = {} for data, ssname in ssdata: templates = data.get('pageTemplates', {}) # templates is a dictionary of pageTemplates for key in templates: template = templates[key] # template is a dict. # template[´frames'] is a list of frames if key in self.pageTemplates: self.pageTemplates[key].update(template) else: self.pageTemplates[key] = template # Get font aliases from all stylesheets in order self.fontsAlias = {} for data, ssname in ssdata: self.fontsAlias.update(data.get('fontsAlias', {})) embedded_fontnames = [] self.embedded = [] # Embed all fonts indicated in all stylesheets for data, ssname in ssdata: embedded = data.get('embeddedFonts', []) for font in embedded: try: # (removed the feature that supported a string here, this isn't # documented or supported) # Each "font" is a list of four files, which will be # used for regular / bold / italic / bold+italic # versions of the font. # If your font doesn't have one of them, just repeat # the regular font. # Example, using the Tuffy font from # http://tulrich.com/fonts/ # "embeddedFonts" : [ # ["Tuffy.ttf", # "Tuffy_Bold.ttf", # "Tuffy_Italic.ttf", # "Tuffy_Bold_Italic.ttf"] # ], # The fonts will be registered with the file name, # minus the extension. if font[0].lower().endswith('.ttf'): # A True Type font for variant in font: location = self.findFont(variant) # strip extension and leading path to get the name # to register the font under filename = os.path.basename(variant) if self.record_dependencies: self.record_dependencies.add(filename) fontname = str(filename.split('.')[0]) pdfmetrics.registerFont(TTFont(fontname, location)) log.info( 'Registering font: %s from %s' % (fontname, location) ) self.embedded.append(fontname) # And map them all together regular, bold, italic, bolditalic = [ variant.split('.')[0] for variant in font ] addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) else: # A Type 1 font # For type 1 fonts we require # [FontName,regular,italic,bold,bolditalic] # where each variant is a (pfbfile,afmfile) pair. # For example, for the URW palladio from TeX: # ["Palatino",("uplr8a.pfb","uplr8a.afm"), # ("uplri8a.pfb","uplri8a.afm"), # ("uplb8a.pfb","uplb8a.afm"), # ("uplbi8a.pfb","uplbi8a.afm")] regular = pdfmetrics.EmbeddedType1Face(*font[1]) italic = pdfmetrics.EmbeddedType1Face(*font[2]) bold = pdfmetrics.EmbeddedType1Face(*font[3]) bolditalic = pdfmetrics.EmbeddedType1Face(*font[4]) except Exception as e: try: if isinstance(font, list): fname = font[0] else: fname = font log.critical( "Error processing font %s: %s", os.path.splitext(fname)[0], str(e), ) sys.exit(1) except Exception as e: log.critical("Error processing font %s: %s", fname, str(e)) sys.exit(1) # Go though all styles in all stylesheets and find all fontNames. # Then decide what to do with them for data, ssname in ssdata: for [skey, style] in self.stylepairs(data): for key in style: if key == 'fontName' or key.endswith('FontName'): # It's an alias, replace it if style[key] in self.fontsAlias: style[key] = self.fontsAlias[style[key]] # Embedded already, nothing to do if style[key] in self.embedded: continue # Standard font, nothing to do if style[key] in ( "Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique", "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique", "Symbol", "Times-Bold", "Times-BoldItalic", "Times-Italic", "Times-Roman", "ZapfDingbats", ): continue # Now we need to do something # See if we can find the font fname, pos = findfonts.guessFont(style[key]) fontList = findfonts.autoEmbed(style[key]) if style[key] not in embedded_fontnames and fontList: embedded_fontnames.append(style[key]) if not fontList: if (fname, pos) in embedded_fontnames: fontList = None else: fontList = findfonts.autoEmbed(fname) if fontList: embedded_fontnames.append((fname, pos)) if fontList: self.embedded += fontList # Maybe the font we got is not called # the same as the one we gave so check that out suff = ["", "-Bold", "-Oblique", "-BoldOblique"] if not fontList[0].startswith(style[key]): # We need to create font aliases, and use them basefname = style[key].split('-')[0] for fname, aliasname in zip( fontList, [basefname + suffix for suffix in suff], ): self.fontsAlias[aliasname] = fname style[key] = self.fontsAlias[basefname + suff[pos]] else: log.error( "Unknown font: \"%s\"," "replacing with Helvetica", style[key], ) style[key] = "Helvetica" # Get styles from all stylesheets in order self.stylesheet = {} self.styles = [] self.linkColor = 'navy' # FIXME: linkColor should probably not be a global # style, and tocColor should probably not # be a special case, but for now I'm going # with the flow... self.tocColor = None for data, ssname in ssdata: self.linkColor = data.get('linkColor') or self.linkColor self.tocColor = data.get('tocColor') or self.tocColor for [skey, style] in self.stylepairs(data): sdict = {} # FIXME: this is done completely backwards for key in style: # Handle color references by name if key == 'color' or key.endswith('Color') and style[key]: style[key] = formatColor(style[key]) elif key == 'commands': style[key] = validateCommands(style[key]) # Handle alignment constants elif key == 'alignment': style[key] = dict( TA_LEFT=0, LEFT=0, TA_CENTER=1, CENTER=1, TA_CENTRE=1, CENTRE=1, TA_RIGHT=2, RIGHT=2, TA_JUSTIFY=4, JUSTIFY=4, DECIMAL=8, )[style[key].upper()] elif key == 'language': if not style[key] in self.languages: self.languages.append(style[key]) sdict[key] = style[key] sdict['name'] = skey # If the style already exists, update it if skey in self.stylesheet: self.stylesheet[skey].update(sdict) else: # New style self.stylesheet[skey] = sdict self.styles.append(sdict) # If the stylesheet has a style name docutils won't reach # make a copy with a sanitized name. # This may make name collisions possible but that should be # rare (who would have custom_name and custom-name in the # same stylesheet? ;-) # Issue 339 styles2 = [] for s in self.styles: if not re.match("^[a-z](-?[a-z0-9]+)*$", s['name']): s2 = copy(s) s2['name'] = docutils.nodes.make_id(s['name']) log.warning( '%s is an invalid docutils class name, adding alias %s' % (s['name'], s2['name']) ) styles2.append(s2) self.styles.extend(styles2) # And create reportlabs stylesheet self.StyleSheet = StyleSheet1() dirty = True while dirty: dirty = False for s in self.styles: if s['name'] in self.StyleSheet: continue try: if 'parent' in s: if s['parent'] is None: if s['name'] != 'base': s['parent'] = self.StyleSheet['base'] else: del s['parent'] else: s['parent'] = self.StyleSheet[s['parent']] else: if s['name'] != 'base': s['parent'] = self.StyleSheet['base'] except KeyError: dirty = True continue # If the style has no bulletFontName but it has a fontName, set it if ('bulletFontName' not in s) and ('fontName' in s): s['bulletFontName'] = s['fontName'] hasFS = True # Adjust fontsize units if 'fontSize' not in s: s['fontSize'] = s['parent'].fontSize s['trueFontSize'] = None hasFS = False elif 'parent' in s: # This means you can set the fontSize to # "2cm" or to "150%" which will be calculated # relative to the parent style s['fontSize'] = self.adjustUnits( s['fontSize'], s['parent'].fontSize ) s['trueFontSize'] = s['fontSize'] else: # If s has no parent, it's base, which has # an explicit point size by default and % # makes no sense, but guess it as % of 10pt s['fontSize'] = self.adjustUnits(s['fontSize'], 10) # If the leading is not set, but the size is, set it if 'leading' not in s and hasFS: s['leading'] = 1.2 * s['fontSize'] # If the bullet font size is not set, set it as fontSize if ('bulletFontSize' not in s) and ('fontSize' in s): s['bulletFontSize'] = s['fontSize'] if 'spaceBefore' in s: if isinstance(s['spaceBefore'], str) and s[ 'spaceBefore' ].startswith('-'): log.warning('A negative spaceBefore is the same as 0') s['spaceBefore'] = self.adjustUnits(s['spaceBefore']) if 'spaceAfter' in s: if isinstance(s['spaceAfter'], str) and s['spaceAfter'].startswith( '-' ): log.warning('A negative spaceAfter is the same as 0') s['spaceAfter'] = self.adjustUnits(s['spaceAfter']) self.StyleSheet.add(ParagraphStyle(**s)) self.emsize = self['base'].fontSize # Set the basefont, for Issue 65 reportlab.rl_config.canvas_basefontname = self['base'].fontName # Set a default font for table cell styles (Issue 65) reportlab.platypus.tables.CellStyle.fontname = self['base'].fontName def __getitem__(self, key): # This 'normalizes' the key. # For example, if the key is todo_node (like sphinx uses), it will be # converted to 'todo-node' which is a valid docutils class name. if not re.match("^[a-z](-?[a-z0-9]+)*$", key): key = docutils.nodes.make_id(key) if key in self.StyleSheet: return self.StyleSheet[key] else: # Sphinx 4 doesn't prepend "pygments-" to its style names when using pygments, # so look to see if we have a pygemts style for this style name pygments_key = "pygments-" + key if pygments_key in self.StyleSheet: return self.StyleSheet[pygments_key] else: if key.startswith('pygments'): if not self.suppress_undefined_style_warning: log.info( "Using undefined style '%s'" ", aliased to style 'code'." % key ) newst = copy(self.StyleSheet['code']) else: if not self.suppress_undefined_style_warning: log.warning( "Using undefined style '%s'" ", aliased to style 'normal'." % key ) newst = copy(self.StyleSheet['normal']) newst.name = key self.StyleSheet.add(newst) return newst def readSheets(self, flist): """Read in the stylesheets. Return a list of (sheetdata, sheetname) tuples. Orders included sheets in front of including sheets. """ # Process from end of flist flist.reverse() # Keep previously seen sheets in sheetdict sheetdict = {} result = [] while flist: ssname = flist.pop() data = sheetdict.get(ssname) if data is None: data = self.readStyle(ssname) if data is None: continue sheetdict[ssname] = data if 'options' in data and 'stylesheets' in data['options']: flist.append(ssname) newsheets = list(data['options']['stylesheets']) newsheets.reverse() flist.extend(newsheets) continue result.append((data, ssname)) return result def readStyle(self, ssname): # If callables are used, they should probably be subclassed # strings, or something else that will print nicely for errors if callable(ssname): return ssname() fname = self.findStyle(ssname) if fname: if self.record_dependencies: self.record_dependencies.add(fname) try: # TODO no longer needed when we drop support for rson # Is it an older rson/json stylesheet with .style extension? root_ext = os.path.splitext(fname) if root_ext[1] == ".style": log.warning( 'Stylesheet "%s" in outdated format, recommend converting to YAML' % (fname) ) return rson_loads(open(fname).read()) # Otherwise assume yaml/yml return yaml.safe_load(open(fname).read()) except ValueError as e: # Error parsing the JSON data log.critical('Error parsing stylesheet "%s": %s' % (fname, str(e))) except IOError as e: # Error opening the ssheet log.critical('Error opening stylesheet "%s": %s' % (fname, str(e))) def findStyle(self, fn): """Find the absolute file name for a given style filename. Given a style filename, searches for it in StyleSearchPath and returns the real file name. """ def innerFind(path, fn): if os.path.isabs(fn): if os.path.isfile(fn): return fn else: for D in path: tfn = os.path.join(D, fn) if os.path.isfile(tfn): return tfn return None for ext in ['', '.yaml', '.yml', '.style', '.json']: result = innerFind(self.StyleSearchPath, fn + ext) if result: break if result is None: log.warning("Can't find stylesheet %s" % fn) return result def findFont(self, fn): """Find the absolute font name for a given font filename. Given a font filename, searches for it in FontSearchPath and returns the real file name. """ if not os.path.isabs(fn): for D in self.FontSearchPath: tfn = os.path.join(D, fn) if os.path.isfile(tfn): return str(tfn) return str(fn) def styleForNode(self, node): """Return the right default style for any kind of node. That usually means "bodytext", but for sidebars, for example, it's sidebar. """ n = docutils.nodes styles = { n.sidebar: 'sidebar', n.figure: 'figure', n.tgroup: 'table', n.table: 'table', n.Admonition: 'admonition', } return self[styles.get(node.__class__, 'bodytext')] def tstyleHead(self, rows=1): """Return a table style spec for a table header of `rows`. The style will be based on the table-heading style from the stylesheet. """ # This alignment thing is exactly backwards from # the alignment for paragraphstyles alignment = {0: 'LEFT', 1: 'CENTER', 2: 'RIGHT', 4: 'JUSTIFY', 8: 'DECIMAL'}[ self['table-heading'].alignment ] return [ ( 'BACKGROUND', (0, 0), (-1, rows - 1), self['table-heading'].backColor, ), ('ALIGN', (0, 0), (-1, rows - 1), alignment), ( 'TEXTCOLOR', (0, 0), (-1, rows - 1), self['table-heading'].textColor, ), ( 'FONT', (0, 0), (-1, rows - 1), self['table-heading'].fontName, self['table-heading'].fontSize, self['table-heading'].leading, ), ('VALIGN', (0, 0), (-1, rows - 1), self['table-heading'].valign), ] def adjustUnits(self, v, total=None, default_unit='pt'): if total is None: total = self.tw return adjustUnits(v, total, self.def_dpi, default_unit, emsize=self.emsize) def combinedStyle(self, styles): """Given a list of style names, it merges them (the existing ones) and returns a new style. The styles that don't exist are silently ignored. For example, if called with styles=['style1','style2'] the returned style will be called 'merged_style1_style2'. The styles that are *later* in the list will have priority. """ validst = [x for x in styles if x in self.StyleSheet] newname = '_'.join(['merged'] + validst) validst = [self[x] for x in validst] newst = copy(validst[0]) for st in validst[1:]: newst.__dict__.update(st.__dict__) newst.name = newname return newst def adjustUnits(v, total=None, dpi=300, default_unit='pt', emsize=10): """Takes something like 2cm and returns 2*cm. If you use % as a unit, it returns the percentage of "total". If total is not given, returns a percentage of the page width. However, if you get to that stage, you are doing it wrong. Example:: >>> adjustUnits('50%',200) 100 """ if v is None or v == "": return None v = str(v) length = re.split(r'(-?[0-9.]+)', v) n = length[1] u = default_unit if len(length) == 3 and length[2]: u = length[2] if u in units.__dict__: return float(n) * units.__dict__[u] else: if u == '%': return float(n) * total / 100 elif u == 'px': return float(n) * units.inch / dpi elif u == 'pt': return float(n) elif u == 'in': return float(n) * units.inch elif u == 'em': return float(n) * emsize elif u == 'ex': return float(n) * emsize / 2 elif u == 'pc': # picas! return float(n) * 12 log.error('Unknown unit "%s"' % u) return float(n) def formatColor(value, numeric=True): """Convert a color like "gray" or "0xf" or "ffff" to something ReportLab will like.""" if value in colors.__dict__: return colors.__dict__[value] else: # Hopefully, a hex color: c = value.strip() if c[0] == '#': c = c[1:] while len(c) < 6: c = '0' + c if numeric: r = int(c[:2], 16) / 255.0 g = int(c[2:4], 16) / 255.0 b = int(c[4:6], 16) / 255.0 if len(c) >= 8: alpha = int(c[6:8], 16) / 255.0 return colors.Color(r, g, b, alpha=alpha) return colors.Color(r, g, b) else: return str("#" + c) # The values are: # * Minimum number of arguments # * Maximum number of arguments # * Valid types of arguments. # # For example, if option FOO takes a list a string and a number, # but the number is optional: # # "FOO":(2,3,"list","string","number") # # The reportlab command could look like # # ["FOO",(0,0),(-1,-1),[1,2],"whatever",4] # # THe (0,0) (-1,-1) are start and stop and are mandatory. # # Possible types of arguments are string, number, color, colorlist validCommands = { # Cell format commands "FONT": (1, 3, "string", "number", "number"), "FONTNAME": (1, 1, "string"), "FACE": (1, 1, "string"), "FONTSIZE": (1, 1, "number"), "SIZE": (1, 1, "number"), "LEADING": (1, 1, "number"), "TEXTCOLOR": (1, 1, "color"), "ALIGNMENT": (1, 1, "string"), "ALIGN": (1, 1, "string"), "LEFTPADDING": (1, 1, "number"), "RIGHTPADDING": (1, 1, "number"), "TOPPADDING": (1, 1, "number"), "BOTTOMPADDING": (1, 1, "number"), "BACKGROUND": (1, 1, "color"), "ROWBACKGROUNDS": (1, 1, "colorlist"), "COLBACKGROUNDS": (1, 1, "colorlist"), "VALIGN": (1, 1, "string"), # Line commands "GRID": (2, 2, "number", "color"), "BOX": (2, 2, "number", "color"), "OUTLINE": (2, 2, "number", "color"), "INNERGRID": (2, 2, "number", "color"), "LINEBELOW": (2, 2, "number", "color"), "LINEABOVE": (2, 2, "number", "color"), "LINEBEFORE": (2, 2, "number", "color"), "LINEAFTER": (2, 2, "number", "color"), # You should NOT have span commands, man! # "SPAN":(,,), } def validateCommands(commands): """Given a list of reportlab's table commands, it fixes some common errors and/or removes commands that can't be fixed""" fixed = [] for command in commands: command[0] = command[0].upper() flag = False # See if the command is valid if command[0] not in validCommands: log.error('Unknown table command %s in stylesheet', command[0]) continue # See if start and stop are the right types if not isinstance(command[1], (list, tuple)): log.error( 'Start cell in table command should be list or tuple, got %s [%s]', type(command[1]), command[1], ) flag = True if not isinstance(command[2], (list, tuple)): log.error( 'Stop cell in table command should be list or tuple, got %s [%s]', type(command[1]), command[1], ) flag = True # See if the number of arguments is right length = len(command) - 3 if length > validCommands[command[0]][1]: log.error('Too many arguments in table command: %s', command) flag = True if length < validCommands[command[0]][0]: log.error('Too few arguments in table command: %s', command) flag = True # Validate argument types for pos, arg in enumerate(command[3:]): typ = validCommands[command[0]][pos + 2] if typ == "color": # Convert all 'string' colors to numeric command[3 + pos] = formatColor(arg) elif typ == "colorlist": command[3 + pos] = [formatColor(c) for c in arg] elif typ == "number": pass elif typ == "string": command[3 + pos] = arg else: log.error("This should never happen: wrong type %s", typ) if not flag: fixed.append(command) return fixed class CallableStyleSheet(str): """Useful for programmatically generated stylesheets. A generated stylesheet is a callable string (name), which returns the pre-digested stylesheet data when called. """ def __new__(cls, name, value=''): self = str.__new__(cls, name) self.value = value return self def __call__(self): return rson_loads(self.value) rst2pdf-0.102/rst2pdf/styles/000077500000000000000000000000001463013543400160125ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/styles/11x17.yaml000066400000000000000000000000431463013543400174540ustar00rootroot00000000000000pageSetup: size: elevenseventeen rst2pdf-0.102/rst2pdf/styles/a0.yaml000066400000000000000000000000261463013543400171740ustar00rootroot00000000000000pageSetup: size: A0 rst2pdf-0.102/rst2pdf/styles/a1-landscape.yaml000066400000000000000000000000401463013543400211210ustar00rootroot00000000000000pageSetup: size: A1-landscape rst2pdf-0.102/rst2pdf/styles/a1.yaml000066400000000000000000000000261463013543400171750ustar00rootroot00000000000000pageSetup: size: A1 rst2pdf-0.102/rst2pdf/styles/a2-landscape.yaml000066400000000000000000000000401463013543400211220ustar00rootroot00000000000000pageSetup: size: A2-landscape rst2pdf-0.102/rst2pdf/styles/a2.yaml000066400000000000000000000000261463013543400171760ustar00rootroot00000000000000pageSetup: size: A2 rst2pdf-0.102/rst2pdf/styles/a3-landscape.yaml000066400000000000000000000000401463013543400211230ustar00rootroot00000000000000pageSetup: size: A3-landscape rst2pdf-0.102/rst2pdf/styles/a3.yaml000066400000000000000000000000261463013543400171770ustar00rootroot00000000000000pageSetup: size: A3 rst2pdf-0.102/rst2pdf/styles/a4-landscape.yaml000066400000000000000000000000401463013543400211240ustar00rootroot00000000000000pageSetup: size: A4-landscape rst2pdf-0.102/rst2pdf/styles/a4.yaml000066400000000000000000000000261463013543400172000ustar00rootroot00000000000000pageSetup: size: A4 rst2pdf-0.102/rst2pdf/styles/a5-landscape.yaml000066400000000000000000000000401463013543400211250ustar00rootroot00000000000000pageSetup: size: A5-landscape rst2pdf-0.102/rst2pdf/styles/a5.yaml000066400000000000000000000000261463013543400172010ustar00rootroot00000000000000pageSetup: size: A5 rst2pdf-0.102/rst2pdf/styles/a6-landscape.yaml000066400000000000000000000000401463013543400211260ustar00rootroot00000000000000pageSetup: size: A6-landscape rst2pdf-0.102/rst2pdf/styles/a6.yaml000066400000000000000000000000261463013543400172020ustar00rootroot00000000000000pageSetup: size: A6 rst2pdf-0.102/rst2pdf/styles/abap.yaml000066400000000000000000000106761463013543400176130ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#000000' pygments-c: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cp: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-dl: parent: code textColor: '#55aa22' pygments-err: parent: code textColor: '#FF0000' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#000000' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#33aaff' pygments-k: parent: code textColor: '#0000ff' pygments-kc: parent: code textColor: '#0000ff' pygments-kd: parent: code textColor: '#0000ff' pygments-kn: parent: code textColor: '#0000ff' pygments-kp: parent: code textColor: '#0000ff' pygments-kr: parent: code textColor: '#0000ff' pygments-kt: parent: code textColor: '#0000ff' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#33aaff' pygments-mb: parent: code textColor: '#33aaff' pygments-mf: parent: code textColor: '#33aaff' pygments-mh: parent: code textColor: '#33aaff' pygments-mi: parent: code textColor: '#33aaff' pygments-mo: parent: code textColor: '#33aaff' pygments-n: parent: code textColor: '#000000' pygments-na: parent: code textColor: '#000000' pygments-nb: parent: code textColor: '#000000' pygments-nc: parent: code textColor: '#000000' pygments-nd: parent: code textColor: '#000000' pygments-ne: parent: code textColor: '#000000' pygments-nf: parent: code textColor: '#000000' pygments-ni: parent: code textColor: '#000000' pygments-nl: parent: code textColor: '#000000' pygments-nn: parent: code textColor: '#000000' pygments-no: parent: code textColor: '#000000' pygments-nt: parent: code textColor: '#000000' pygments-nv: parent: code textColor: '#000000' pygments-nx: parent: code textColor: '#000000' pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: '#0000ff' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: '#000000' pygments-s: parent: code textColor: '#55aa22' pygments-s1: parent: code textColor: '#55aa22' pygments-s2: parent: code textColor: '#55aa22' pygments-sa: parent: code textColor: '#55aa22' pygments-sb: parent: code textColor: '#55aa22' pygments-sc: parent: code textColor: '#55aa22' pygments-sd: parent: code textColor: '#55aa22' pygments-se: parent: code textColor: '#55aa22' pygments-sh: parent: code textColor: '#55aa22' pygments-si: parent: code textColor: '#55aa22' pygments-sr: parent: code textColor: '#55aa22' pygments-ss: parent: code textColor: '#55aa22' pygments-sx: parent: code textColor: '#55aa22' pygments-vc: parent: code textColor: '#000000' pygments-vg: parent: code textColor: '#000000' pygments-vi: parent: code textColor: '#000000' pygments-vm: parent: code textColor: '#000000' pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/algol.yaml000066400000000000000000000124321463013543400177760ustar00rootroot00000000000000styles: pygments-bp: fontName: fontMonoItalic parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cp: fontName: fontMonoBold parent: code textColor: '#888888' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cs: fontName: fontMonoBold parent: code textColor: '#888888' pygments-dl: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: black pygments-k: fontName: fontMonoBold parent: code textColor: black pygments-kc: fontName: fontMonoBold parent: code textColor: black pygments-kd: fontName: fontMonoItalic parent: code textColor: black pygments-kn: fontName: fontMonoBold parent: code textColor: black pygments-kp: fontName: fontMonoBold parent: code textColor: black pygments-kr: fontName: fontMonoBold parent: code textColor: black pygments-kt: fontName: fontMonoBold parent: code textColor: black pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: black pygments-mb: parent: code textColor: black pygments-mf: parent: code textColor: black pygments-mh: parent: code textColor: black pygments-mi: parent: code textColor: black pygments-mo: parent: code textColor: black pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: fontName: fontMonoItalic parent: code textColor: black pygments-nc: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-no: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-nt: parent: code textColor: black pygments-nv: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: fontName: fontMonoBold parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-s1: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-s2: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sa: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sb: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sc: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-se: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sh: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-si: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sr: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-ss: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sx: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vc: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vg: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vi: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vm: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/algol_nu.yaml000066400000000000000000000124321463013543400205000ustar00rootroot00000000000000styles: pygments-bp: fontName: fontMonoItalic parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cp: fontName: fontMonoBold parent: code textColor: '#888888' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cs: fontName: fontMonoBold parent: code textColor: '#888888' pygments-dl: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: black pygments-k: fontName: fontMonoBold parent: code textColor: black pygments-kc: fontName: fontMonoBold parent: code textColor: black pygments-kd: fontName: fontMonoItalic parent: code textColor: black pygments-kn: fontName: fontMonoBold parent: code textColor: black pygments-kp: fontName: fontMonoBold parent: code textColor: black pygments-kr: fontName: fontMonoBold parent: code textColor: black pygments-kt: fontName: fontMonoBold parent: code textColor: black pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: black pygments-mb: parent: code textColor: black pygments-mf: parent: code textColor: black pygments-mh: parent: code textColor: black pygments-mi: parent: code textColor: black pygments-mo: parent: code textColor: black pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: fontName: fontMonoItalic parent: code textColor: black pygments-nc: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-no: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-nt: parent: code textColor: black pygments-nv: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: fontName: fontMonoBold parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-s1: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-s2: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sa: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sb: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sc: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-se: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sh: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-si: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sr: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-ss: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-sx: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vc: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vg: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vi: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-vm: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/arduino.yaml000066400000000000000000000103671463013543400203460ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#728E00' pygments-c: parent: code textColor: '#95a5a6' pygments-c1: parent: code textColor: '#95a5a6' pygments-ch: parent: code textColor: '#95a5a6' pygments-cm: parent: code textColor: '#95a5a6' pygments-cp: parent: code textColor: '#728E00' pygments-cpf: parent: code textColor: '#95a5a6' pygments-cs: parent: code textColor: '#95a5a6' pygments-dl: parent: code textColor: '#7F8C8D' pygments-err: parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#D35400' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#8A7B52' pygments-k: parent: code textColor: '#728E00' pygments-kc: parent: code textColor: '#00979D' pygments-kd: parent: code textColor: '#728E00' pygments-kn: parent: code textColor: '#728E00' pygments-kp: parent: code textColor: '#00979D' pygments-kr: parent: code textColor: '#00979D' pygments-kt: parent: code textColor: '#00979D' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#8A7B52' pygments-mb: parent: code textColor: '#8A7B52' pygments-mf: parent: code textColor: '#8A7B52' pygments-mh: parent: code textColor: '#8A7B52' pygments-mi: parent: code textColor: '#8A7B52' pygments-mo: parent: code textColor: '#8A7B52' pygments-n: parent: code textColor: '#434f54' pygments-na: parent: code textColor: '#434f54' pygments-nb: parent: code textColor: '#728E00' pygments-nc: parent: code textColor: '#434f54' pygments-nd: parent: code textColor: '#434f54' pygments-ne: parent: code textColor: '#434f54' pygments-nf: parent: code textColor: '#D35400' pygments-ni: parent: code textColor: '#434f54' pygments-nl: parent: code textColor: '#434f54' pygments-nn: parent: code textColor: '#434f54' pygments-no: parent: code textColor: '#434f54' pygments-nt: parent: code textColor: '#434f54' pygments-nv: parent: code textColor: '#434f54' pygments-nx: parent: code textColor: '#728E00' pygments-o: parent: code textColor: '#728E00' pygments-ow: parent: code textColor: '#728E00' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: '#434f54' pygments-s: parent: code textColor: '#7F8C8D' pygments-s1: parent: code textColor: '#7F8C8D' pygments-s2: parent: code textColor: '#7F8C8D' pygments-sa: parent: code textColor: '#7F8C8D' pygments-sb: parent: code textColor: '#7F8C8D' pygments-sc: parent: code textColor: '#7F8C8D' pygments-sd: parent: code textColor: '#7F8C8D' pygments-se: parent: code textColor: '#7F8C8D' pygments-sh: parent: code textColor: '#7F8C8D' pygments-si: parent: code textColor: '#7F8C8D' pygments-sr: parent: code textColor: '#7F8C8D' pygments-ss: parent: code textColor: '#7F8C8D' pygments-sx: parent: code textColor: '#7F8C8D' pygments-vc: parent: code textColor: '#434f54' pygments-vg: parent: code textColor: '#434f54' pygments-vi: parent: code textColor: '#434f54' pygments-vm: parent: code textColor: '#434f54' pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/autumn.yaml000066400000000000000000000111561463013543400202130ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#00aaaa' pygments-c: fontName: fontMonoItalic parent: code textColor: '#aaaaaa' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#aaaaaa' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#aaaaaa' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#aaaaaa' pygments-cp: parent: code textColor: '#4c8317' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#aaaaaa' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#0000aa' pygments-dl: parent: code textColor: '#aa5500' pygments-err: backColor: '#FFAAAA' parent: code textColor: '#FF0000' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#00aa00' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#aa0000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00aa00' pygments-go: parent: code textColor: '#888888' pygments-gp: parent: code textColor: '#555555' pygments-gr: parent: code textColor: '#aa0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#aa0000' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#009999' pygments-k: parent: code textColor: '#0000aa' pygments-kc: parent: code textColor: '#0000aa' pygments-kd: parent: code textColor: '#0000aa' pygments-kn: parent: code textColor: '#0000aa' pygments-kp: parent: code textColor: '#0000aa' pygments-kr: parent: code textColor: '#0000aa' pygments-kt: parent: code textColor: '#00aaaa' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#009999' pygments-mb: parent: code textColor: '#009999' pygments-mf: parent: code textColor: '#009999' pygments-mh: parent: code textColor: '#009999' pygments-mi: parent: code textColor: '#009999' pygments-mo: parent: code textColor: '#009999' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#1e90ff' pygments-nb: parent: code textColor: '#00aaaa' pygments-nc: parent: code textColor: '#00aa00' pygments-nd: parent: code textColor: '#888888' pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: '#00aa00' pygments-ni: fontName: fontMonoBold parent: code textColor: '#880000' pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: '#00aaaa' pygments-no: parent: code textColor: '#aa0000' pygments-nt: fontName: fontMonoBold parent: code textColor: '#1e90ff' pygments-nv: parent: code textColor: '#aa0000' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: '#0000aa' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#aa5500' pygments-s1: parent: code textColor: '#aa5500' pygments-s2: parent: code textColor: '#aa5500' pygments-sa: parent: code textColor: '#aa5500' pygments-sb: parent: code textColor: '#aa5500' pygments-sc: parent: code textColor: '#aa5500' pygments-sd: parent: code textColor: '#aa5500' pygments-se: parent: code textColor: '#aa5500' pygments-sh: parent: code textColor: '#aa5500' pygments-si: parent: code textColor: '#aa5500' pygments-sr: parent: code textColor: '#009999' pygments-ss: parent: code textColor: '#0000aa' pygments-sx: parent: code textColor: '#aa5500' pygments-vc: parent: code textColor: '#aa0000' pygments-vg: parent: code textColor: '#aa0000' pygments-vi: parent: code textColor: '#aa0000' pygments-vm: parent: code textColor: '#aa0000' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/b0.yaml000066400000000000000000000000261463013543400171750ustar00rootroot00000000000000pageSetup: size: b0 rst2pdf-0.102/rst2pdf/styles/b1-landscape.yaml000066400000000000000000000000401463013543400211220ustar00rootroot00000000000000pageSetup: size: b1-landscape rst2pdf-0.102/rst2pdf/styles/b1.yaml000066400000000000000000000000261463013543400171760ustar00rootroot00000000000000pageSetup: size: b1 rst2pdf-0.102/rst2pdf/styles/b2-landscape.yaml000066400000000000000000000000401463013543400211230ustar00rootroot00000000000000pageSetup: size: b2-landscape rst2pdf-0.102/rst2pdf/styles/b2.yaml000066400000000000000000000000261463013543400171770ustar00rootroot00000000000000pageSetup: size: b2 rst2pdf-0.102/rst2pdf/styles/b3-landscape.yaml000066400000000000000000000000401463013543400211240ustar00rootroot00000000000000pageSetup: size: b3-landscape rst2pdf-0.102/rst2pdf/styles/b3.yaml000066400000000000000000000000261463013543400172000ustar00rootroot00000000000000pageSetup: size: b3 rst2pdf-0.102/rst2pdf/styles/b4-landscape.yaml000066400000000000000000000000401463013543400211250ustar00rootroot00000000000000pageSetup: size: b4-landscape rst2pdf-0.102/rst2pdf/styles/b4.yaml000066400000000000000000000000261463013543400172010ustar00rootroot00000000000000pageSetup: size: b4 rst2pdf-0.102/rst2pdf/styles/b5-landscape.yaml000066400000000000000000000000401463013543400211260ustar00rootroot00000000000000pageSetup: size: b5-landscape rst2pdf-0.102/rst2pdf/styles/b5.yaml000066400000000000000000000000261463013543400172020ustar00rootroot00000000000000pageSetup: size: b5 rst2pdf-0.102/rst2pdf/styles/b6-landscape.yaml000066400000000000000000000000401463013543400211270ustar00rootroot00000000000000pageSetup: size: b6-landscape rst2pdf-0.102/rst2pdf/styles/b6.yaml000066400000000000000000000000261463013543400172030ustar00rootroot00000000000000pageSetup: size: b6 rst2pdf-0.102/rst2pdf/styles/borland.yaml000066400000000000000000000113511463013543400203200ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cp: parent: code textColor: '#008080' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cs: fontName: fontMonoBold parent: code textColor: '#008800' pygments-dl: parent: code textColor: '#0000FF' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: black pygments-g: parent: code textColor: black pygments-gd: backColor: '#ffdddd' parent: code textColor: '#000000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: parent: code textColor: '#999999' pygments-gi: backColor: '#ddffdd' parent: code textColor: '#000000' pygments-go: parent: code textColor: '#888888' pygments-gp: parent: code textColor: '#555555' pygments-gr: parent: code textColor: '#aa0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#aa0000' pygments-gu: parent: code textColor: '#aaaaaa' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#0000FF' pygments-k: fontName: fontMonoBold parent: code textColor: '#000080' pygments-kc: fontName: fontMonoBold parent: code textColor: '#000080' pygments-kd: fontName: fontMonoBold parent: code textColor: '#000080' pygments-kn: fontName: fontMonoBold parent: code textColor: '#000080' pygments-kp: fontName: fontMonoBold parent: code textColor: '#000080' pygments-kr: fontName: fontMonoBold parent: code textColor: '#000080' pygments-kt: fontName: fontMonoBold parent: code textColor: '#000080' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#0000FF' pygments-mb: parent: code textColor: '#0000FF' pygments-mf: parent: code textColor: '#0000FF' pygments-mh: parent: code textColor: '#0000FF' pygments-mi: parent: code textColor: '#0000FF' pygments-mo: parent: code textColor: '#0000FF' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#FF0000' pygments-nb: parent: code textColor: black pygments-nc: parent: code textColor: black pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: black pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: fontName: fontMonoBold parent: code textColor: '#000080' pygments-nv: parent: code textColor: black pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: fontName: fontMonoBold parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#0000FF' pygments-s1: parent: code textColor: '#0000FF' pygments-s2: parent: code textColor: '#0000FF' pygments-sa: parent: code textColor: '#0000FF' pygments-sb: parent: code textColor: '#0000FF' pygments-sc: parent: code textColor: '#800080' pygments-sd: parent: code textColor: '#0000FF' pygments-se: parent: code textColor: '#0000FF' pygments-sh: parent: code textColor: '#0000FF' pygments-si: parent: code textColor: '#0000FF' pygments-sr: parent: code textColor: '#0000FF' pygments-ss: parent: code textColor: '#0000FF' pygments-sx: parent: code textColor: '#0000FF' pygments-vc: parent: code textColor: black pygments-vg: parent: code textColor: black pygments-vi: parent: code textColor: black pygments-vm: parent: code textColor: black pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/bw.yaml000066400000000000000000000120011463013543400173000ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: black pygments-c1: fontName: fontMonoItalic parent: code textColor: black pygments-ch: fontName: fontMonoItalic parent: code textColor: black pygments-cm: fontName: fontMonoItalic parent: code textColor: black pygments-cp: parent: code textColor: black pygments-cpf: fontName: fontMonoItalic parent: code textColor: black pygments-cs: fontName: fontMonoItalic parent: code textColor: black pygments-dl: fontName: fontMonoItalic parent: code textColor: black pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: black pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: fontName: fontMonoBold parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: fontName: fontMonoBold parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: black pygments-k: fontName: fontMonoBold parent: code textColor: black pygments-kc: fontName: fontMonoBold parent: code textColor: black pygments-kd: fontName: fontMonoBold parent: code textColor: black pygments-kn: fontName: fontMonoBold parent: code textColor: black pygments-kp: parent: code textColor: black pygments-kr: fontName: fontMonoBold parent: code textColor: black pygments-kt: parent: code textColor: black pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: black pygments-mb: parent: code textColor: black pygments-mf: parent: code textColor: black pygments-mh: parent: code textColor: black pygments-mi: parent: code textColor: black pygments-mo: parent: code textColor: black pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: black pygments-nc: fontName: fontMonoBold parent: code textColor: black pygments-nd: parent: code textColor: black pygments-ne: fontName: fontMonoBold parent: code textColor: black pygments-nf: parent: code textColor: black pygments-ni: fontName: fontMonoBold parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: fontName: fontMonoBold parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: fontName: fontMonoBold parent: code textColor: black pygments-nv: parent: code textColor: black pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: fontName: fontMonoBold parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: fontName: fontMonoItalic parent: code textColor: black pygments-s1: fontName: fontMonoItalic parent: code textColor: black pygments-s2: fontName: fontMonoItalic parent: code textColor: black pygments-sa: fontName: fontMonoItalic parent: code textColor: black pygments-sb: fontName: fontMonoItalic parent: code textColor: black pygments-sc: fontName: fontMonoItalic parent: code textColor: black pygments-sd: fontName: fontMonoItalic parent: code textColor: black pygments-se: fontName: fontMonoItalic parent: code textColor: black pygments-sh: fontName: fontMonoItalic parent: code textColor: black pygments-si: fontName: fontMonoItalic parent: code textColor: black pygments-sr: fontName: fontMonoItalic parent: code textColor: black pygments-ss: fontName: fontMonoItalic parent: code textColor: black pygments-sx: fontName: fontMonoItalic parent: code textColor: black pygments-vc: parent: code textColor: black pygments-vg: parent: code textColor: black pygments-vi: parent: code textColor: black pygments-vm: parent: code textColor: black pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/colorful.yaml000066400000000000000000000125751463013543400205350ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#007020' pygments-c: parent: code textColor: '#888888' pygments-c1: parent: code textColor: '#888888' pygments-ch: parent: code textColor: '#888888' pygments-cm: parent: code textColor: '#888888' pygments-cp: parent: code textColor: '#557799' pygments-cpf: parent: code textColor: '#888888' pygments-cs: fontName: fontMonoBold parent: code textColor: '#cc0000' pygments-dl: backColor: '#fff0f0' parent: code textColor: black pygments-err: backColor: '#FFAAAA' parent: code textColor: '#FF0000' pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoBold parent: code textColor: '#0066BB' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#A00000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#888888' pygments-gp: fontName: fontMonoBold parent: code textColor: '#c65d09' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#0044DD' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-k: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kc: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kd: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kn: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kp: fontName: fontMonoBold parent: code textColor: '#003388' pygments-kr: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kt: fontName: fontMonoBold parent: code textColor: '#333399' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: fontName: fontMonoBold parent: code textColor: '#6600EE' pygments-mb: fontName: fontMonoBold parent: code textColor: '#6600EE' pygments-mf: fontName: fontMonoBold parent: code textColor: '#6600EE' pygments-mh: fontName: fontMonoBold parent: code textColor: '#005588' pygments-mi: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-mo: fontName: fontMonoBold parent: code textColor: '#4400EE' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#0000CC' pygments-nb: parent: code textColor: '#007020' pygments-nc: fontName: fontMonoBold parent: code textColor: '#BB0066' pygments-nd: fontName: fontMonoBold parent: code textColor: '#555555' pygments-ne: fontName: fontMonoBold parent: code textColor: '#FF0000' pygments-nf: fontName: fontMonoBold parent: code textColor: '#0066BB' pygments-ni: fontName: fontMonoBold parent: code textColor: '#880000' pygments-nl: fontName: fontMonoBold parent: code textColor: '#997700' pygments-nn: fontName: fontMonoBold parent: code textColor: '#0e84b5' pygments-no: fontName: fontMonoBold parent: code textColor: '#003366' pygments-nt: parent: code textColor: '#007700' pygments-nv: parent: code textColor: '#996633' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#333333' pygments-ow: fontName: fontMonoBold parent: code textColor: '#000000' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: backColor: '#fff0f0' parent: code textColor: black pygments-s1: backColor: '#fff0f0' parent: code textColor: black pygments-s2: backColor: '#fff0f0' parent: code textColor: black pygments-sa: backColor: '#fff0f0' parent: code textColor: black pygments-sb: backColor: '#fff0f0' parent: code textColor: black pygments-sc: parent: code textColor: '#0044DD' pygments-sd: parent: code textColor: '#DD4422' pygments-se: backColor: '#fff0f0' fontName: fontMonoBold parent: code textColor: '#666666' pygments-sh: backColor: '#fff0f0' parent: code textColor: black pygments-si: backColor: '#eeeeee' parent: code textColor: black pygments-sr: backColor: '#fff0ff' parent: code textColor: '#000000' pygments-ss: parent: code textColor: '#AA6600' pygments-sx: backColor: '#fff0f0' parent: code textColor: '#DD2200' pygments-vc: parent: code textColor: '#336699' pygments-vg: fontName: fontMonoBold parent: code textColor: '#dd7700' pygments-vi: parent: code textColor: '#3333BB' pygments-vm: parent: code textColor: '#996633' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/debugtables.yaml000066400000000000000000000027311463013543400211620ustar00rootroot00000000000000styles: bullet-list: commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - INNERGRID - - 0 - 0 - - -1 - -1 - 0.25 - black - - BOX - - 0 - 0 - - -1 - -1 - 0.25 - black endnote: colWidths: - 3cm - null commands: - - INNERGRID - - 0 - 0 - - -1 - -1 - 0.25 - black - - BOX - - 0 - 0 - - -1 - -1 - 0.25 - black field-list: commands: - - INNERGRID - - 0 - 0 - - -1 - -1 - 0.25 - black - - BOX - - 0 - 0 - - -1 - -1 - 0.25 - black item-list: commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - TOPPADDING - - 0 - 0 - - -1 - -1 - 0 - - BOTTOMPADDING - - 0 - 0 - - -1 - -1 - 0 - - RIGHTPADDING - - 0 - 0 - - 1 - -1 - 0 - - INNERGRID - - 0 - 0 - - -1 - -1 - 0.25 - black - - BOX - - 0 - 0 - - -1 - -1 - 0.25 - black option-list: commands: - - INNERGRID - - 0 - 0 - - -1 - -1 - 0.25 - black - - BOX - - 0 - 0 - - -1 - -1 - 0.25 - black rst2pdf-0.102/rst2pdf/styles/default.yaml000066400000000000000000000116761463013543400203350ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#008000' pygments-c: fontName: fontMonoItalic parent: code textColor: '#408080' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#408080' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#408080' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#408080' pygments-cp: parent: code textColor: '#BC7A00' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#408080' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#408080' pygments-dl: parent: code textColor: '#BA2121' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#0000FF' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#A00000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#888888' pygments-gp: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#0044DD' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#666666' pygments-k: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kc: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kd: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kn: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kp: parent: code textColor: '#008000' pygments-kr: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kt: parent: code textColor: '#B00040' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#666666' pygments-mb: parent: code textColor: '#666666' pygments-mf: parent: code textColor: '#666666' pygments-mh: parent: code textColor: '#666666' pygments-mi: parent: code textColor: '#666666' pygments-mo: parent: code textColor: '#666666' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#7D9029' pygments-nb: parent: code textColor: '#008000' pygments-nc: fontName: fontMonoBold parent: code textColor: '#0000FF' pygments-nd: parent: code textColor: '#AA22FF' pygments-ne: fontName: fontMonoBold parent: code textColor: '#D2413A' pygments-nf: parent: code textColor: '#0000FF' pygments-ni: fontName: fontMonoBold parent: code textColor: '#999999' pygments-nl: parent: code textColor: '#A0A000' pygments-nn: fontName: fontMonoBold parent: code textColor: '#0000FF' pygments-no: parent: code textColor: '#880000' pygments-nt: fontName: fontMonoBold parent: code textColor: '#008000' pygments-nv: parent: code textColor: '#19177C' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#666666' pygments-ow: fontName: fontMonoBold parent: code textColor: '#AA22FF' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#BA2121' pygments-s1: parent: code textColor: '#BA2121' pygments-s2: parent: code textColor: '#BA2121' pygments-sa: parent: code textColor: '#BA2121' pygments-sb: parent: code textColor: '#BA2121' pygments-sc: parent: code textColor: '#BA2121' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#BA2121' pygments-se: fontName: fontMonoBold parent: code textColor: '#BB6622' pygments-sh: parent: code textColor: '#BA2121' pygments-si: fontName: fontMonoBold parent: code textColor: '#BB6688' pygments-sr: parent: code textColor: '#BB6688' pygments-ss: parent: code textColor: '#19177C' pygments-sx: parent: code textColor: '#008000' pygments-vc: parent: code textColor: '#19177C' pygments-vg: parent: code textColor: '#19177C' pygments-vi: parent: code textColor: '#19177C' pygments-vm: parent: code textColor: '#19177C' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/dejavu.yaml000066400000000000000000000001331463013543400201510ustar00rootroot00000000000000fontsAlias: fontSans: DejaVu Sans fontMono: DejaVu Sans Mono fontSerif: DejaVu Serif rst2pdf-0.102/rst2pdf/styles/double-sided.yaml000066400000000000000000000000401463013543400212300ustar00rootroot00000000000000pageSetup: margin-gutter: 2cm rst2pdf-0.102/rst2pdf/styles/eightpoint.yaml000066400000000000000000000000401463013543400210420ustar00rootroot00000000000000styles: base: fontSize: 8 rst2pdf-0.102/rst2pdf/styles/emacs.yaml000066400000000000000000000116741463013543400177770ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#AA22FF' pygments-c: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cp: parent: code textColor: '#008800' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cs: fontName: fontMonoBold parent: code textColor: '#008800' pygments-dl: parent: code textColor: '#BB4444' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#00A000' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#A00000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#888888' pygments-gp: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#0044DD' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#666666' pygments-k: fontName: fontMonoBold parent: code textColor: '#AA22FF' pygments-kc: fontName: fontMonoBold parent: code textColor: '#AA22FF' pygments-kd: fontName: fontMonoBold parent: code textColor: '#AA22FF' pygments-kn: fontName: fontMonoBold parent: code textColor: '#AA22FF' pygments-kp: parent: code textColor: '#AA22FF' pygments-kr: fontName: fontMonoBold parent: code textColor: '#AA22FF' pygments-kt: fontName: fontMonoBold parent: code textColor: '#00BB00' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#666666' pygments-mb: parent: code textColor: '#666666' pygments-mf: parent: code textColor: '#666666' pygments-mh: parent: code textColor: '#666666' pygments-mi: parent: code textColor: '#666666' pygments-mo: parent: code textColor: '#666666' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#BB4444' pygments-nb: parent: code textColor: '#AA22FF' pygments-nc: parent: code textColor: '#0000FF' pygments-nd: parent: code textColor: '#AA22FF' pygments-ne: fontName: fontMonoBold parent: code textColor: '#D2413A' pygments-nf: parent: code textColor: '#00A000' pygments-ni: fontName: fontMonoBold parent: code textColor: '#999999' pygments-nl: parent: code textColor: '#A0A000' pygments-nn: fontName: fontMonoBold parent: code textColor: '#0000FF' pygments-no: parent: code textColor: '#880000' pygments-nt: fontName: fontMonoBold parent: code textColor: '#008000' pygments-nv: parent: code textColor: '#B8860B' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#666666' pygments-ow: fontName: fontMonoBold parent: code textColor: '#AA22FF' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#BB4444' pygments-s1: parent: code textColor: '#BB4444' pygments-s2: parent: code textColor: '#BB4444' pygments-sa: parent: code textColor: '#BB4444' pygments-sb: parent: code textColor: '#BB4444' pygments-sc: parent: code textColor: '#BB4444' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#BB4444' pygments-se: fontName: fontMonoBold parent: code textColor: '#BB6622' pygments-sh: parent: code textColor: '#BB4444' pygments-si: fontName: fontMonoBold parent: code textColor: '#BB6688' pygments-sr: parent: code textColor: '#BB6688' pygments-ss: parent: code textColor: '#B8860B' pygments-sx: parent: code textColor: '#008000' pygments-vc: parent: code textColor: '#B8860B' pygments-vg: parent: code textColor: '#B8860B' pygments-vi: parent: code textColor: '#B8860B' pygments-vm: parent: code textColor: '#B8860B' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/freetype-sans.yaml000066400000000000000000000001141463013543400214570ustar00rootroot00000000000000fontsAlias: fontSans: Sans fontMono: Monospace fontSerif: Serif-Roman rst2pdf-0.102/rst2pdf/styles/freetype-serif.yaml000066400000000000000000000000641463013543400216270ustar00rootroot00000000000000fontsAlias: fontSans: Serif fontMono: Monospace rst2pdf-0.102/rst2pdf/styles/friendly.yaml000066400000000000000000000117271463013543400205220ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#007020' pygments-c: fontName: fontMonoItalic parent: code textColor: '#60a0b0' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#60a0b0' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#60a0b0' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#60a0b0' pygments-cp: parent: code textColor: '#007020' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#60a0b0' pygments-cs: backColor: '#fff0f0' parent: code textColor: '#60a0b0' pygments-dl: parent: code textColor: '#4070a0' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#06287e' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#A00000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#888888' pygments-gp: fontName: fontMonoBold parent: code textColor: '#c65d09' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#0044DD' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#40a070' pygments-k: fontName: fontMonoBold parent: code textColor: '#007020' pygments-kc: fontName: fontMonoBold parent: code textColor: '#007020' pygments-kd: fontName: fontMonoBold parent: code textColor: '#007020' pygments-kn: fontName: fontMonoBold parent: code textColor: '#007020' pygments-kp: parent: code textColor: '#007020' pygments-kr: fontName: fontMonoBold parent: code textColor: '#007020' pygments-kt: parent: code textColor: '#902000' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#40a070' pygments-mb: parent: code textColor: '#40a070' pygments-mf: parent: code textColor: '#40a070' pygments-mh: parent: code textColor: '#40a070' pygments-mi: parent: code textColor: '#40a070' pygments-mo: parent: code textColor: '#40a070' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#4070a0' pygments-nb: parent: code textColor: '#007020' pygments-nc: fontName: fontMonoBold parent: code textColor: '#0e84b5' pygments-nd: fontName: fontMonoBold parent: code textColor: '#555555' pygments-ne: parent: code textColor: '#007020' pygments-nf: parent: code textColor: '#06287e' pygments-ni: fontName: fontMonoBold parent: code textColor: '#d55537' pygments-nl: fontName: fontMonoBold parent: code textColor: '#002070' pygments-nn: fontName: fontMonoBold parent: code textColor: '#0e84b5' pygments-no: parent: code textColor: '#60add5' pygments-nt: fontName: fontMonoBold parent: code textColor: '#062873' pygments-nv: parent: code textColor: '#bb60d5' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#666666' pygments-ow: fontName: fontMonoBold parent: code textColor: '#007020' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#4070a0' pygments-s1: parent: code textColor: '#4070a0' pygments-s2: parent: code textColor: '#4070a0' pygments-sa: parent: code textColor: '#4070a0' pygments-sb: parent: code textColor: '#4070a0' pygments-sc: parent: code textColor: '#4070a0' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#4070a0' pygments-se: fontName: fontMonoBold parent: code textColor: '#4070a0' pygments-sh: parent: code textColor: '#4070a0' pygments-si: fontName: fontMonoItalic parent: code textColor: '#70a0d0' pygments-sr: parent: code textColor: '#235388' pygments-ss: parent: code textColor: '#517918' pygments-sx: parent: code textColor: '#c65d09' pygments-vc: parent: code textColor: '#bb60d5' pygments-vg: parent: code textColor: '#bb60d5' pygments-vi: parent: code textColor: '#bb60d5' pygments-vm: parent: code textColor: '#bb60d5' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/fruity.yaml000066400000000000000000000123171463013543400202240ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#ffffff' pygments-c: backColor: '#0f140f' fontName: fontMonoItalic parent: code textColor: '#008800' pygments-c1: backColor: '#0f140f' fontName: fontMonoItalic parent: code textColor: '#008800' pygments-ch: backColor: '#0f140f' fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cm: backColor: '#0f140f' fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cp: backColor: '#0f140f' fontName: fontMonoItalic parent: code textColor: '#ff0007' pygments-cpf: backColor: '#0f140f' fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cs: backColor: '#0f140f' fontName: fontMonoItalic parent: code textColor: '#008800' pygments-dl: parent: code textColor: '#0086d2' pygments-err: parent: code textColor: '#ffffff' pygments-esc: parent: code textColor: '#ffffff' pygments-fm: fontName: fontMonoBold parent: code textColor: '#ff0086' pygments-g: parent: code textColor: '#ffffff' pygments-gd: parent: code textColor: '#ffffff' pygments-ge: parent: code textColor: '#ffffff' pygments-gh: fontName: fontMonoBold parent: code textColor: '#ffffff' pygments-gi: parent: code textColor: '#ffffff' pygments-go: backColor: '#222222' parent: code textColor: '#444444' pygments-gp: parent: code textColor: '#ffffff' pygments-gr: parent: code textColor: '#ffffff' pygments-gs: parent: code textColor: '#ffffff' pygments-gt: parent: code textColor: '#ffffff' pygments-gu: fontName: fontMonoBold parent: code textColor: '#ffffff' pygments-hll: backColor: '#333333' parent: code textColor: black pygments-il: fontName: fontMonoBold parent: code textColor: '#0086f7' pygments-k: fontName: fontMonoBold parent: code textColor: '#fb660a' pygments-kc: fontName: fontMonoBold parent: code textColor: '#fb660a' pygments-kd: fontName: fontMonoBold parent: code textColor: '#fb660a' pygments-kn: fontName: fontMonoBold parent: code textColor: '#fb660a' pygments-kp: parent: code textColor: '#fb660a' pygments-kr: fontName: fontMonoBold parent: code textColor: '#fb660a' pygments-kt: fontName: fontMonoBold parent: code textColor: '#cdcaa9' pygments-l: parent: code textColor: '#ffffff' pygments-ld: parent: code textColor: '#ffffff' pygments-m: fontName: fontMonoBold parent: code textColor: '#0086f7' pygments-mb: fontName: fontMonoBold parent: code textColor: '#0086f7' pygments-mf: fontName: fontMonoBold parent: code textColor: '#0086f7' pygments-mh: fontName: fontMonoBold parent: code textColor: '#0086f7' pygments-mi: fontName: fontMonoBold parent: code textColor: '#0086f7' pygments-mo: fontName: fontMonoBold parent: code textColor: '#0086f7' pygments-n: parent: code textColor: '#ffffff' pygments-na: fontName: fontMonoBold parent: code textColor: '#ff0086' pygments-nb: parent: code textColor: '#ffffff' pygments-nc: parent: code textColor: '#ffffff' pygments-nd: parent: code textColor: '#ffffff' pygments-ne: parent: code textColor: '#ffffff' pygments-nf: fontName: fontMonoBold parent: code textColor: '#ff0086' pygments-ni: parent: code textColor: '#ffffff' pygments-nl: parent: code textColor: '#ffffff' pygments-nn: parent: code textColor: '#ffffff' pygments-no: parent: code textColor: '#0086d2' pygments-nt: fontName: fontMonoBold parent: code textColor: '#fb660a' pygments-nv: parent: code textColor: '#fb660a' pygments-nx: parent: code textColor: '#ffffff' pygments-o: parent: code textColor: '#ffffff' pygments-ow: parent: code textColor: '#ffffff' pygments-p: parent: code textColor: '#ffffff' pygments-py: parent: code textColor: '#ffffff' pygments-s: parent: code textColor: '#0086d2' pygments-s1: parent: code textColor: '#0086d2' pygments-s2: parent: code textColor: '#0086d2' pygments-sa: parent: code textColor: '#0086d2' pygments-sb: parent: code textColor: '#0086d2' pygments-sc: parent: code textColor: '#0086d2' pygments-sd: parent: code textColor: '#0086d2' pygments-se: parent: code textColor: '#0086d2' pygments-sh: parent: code textColor: '#0086d2' pygments-si: parent: code textColor: '#0086d2' pygments-sr: parent: code textColor: '#0086d2' pygments-ss: parent: code textColor: '#0086d2' pygments-sx: parent: code textColor: '#0086d2' pygments-vc: parent: code textColor: '#fb660a' pygments-vg: parent: code textColor: '#fb660a' pygments-vi: parent: code textColor: '#fb660a' pygments-vm: parent: code textColor: '#fb660a' pygments-w: parent: code textColor: '#888888' pygments-x: parent: code textColor: '#ffffff' rst2pdf-0.102/rst2pdf/styles/igor.yaml000066400000000000000000000105261463013543400176420ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: '#FF0000' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#FF0000' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#FF0000' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#FF0000' pygments-cp: fontName: fontMonoItalic parent: code textColor: '#FF0000' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#FF0000' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#FF0000' pygments-dl: parent: code textColor: '#009C00' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#C34E00' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: black pygments-k: parent: code textColor: '#0000FF' pygments-kc: parent: code textColor: '#0000FF' pygments-kd: parent: code textColor: '#0000FF' pygments-kn: parent: code textColor: '#0000FF' pygments-kp: parent: code textColor: '#0000FF' pygments-kr: parent: code textColor: '#0000FF' pygments-kt: parent: code textColor: '#0000FF' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: black pygments-mb: parent: code textColor: black pygments-mf: parent: code textColor: black pygments-mh: parent: code textColor: black pygments-mi: parent: code textColor: black pygments-mo: parent: code textColor: black pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: black pygments-nc: parent: code textColor: '#007575' pygments-nd: parent: code textColor: '#CC00A3' pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: '#C34E00' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: parent: code textColor: black pygments-nv: parent: code textColor: black pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#009C00' pygments-s1: parent: code textColor: '#009C00' pygments-s2: parent: code textColor: '#009C00' pygments-sa: parent: code textColor: '#009C00' pygments-sb: parent: code textColor: '#009C00' pygments-sc: parent: code textColor: '#009C00' pygments-sd: parent: code textColor: '#009C00' pygments-se: parent: code textColor: '#009C00' pygments-sh: parent: code textColor: '#009C00' pygments-si: parent: code textColor: '#009C00' pygments-sr: parent: code textColor: '#009C00' pygments-ss: parent: code textColor: '#009C00' pygments-sx: parent: code textColor: '#009C00' pygments-vc: parent: code textColor: black pygments-vg: parent: code textColor: black pygments-vi: parent: code textColor: black pygments-vm: parent: code textColor: black pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/legal.yaml000066400000000000000000000000311463013543400177540ustar00rootroot00000000000000pageSetup: size: legal rst2pdf-0.102/rst2pdf/styles/letter-landscape.yaml000066400000000000000000000000441463013543400221230ustar00rootroot00000000000000pageSetup: size: letter-landscape rst2pdf-0.102/rst2pdf/styles/letter.yaml000066400000000000000000000000321463013543400201700ustar00rootroot00000000000000pageSetup: size: letter rst2pdf-0.102/rst2pdf/styles/lovelace.yaml000066400000000000000000000112371463013543400204740ustar00rootroot00000000000000styles: pygments-bp: fontName: fontMonoItalic parent: code textColor: '#388038' pygments-c: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#287088' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cp: parent: code textColor: '#289870' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#888888' pygments-dl: parent: code textColor: '#b85820' pygments-err: backColor: '#a848a8' parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#b85820' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#c02828' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: parent: code textColor: '#666666' pygments-gi: parent: code textColor: '#388038' pygments-go: parent: code textColor: '#666666' pygments-gp: parent: code textColor: '#444444' pygments-gr: parent: code textColor: '#c02828' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#2838b0' pygments-gu: parent: code textColor: '#444444' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#444444' pygments-k: parent: code textColor: '#2838b0' pygments-kc: fontName: fontMonoItalic parent: code textColor: '#444444' pygments-kd: fontName: fontMonoItalic parent: code textColor: '#2838b0' pygments-kn: parent: code textColor: '#2838b0' pygments-kp: parent: code textColor: '#2838b0' pygments-kr: parent: code textColor: '#2838b0' pygments-kt: fontName: fontMonoItalic parent: code textColor: '#2838b0' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#444444' pygments-mb: parent: code textColor: '#444444' pygments-mf: parent: code textColor: '#444444' pygments-mh: parent: code textColor: '#444444' pygments-mi: parent: code textColor: '#444444' pygments-mo: parent: code textColor: '#444444' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#388038' pygments-nb: parent: code textColor: '#388038' pygments-nc: parent: code textColor: '#287088' pygments-nd: parent: code textColor: '#287088' pygments-ne: parent: code textColor: '#908828' pygments-nf: parent: code textColor: '#785840' pygments-ni: parent: code textColor: '#709030' pygments-nl: parent: code textColor: '#289870' pygments-nn: parent: code textColor: '#289870' pygments-no: parent: code textColor: '#b85820' pygments-nt: parent: code textColor: '#2838b0' pygments-nv: parent: code textColor: '#b04040' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#666666' pygments-ow: parent: code textColor: '#a848a8' pygments-p: parent: code textColor: '#888888' pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#b83838' pygments-s1: parent: code textColor: '#b83838' pygments-s2: parent: code textColor: '#b83838' pygments-sa: parent: code textColor: '#444444' pygments-sb: parent: code textColor: '#b83838' pygments-sc: parent: code textColor: '#a848a8' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#b85820' pygments-se: parent: code textColor: '#709030' pygments-sh: parent: code textColor: '#b83838' pygments-si: parent: code textColor: '#b83838' pygments-sr: parent: code textColor: '#a848a8' pygments-ss: parent: code textColor: '#b83838' pygments-sx: parent: code textColor: '#a848a8' pygments-vc: parent: code textColor: '#b04040' pygments-vg: parent: code textColor: '#908828' pygments-vi: parent: code textColor: '#b04040' pygments-vm: parent: code textColor: '#b85820' pygments-w: parent: code textColor: '#a89028' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/manni.yaml000066400000000000000000000120051463013543400177760ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#336666' pygments-c: fontName: fontMonoItalic parent: code textColor: '#0099FF' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#0099FF' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#0099FF' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#0099FF' pygments-cp: parent: code textColor: '#009999' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#0099FF' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#0099FF' pygments-dl: parent: code textColor: '#CC3300' pygments-err: backColor: '#FFAAAA' parent: code textColor: '#AA0000' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#CC00FF' pygments-g: parent: code textColor: black pygments-gd: backColor: '#FFCCCC' parent: code textColor: black pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#003300' pygments-gi: backColor: '#CCFFCC' parent: code textColor: black pygments-go: parent: code textColor: '#AAAAAA' pygments-gp: fontName: fontMonoBold parent: code textColor: '#000099' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#99CC66' pygments-gu: fontName: fontMonoBold parent: code textColor: '#003300' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#FF6600' pygments-k: fontName: fontMonoBold parent: code textColor: '#006699' pygments-kc: fontName: fontMonoBold parent: code textColor: '#006699' pygments-kd: fontName: fontMonoBold parent: code textColor: '#006699' pygments-kn: fontName: fontMonoBold parent: code textColor: '#006699' pygments-kp: parent: code textColor: '#006699' pygments-kr: fontName: fontMonoBold parent: code textColor: '#006699' pygments-kt: fontName: fontMonoBold parent: code textColor: '#007788' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#FF6600' pygments-mb: parent: code textColor: '#FF6600' pygments-mf: parent: code textColor: '#FF6600' pygments-mh: parent: code textColor: '#FF6600' pygments-mi: parent: code textColor: '#FF6600' pygments-mo: parent: code textColor: '#FF6600' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#330099' pygments-nb: parent: code textColor: '#336666' pygments-nc: fontName: fontMonoBold parent: code textColor: '#00AA88' pygments-nd: parent: code textColor: '#9999FF' pygments-ne: fontName: fontMonoBold parent: code textColor: '#CC0000' pygments-nf: parent: code textColor: '#CC00FF' pygments-ni: fontName: fontMonoBold parent: code textColor: '#999999' pygments-nl: parent: code textColor: '#9999FF' pygments-nn: fontName: fontMonoBold parent: code textColor: '#00CCFF' pygments-no: parent: code textColor: '#336600' pygments-nt: fontName: fontMonoBold parent: code textColor: '#330099' pygments-nv: parent: code textColor: '#003333' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#555555' pygments-ow: fontName: fontMonoBold parent: code textColor: '#000000' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#CC3300' pygments-s1: parent: code textColor: '#CC3300' pygments-s2: parent: code textColor: '#CC3300' pygments-sa: parent: code textColor: '#CC3300' pygments-sb: parent: code textColor: '#CC3300' pygments-sc: parent: code textColor: '#CC3300' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#CC3300' pygments-se: fontName: fontMonoBold parent: code textColor: '#CC3300' pygments-sh: parent: code textColor: '#CC3300' pygments-si: parent: code textColor: '#AA0000' pygments-sr: parent: code textColor: '#33AAAA' pygments-ss: parent: code textColor: '#FFCC33' pygments-sx: parent: code textColor: '#CC3300' pygments-vc: parent: code textColor: '#003333' pygments-vg: parent: code textColor: '#003333' pygments-vi: parent: code textColor: '#003333' pygments-vm: parent: code textColor: '#003333' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/monokai.yaml000066400000000000000000000105441463013543400203370ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#f8f8f2' pygments-c: parent: code textColor: '#75715e' pygments-c1: parent: code textColor: '#75715e' pygments-ch: parent: code textColor: '#75715e' pygments-cm: parent: code textColor: '#75715e' pygments-cp: parent: code textColor: '#75715e' pygments-cpf: parent: code textColor: '#75715e' pygments-cs: parent: code textColor: '#75715e' pygments-dl: parent: code textColor: '#e6db74' pygments-err: backColor: '#1e0010' parent: code textColor: '#960050' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#a6e22e' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#f92672' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: '#a6e22e' pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: '#75715e' pygments-hll: backColor: '#49483e' parent: code textColor: black pygments-il: parent: code textColor: '#ae81ff' pygments-k: parent: code textColor: '#66d9ef' pygments-kc: parent: code textColor: '#66d9ef' pygments-kd: parent: code textColor: '#66d9ef' pygments-kn: parent: code textColor: '#f92672' pygments-kp: parent: code textColor: '#66d9ef' pygments-kr: parent: code textColor: '#66d9ef' pygments-kt: parent: code textColor: '#66d9ef' pygments-l: parent: code textColor: '#ae81ff' pygments-ld: parent: code textColor: '#e6db74' pygments-m: parent: code textColor: '#ae81ff' pygments-mb: parent: code textColor: '#ae81ff' pygments-mf: parent: code textColor: '#ae81ff' pygments-mh: parent: code textColor: '#ae81ff' pygments-mi: parent: code textColor: '#ae81ff' pygments-mo: parent: code textColor: '#ae81ff' pygments-n: parent: code textColor: '#f8f8f2' pygments-na: parent: code textColor: '#a6e22e' pygments-nb: parent: code textColor: '#f8f8f2' pygments-nc: parent: code textColor: '#a6e22e' pygments-nd: parent: code textColor: '#a6e22e' pygments-ne: parent: code textColor: '#a6e22e' pygments-nf: parent: code textColor: '#a6e22e' pygments-ni: parent: code textColor: '#f8f8f2' pygments-nl: parent: code textColor: '#f8f8f2' pygments-nn: parent: code textColor: '#f8f8f2' pygments-no: parent: code textColor: '#66d9ef' pygments-nt: parent: code textColor: '#f92672' pygments-nv: parent: code textColor: '#f8f8f2' pygments-nx: parent: code textColor: '#a6e22e' pygments-o: parent: code textColor: '#f92672' pygments-ow: parent: code textColor: '#f92672' pygments-p: parent: code textColor: '#f8f8f2' pygments-py: parent: code textColor: '#f8f8f2' pygments-s: parent: code textColor: '#e6db74' pygments-s1: parent: code textColor: '#e6db74' pygments-s2: parent: code textColor: '#e6db74' pygments-sa: parent: code textColor: '#e6db74' pygments-sb: parent: code textColor: '#e6db74' pygments-sc: parent: code textColor: '#e6db74' pygments-sd: parent: code textColor: '#e6db74' pygments-se: parent: code textColor: '#ae81ff' pygments-sh: parent: code textColor: '#e6db74' pygments-si: parent: code textColor: '#e6db74' pygments-sr: parent: code textColor: '#e6db74' pygments-ss: parent: code textColor: '#e6db74' pygments-sx: parent: code textColor: '#e6db74' pygments-vc: parent: code textColor: '#f8f8f2' pygments-vg: parent: code textColor: '#f8f8f2' pygments-vi: parent: code textColor: '#f8f8f2' pygments-vm: parent: code textColor: '#f8f8f2' pygments-w: parent: code textColor: '#f8f8f2' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/murphy.yaml000066400000000000000000000127321463013543400202270ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#007722' pygments-c: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-cp: parent: code textColor: '#557799' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#666666' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#cc0000' pygments-dl: backColor: '#e0e0ff' parent: code textColor: black pygments-err: backColor: '#FFAAAA' parent: code textColor: '#FF0000' pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoBold parent: code textColor: '#55eedd' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#A00000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#888888' pygments-gp: fontName: fontMonoBold parent: code textColor: '#c65d09' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#0044DD' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: fontName: fontMonoBold parent: code textColor: '#6666ff' pygments-k: fontName: fontMonoBold parent: code textColor: '#228899' pygments-kc: fontName: fontMonoBold parent: code textColor: '#228899' pygments-kd: fontName: fontMonoBold parent: code textColor: '#228899' pygments-kn: fontName: fontMonoBold parent: code textColor: '#228899' pygments-kp: fontName: fontMonoBold parent: code textColor: '#0088ff' pygments-kr: fontName: fontMonoBold parent: code textColor: '#228899' pygments-kt: fontName: fontMonoBold parent: code textColor: '#6666ff' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: fontName: fontMonoBold parent: code textColor: '#6600EE' pygments-mb: fontName: fontMonoBold parent: code textColor: '#6600EE' pygments-mf: fontName: fontMonoBold parent: code textColor: '#6600EE' pygments-mh: fontName: fontMonoBold parent: code textColor: '#005588' pygments-mi: fontName: fontMonoBold parent: code textColor: '#6666ff' pygments-mo: fontName: fontMonoBold parent: code textColor: '#4400EE' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#000077' pygments-nb: parent: code textColor: '#007722' pygments-nc: fontName: fontMonoBold parent: code textColor: '#ee99ee' pygments-nd: fontName: fontMonoBold parent: code textColor: '#555555' pygments-ne: fontName: fontMonoBold parent: code textColor: '#FF0000' pygments-nf: fontName: fontMonoBold parent: code textColor: '#55eedd' pygments-ni: parent: code textColor: '#880000' pygments-nl: fontName: fontMonoBold parent: code textColor: '#997700' pygments-nn: fontName: fontMonoBold parent: code textColor: '#0e84b5' pygments-no: fontName: fontMonoBold parent: code textColor: '#55eedd' pygments-nt: parent: code textColor: '#007700' pygments-nv: parent: code textColor: '#003366' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#333333' pygments-ow: fontName: fontMonoBold parent: code textColor: '#000000' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: backColor: '#e0e0ff' parent: code textColor: black pygments-s1: backColor: '#e0e0ff' parent: code textColor: black pygments-s2: backColor: '#e0e0ff' parent: code textColor: black pygments-sa: backColor: '#e0e0ff' parent: code textColor: black pygments-sb: backColor: '#e0e0ff' parent: code textColor: black pygments-sc: parent: code textColor: '#8888FF' pygments-sd: parent: code textColor: '#DD4422' pygments-se: backColor: '#e0e0ff' fontName: fontMonoBold parent: code textColor: '#666666' pygments-sh: backColor: '#e0e0ff' parent: code textColor: black pygments-si: backColor: '#eeeeee' parent: code textColor: black pygments-sr: backColor: '#e0e0ff' parent: code textColor: '#000000' pygments-ss: parent: code textColor: '#ffcc88' pygments-sx: backColor: '#e0e0ff' parent: code textColor: '#ff8888' pygments-vc: parent: code textColor: '#ccccff' pygments-vg: parent: code textColor: '#ff8844' pygments-vi: parent: code textColor: '#aaaaff' pygments-vm: parent: code textColor: '#003366' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/native.yaml000066400000000000000000000115371463013543400201730ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#24909d' pygments-c: fontName: fontMonoItalic parent: code textColor: '#999999' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#999999' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#999999' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#999999' pygments-cp: fontName: fontMonoBold parent: code textColor: '#cd2828' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#999999' pygments-cs: backColor: '#520000' fontName: fontMonoBold parent: code textColor: '#e50808' pygments-dl: parent: code textColor: '#ed9d13' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: '#d0d0d0' pygments-fm: parent: code textColor: '#447fcf' pygments-g: parent: code textColor: '#d0d0d0' pygments-gd: parent: code textColor: '#d22323' pygments-ge: fontName: fontMonoItalic parent: code textColor: '#d0d0d0' pygments-gh: fontName: fontMonoBold parent: code textColor: '#ffffff' pygments-gi: parent: code textColor: '#589819' pygments-go: parent: code textColor: '#cccccc' pygments-gp: parent: code textColor: '#aaaaaa' pygments-gr: parent: code textColor: '#d22323' pygments-gs: fontName: fontMonoBold parent: code textColor: '#d0d0d0' pygments-gt: parent: code textColor: '#d22323' pygments-gu: parent: code textColor: '#ffffff' pygments-hll: backColor: '#404040' parent: code textColor: black pygments-il: parent: code textColor: '#3677a9' pygments-k: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-kc: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-kd: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-kn: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-kp: parent: code textColor: '#6ab825' pygments-kr: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-kt: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-l: parent: code textColor: '#d0d0d0' pygments-ld: parent: code textColor: '#d0d0d0' pygments-m: parent: code textColor: '#3677a9' pygments-mb: parent: code textColor: '#3677a9' pygments-mf: parent: code textColor: '#3677a9' pygments-mh: parent: code textColor: '#3677a9' pygments-mi: parent: code textColor: '#3677a9' pygments-mo: parent: code textColor: '#3677a9' pygments-n: parent: code textColor: '#d0d0d0' pygments-na: parent: code textColor: '#bbbbbb' pygments-nb: parent: code textColor: '#24909d' pygments-nc: parent: code textColor: '#447fcf' pygments-nd: parent: code textColor: '#ffa500' pygments-ne: parent: code textColor: '#bbbbbb' pygments-nf: parent: code textColor: '#447fcf' pygments-ni: parent: code textColor: '#d0d0d0' pygments-nl: parent: code textColor: '#d0d0d0' pygments-nn: parent: code textColor: '#447fcf' pygments-no: parent: code textColor: '#40ffff' pygments-nt: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-nv: parent: code textColor: '#40ffff' pygments-nx: parent: code textColor: '#d0d0d0' pygments-o: parent: code textColor: '#d0d0d0' pygments-ow: fontName: fontMonoBold parent: code textColor: '#6ab825' pygments-p: parent: code textColor: '#d0d0d0' pygments-py: parent: code textColor: '#d0d0d0' pygments-s: parent: code textColor: '#ed9d13' pygments-s1: parent: code textColor: '#ed9d13' pygments-s2: parent: code textColor: '#ed9d13' pygments-sa: parent: code textColor: '#ed9d13' pygments-sb: parent: code textColor: '#ed9d13' pygments-sc: parent: code textColor: '#ed9d13' pygments-sd: parent: code textColor: '#ed9d13' pygments-se: parent: code textColor: '#ed9d13' pygments-sh: parent: code textColor: '#ed9d13' pygments-si: parent: code textColor: '#ed9d13' pygments-sr: parent: code textColor: '#ed9d13' pygments-ss: parent: code textColor: '#ed9d13' pygments-sx: parent: code textColor: '#ffa500' pygments-vc: parent: code textColor: '#40ffff' pygments-vg: parent: code textColor: '#40ffff' pygments-vi: parent: code textColor: '#40ffff' pygments-vm: parent: code textColor: '#40ffff' pygments-w: parent: code textColor: '#666666' pygments-x: parent: code textColor: '#d0d0d0' rst2pdf-0.102/rst2pdf/styles/no-compact-lists.yaml000066400000000000000000000001721463013543400220720ustar00rootroot00000000000000styles: bullet-list: parent: bodytext spaceBefore: 8 enumerated-list: parent: bodytext spaceBefore: 8 rst2pdf-0.102/rst2pdf/styles/paraiso-dark.yaml000066400000000000000000000106441463013543400212600ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#e7e9db' pygments-c: parent: code textColor: '#776e71' pygments-c1: parent: code textColor: '#776e71' pygments-ch: parent: code textColor: '#776e71' pygments-cm: parent: code textColor: '#776e71' pygments-cp: parent: code textColor: '#776e71' pygments-cpf: parent: code textColor: '#776e71' pygments-cs: parent: code textColor: '#776e71' pygments-dl: parent: code textColor: '#48b685' pygments-err: parent: code textColor: '#ef6155' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#06b6ef' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#ef6155' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#e7e9db' pygments-gi: parent: code textColor: '#48b685' pygments-go: parent: code textColor: black pygments-gp: fontName: fontMonoBold parent: code textColor: '#776e71' pygments-gr: parent: code textColor: black pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: fontName: fontMonoBold parent: code textColor: '#5bc4bf' pygments-hll: backColor: '#4f424c' parent: code textColor: black pygments-il: parent: code textColor: '#f99b15' pygments-k: parent: code textColor: '#815ba4' pygments-kc: parent: code textColor: '#815ba4' pygments-kd: parent: code textColor: '#815ba4' pygments-kn: parent: code textColor: '#5bc4bf' pygments-kp: parent: code textColor: '#815ba4' pygments-kr: parent: code textColor: '#815ba4' pygments-kt: parent: code textColor: '#fec418' pygments-l: parent: code textColor: '#f99b15' pygments-ld: parent: code textColor: '#48b685' pygments-m: parent: code textColor: '#f99b15' pygments-mb: parent: code textColor: '#f99b15' pygments-mf: parent: code textColor: '#f99b15' pygments-mh: parent: code textColor: '#f99b15' pygments-mi: parent: code textColor: '#f99b15' pygments-mo: parent: code textColor: '#f99b15' pygments-n: parent: code textColor: '#e7e9db' pygments-na: parent: code textColor: '#06b6ef' pygments-nb: parent: code textColor: '#e7e9db' pygments-nc: parent: code textColor: '#fec418' pygments-nd: parent: code textColor: '#5bc4bf' pygments-ne: parent: code textColor: '#ef6155' pygments-nf: parent: code textColor: '#06b6ef' pygments-ni: parent: code textColor: '#e7e9db' pygments-nl: parent: code textColor: '#e7e9db' pygments-nn: parent: code textColor: '#fec418' pygments-no: parent: code textColor: '#ef6155' pygments-nt: parent: code textColor: '#5bc4bf' pygments-nv: parent: code textColor: '#ef6155' pygments-nx: parent: code textColor: '#06b6ef' pygments-o: parent: code textColor: '#5bc4bf' pygments-ow: parent: code textColor: '#5bc4bf' pygments-p: parent: code textColor: '#e7e9db' pygments-py: parent: code textColor: '#e7e9db' pygments-s: parent: code textColor: '#48b685' pygments-s1: parent: code textColor: '#48b685' pygments-s2: parent: code textColor: '#48b685' pygments-sa: parent: code textColor: '#48b685' pygments-sb: parent: code textColor: '#48b685' pygments-sc: parent: code textColor: '#e7e9db' pygments-sd: parent: code textColor: '#776e71' pygments-se: parent: code textColor: '#f99b15' pygments-sh: parent: code textColor: '#48b685' pygments-si: parent: code textColor: '#f99b15' pygments-sr: parent: code textColor: '#48b685' pygments-ss: parent: code textColor: '#48b685' pygments-sx: parent: code textColor: '#48b685' pygments-vc: parent: code textColor: '#ef6155' pygments-vg: parent: code textColor: '#ef6155' pygments-vi: parent: code textColor: '#ef6155' pygments-vm: parent: code textColor: '#ef6155' pygments-w: parent: code textColor: '#e7e9db' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/paraiso-light.yaml000066400000000000000000000106441463013543400214460ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#2f1e2e' pygments-c: parent: code textColor: '#8d8687' pygments-c1: parent: code textColor: '#8d8687' pygments-ch: parent: code textColor: '#8d8687' pygments-cm: parent: code textColor: '#8d8687' pygments-cp: parent: code textColor: '#8d8687' pygments-cpf: parent: code textColor: '#8d8687' pygments-cs: parent: code textColor: '#8d8687' pygments-dl: parent: code textColor: '#48b685' pygments-err: parent: code textColor: '#ef6155' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#06b6ef' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#ef6155' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#2f1e2e' pygments-gi: parent: code textColor: '#48b685' pygments-go: parent: code textColor: black pygments-gp: fontName: fontMonoBold parent: code textColor: '#8d8687' pygments-gr: parent: code textColor: black pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: fontName: fontMonoBold parent: code textColor: '#5bc4bf' pygments-hll: backColor: '#a39e9b' parent: code textColor: black pygments-il: parent: code textColor: '#f99b15' pygments-k: parent: code textColor: '#815ba4' pygments-kc: parent: code textColor: '#815ba4' pygments-kd: parent: code textColor: '#815ba4' pygments-kn: parent: code textColor: '#5bc4bf' pygments-kp: parent: code textColor: '#815ba4' pygments-kr: parent: code textColor: '#815ba4' pygments-kt: parent: code textColor: '#fec418' pygments-l: parent: code textColor: '#f99b15' pygments-ld: parent: code textColor: '#48b685' pygments-m: parent: code textColor: '#f99b15' pygments-mb: parent: code textColor: '#f99b15' pygments-mf: parent: code textColor: '#f99b15' pygments-mh: parent: code textColor: '#f99b15' pygments-mi: parent: code textColor: '#f99b15' pygments-mo: parent: code textColor: '#f99b15' pygments-n: parent: code textColor: '#2f1e2e' pygments-na: parent: code textColor: '#06b6ef' pygments-nb: parent: code textColor: '#2f1e2e' pygments-nc: parent: code textColor: '#fec418' pygments-nd: parent: code textColor: '#5bc4bf' pygments-ne: parent: code textColor: '#ef6155' pygments-nf: parent: code textColor: '#06b6ef' pygments-ni: parent: code textColor: '#2f1e2e' pygments-nl: parent: code textColor: '#2f1e2e' pygments-nn: parent: code textColor: '#fec418' pygments-no: parent: code textColor: '#ef6155' pygments-nt: parent: code textColor: '#5bc4bf' pygments-nv: parent: code textColor: '#ef6155' pygments-nx: parent: code textColor: '#06b6ef' pygments-o: parent: code textColor: '#5bc4bf' pygments-ow: parent: code textColor: '#5bc4bf' pygments-p: parent: code textColor: '#2f1e2e' pygments-py: parent: code textColor: '#2f1e2e' pygments-s: parent: code textColor: '#48b685' pygments-s1: parent: code textColor: '#48b685' pygments-s2: parent: code textColor: '#48b685' pygments-sa: parent: code textColor: '#48b685' pygments-sb: parent: code textColor: '#48b685' pygments-sc: parent: code textColor: '#2f1e2e' pygments-sd: parent: code textColor: '#8d8687' pygments-se: parent: code textColor: '#f99b15' pygments-sh: parent: code textColor: '#48b685' pygments-si: parent: code textColor: '#f99b15' pygments-sr: parent: code textColor: '#48b685' pygments-ss: parent: code textColor: '#48b685' pygments-sx: parent: code textColor: '#48b685' pygments-vc: parent: code textColor: '#ef6155' pygments-vg: parent: code textColor: '#ef6155' pygments-vi: parent: code textColor: '#ef6155' pygments-vm: parent: code textColor: '#ef6155' pygments-w: parent: code textColor: '#2f1e2e' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/pastie.yaml000066400000000000000000000126171463013543400201720ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#003388' pygments-c: parent: code textColor: '#888888' pygments-c1: parent: code textColor: '#888888' pygments-ch: parent: code textColor: '#888888' pygments-cm: parent: code textColor: '#888888' pygments-cp: fontName: fontMonoBold parent: code textColor: '#cc0000' pygments-cpf: parent: code textColor: '#888888' pygments-cs: backColor: '#fff0f0' fontName: fontMonoBold parent: code textColor: '#cc0000' pygments-dl: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoBold parent: code textColor: '#0066bb' pygments-g: parent: code textColor: black pygments-gd: backColor: '#ffdddd' parent: code textColor: '#000000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: parent: code textColor: '#333333' pygments-gi: backColor: '#ddffdd' parent: code textColor: '#000000' pygments-go: parent: code textColor: '#888888' pygments-gp: parent: code textColor: '#555555' pygments-gr: parent: code textColor: '#aa0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#aa0000' pygments-gu: parent: code textColor: '#666666' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-k: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kc: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kd: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kn: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kp: parent: code textColor: '#008800' pygments-kr: fontName: fontMonoBold parent: code textColor: '#008800' pygments-kt: fontName: fontMonoBold parent: code textColor: '#888888' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-mb: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-mf: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-mh: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-mi: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-mo: fontName: fontMonoBold parent: code textColor: '#0000DD' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#336699' pygments-nb: parent: code textColor: '#003388' pygments-nc: fontName: fontMonoBold parent: code textColor: '#bb0066' pygments-nd: parent: code textColor: '#555555' pygments-ne: fontName: fontMonoBold parent: code textColor: '#bb0066' pygments-nf: fontName: fontMonoBold parent: code textColor: '#0066bb' pygments-ni: parent: code textColor: black pygments-nl: fontName: fontMonoItalic parent: code textColor: '#336699' pygments-nn: fontName: fontMonoBold parent: code textColor: '#bb0066' pygments-no: fontName: fontMonoBold parent: code textColor: '#003366' pygments-nt: fontName: fontMonoBold parent: code textColor: '#bb0066' pygments-nv: parent: code textColor: '#336699' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: '#008800' pygments-p: parent: code textColor: black pygments-py: fontName: fontMonoBold parent: code textColor: '#336699' pygments-s: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-s1: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-s2: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-sa: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-sb: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-sc: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-sd: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-se: backColor: '#fff0f0' parent: code textColor: '#0044dd' pygments-sh: backColor: '#fff0f0' parent: code textColor: '#dd2200' pygments-si: backColor: '#fff0f0' parent: code textColor: '#3333bb' pygments-sr: backColor: '#fff0ff' parent: code textColor: '#008800' pygments-ss: backColor: '#fff0f0' parent: code textColor: '#aa6600' pygments-sx: backColor: '#f0fff0' parent: code textColor: '#22bb22' pygments-vc: parent: code textColor: '#336699' pygments-vg: parent: code textColor: '#dd7700' pygments-vi: parent: code textColor: '#3333bb' pygments-vm: parent: code textColor: '#336699' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/perldoc.yaml000066400000000000000000000113201463013543400203230ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#658b00' pygments-c: parent: code textColor: '#228B22' pygments-c1: parent: code textColor: '#228B22' pygments-ch: parent: code textColor: '#228B22' pygments-cm: parent: code textColor: '#228B22' pygments-cp: parent: code textColor: '#1e889b' pygments-cpf: parent: code textColor: '#228B22' pygments-cs: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-dl: parent: code textColor: '#CD5555' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#008b45' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: '#aa0000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00aa00' pygments-go: parent: code textColor: '#888888' pygments-gp: parent: code textColor: '#555555' pygments-gr: parent: code textColor: '#aa0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#aa0000' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#B452CD' pygments-k: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-kc: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-kd: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-kn: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-kp: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-kr: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-kt: fontName: fontMonoBold parent: code textColor: '#00688B' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#B452CD' pygments-mb: parent: code textColor: '#B452CD' pygments-mf: parent: code textColor: '#B452CD' pygments-mh: parent: code textColor: '#B452CD' pygments-mi: parent: code textColor: '#B452CD' pygments-mo: parent: code textColor: '#B452CD' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#658b00' pygments-nb: parent: code textColor: '#658b00' pygments-nc: fontName: fontMonoBold parent: code textColor: '#008b45' pygments-nd: parent: code textColor: '#707a7c' pygments-ne: fontName: fontMonoBold parent: code textColor: '#008b45' pygments-nf: parent: code textColor: '#008b45' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: '#008b45' pygments-no: parent: code textColor: '#00688B' pygments-nt: fontName: fontMonoBold parent: code textColor: '#8B008B' pygments-nv: parent: code textColor: '#00688B' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: '#8B008B' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#CD5555' pygments-s1: parent: code textColor: '#CD5555' pygments-s2: parent: code textColor: '#CD5555' pygments-sa: parent: code textColor: '#CD5555' pygments-sb: parent: code textColor: '#CD5555' pygments-sc: parent: code textColor: '#CD5555' pygments-sd: parent: code textColor: '#CD5555' pygments-se: parent: code textColor: '#CD5555' pygments-sh: fontName: fontMonoItalic parent: code textColor: '#1c7e71' pygments-si: parent: code textColor: '#CD5555' pygments-sr: parent: code textColor: '#1c7e71' pygments-ss: parent: code textColor: '#CD5555' pygments-sx: parent: code textColor: '#cb6c20' pygments-vc: parent: code textColor: '#00688B' pygments-vg: parent: code textColor: '#00688B' pygments-vi: parent: code textColor: '#00688B' pygments-vm: parent: code textColor: '#00688B' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/rainbow_dash.yaml000066400000000000000000000124531463013543400213430ustar00rootroot00000000000000styles: pygments-bp: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-c: fontName: fontMonoItalic parent: code textColor: '#0080ff' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#0080ff' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#0080ff' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#0080ff' pygments-cp: parent: code textColor: '#0080ff' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#0080ff' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#0080ff' pygments-dl: parent: code textColor: '#00cc66' pygments-err: backColor: '#cc0000' parent: code textColor: '#ffffff' pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoBold parent: code textColor: '#ff8000' pygments-g: parent: code textColor: black pygments-gd: backColor: '#ffcccc' parent: code textColor: black pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-gi: backColor: '#ccffcc' parent: code textColor: black pygments-go: parent: code textColor: '#aaaaaa' pygments-gp: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-gr: parent: code textColor: '#ff0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#c5060b' pygments-gu: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-k: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-kc: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-kd: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-kn: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-kp: parent: code textColor: '#2c5dcd' pygments-kr: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-kt: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-mb: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-mf: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-mh: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-mi: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-mo: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-n: parent: code textColor: black pygments-na: fontName: fontMonoItalic parent: code textColor: '#2c5dcd' pygments-nb: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-nc: parent: code textColor: black pygments-nd: fontName: fontMonoBold parent: code textColor: '#ff8000' pygments-ne: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-nf: fontName: fontMonoBold parent: code textColor: '#ff8000' pygments-ni: fontName: fontMonoBold parent: code textColor: '#5918bb' pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: '#318495' pygments-nt: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-nv: parent: code textColor: black pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: '#2c5dcd' pygments-ow: fontName: fontMonoBold parent: code textColor: '#2c5dcd' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#00cc66' pygments-s1: parent: code textColor: '#00cc66' pygments-s2: parent: code textColor: '#00cc66' pygments-sa: parent: code textColor: '#00cc66' pygments-sb: parent: code textColor: '#00cc66' pygments-sc: parent: code textColor: '#00cc66' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#00cc66' pygments-se: fontName: fontMonoBold parent: code textColor: '#c5060b' pygments-sh: parent: code textColor: '#00cc66' pygments-si: parent: code textColor: '#00cc66' pygments-sr: parent: code textColor: '#00cc66' pygments-ss: fontName: fontMonoBold parent: code textColor: '#c5060b' pygments-sx: parent: code textColor: '#318495' pygments-vc: parent: code textColor: black pygments-vg: parent: code textColor: black pygments-vi: parent: code textColor: black pygments-vm: parent: code textColor: black pygments-w: parent: code textColor: '#cbcbcb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/rrt.yaml000066400000000000000000000102331463013543400175040ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: parent: code textColor: '#00ff00' pygments-c1: parent: code textColor: '#00ff00' pygments-ch: parent: code textColor: '#00ff00' pygments-cm: parent: code textColor: '#00ff00' pygments-cp: parent: code textColor: '#e5e5e5' pygments-cpf: parent: code textColor: '#00ff00' pygments-cs: parent: code textColor: '#00ff00' pygments-dl: parent: code textColor: '#87ceeb' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#ffff00' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#0000ff' parent: code textColor: black pygments-il: parent: code textColor: black pygments-k: parent: code textColor: '#ff0000' pygments-kc: parent: code textColor: '#ff0000' pygments-kd: parent: code textColor: '#ff0000' pygments-kn: parent: code textColor: '#ff0000' pygments-kp: parent: code textColor: '#ff0000' pygments-kr: parent: code textColor: '#ff0000' pygments-kt: parent: code textColor: '#ee82ee' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: black pygments-mb: parent: code textColor: black pygments-mf: parent: code textColor: black pygments-mh: parent: code textColor: black pygments-mi: parent: code textColor: black pygments-mo: parent: code textColor: black pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: black pygments-nc: parent: code textColor: black pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: '#ffff00' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: '#7fffd4' pygments-nt: parent: code textColor: black pygments-nv: parent: code textColor: '#eedd82' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#87ceeb' pygments-s1: parent: code textColor: '#87ceeb' pygments-s2: parent: code textColor: '#87ceeb' pygments-sa: parent: code textColor: '#87ceeb' pygments-sb: parent: code textColor: '#87ceeb' pygments-sc: parent: code textColor: '#87ceeb' pygments-sd: parent: code textColor: '#87ceeb' pygments-se: parent: code textColor: '#87ceeb' pygments-sh: parent: code textColor: '#87ceeb' pygments-si: parent: code textColor: '#87ceeb' pygments-sr: parent: code textColor: '#87ceeb' pygments-ss: parent: code textColor: '#87ceeb' pygments-sx: parent: code textColor: '#87ceeb' pygments-vc: parent: code textColor: '#eedd82' pygments-vg: parent: code textColor: '#eedd82' pygments-vi: parent: code textColor: '#eedd82' pygments-vm: parent: code textColor: '#eedd82' pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/rst2pdf-0-9.yaml000066400000000000000000000314401463013543400205670ustar00rootroot00000000000000embeddedFonts: [] fontsAlias: fontSans: Helvetica fontSansBold: Helvetica-Bold fontSansBoldItalic: Helvetica-BoldOblique fontSansItalic: Helvetica-Oblique fontMono: Courier fontMonoBold: Courier-Bold fontMonoBoldItalic: Courier-BoldOblique fontMonoItalic: Courier-Oblique fontSerif: Times-Roman linkColor: navy pageSetup: firstTemplate: oneColumn height: null margin-bottom: 2cm margin-gutter: 0cm margin-left: 2cm margin-right: 2cm margin-top: 2cm size: A4 spacing-footer: 5mm spacing-header: 5mm width: null pageTemplates: coverPage: frames: - - 0cm - 0cm - 100% - 100% showFooter: false showHeader: false cutePage: defaultFooter: '###Page###' defaultHeader: '###Section###' frames: - - 0% - 0% - 100% - 100% showFooter: true showHeader: true emptyPage: frames: - - 0cm - 0cm - 100% - 100% showFooter: false showHeader: false oneColumn: frames: - - 0cm - 0cm - 100% - 100% showFooter: true showHeader: true threeColumn: frames: - - 2% - 0cm - 29.333% - 100% - - 35.333% - 0cm - 29.333% - 100% - - 68.666% - 0cm - 29.333% - 100% showFooter: true showHeader: true twoColumn: frames: - - 0cm - 0cm - 49% - 100% - - 51% - 0cm - 49% - 100% showFooter: true showHeader: true styles: aafigure: parent: literal abstract: parent: normal admonition: backColor: beige borderColor: darkgray borderPadding: - 16 - 16 - 16 - 16 borderWidth: 0.5 commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP parent: normal spaceAfter: 6 spaceBefore: 12 admonition-heading: parent: heading3 admonition-title: parent: heading3 attention: parent: admonition attention-heading: parent: admonition-heading attribution: alignment: TA_RIGHT parent: bodytext base: alignment: TA_LEFT allowOrphans: false allowWidows: false backColor: null borderColor: null borderPadding: 0 borderRadius: null borderWidth: 0 bulletFontName: fontSans bulletFontSize: 10 bulletIndent: 0 commands: [] firstLineIndent: 0 fontName: fontSans fontSize: 10 hyphenation: false leading: 12 leftIndent: 0 parent: null rightIndent: 0 spaceAfter: 0 spaceBefore: 0 strike: false textColor: black underline: false wordWrap: null blockquote: leftIndent: 20 parent: bodytext bodytext: alignment: TA_JUSTIFY hyphenation: true parent: normal spaceBefore: 6 bullet-list: colWidths: - '20' - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - RIGHTPADDING - - 0 - 0 - - 1 - -1 - 0 parent: bodytext bullet-list-item: parent: bodytext caution: parent: admonition caution-heading: parent: admonition-heading center: alignment: center parent: bodytext code: backColor: beige borderColor: darkgray borderPadding: 6 borderWidth: 0.5 leftIndent: 0 parent: literal spaceAfter: 8 spaceBefore: 8 contents: parent: normal danger: parent: admonition danger-heading: parent: admonition-heading dedication: parent: normal definition: bulletIndent: 0 colWidths: - 20pt - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - LEFTPADDING - - 0 - 0 - - -1 - -1 - 0 - - BOTTOMPADDING - - 0 - 0 - - -1 - -1 - 0 - - RIGHTPADDING - - 0 - 0 - - -1 - -1 - 0 firstLineIndent: 0 parent: bodytext spaceBefore: 0 definition-list-classifier: fontName: fontSansItalic parent: normal definition-list-term: fontName: fontSansBold keepWithNext: false parent: normal spaceAfter: 0 spaceBefore: 4 endnote: colWidths: - 3cm - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - TOPPADDING - - 0 - 0 - - -1 - -1 - 0 - - BOTTOMPADDING - - 0 - 0 - - -1 - -1 - 0 - - RIGHTPADDING - - 0 - 0 - - 1 - -1 - 0 parent: bodytext error: parent: admonition error-heading: parent: admonition-heading field-list: colWidths: - 3cm - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - TOPPADDING - - 0 - 0 - - -1 - -1 - 0 parent: bodytext spaceBefore: 6 fieldname: alignment: TA_RIGHT fontName: fontSansBold parent: bodytext fieldvalue: parent: bodytext figure: alignment: TA_CENTER colWidths: - 100% commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - ALIGN - - 0 - 0 - - -1 - -1 - CENTER parent: bodytext figure-caption: alignment: TA_CENTER fontName: fontSansItalic parent: bodytext figure-legend: parent: bodytext footer: alignment: TA_CENTER parent: normal header: alignment: TA_CENTER parent: normal heading: keepWithNext: true parent: normal spaceAfter: 6 spaceBefore: 12 heading1: fontName: fontSansBold fontSize: 175% parent: heading heading2: fontName: fontSansBold fontSize: 150% parent: heading heading3: fontName: fontSansBoldItalic fontSize: 125% parent: heading heading4: fontName: fontSansBoldItalic parent: heading heading5: fontName: fontSansBoldItalic parent: heading heading6: fontName: fontSansBoldItalic parent: heading hint: parent: admonition hint-heading: parent: admonition-heading image: alignment: TA_CENTER parent: bodytext important: parent: admonition important-heading: parent: admonition-heading italic: fontName: fontSansItalic parent: bodytext item-list: colWidths: - 20pt - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - RIGHTPADDING - - 0 - 0 - - 1 - -1 - 0 parent: bodytext item-list-item: parent: bodytext line: parent: lineblock spaceBefore: 0 lineblock: parent: bodytext linenumber: parent: code literal: firstLineIndent: 0 fontName: fontMono hyphenation: false parent: normal wordWrap: null normal: parent: base note: parent: admonition note-heading: parent: admonition-heading option-list: colWidths: - null - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - TOPPADDING - - 0 - 0 - - -1 - -1 - 0 pygments-bp: parent: code textColor: '#AA22FF' pygments-c: parent: code textColor: '#008800' pygments-c1: parent: code textColor: '#008800' pygments-cm: parent: code textColor: '#008800' pygments-cp: parent: code textColor: '#008800' pygments-cs: parent: code textColor: '#008800' pygments-diml: parent: code textColor: '#aaaaaa' pygments-err: parent: code pygments-gd: parent: code textColor: '#A00000' pygments-ge: parent: code pygments-gh: parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#808080' pygments-gp: parent: code textColor: '#000080' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: parent: code pygments-gt: parent: code textColor: '#0040D0' pygments-gu: parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code pygments-il: parent: code textColor: '#666666' pygments-k: parent: code textColor: '#AA22FF' pygments-kc: parent: code textColor: '#AA22FF' pygments-kd: parent: code textColor: '#AA22FF' pygments-kn: parent: code textColor: '#AA22FF' pygments-kp: parent: code textColor: '#AA22FF' pygments-kr: parent: code textColor: '#AA22FF' pygments-kt: parent: code textColor: '#00BB00' pygments-m: parent: code textColor: '#666666' pygments-mf: parent: code textColor: '#666666' pygments-mh: parent: code textColor: '#666666' pygments-mi: parent: code textColor: '#666666' pygments-mo: parent: code textColor: '#666666' pygments-n: parent: code pygments-na: parent: code textColor: '#BB4444' pygments-nb: parent: code textColor: '#AA22FF' pygments-nc: parent: code textColor: '#0000FF' pygments-nd: parent: code textColor: '#AA22FF' pygments-ne: parent: code textColor: '#D2413A' pygments-nf: parent: code textColor: '#00A000' pygments-ni: parent: code textColor: '#999999' pygments-nl: parent: code textColor: '#A0A000' pygments-nn: parent: code textColor: '#0000FF' pygments-no: parent: code textColor: '#880000' pygments-nt: parent: code textColor: '#008000' pygments-nv: parent: code textColor: '#B8860B' pygments-nx: parent: code pygments-o: parent: code textColor: '#666666' pygments-ow: parent: code textColor: '#AA22FF' pygments-p: parent: code pygments-s: parent: code textColor: '#BB4444' pygments-s1: parent: code textColor: '#BB4444' pygments-s2: parent: code textColor: '#BB4444' pygments-sb: parent: code textColor: '#BB4444' pygments-sc: parent: code textColor: '#BB4444' pygments-sd: parent: code textColor: '#BB4444' pygments-se: parent: code textColor: '#BB6622' pygments-sh: parent: code textColor: '#BB4444' pygments-si: parent: code textColor: '#BB6688' pygments-sr: parent: code textColor: '#BB6688' pygments-ss: parent: code textColor: '#B8860B' pygments-sx: parent: code textColor: '#008000' pygments-vc: parent: code textColor: '#B8860B' pygments-vg: parent: code textColor: '#B8860B' pygments-vi: parent: code textColor: '#B8860B' pygments-w: parent: code textColor: '#bbbbbb' right: alignment: right parent: bodytext rubric: alignment: TA_CENTER parent: bodytext textColor: darkred separation: parent: normal sidebar: backColor: beige borderColor: darkgray borderPadding: 8 borderWidth: 0.5 float: none parent: normal width: 100% sidebar-subtitle: parent: heading4 sidebar-title: parent: heading3 subtitle: fontSize: 75% parent: title spaceBefore: 12 table: alignment: TA_CENTER commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - INNERGRID - - 0 - 0 - - -1 - -1 - 0.25 - black - - ROWBACKGROUNDS - - 0 - 0 - - -1 - -1 - - white - '#E0E0E0' - - BOX - - 0 - 0 - - -1 - -1 - 0.25 - black spaceAfter: 0 spaceBefore: 6 table-body: parent: normal table-heading: alignment: TA_CENTER backColor: beige borderPadding: 0 parent: normal valign: BOTTOM table-title: alignment: TA_CENTER keepWithNext: false parent: heading4 tableofcontents: parent: normal tip: parent: admonition tip-heading: parent: admonition-heading title: alignment: TA_CENTER fontName: fontSansBold fontSize: 200% keepWithNext: false parent: heading spaceAfter: 10 title-reference: fontName: fontSansItalic parent: normal toc: parent: normal fontName: fontSans fontSize: 100% toc1: fontName: fontSansBold parent: toc toc10: leftIndent: 100 parent: toc toc11: leftIndent: 100 parent: toc toc12: leftIndent: 100 parent: toc toc13: leftIndent: 100 parent: toc toc14: leftIndent: 100 parent: toc toc15: leftIndent: 100 parent: toc toc2: leftIndent: 20 parent: toc toc3: leftIndent: 40 parent: toc toc4: leftIndent: 60 parent: toc toc5: leftIndent: 80 parent: toc toc6: leftIndent: 100 parent: toc toc7: leftIndent: 100 parent: toc toc8: leftIndent: 100 parent: toc toc9: leftIndent: 100 parent: toc topic-title: parent: heading3 warning: parent: admonition warning-heading: parent: admonition-heading rst2pdf-0.102/rst2pdf/styles/sas.yaml000066400000000000000000000116301463013543400174650ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#2c2cff' pygments-c: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cp: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-dl: parent: code textColor: '#800080' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoItalic parent: code textColor: black pygments-g: parent: code textColor: '#2c2cff' pygments-gd: parent: code textColor: '#2c2cff' pygments-ge: parent: code textColor: '#008800' pygments-gh: parent: code textColor: '#2c2cff' pygments-gi: parent: code textColor: '#2c2cff' pygments-go: parent: code textColor: '#2c2cff' pygments-gp: parent: code textColor: '#2c2cff' pygments-gr: parent: code textColor: '#d30202' pygments-gs: parent: code textColor: '#2c2cff' pygments-gt: parent: code textColor: '#2c2cff' pygments-gu: parent: code textColor: '#2c2cff' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: fontName: fontMonoBold parent: code textColor: '#2e8b57' pygments-k: parent: code textColor: '#2c2cff' pygments-kc: fontName: fontMonoBold parent: code textColor: '#2c2cff' pygments-kd: parent: code textColor: '#2c2cff' pygments-kn: parent: code textColor: '#2c2cff' pygments-kp: parent: code textColor: '#2c2cff' pygments-kr: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kt: parent: code textColor: '#2c2cff' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: fontName: fontMonoBold parent: code textColor: '#2e8b57' pygments-mb: fontName: fontMonoBold parent: code textColor: '#2e8b57' pygments-mf: fontName: fontMonoBold parent: code textColor: '#2e8b57' pygments-mh: fontName: fontMonoBold parent: code textColor: '#2e8b57' pygments-mi: fontName: fontMonoBold parent: code textColor: '#2e8b57' pygments-mo: fontName: fontMonoBold parent: code textColor: '#2e8b57' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: '#2c2cff' pygments-nc: parent: code textColor: black pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: fontName: fontMonoItalic parent: code textColor: black pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: parent: code textColor: black pygments-nv: fontName: fontMonoBold parent: code textColor: '#2c2cff' pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#800080' pygments-s1: parent: code textColor: '#800080' pygments-s2: parent: code textColor: '#800080' pygments-sa: parent: code textColor: '#800080' pygments-sb: parent: code textColor: '#800080' pygments-sc: parent: code textColor: '#800080' pygments-sd: parent: code textColor: '#800080' pygments-se: parent: code textColor: '#800080' pygments-sh: parent: code textColor: '#800080' pygments-si: parent: code textColor: '#800080' pygments-sr: parent: code textColor: '#800080' pygments-ss: parent: code textColor: '#800080' pygments-sx: parent: code textColor: '#800080' pygments-vc: fontName: fontMonoBold parent: code textColor: '#2c2cff' pygments-vg: fontName: fontMonoBold parent: code textColor: '#2c2cff' pygments-vi: fontName: fontMonoBold parent: code textColor: '#2c2cff' pygments-vm: fontName: fontMonoBold parent: code textColor: '#2c2cff' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: backColor: '#ffffe0' parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/serif.yaml000066400000000000000000000000441463013543400200040ustar00rootroot00000000000000fontsAlias: fontSans: Times-Roman rst2pdf-0.102/rst2pdf/styles/solarized-dark.yaml000066400000000000000000000110701463013543400216100ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#268bd2' pygments-c: fontName: fontMonoItalic parent: code textColor: '#586e75' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#586e75' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#586e75' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#586e75' pygments-cp: parent: code textColor: '#d33682' pygments-cpf: parent: code textColor: '#586e75' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#586e75' pygments-dl: parent: code textColor: '#2aa198' pygments-err: backColor: '#dc322f' parent: code textColor: '#839496' pygments-esc: parent: code textColor: '#839496' pygments-fm: parent: code textColor: '#268bd2' pygments-g: parent: code textColor: '#839496' pygments-gd: parent: code textColor: '#dc322f' pygments-ge: fontName: fontMonoItalic parent: code textColor: '#839496' pygments-gh: fontName: fontMonoBold parent: code textColor: '#839496' pygments-gi: parent: code textColor: '#859900' pygments-go: parent: code textColor: '#839496' pygments-gp: parent: code textColor: '#839496' pygments-gr: parent: code textColor: '#dc322f' pygments-gs: fontName: fontMonoBold parent: code textColor: '#839496' pygments-gt: parent: code textColor: '#268bd2' pygments-gu: parent: code textColor: '#839496' pygments-hll: backColor: '#073642' parent: code textColor: black pygments-il: parent: code textColor: '#2aa198' pygments-k: parent: code textColor: '#859900' pygments-kc: parent: code textColor: '#2aa198' pygments-kd: parent: code textColor: '#2aa198' pygments-kn: parent: code textColor: '#cb4b16' pygments-kp: parent: code textColor: '#859900' pygments-kr: parent: code textColor: '#859900' pygments-kt: parent: code textColor: '#b58900' pygments-l: parent: code textColor: '#839496' pygments-ld: parent: code textColor: '#839496' pygments-m: parent: code textColor: '#2aa198' pygments-mb: parent: code textColor: '#2aa198' pygments-mf: parent: code textColor: '#2aa198' pygments-mh: parent: code textColor: '#2aa198' pygments-mi: parent: code textColor: '#2aa198' pygments-mo: parent: code textColor: '#2aa198' pygments-n: parent: code textColor: '#839496' pygments-na: parent: code textColor: '#839496' pygments-nb: parent: code textColor: '#268bd2' pygments-nc: parent: code textColor: '#268bd2' pygments-nd: parent: code textColor: '#268bd2' pygments-ne: parent: code textColor: '#268bd2' pygments-nf: parent: code textColor: '#268bd2' pygments-ni: parent: code textColor: '#268bd2' pygments-nl: parent: code textColor: '#268bd2' pygments-nn: parent: code textColor: '#268bd2' pygments-no: parent: code textColor: '#268bd2' pygments-nt: parent: code textColor: '#268bd2' pygments-nv: parent: code textColor: '#268bd2' pygments-nx: parent: code textColor: '#839496' pygments-o: parent: code textColor: '#586e75' pygments-ow: parent: code textColor: '#859900' pygments-p: parent: code textColor: '#839496' pygments-py: parent: code textColor: '#839496' pygments-s: parent: code textColor: '#2aa198' pygments-s1: parent: code textColor: '#2aa198' pygments-s2: parent: code textColor: '#2aa198' pygments-sa: parent: code textColor: '#2aa198' pygments-sb: parent: code textColor: '#2aa198' pygments-sc: parent: code textColor: '#2aa198' pygments-sd: parent: code textColor: '#586e75' pygments-se: parent: code textColor: '#2aa198' pygments-sh: parent: code textColor: '#2aa198' pygments-si: parent: code textColor: '#2aa198' pygments-sr: parent: code textColor: '#cb4b16' pygments-ss: parent: code textColor: '#2aa198' pygments-sx: parent: code textColor: '#2aa198' pygments-vc: parent: code textColor: '#268bd2' pygments-vg: parent: code textColor: '#268bd2' pygments-vi: parent: code textColor: '#268bd2' pygments-vm: parent: code textColor: '#268bd2' pygments-w: parent: code textColor: '#839496' pygments-x: parent: code textColor: '#839496' rst2pdf-0.102/rst2pdf/styles/solarized-light.yaml000066400000000000000000000110701463013543400217760ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#268bd2' pygments-c: fontName: fontMonoItalic parent: code textColor: '#93a1a1' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#93a1a1' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#93a1a1' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#93a1a1' pygments-cp: parent: code textColor: '#d33682' pygments-cpf: parent: code textColor: '#93a1a1' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#93a1a1' pygments-dl: parent: code textColor: '#2aa198' pygments-err: backColor: '#dc322f' parent: code textColor: '#657b83' pygments-esc: parent: code textColor: '#657b83' pygments-fm: parent: code textColor: '#268bd2' pygments-g: parent: code textColor: '#657b83' pygments-gd: parent: code textColor: '#dc322f' pygments-ge: fontName: fontMonoItalic parent: code textColor: '#657b83' pygments-gh: fontName: fontMonoBold parent: code textColor: '#657b83' pygments-gi: parent: code textColor: '#859900' pygments-go: parent: code textColor: '#657b83' pygments-gp: parent: code textColor: '#657b83' pygments-gr: parent: code textColor: '#dc322f' pygments-gs: fontName: fontMonoBold parent: code textColor: '#657b83' pygments-gt: parent: code textColor: '#268bd2' pygments-gu: parent: code textColor: '#657b83' pygments-hll: backColor: '#eee8d5' parent: code textColor: black pygments-il: parent: code textColor: '#2aa198' pygments-k: parent: code textColor: '#859900' pygments-kc: parent: code textColor: '#2aa198' pygments-kd: parent: code textColor: '#2aa198' pygments-kn: parent: code textColor: '#cb4b16' pygments-kp: parent: code textColor: '#859900' pygments-kr: parent: code textColor: '#859900' pygments-kt: parent: code textColor: '#b58900' pygments-l: parent: code textColor: '#657b83' pygments-ld: parent: code textColor: '#657b83' pygments-m: parent: code textColor: '#2aa198' pygments-mb: parent: code textColor: '#2aa198' pygments-mf: parent: code textColor: '#2aa198' pygments-mh: parent: code textColor: '#2aa198' pygments-mi: parent: code textColor: '#2aa198' pygments-mo: parent: code textColor: '#2aa198' pygments-n: parent: code textColor: '#657b83' pygments-na: parent: code textColor: '#657b83' pygments-nb: parent: code textColor: '#268bd2' pygments-nc: parent: code textColor: '#268bd2' pygments-nd: parent: code textColor: '#268bd2' pygments-ne: parent: code textColor: '#268bd2' pygments-nf: parent: code textColor: '#268bd2' pygments-ni: parent: code textColor: '#268bd2' pygments-nl: parent: code textColor: '#268bd2' pygments-nn: parent: code textColor: '#268bd2' pygments-no: parent: code textColor: '#268bd2' pygments-nt: parent: code textColor: '#268bd2' pygments-nv: parent: code textColor: '#268bd2' pygments-nx: parent: code textColor: '#657b83' pygments-o: parent: code textColor: '#93a1a1' pygments-ow: parent: code textColor: '#859900' pygments-p: parent: code textColor: '#657b83' pygments-py: parent: code textColor: '#657b83' pygments-s: parent: code textColor: '#2aa198' pygments-s1: parent: code textColor: '#2aa198' pygments-s2: parent: code textColor: '#2aa198' pygments-sa: parent: code textColor: '#2aa198' pygments-sb: parent: code textColor: '#2aa198' pygments-sc: parent: code textColor: '#2aa198' pygments-sd: parent: code textColor: '#93a1a1' pygments-se: parent: code textColor: '#2aa198' pygments-sh: parent: code textColor: '#2aa198' pygments-si: parent: code textColor: '#2aa198' pygments-sr: parent: code textColor: '#cb4b16' pygments-ss: parent: code textColor: '#2aa198' pygments-sx: parent: code textColor: '#2aa198' pygments-vc: parent: code textColor: '#268bd2' pygments-vg: parent: code textColor: '#268bd2' pygments-vi: parent: code textColor: '#268bd2' pygments-vm: parent: code textColor: '#268bd2' pygments-w: parent: code textColor: '#657b83' pygments-x: parent: code textColor: '#657b83' rst2pdf-0.102/rst2pdf/styles/sphinx.yaml000066400000000000000000000170051463013543400202120ustar00rootroot00000000000000pageSetup: firstTemplate: coverPage margin-bottom: 8mm margin-left: 12mm margin-right: 12mm margin-top: 8mm styles: admonition: backColor: '#EEFFCC' borderColor: '#AACC99' borderPadding: 8 borderWidth: 0.5 commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP spaceAfter: 6 spaceBefore: 12 admonition-heading: backColor: null borderColor: null borderPadding: 0 borderWidth: 0 leftIndent: 0 parent: heading3 textColor: black admonition-title: backColor: null borderColor: null borderPadding: 0 borderWidth: 0 leftIndent: 0 parent: heading3 attribute: parent: bodytext author: alignment: TA_CENTER fontName: fontSansBold fontSize: 120% parent: bodytext centered: alignment: TA_CENTER fontName: fontSerif parent: bodytext class: parent: bodytext code: allowOrphans: false allowWidows: false backColor: null borderColor: null borderPadding: - 6 - 0 - 0 - 4 borderWidth: 0.3 spaceBefore: 0 confval: parent: bodytext data: parent: bodytext desc: parent: bodytext spaceBefore: 6 descclassname: fontName: fontMono parent: literal descname: fontName: fontMonoBold parent: literal descparameter: fontName: fontMono parent: literal desctype: fontName: fontMono parent: literal directive: parent: bodytext exception: parent: bodytext heading: backColor: '#F2F2F2' borderColor: '#CCCCCC' borderPadding: - 6 - 0 - 0 - 10 borderWidth: 0.3 fontName: fontSansBold fontSize: 10 leading: 10 leftIndent: 0 spaceBefore: 16 textColor: '#20435C' heading1: fontSize: 200% heading2: fontSize: 160% heading3: fontSize: 140% heading4: fontSize: 120% heading5: fontSize: 110% heading6: fontSize: 100% hlist: alignment: TA_CENTER commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP parent: normal spaceAfter: 0 spaceBefore: 6 kbd: parent: bodytext method: fontName: fontSansBold parent: bodytext note: backColor: '#EEEEEE' borderColor: '#CCCCCC' parent: admonition optional: fontName: fontMonoBold parent: literal pygments-bp: parent: code textColor: '#007020' pygments-c: parent: code textColor: '#808080' pygments-c1: parent: code textColor: '#808080' pygments-cm: parent: code textColor: '#808080' pygments-cp: parent: code textColor: '#507090' pygments-cs: fontName: fontMonoBold parent: code textColor: '#cc0000' pygments-err: backColor: '#F0A0A0' parent: code textColor: '#F00000' pygments-gd: parent: code textColor: '#A00000' pygments-ge: fontName: fontMonoItalic parent: code pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#808080' pygments-gp: fontName: fontMonoBold parent: code textColor: '#c65d09' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code pygments-gt: parent: code textColor: '#0040D0' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code pygments-il: fontName: fontMonoBold parent: code textColor: '#0000D0' pygments-k: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kc: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kd: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kn: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kp: fontName: fontMonoBold parent: code textColor: '#003080' pygments-kr: fontName: fontMonoBold parent: code textColor: '#008000' pygments-kt: fontName: fontMonoBold parent: code textColor: '#303090' pygments-m: fontName: fontMonoBold parent: code textColor: '#6000E0' pygments-mf: fontName: fontMonoBold parent: code textColor: '#6000E0' pygments-mh: fontName: fontMonoBold parent: code textColor: '#005080' pygments-mi: fontName: fontMonoBold parent: code textColor: '#0000D0' pygments-mo: fontName: fontMonoBold parent: code textColor: '#4000E0' pygments-n-identifier: parent: code pygments-na: parent: code textColor: '#0000C0' pygments-nb: parent: code textColor: '#007020' pygments-nc: fontName: fontMonoBold parent: code textColor: '#B00060' pygments-nd: fontName: fontMonoBold parent: code textColor: '#505050' pygments-ne: fontName: fontMonoBold parent: code textColor: '#F00000' pygments-nf: fontName: fontMonoBold parent: code textColor: '#0060B0' pygments-ni: fontName: fontMonoBold parent: code textColor: '#800000' pygments-nl: fontName: fontMonoBold parent: code textColor: '#907000' pygments-nn: fontName: fontMonoBold parent: code textColor: '#0e84b5' pygments-no: fontName: fontMonoBold parent: code textColor: '#003060' pygments-nt: parent: code textColor: '#007000' pygments-nv: parent: code textColor: '#906030' pygments-o: parent: code textColor: '#303030' pygments-ow: fontName: fontMonoBold parent: code textColor: '#000000' pygments-s: backColor: '#fff0f0' parent: code pygments-s1: backColor: '#fff0f0' parent: code pygments-s2: backColor: '#fff0f0' parent: code pygments-sb: backColor: '#fff0f0' parent: code pygments-sc: parent: code textColor: '#0040D0' pygments-sd: parent: code textColor: '#D04020' pygments-se: backColor: '#fff0f0' fontName: fontMonoBold parent: code textColor: '#606060' pygments-sh: backColor: '#fff0f0' parent: code pygments-si: backColor: '#e0e0e0' parent: code pygments-sr: backColor: '#fff0ff' parent: code textColor: '#000000' pygments-ss: parent: code textColor: '#A06000' pygments-sx: backColor: '#fff0f0' parent: code textColor: '#D02000' pygments-vc: parent: code textColor: '#306090' pygments-vg: fontName: fontMonoBold parent: code textColor: '#d07000' pygments-vi: parent: code textColor: '#3030B0' pygments-w: parent: code textColor: '#bbbbbb' returns: parent: bodytext role: parent: bodytext seealso: backColor: '#FFFFCC' borderColor: '#FFFF66' parent: admonition sidebar: backColor: '#EEFFCC' borderColor: '#AACC99' borderPadding: 8 borderWidth: 0.5 spaceAfter: 6 spaceBefore: 12 sidebar-subtitle: backColor: null borderColor: null borderPadding: 0 borderWidth: 0 leftIndent: 0 parent: heading4 spaceBefore: 0 sidebar-title: backColor: null borderColor: null borderPadding: 0 borderWidth: 0 leftIndent: 0 parent: heading3 table-heading: borderWidth: 0 parent: heading todo-node: backColor: '#FFFFFF' borderColor: '#CCCCCC' parent: admonition versionmodified: fontName: fontSansItalic parent: bodytext warning: backColor: '#FFE4E4' borderColor: '#FF6666' parent: admonition xref: fontName: fontMonoBold parent: code rst2pdf-0.102/rst2pdf/styles/stata-dark.yaml000066400000000000000000000113531463013543400207340ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: '#777777' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#777777' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#777777' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#777777' pygments-cp: fontName: fontMonoItalic parent: code textColor: '#777777' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#777777' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#777777' pygments-dl: parent: code textColor: '#51cc99' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#6a6aff' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: '#ffffff' pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#49483e' parent: code textColor: black pygments-il: parent: code textColor: '#4FB8CC' pygments-k: fontName: fontMonoBold parent: code textColor: '#7686bb' pygments-kc: fontName: fontMonoBold parent: code textColor: '#7686bb' pygments-kd: fontName: fontMonoBold parent: code textColor: '#7686bb' pygments-kn: fontName: fontMonoBold parent: code textColor: '#7686bb' pygments-kp: fontName: fontMonoBold parent: code textColor: '#7686bb' pygments-kr: fontName: fontMonoBold parent: code textColor: '#7686bb' pygments-kt: fontName: fontMonoBold parent: code textColor: '#7686bb' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#4FB8CC' pygments-mb: parent: code textColor: '#4FB8CC' pygments-mf: parent: code textColor: '#4FB8CC' pygments-mh: parent: code textColor: '#4FB8CC' pygments-mi: parent: code textColor: '#4FB8CC' pygments-mo: parent: code textColor: '#4FB8CC' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: black pygments-nc: parent: code textColor: black pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: '#6a6aff' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: parent: code textColor: black pygments-nv: fontName: fontMonoBold parent: code textColor: '#7AB4DB' pygments-nx: parent: code textColor: '#e2828e' pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#51cc99' pygments-s1: parent: code textColor: '#51cc99' pygments-s2: parent: code textColor: '#51cc99' pygments-sa: parent: code textColor: '#51cc99' pygments-sb: parent: code textColor: '#51cc99' pygments-sc: parent: code textColor: '#51cc99' pygments-sd: parent: code textColor: '#51cc99' pygments-se: parent: code textColor: '#51cc99' pygments-sh: parent: code textColor: '#51cc99' pygments-si: parent: code textColor: '#51cc99' pygments-sr: parent: code textColor: '#51cc99' pygments-ss: parent: code textColor: '#51cc99' pygments-sx: parent: code textColor: '#51cc99' pygments-vc: fontName: fontMonoBold parent: code textColor: '#7AB4DB' pygments-vg: fontName: fontMonoBold parent: code textColor: '#BE646C' pygments-vi: fontName: fontMonoBold parent: code textColor: '#7AB4DB' pygments-vm: fontName: fontMonoBold parent: code textColor: '#7AB4DB' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/stata-light.yaml000066400000000000000000000113471463013543400211250ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cp: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-dl: parent: code textColor: '#7a2424' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#2c2cff' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#2c2cff' pygments-k: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kc: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kd: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kn: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kp: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kr: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kt: fontName: fontMonoBold parent: code textColor: '#353580' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#2c2cff' pygments-mb: parent: code textColor: '#2c2cff' pygments-mf: parent: code textColor: '#2c2cff' pygments-mh: parent: code textColor: '#2c2cff' pygments-mi: parent: code textColor: '#2c2cff' pygments-mo: parent: code textColor: '#2c2cff' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: black pygments-nc: parent: code textColor: black pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: '#2c2cff' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: parent: code textColor: black pygments-nv: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-nx: parent: code textColor: '#be646c' pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#7a2424' pygments-s1: parent: code textColor: '#7a2424' pygments-s2: parent: code textColor: '#7a2424' pygments-sa: parent: code textColor: '#7a2424' pygments-sb: parent: code textColor: '#7a2424' pygments-sc: parent: code textColor: '#7a2424' pygments-sd: parent: code textColor: '#7a2424' pygments-se: parent: code textColor: '#7a2424' pygments-sh: parent: code textColor: '#7a2424' pygments-si: parent: code textColor: '#7a2424' pygments-sr: parent: code textColor: '#7a2424' pygments-ss: parent: code textColor: '#7a2424' pygments-sx: parent: code textColor: '#7a2424' pygments-vc: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-vg: fontName: fontMonoBold parent: code textColor: '#b5565e' pygments-vi: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-vm: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/stata.yaml000066400000000000000000000113471463013543400200200ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cp: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#008800' pygments-dl: parent: code textColor: '#7a2424' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#2c2cff' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#2c2cff' pygments-k: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kc: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kd: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kn: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kp: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kr: fontName: fontMonoBold parent: code textColor: '#353580' pygments-kt: fontName: fontMonoBold parent: code textColor: '#353580' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#2c2cff' pygments-mb: parent: code textColor: '#2c2cff' pygments-mf: parent: code textColor: '#2c2cff' pygments-mh: parent: code textColor: '#2c2cff' pygments-mi: parent: code textColor: '#2c2cff' pygments-mo: parent: code textColor: '#2c2cff' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: black pygments-nc: parent: code textColor: black pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: '#2c2cff' pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: parent: code textColor: black pygments-nv: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-nx: parent: code textColor: '#be646c' pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#7a2424' pygments-s1: parent: code textColor: '#7a2424' pygments-s2: parent: code textColor: '#7a2424' pygments-sa: parent: code textColor: '#7a2424' pygments-sb: parent: code textColor: '#7a2424' pygments-sc: parent: code textColor: '#7a2424' pygments-sd: parent: code textColor: '#7a2424' pygments-se: parent: code textColor: '#7a2424' pygments-sh: parent: code textColor: '#7a2424' pygments-si: parent: code textColor: '#7a2424' pygments-sr: parent: code textColor: '#7a2424' pygments-ss: parent: code textColor: '#7a2424' pygments-sx: parent: code textColor: '#7a2424' pygments-vc: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-vg: fontName: fontMonoBold parent: code textColor: '#b5565e' pygments-vi: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-vm: fontName: fontMonoBold parent: code textColor: '#35baba' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/styles.yaml000066400000000000000000000311561463013543400202270ustar00rootroot00000000000000embeddedFonts: [] fontsAlias: fontSerifBold: Times-Bold fontSerifBoldItalic: Times-BoldItalic fontSerif: Times-Roman fontSerifItalic: Times-Italic fontMono: Courier fontMonoBold: Courier-Bold fontMonoBoldItalic: Courier-BoldOblique fontMonoItalic: Courier-Oblique fontSans: Helvetica fontSansBold: Helvetica-Bold fontSansBoldItalic: Helvetica-BoldOblique fontSansItalic: Helvetica-Oblique linkColor: "#006699" pageSetup: firstTemplate: mainPage height: null margin-bottom: 1.5cm margin-gutter: 0cm margin-left: 1.8cm margin-right: 1.8cm margin-top: 2cm size: A4 spacing-footer: 5mm spacing-header: 5mm width: null pageTemplates: mainPage: frames: - - 0% - 0% - 100% - 100% showFooter: true showHeader: true decoratedPage: defaultFooter: '###Page###' defaultHeader: '###Section###' frames: - - 0% - 0% - 100% - 100% showFooter: true showHeader: true emptyPage: frames: - - 0cm - 0cm - 100% - 100% showFooter: false showHeader: false coverPage: frames: - - 0cm - 0cm - 100% - 100% showFooter: false showHeader: false oneColumn: frames: - - 0cm - 0cm - 100% - 100% showFooter: true showHeader: true twoColumn: frames: - - 0cm - 0cm - 49% - 100% - - 51% - 0cm - 49% - 100% showFooter: true showHeader: true styles: aafigure: parent: literal abstract: parent: normal admonition: backColor: cornsilk borderColor: darkgray borderPadding: - 16 - 16 - 16 - 16 borderWidth: 0.5 commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP parent: normal spaceAfter: 6 spaceBefore: 12 admonition-heading: parent: heading3 admonition-title: parent: heading3 attention: parent: admonition attention-heading: parent: admonition-heading attribution: alignment: TA_RIGHT parent: bodytext base: alignment: TA_LEFT allowOrphans: false allowWidows: false backColor: null borderColor: null borderPadding: 0 borderRadius: null borderWidth: 0 bulletFontName: fontMono bulletFontSize: 10 bulletIndent: 0 commands: [] firstLineIndent: 0 fontName: fontSans fontSize: 10 hyphenation: false leading: 12 leftIndent: 0 parent: null rightIndent: 0 spaceAfter: 0 spaceBefore: 0 strike: false textColor: black underline: false wordWrap: null blockquote: leftIndent: 20 parent: bodytext bodytext: alignment: TA_JUSTIFY hyphenation: true parent: normal spaceBefore: 6 bullet-list: colWidths: - '20' - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - RIGHTPADDING - - 0 - 0 - - 1 - -1 - 0 parent: bodytext bullet-list-item: parent: bodytext caution: parent: admonition caution-heading: parent: admonition-heading center: alignment: center parent: bodytext code: backColor: aliceblue borderColor: darkgray borderPadding: 6 borderWidth: 0.5 leftIndent: 0 parent: literal spaceAfter: 8 spaceBefore: 8 contents: parent: normal danger: parent: admonition danger-heading: parent: admonition-heading dedication: parent: normal definition: bulletIndent: 0 colWidths: - 20pt - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - LEFTPADDING - - 0 - 0 - - -1 - -1 - 0 - - BOTTOMPADDING - - 0 - 0 - - -1 - -1 - 0 - - RIGHTPADDING - - 0 - 0 - - -1 - -1 - 0 firstLineIndent: 0 parent: bodytext spaceBefore: 0 definition-list-classifier: fontName: fontSansItalic parent: normal definition-list-term: fontName: fontSansBold keepWithNext: false parent: normal spaceAfter: 0 spaceBefore: 4 endnote: colWidths: - 3cm - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - TOPPADDING - - 0 - 0 - - -1 - -1 - 0 - - BOTTOMPADDING - - 0 - 0 - - -1 - -1 - 0 - - RIGHTPADDING - - 0 - 0 - - 1 - -1 - 0 parent: bodytext error: parent: admonition error-heading: parent: admonition-heading field-list: colWidths: - 3cm - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - TOPPADDING - - 0 - 0 - - -1 - -1 - 0 parent: bodytext spaceBefore: 6 fieldname: alignment: TA_RIGHT fontName: fontSansBold parent: bodytext fieldvalue: parent: bodytext figure: alignment: TA_CENTER colWidths: - 100% commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - ALIGN - - 0 - 0 - - -1 - -1 - CENTER parent: bodytext figure-caption: alignment: TA_CENTER fontName: fontSansItalic parent: bodytext figure-legend: parent: bodytext footer: alignment: TA_CENTER parent: normal header: alignment: TA_CENTER parent: normal heading: keepWithNext: true parent: normal spaceAfter: 6 spaceBefore: 12 fontName: fontSerif textColor: "#222222" heading1: fontSize: 175% parent: heading heading2: fontSize: 150% parent: heading heading3: fontSize: 125% parent: heading heading4: parent: heading heading5: parent: heading heading6: parent: heading hint: parent: admonition hint-heading: parent: admonition-heading image: alignment: TA_CENTER parent: bodytext important: parent: admonition important-heading: parent: admonition-heading italic: fontName: fontSansItalic parent: bodytext item-list: colWidths: - 20pt - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - RIGHTPADDING - - 0 - 0 - - 1 - -1 - 0 parent: bodytext item-list-item: parent: bodytext line: parent: lineblock spaceBefore: 0 lineblock: parent: bodytext linenumber: parent: code literal: firstLineIndent: 0 fontName: fontMono hyphenation: false parent: normal wordWrap: null normal: parent: base note: parent: admonition note-heading: parent: admonition-heading option-list: colWidths: - null - null commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - TOPPADDING - - 0 - 0 - - -1 - -1 - 0 pygments-bp: parent: code textColor: '#AA22FF' pygments-c: parent: code textColor: '#008800' pygments-c1: parent: code textColor: '#008800' pygments-cm: parent: code textColor: '#008800' pygments-cp: parent: code textColor: '#008800' pygments-cs: parent: code textColor: '#008800' pygments-diml: parent: code textColor: '#aaaaaa' pygments-err: parent: code pygments-gd: parent: code textColor: '#A00000' pygments-ge: parent: code pygments-gh: parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: parent: code textColor: '#808080' pygments-gp: parent: code textColor: '#000080' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: parent: code pygments-gt: parent: code textColor: '#0040D0' pygments-gu: parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code pygments-il: parent: code textColor: '#666666' pygments-k: parent: code textColor: '#AA22FF' pygments-kc: parent: code textColor: '#AA22FF' pygments-kd: parent: code textColor: '#AA22FF' pygments-kn: parent: code textColor: '#AA22FF' pygments-kp: parent: code textColor: '#AA22FF' pygments-kr: parent: code textColor: '#AA22FF' pygments-kt: parent: code textColor: '#00BB00' pygments-m: parent: code textColor: '#666666' pygments-mf: parent: code textColor: '#666666' pygments-mh: parent: code textColor: '#666666' pygments-mi: parent: code textColor: '#666666' pygments-mo: parent: code textColor: '#666666' pygments-n: parent: code pygments-na: parent: code textColor: '#BB4444' pygments-nb: parent: code textColor: '#AA22FF' pygments-nc: parent: code textColor: '#0000FF' pygments-nd: parent: code textColor: '#AA22FF' pygments-ne: parent: code textColor: '#D2413A' pygments-nf: parent: code textColor: '#00A000' pygments-ni: parent: code textColor: '#999999' pygments-nl: parent: code textColor: '#A0A000' pygments-nn: parent: code textColor: '#0000FF' pygments-no: parent: code textColor: '#880000' pygments-nt: parent: code textColor: '#008000' pygments-nv: parent: code textColor: '#B8860B' pygments-nx: parent: code pygments-o: parent: code textColor: '#666666' pygments-ow: parent: code textColor: '#AA22FF' pygments-p: parent: code pygments-s: parent: code textColor: '#BB4444' pygments-s1: parent: code textColor: '#BB4444' pygments-s2: parent: code textColor: '#BB4444' pygments-sb: parent: code textColor: '#BB4444' pygments-sc: parent: code textColor: '#BB4444' pygments-sd: parent: code textColor: '#BB4444' pygments-se: parent: code textColor: '#BB6622' pygments-sh: parent: code textColor: '#BB4444' pygments-si: parent: code textColor: '#BB6688' pygments-sr: parent: code textColor: '#BB6688' pygments-ss: parent: code textColor: '#B8860B' pygments-sx: parent: code textColor: '#008000' pygments-vc: parent: code textColor: '#B8860B' pygments-vg: parent: code textColor: '#B8860B' pygments-vi: parent: code textColor: '#B8860B' pygments-w: parent: code textColor: '#bbbbbb' right: alignment: right parent: bodytext rubric: alignment: TA_CENTER parent: bodytext textColor: darkred separation: parent: normal sidebar: backColor: cornsilk borderColor: darkgray borderPadding: 8 borderWidth: 0.5 float: none parent: normal width: 100% sidebar-subtitle: parent: heading4 sidebar-title: parent: heading3 subtitle: fontSize: 75% parent: title spaceBefore: 12 table: parent: normal alignment: TA_CENTER commands: - - VALIGN - - 0 - 0 - - -1 - -1 - TOP - - INNERGRID - - 0 - 0 - - -1 - -1 - 0.25 - black - - ROWBACKGROUNDS - - 0 - 0 - - -1 - -1 - - white - '#E0E0E0' - - BOX - - 0 - 0 - - -1 - -1 - 0.25 - black spaceAfter: 0 spaceBefore: 6 table-body: parent: normal table-heading: alignment: TA_CENTER borderPadding: 0 fontName: fontSansBold valign: BOTTOM table-title: alignment: TA_CENTER keepWithNext: false parent: heading4 tableofcontents: parent: normal tip: parent: admonition tip-heading: parent: admonition-heading title: alignment: TA_CENTER fontSize: 200% keepWithNext: false parent: heading spaceAfter: 36 title-reference: fontName: fontSansItalic parent: normal toc: parent: normal fontSize: 85% toc1: fontName: fontSansBold parent: toc toc10: leftIndent: 100 parent: toc toc11: leftIndent: 100 parent: toc toc12: leftIndent: 100 parent: toc toc13: leftIndent: 100 parent: toc toc14: leftIndent: 100 parent: toc toc15: leftIndent: 100 parent: toc toc2: leftIndent: 20 parent: toc toc3: leftIndent: 40 parent: toc toc4: leftIndent: 60 parent: toc toc5: leftIndent: 80 parent: toc toc6: leftIndent: 100 parent: toc toc7: leftIndent: 100 parent: toc toc8: leftIndent: 100 parent: toc toc9: leftIndent: 100 parent: toc topic-title: parent: heading3 warning: parent: admonition warning-heading: parent: admonition-heading rst2pdf-0.102/rst2pdf/styles/tango.yaml000066400000000000000000000123411463013543400200070ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#3465a4' pygments-c: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-cp: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-dl: parent: code textColor: '#4e9a06' pygments-err: parent: code textColor: '#a40000' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#000000' pygments-g: parent: code textColor: '#000000' pygments-gd: parent: code textColor: '#a40000' pygments-ge: fontName: fontMonoItalic parent: code textColor: '#000000' pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00A000' pygments-go: fontName: fontMonoItalic parent: code textColor: '#000000' pygments-gp: parent: code textColor: '#8f5902' pygments-gr: parent: code textColor: '#ef2929' pygments-gs: fontName: fontMonoBold parent: code textColor: '#000000' pygments-gt: fontName: fontMonoBold parent: code textColor: '#a40000' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: fontName: fontMonoBold parent: code textColor: '#0000cf' pygments-k: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-kc: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-kd: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-kn: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-kp: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-kr: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-kt: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-l: parent: code textColor: '#000000' pygments-ld: parent: code textColor: '#000000' pygments-m: fontName: fontMonoBold parent: code textColor: '#0000cf' pygments-mb: fontName: fontMonoBold parent: code textColor: '#0000cf' pygments-mf: fontName: fontMonoBold parent: code textColor: '#0000cf' pygments-mh: fontName: fontMonoBold parent: code textColor: '#0000cf' pygments-mi: fontName: fontMonoBold parent: code textColor: '#0000cf' pygments-mo: fontName: fontMonoBold parent: code textColor: '#0000cf' pygments-n: parent: code textColor: '#000000' pygments-na: parent: code textColor: '#c4a000' pygments-nb: parent: code textColor: '#204a87' pygments-nc: parent: code textColor: '#000000' pygments-nd: fontName: fontMonoBold parent: code textColor: '#5c35cc' pygments-ne: fontName: fontMonoBold parent: code textColor: '#cc0000' pygments-nf: parent: code textColor: '#000000' pygments-ni: parent: code textColor: '#ce5c00' pygments-nl: parent: code textColor: '#f57900' pygments-nn: parent: code textColor: '#000000' pygments-no: parent: code textColor: '#000000' pygments-nt: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-nv: parent: code textColor: '#000000' pygments-nx: parent: code textColor: '#000000' pygments-o: fontName: fontMonoBold parent: code textColor: '#ce5c00' pygments-ow: fontName: fontMonoBold parent: code textColor: '#204a87' pygments-p: fontName: fontMonoBold parent: code textColor: '#000000' pygments-py: parent: code textColor: '#000000' pygments-s: parent: code textColor: '#4e9a06' pygments-s1: parent: code textColor: '#4e9a06' pygments-s2: parent: code textColor: '#4e9a06' pygments-sa: parent: code textColor: '#4e9a06' pygments-sb: parent: code textColor: '#4e9a06' pygments-sc: parent: code textColor: '#4e9a06' pygments-sd: fontName: fontMonoItalic parent: code textColor: '#8f5902' pygments-se: parent: code textColor: '#4e9a06' pygments-sh: parent: code textColor: '#4e9a06' pygments-si: parent: code textColor: '#4e9a06' pygments-sr: parent: code textColor: '#4e9a06' pygments-ss: parent: code textColor: '#4e9a06' pygments-sx: parent: code textColor: '#4e9a06' pygments-vc: parent: code textColor: '#000000' pygments-vg: parent: code textColor: '#000000' pygments-vi: parent: code textColor: '#000000' pygments-vm: parent: code textColor: '#000000' pygments-w: parent: code textColor: '#f8f8f8' pygments-x: parent: code textColor: '#000000' rst2pdf-0.102/rst2pdf/styles/tenpoint.yaml000066400000000000000000000000411463013543400205310ustar00rootroot00000000000000styles: base: fontSize: 10 rst2pdf-0.102/rst2pdf/styles/trac.yaml000066400000000000000000000116221463013543400176310ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#999999' pygments-c: fontName: fontMonoItalic parent: code textColor: '#999988' pygments-c1: fontName: fontMonoItalic parent: code textColor: '#999988' pygments-ch: fontName: fontMonoItalic parent: code textColor: '#999988' pygments-cm: fontName: fontMonoItalic parent: code textColor: '#999988' pygments-cp: fontName: fontMonoBold parent: code textColor: '#999999' pygments-cpf: fontName: fontMonoItalic parent: code textColor: '#999988' pygments-cs: fontName: fontMonoItalic parent: code textColor: '#999999' pygments-dl: parent: code textColor: '#bb8844' pygments-err: backColor: '#e3d2d2' parent: code textColor: '#a61717' pygments-esc: parent: code textColor: black pygments-fm: fontName: fontMonoBold parent: code textColor: '#990000' pygments-g: parent: code textColor: black pygments-gd: backColor: '#ffdddd' parent: code textColor: '#000000' pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: parent: code textColor: '#999999' pygments-gi: backColor: '#ddffdd' parent: code textColor: '#000000' pygments-go: parent: code textColor: '#888888' pygments-gp: parent: code textColor: '#555555' pygments-gr: parent: code textColor: '#aa0000' pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: '#aa0000' pygments-gu: parent: code textColor: '#aaaaaa' pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#009999' pygments-k: fontName: fontMonoBold parent: code textColor: black pygments-kc: fontName: fontMonoBold parent: code textColor: black pygments-kd: fontName: fontMonoBold parent: code textColor: black pygments-kn: fontName: fontMonoBold parent: code textColor: black pygments-kp: fontName: fontMonoBold parent: code textColor: black pygments-kr: fontName: fontMonoBold parent: code textColor: black pygments-kt: fontName: fontMonoBold parent: code textColor: '#445588' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: '#009999' pygments-mb: parent: code textColor: '#009999' pygments-mf: parent: code textColor: '#009999' pygments-mh: parent: code textColor: '#009999' pygments-mi: parent: code textColor: '#009999' pygments-mo: parent: code textColor: '#009999' pygments-n: parent: code textColor: black pygments-na: parent: code textColor: '#008080' pygments-nb: parent: code textColor: '#999999' pygments-nc: fontName: fontMonoBold parent: code textColor: '#445588' pygments-nd: parent: code textColor: black pygments-ne: fontName: fontMonoBold parent: code textColor: '#990000' pygments-nf: fontName: fontMonoBold parent: code textColor: '#990000' pygments-ni: parent: code textColor: '#800080' pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: '#555555' pygments-no: parent: code textColor: '#008080' pygments-nt: parent: code textColor: '#000080' pygments-nv: parent: code textColor: '#008080' pygments-nx: parent: code textColor: black pygments-o: fontName: fontMonoBold parent: code textColor: black pygments-ow: fontName: fontMonoBold parent: code textColor: black pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#bb8844' pygments-s1: parent: code textColor: '#bb8844' pygments-s2: parent: code textColor: '#bb8844' pygments-sa: parent: code textColor: '#bb8844' pygments-sb: parent: code textColor: '#bb8844' pygments-sc: parent: code textColor: '#bb8844' pygments-sd: parent: code textColor: '#bb8844' pygments-se: parent: code textColor: '#bb8844' pygments-sh: parent: code textColor: '#bb8844' pygments-si: parent: code textColor: '#bb8844' pygments-sr: parent: code textColor: '#808000' pygments-ss: parent: code textColor: '#bb8844' pygments-sx: parent: code textColor: '#bb8844' pygments-vc: parent: code textColor: '#008080' pygments-vg: parent: code textColor: '#008080' pygments-vi: parent: code textColor: '#008080' pygments-vm: parent: code textColor: '#008080' pygments-w: parent: code textColor: '#bbbbbb' pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/twelvepoint.yaml000066400000000000000000000000411463013543400212510ustar00rootroot00000000000000styles: base: fontSize: 12 rst2pdf-0.102/rst2pdf/styles/twocolumn.yaml000066400000000000000000000001151463013543400207220ustar00rootroot00000000000000pageSetup: firstTemplate: twoColumn margin-left: 1cm margin-right: 1cm rst2pdf-0.102/rst2pdf/styles/vim.yaml000066400000000000000000000107721463013543400175000ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#cd00cd' pygments-c: parent: code textColor: '#000080' pygments-c1: parent: code textColor: '#000080' pygments-ch: parent: code textColor: '#000080' pygments-cm: parent: code textColor: '#000080' pygments-cp: parent: code textColor: '#000080' pygments-cpf: parent: code textColor: '#000080' pygments-cs: fontName: fontMonoBold parent: code textColor: '#cd0000' pygments-dl: parent: code textColor: '#cd0000' pygments-err: parent: code textColor: '#cccccc' pygments-esc: parent: code textColor: '#cccccc' pygments-fm: parent: code textColor: '#cccccc' pygments-g: parent: code textColor: '#cccccc' pygments-gd: parent: code textColor: '#cd0000' pygments-ge: fontName: fontMonoItalic parent: code textColor: '#cccccc' pygments-gh: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gi: parent: code textColor: '#00cd00' pygments-go: parent: code textColor: '#888888' pygments-gp: fontName: fontMonoBold parent: code textColor: '#000080' pygments-gr: parent: code textColor: '#FF0000' pygments-gs: fontName: fontMonoBold parent: code textColor: '#cccccc' pygments-gt: parent: code textColor: '#0044DD' pygments-gu: fontName: fontMonoBold parent: code textColor: '#800080' pygments-hll: backColor: '#222222' parent: code textColor: black pygments-il: parent: code textColor: '#cd00cd' pygments-k: parent: code textColor: '#cdcd00' pygments-kc: parent: code textColor: '#cdcd00' pygments-kd: parent: code textColor: '#00cd00' pygments-kn: parent: code textColor: '#cd00cd' pygments-kp: parent: code textColor: '#cdcd00' pygments-kr: parent: code textColor: '#cdcd00' pygments-kt: parent: code textColor: '#00cd00' pygments-l: parent: code textColor: '#cccccc' pygments-ld: parent: code textColor: '#cccccc' pygments-m: parent: code textColor: '#cd00cd' pygments-mb: parent: code textColor: '#cd00cd' pygments-mf: parent: code textColor: '#cd00cd' pygments-mh: parent: code textColor: '#cd00cd' pygments-mi: parent: code textColor: '#cd00cd' pygments-mo: parent: code textColor: '#cd00cd' pygments-n: parent: code textColor: '#cccccc' pygments-na: parent: code textColor: '#cccccc' pygments-nb: parent: code textColor: '#cd00cd' pygments-nc: parent: code textColor: '#00cdcd' pygments-nd: parent: code textColor: '#cccccc' pygments-ne: fontName: fontMonoBold parent: code textColor: '#666699' pygments-nf: parent: code textColor: '#cccccc' pygments-ni: parent: code textColor: '#cccccc' pygments-nl: parent: code textColor: '#cccccc' pygments-nn: parent: code textColor: '#cccccc' pygments-no: parent: code textColor: '#cccccc' pygments-nt: parent: code textColor: '#cccccc' pygments-nv: parent: code textColor: '#00cdcd' pygments-nx: parent: code textColor: '#cccccc' pygments-o: parent: code textColor: '#3399cc' pygments-ow: parent: code textColor: '#cdcd00' pygments-p: parent: code textColor: '#cccccc' pygments-py: parent: code textColor: '#cccccc' pygments-s: parent: code textColor: '#cd0000' pygments-s1: parent: code textColor: '#cd0000' pygments-s2: parent: code textColor: '#cd0000' pygments-sa: parent: code textColor: '#cd0000' pygments-sb: parent: code textColor: '#cd0000' pygments-sc: parent: code textColor: '#cd0000' pygments-sd: parent: code textColor: '#cd0000' pygments-se: parent: code textColor: '#cd0000' pygments-sh: parent: code textColor: '#cd0000' pygments-si: parent: code textColor: '#cd0000' pygments-sr: parent: code textColor: '#cd0000' pygments-ss: parent: code textColor: '#cd0000' pygments-sx: parent: code textColor: '#cd0000' pygments-vc: parent: code textColor: '#00cdcd' pygments-vg: parent: code textColor: '#00cdcd' pygments-vi: parent: code textColor: '#00cdcd' pygments-vm: parent: code textColor: '#00cdcd' pygments-w: parent: code textColor: '#cccccc' pygments-x: parent: code textColor: '#cccccc' rst2pdf-0.102/rst2pdf/styles/vs.yaml000066400000000000000000000104141463013543400173260ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: black pygments-c: parent: code textColor: '#008000' pygments-c1: parent: code textColor: '#008000' pygments-ch: parent: code textColor: '#008000' pygments-cm: parent: code textColor: '#008000' pygments-cp: parent: code textColor: '#0000ff' pygments-cpf: parent: code textColor: '#008000' pygments-cs: parent: code textColor: '#008000' pygments-dl: parent: code textColor: '#a31515' pygments-err: parent: code textColor: black pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: black pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: fontName: fontMonoItalic parent: code textColor: black pygments-gh: fontName: fontMonoBold parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: fontName: fontMonoBold parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: fontName: fontMonoBold parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: fontName: fontMonoBold parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: black pygments-k: parent: code textColor: '#0000ff' pygments-kc: parent: code textColor: '#0000ff' pygments-kd: parent: code textColor: '#0000ff' pygments-kn: parent: code textColor: '#0000ff' pygments-kp: parent: code textColor: '#0000ff' pygments-kr: parent: code textColor: '#0000ff' pygments-kt: parent: code textColor: '#2b91af' pygments-l: parent: code textColor: black pygments-ld: parent: code textColor: black pygments-m: parent: code textColor: black pygments-mb: parent: code textColor: black pygments-mf: parent: code textColor: black pygments-mh: parent: code textColor: black pygments-mi: parent: code textColor: black pygments-mo: parent: code textColor: black pygments-n: parent: code textColor: black pygments-na: parent: code textColor: black pygments-nb: parent: code textColor: black pygments-nc: parent: code textColor: '#2b91af' pygments-nd: parent: code textColor: black pygments-ne: parent: code textColor: black pygments-nf: parent: code textColor: black pygments-ni: parent: code textColor: black pygments-nl: parent: code textColor: black pygments-nn: parent: code textColor: black pygments-no: parent: code textColor: black pygments-nt: parent: code textColor: black pygments-nv: parent: code textColor: black pygments-nx: parent: code textColor: black pygments-o: parent: code textColor: black pygments-ow: parent: code textColor: '#0000ff' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: black pygments-s: parent: code textColor: '#a31515' pygments-s1: parent: code textColor: '#a31515' pygments-s2: parent: code textColor: '#a31515' pygments-sa: parent: code textColor: '#a31515' pygments-sb: parent: code textColor: '#a31515' pygments-sc: parent: code textColor: '#a31515' pygments-sd: parent: code textColor: '#a31515' pygments-se: parent: code textColor: '#a31515' pygments-sh: parent: code textColor: '#a31515' pygments-si: parent: code textColor: '#a31515' pygments-sr: parent: code textColor: '#a31515' pygments-ss: parent: code textColor: '#a31515' pygments-sx: parent: code textColor: '#a31515' pygments-vc: parent: code textColor: black pygments-vg: parent: code textColor: black pygments-vi: parent: code textColor: black pygments-vm: parent: code textColor: black pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/styles/xcode.yaml000066400000000000000000000103771463013543400200100ustar00rootroot00000000000000styles: pygments-bp: parent: code textColor: '#5B269A' pygments-c: parent: code textColor: '#177500' pygments-c1: parent: code textColor: '#177500' pygments-ch: parent: code textColor: '#177500' pygments-cm: parent: code textColor: '#177500' pygments-cp: parent: code textColor: '#633820' pygments-cpf: parent: code textColor: '#177500' pygments-cs: parent: code textColor: '#177500' pygments-dl: parent: code textColor: '#C41A16' pygments-err: parent: code textColor: '#000000' pygments-esc: parent: code textColor: black pygments-fm: parent: code textColor: '#000000' pygments-g: parent: code textColor: black pygments-gd: parent: code textColor: black pygments-ge: parent: code textColor: black pygments-gh: parent: code textColor: black pygments-gi: parent: code textColor: black pygments-go: parent: code textColor: black pygments-gp: parent: code textColor: black pygments-gr: parent: code textColor: black pygments-gs: parent: code textColor: black pygments-gt: parent: code textColor: black pygments-gu: parent: code textColor: black pygments-hll: backColor: '#ffffcc' parent: code textColor: black pygments-il: parent: code textColor: '#1C01CE' pygments-k: parent: code textColor: '#A90D91' pygments-kc: parent: code textColor: '#A90D91' pygments-kd: parent: code textColor: '#A90D91' pygments-kn: parent: code textColor: '#A90D91' pygments-kp: parent: code textColor: '#A90D91' pygments-kr: parent: code textColor: '#A90D91' pygments-kt: parent: code textColor: '#A90D91' pygments-l: parent: code textColor: '#1C01CE' pygments-ld: parent: code textColor: '#1C01CE' pygments-m: parent: code textColor: '#1C01CE' pygments-mb: parent: code textColor: '#1C01CE' pygments-mf: parent: code textColor: '#1C01CE' pygments-mh: parent: code textColor: '#1C01CE' pygments-mi: parent: code textColor: '#1C01CE' pygments-mo: parent: code textColor: '#1C01CE' pygments-n: parent: code textColor: '#000000' pygments-na: parent: code textColor: '#836C28' pygments-nb: parent: code textColor: '#A90D91' pygments-nc: parent: code textColor: '#3F6E75' pygments-nd: parent: code textColor: '#000000' pygments-ne: parent: code textColor: '#000000' pygments-nf: parent: code textColor: '#000000' pygments-ni: parent: code textColor: '#000000' pygments-nl: parent: code textColor: '#000000' pygments-nn: parent: code textColor: '#000000' pygments-no: parent: code textColor: '#000000' pygments-nt: parent: code textColor: '#000000' pygments-nv: parent: code textColor: '#000000' pygments-nx: parent: code textColor: '#000000' pygments-o: parent: code textColor: '#000000' pygments-ow: parent: code textColor: '#000000' pygments-p: parent: code textColor: black pygments-py: parent: code textColor: '#000000' pygments-s: parent: code textColor: '#C41A16' pygments-s1: parent: code textColor: '#C41A16' pygments-s2: parent: code textColor: '#C41A16' pygments-sa: parent: code textColor: '#C41A16' pygments-sb: parent: code textColor: '#C41A16' pygments-sc: parent: code textColor: '#2300CE' pygments-sd: parent: code textColor: '#C41A16' pygments-se: parent: code textColor: '#C41A16' pygments-sh: parent: code textColor: '#C41A16' pygments-si: parent: code textColor: '#C41A16' pygments-sr: parent: code textColor: '#C41A16' pygments-ss: parent: code textColor: '#C41A16' pygments-sx: parent: code textColor: '#C41A16' pygments-vc: parent: code textColor: '#000000' pygments-vg: parent: code textColor: '#000000' pygments-vi: parent: code textColor: '#000000' pygments-vm: parent: code textColor: '#000000' pygments-w: parent: code textColor: black pygments-x: parent: code textColor: black rst2pdf-0.102/rst2pdf/svgimage.py000066400000000000000000000046351463013543400166530ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_RIGHT from reportlab.platypus import Flowable, Paragraph from svglib.svglib import svg2rlg class SVGImage(Flowable): def __init__( self, filename, width=None, height=None, kind='direct', mask=None, lazy=True, srcinfo=None, ): Flowable.__init__(self) self._kind = kind self._mode = 'svg2rlg' self.doc = svg2rlg(filename) self.imageWidth = width self.imageHeight = height x1, y1, x2, y2 = self.doc.getBounds() # Actually, svg2rlg's getBounds seems broken. self._w, self._h = x2, y2 if not self.imageWidth: self.imageWidth = self._w if not self.imageHeight: self.imageHeight = self._h self.__ratio = float(self.imageWidth) / self.imageHeight if kind in ['direct', 'absolute']: self.drawWidth = width or self.imageWidth self.drawHeight = height or self.imageHeight elif kind in ['bound', 'proportional']: factor = min( float(width) / self.imageWidth, float(height) / self.imageHeight, ) self.drawWidth = self.imageWidth * factor self.drawHeight = self.imageHeight * factor def wrap(self, aW, aH): return self.drawWidth, self.drawHeight def drawOn(self, canv, x, y, _sW=0): if _sW and hasattr(self, 'hAlign'): a = self.hAlign if a in ('CENTER', 'CENTRE', TA_CENTER): x += 0.5 * _sW elif a in ('RIGHT', TA_RIGHT): x += _sW elif a not in ('LEFT', TA_LEFT): raise ValueError("Bad hAlign value " + str(a)) canv.saveState() canv.translate(x, y) canv.scale(self.drawWidth / self._w, self.drawHeight / self._h) self.doc._drawOn(canv) canv.restoreState() if __name__ == "__main__": import sys from reportlab.platypus import SimpleDocTemplate from reportlab.lib.styles import getSampleStyleSheet doc = SimpleDocTemplate('svgtest.pdf') styles = getSampleStyleSheet() style = styles['Normal'] Story = [ Paragraph("Before the image", style), SVGImage(sys.argv[1]), Paragraph("After the image", style), ] doc.build(Story) rst2pdf-0.102/rst2pdf/templates/000077500000000000000000000000001463013543400164655ustar00rootroot00000000000000rst2pdf-0.102/rst2pdf/templates/cover.tmpl000066400000000000000000000001761463013543400205050ustar00rootroot00000000000000{% if title: %} .. class:: title {{title}} {% endif %} {% if subtitle: %} .. class:: subtitle {{subtitle}} {% endif %} rst2pdf-0.102/rst2pdf/templates/sphinxcover.tmpl000066400000000000000000000005521463013543400217350ustar00rootroot00000000000000.. role:: normal {% if title: %} .. cssclass:: title {{title}} {% endif %} {% if subtitle: %} .. cssclass:: subtitle {{subtitle}} {% endif %} .. raw:: pdf Spacer 0 3cm {% for author in authors: %} .. cssclass:: author {{author}} {% endfor %} .. raw:: pdf Spacer 0 3cm .. cssclass:: author :normal:`{{date}}` .. raw:: pdf OddPageBreak rst2pdf-0.102/rst2pdf/utils.py000066400000000000000000000217131463013543400162050ustar00rootroot00000000000000# -*- coding: utf-8 -*- # See LICENSE.txt for licensing terms import shlex import jinja2 from reportlab.lib.colors import Color from reportlab.platypus.flowables import CondPageBreak from . import flowables from .log import log, nodeid from .styles import adjustUnits PageCounter = None def parseRaw(data, node): """Parse and process a simple DSL to handle creation of flowables. Supported (can add others on request): * PageBreak [