From 4ed78e537c98572ace12bab88430f55533fb4ef8 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Tue, 6 May 2014 16:05:45 -0700 Subject: [PATCH 01/54] bump version --- doc/www/config.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/www/config.json b/doc/www/config.json index 577a8327..e7a6b54b 100644 --- a/doc/www/config.json +++ b/doc/www/config.json @@ -11,23 +11,23 @@ }, manual: { titleText: "

User's Manual

", - subtext: 'A guide to using OpenSCAM v0.2.4 or newer.', + subtext: 'A guide to using OpenSCAM v0.2.5 or newer.', } }, - version: '0.2.4 beta', + version: '0.2.5 beta', repoURL: 'https://github.com/CauldronDevelopmentLLC/OpenSCAM', releases: [ ['Windows', ['windows-128.png'], - 'windows-xp-32bit', 'openscam_0.2.4_x86.exe'], + 'windows-xp-32bit', 'openscam_0.2.5_x86.exe'], ['Mac OS-X', ['osx-128.png'], - 'osx-10.6.4-64bit', 'openscam_0.2.4_x86_64.pkg'], + 'osx-10.6.4-64bit', 'openscam_0.2.5_x86_64.pkg'], ['Debian Linux 64-bit', ['debian-128.png', 'mint-128.png'], - 'debian-testing-64bit', 'openscam_0.2.4_amd64.deb'], + 'debian-testing-64bit', 'openscam_0.2.5_amd64.deb'], ['Debian Linux 32-bit', ['debian-128.png', 'mint-128.png'], - 'debian-testing-32bit', 'openscam_0.2.4_i386.deb'], + 'debian-testing-32bit', 'openscam_0.2.5_i386.deb'], ['Ubuntu Precise Penguin 64-bit', ['ubuntu-128.png'], - 'ubuntu-precise-64bit', 'openscam_0.2.4_amd64.deb'], + 'ubuntu-precise-64bit', 'openscam_0.2.5_amd64.deb'], ['LinuxCNC 10.04', ['ubuntu-128.png'], - 'linuxcnc-10.04-32bit', 'openscam_0.2.4_i386.deb'] + 'linuxcnc-10.04-32bit', 'openscam_0.2.5_i386.deb'] ] } From 16899f3c6cf9505328dcd897505077e6732fdc06 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Wed, 7 May 2014 11:59:54 -0700 Subject: [PATCH 02/54] Always build build info --- SConstruct | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 45815246..73b19863 100644 --- a/SConstruct +++ b/SConstruct @@ -98,7 +98,9 @@ qrc = env.Qrc4('build/qrc_openscam.cpp', 'qt/openscam.qrc') src += qrc # Build Info -src += env.BuildInfo('build/build_info.cpp', []) +info = env.BuildInfo('build/build_info.cpp', []) +AlwaysBuild(info) +src += info # Build From b9cab85890bb2056ea88cdf8764d3384224e3aff Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Thu, 8 May 2014 13:59:13 -0700 Subject: [PATCH 03/54] Ubuntu build is broken --- doc/www/config.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/www/config.json b/doc/www/config.json index e7a6b54b..c02cb4fb 100644 --- a/doc/www/config.json +++ b/doc/www/config.json @@ -25,8 +25,6 @@ 'debian-testing-64bit', 'openscam_0.2.5_amd64.deb'], ['Debian Linux 32-bit', ['debian-128.png', 'mint-128.png'], 'debian-testing-32bit', 'openscam_0.2.5_i386.deb'], - ['Ubuntu Precise Penguin 64-bit', ['ubuntu-128.png'], - 'ubuntu-precise-64bit', 'openscam_0.2.5_amd64.deb'], ['LinuxCNC 10.04', ['ubuntu-128.png'], 'linuxcnc-10.04-32bit', 'openscam_0.2.5_i386.deb'] ] From 2a8c0b7f0a6d26cb9895c02c9bb4fe9f45c7a90e Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Mon, 19 May 2014 19:43:34 -0700 Subject: [PATCH 04/54] Protect tool path and surface threads --- src/openscam/qt/QtWin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openscam/qt/QtWin.cpp b/src/openscam/qt/QtWin.cpp index fc9477f0..70c7655c 100644 --- a/src/openscam/qt/QtWin.cpp +++ b/src/openscam/qt/QtWin.cpp @@ -445,6 +445,7 @@ void QtWin::toolPathComplete() { redraw(); // Start surface thread + if (!surfaceThread.isNull()) surfaceThread->join(); surfaceThread = new SurfaceThread(surfaceCompleteEvent, this, cutSim, toolPath, project->getWorkpieceBounds(), project->getResolution(), view->getTime(), @@ -482,6 +483,7 @@ void QtWin::reload(bool now) { stop(); // Start tool path thread + if (!toolPathThread.isNull()) toolPathThread->join(); toolPathThread = new ToolPathThread(toolPathCompleteEvent, this, cutSim, project->getToolTable(), project->getAbsoluteFiles()); From c974c8a1732822e6d99cc2d5488de85b690a3c36 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Thu, 29 May 2014 20:57:07 -0700 Subject: [PATCH 05/54] Updates for cbang changes --- src/openscam/cutsim/Project.cpp | 2 +- src/tplang/DXFLibrary.cpp | 2 +- src/tplang/GCodeLibrary.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/openscam/cutsim/Project.cpp b/src/openscam/cutsim/Project.cpp index 01b44df1..b9607ff6 100644 --- a/src/openscam/cutsim/Project.cpp +++ b/src/openscam/cutsim/Project.cpp @@ -112,7 +112,7 @@ string Project::makeRelative(const string &path) const { string Project::makeAbsolute(const string &path) const { string dir = filename.empty() ? SystemUtilities::getcwd() : SystemUtilities::dirname(filename); - return SystemUtilities::makeRelative(dir, path); + return SystemUtilities::absolute(dir, path); } diff --git a/src/tplang/DXFLibrary.cpp b/src/tplang/DXFLibrary.cpp index 51a43e4b..ebf440f4 100644 --- a/src/tplang/DXFLibrary.cpp +++ b/src/tplang/DXFLibrary.cpp @@ -53,7 +53,7 @@ void DXFLibrary::add(js::ObjectTemplate &tmpl) { js::Value DXFLibrary::openCB(const js::Arguments &args) { string path = - SystemUtilities::makeRelative(ctx.currentPath(), args.getString("path")); + SystemUtilities::absolute(ctx.currentPath(), args.getString("path")); DXFReader reader; reader.read(path); diff --git a/src/tplang/GCodeLibrary.cpp b/src/tplang/GCodeLibrary.cpp index 72110a1e..30deb7cd 100644 --- a/src/tplang/GCodeLibrary.cpp +++ b/src/tplang/GCodeLibrary.cpp @@ -91,7 +91,7 @@ void GCodeLibrary::add(js::ObjectTemplate &tmpl) { js::Value GCodeLibrary::gcodeCB(const js::Arguments &args) { string path = - SystemUtilities::makeRelative(ctx.currentPath(), args.getString("path")); + SystemUtilities::absolute(ctx.currentPath(), args.getString("path")); ctx.pushPath(path); SmartFunctor popPath(&ctx, &TPLContext::popPath); From 923da8f517fe925995ec0895b00470a1f7d50440 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Thu, 4 Dec 2014 09:46:18 -0800 Subject: [PATCH 06/54] Fix G98 and G99 swap. --- src/openscam/sim/Controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openscam/sim/Controller.cpp b/src/openscam/sim/Controller.cpp index 7c6fadcd..d1780231 100644 --- a/src/openscam/sim/Controller.cpp +++ b/src/openscam/sim/Controller.cpp @@ -491,8 +491,8 @@ void Controller::execute(const Code &code, int vars) { break; case 970: spinMode = MachineInterface::REVOLUTIONS_PER_MINUTE; break; - case 980: returnMode = RETURN_TO_R; break; - case 990: returnMode = RETURN_TO_OLD_Z; break; + case 980: returnMode = RETURN_TO_OLD_Z; break; + case 990: returnMode = RETURN_TO_R; break; default: implemented = false; } From 3e6abe5496842260190c973ff4f7c6befc5b5370 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Thu, 1 Jan 2015 16:55:27 -0800 Subject: [PATCH 07/54] Don't load packager if not pacaking, affects issue #112 --- SConstruct | 99 +++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/SConstruct b/SConstruct index 73b19863..592aa1e9 100644 --- a/SConstruct +++ b/SConstruct @@ -183,52 +183,53 @@ if 'package' in COMMAND_LINE_TARGETS and env['PLATFORM'] == 'win32' and \ # Package -pkg = env.Packager( - 'OpenSCAM', - version = version, - maintainer = 'Joseph Coffland ', - vendor = 'Cauldron Development LLC', - url = 'http://openscam.com/', - license = 'COPYING', - bug_url = 'http://openscam.com/', - summary = 'Open-Source Simulation & Computer Aided Machining', - description = description, - prefix = '/usr', - icons = ('osx/openscam.icns', 'images/openscam.png'), - - documents = ['README.md', 'CHANGELOG.md'] + examples, - programs = map(lambda x: str(x[0]), execs), - desktop_menu = ['OpenSCAM.desktop'], - changelog = 'CHANGELOG.md', - - nsi = 'openscam.nsi', - msvc_redist = msvc_redist, - - deb_directory = 'debian', - deb_section = 'miscellaneous', - deb_depends = 'debconf | debconf-2.0, libc6, libbz2-1.0, zlib1g, ' +\ - 'libexpat1, libsqlite3-0, libqtcore4, libqtgui4, libqt4-opengl, ' +\ - 'libcairo2', - deb_priority = 'optional', - - rpm_license = 'GPLv2+', - rpm_group = 'Applications/Engineering', - rpm_requires = 'expat, bzip2-libs', - - app_id = 'org.openscam', - app_resources = [['osx/Resources', '.']], - app_copyright = 'Copyright 2011-2014, Cauldron Development LLC', - app_signature = 'scam', - app_other_info = { - 'CFBundleExecutable': 'openscam', # Overrides 'programs' - 'CFBundleIconFile': 'openscam.icns', - }, - app_finish_cmd = 'macdeployqt', - pkg_scripts = 'osx/Scripts', - pkg_resources = 'osx/Resources', - pkg_distribution = 'osx/distribution.xml', - pkg_plist = 'osx/pkg.plist', - ) - -AlwaysBuild(pkg) -env.Alias('package', pkg) +if 'package' in COMMAND_LINE_TARGETS: + pkg = env.Packager( + 'OpenSCAM', + version = version, + maintainer = 'Joseph Coffland ', + vendor = 'Cauldron Development LLC', + url = 'http://openscam.com/', + license = 'COPYING', + bug_url = 'http://openscam.com/', + summary = 'Open-Source Simulation & Computer Aided Machining', + description = description, + prefix = '/usr', + icons = ('osx/openscam.icns', 'images/openscam.png'), + + documents = ['README.md', 'CHANGELOG.md'] + examples, + programs = map(lambda x: str(x[0]), execs), + desktop_menu = ['OpenSCAM.desktop'], + changelog = 'CHANGELOG.md', + + nsi = 'openscam.nsi', + msvc_redist = msvc_redist, + + deb_directory = 'debian', + deb_section = 'miscellaneous', + deb_depends = 'debconf | debconf-2.0, libc6, libbz2-1.0, zlib1g, ' +\ + 'libexpat1, libsqlite3-0, libqtcore4, libqtgui4, libqt4-opengl, ' +\ + 'libcairo2', + deb_priority = 'optional', + + rpm_license = 'GPLv2+', + rpm_group = 'Applications/Engineering', + rpm_requires = 'expat, bzip2-libs', + + app_id = 'org.openscam', + app_resources = [['osx/Resources', '.']], + app_copyright = 'Copyright 2011-2014, Cauldron Development LLC', + app_signature = 'scam', + app_other_info = { + 'CFBundleExecutable': 'openscam', # Overrides 'programs' + 'CFBundleIconFile': 'openscam.icns', + }, + app_finish_cmd = 'macdeployqt', + pkg_scripts = 'osx/Scripts', + pkg_resources = 'osx/Resources', + pkg_distribution = 'osx/distribution.xml', + pkg_plist = 'osx/pkg.plist', + ) + + AlwaysBuild(pkg) + env.Alias('package', pkg) From fc3cd959ae5aa7a3187490b368c84d654900b71c Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Mon, 5 Jan 2015 18:41:52 -0800 Subject: [PATCH 08/54] Fix automatic workpiece z-offset problem. Issue #105. --- src/openscam/cutsim/Project.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openscam/cutsim/Project.cpp b/src/openscam/cutsim/Project.cpp index b9607ff6..eb2c75cf 100644 --- a/src/openscam/cutsim/Project.cpp +++ b/src/openscam/cutsim/Project.cpp @@ -287,9 +287,9 @@ void Project::updateAutomaticWorkpiece(ToolPath &path) { Vector3R bMax = wpBounds.getMax(); wpBounds = Rectangle3R(bMin, Vector3R(bMax.x(), bMax.y(), 0)); - // At least a height of 2 + // At least 2mm thick if (wpBounds.getHeight() < 2) - wpBounds = Rectangle3R(Vector3R(bMin.x(), bMin.y(), bMax.z() - 2), bMax); + wpBounds.add(Vector3R(bMin.x(), bMin.y(), bMin.z() - 2)); if (wpBounds.isReal()) { // Margin From 48afc8c1ae3c47f95b7e212afc97761a7681b1a6 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Tue, 3 Feb 2015 21:44:50 -0800 Subject: [PATCH 09/54] Fix arcs --- src/openscam/sim/Controller.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/openscam/sim/Controller.cpp b/src/openscam/sim/Controller.cpp index d1780231..6c4cc2a2 100644 --- a/src/openscam/sim/Controller.cpp +++ b/src/openscam/sim/Controller.cpp @@ -333,7 +333,7 @@ void Controller::reset() { naiveCamTolerance = 0; modalMotion = false; incrementalDistanceMode = false; - arcIncrementalDistanceMode = false; + arcIncrementalDistanceMode = true; moveInAbsoluteCoords = false; machine.setMetric(); @@ -471,9 +471,9 @@ void Controller::execute(const Code &code, int vars) { case 890: drill(vars, true, true, false); // Dwell, Feed Out case 900: incrementalDistanceMode = false; break; - case 901: arcIncrementalDistanceMode = false; break; + case 901: arcIncrementalDistanceMode = false; implemented = false; break; case 910: incrementalDistanceMode = true; implemented = false; break; - case 911: arcIncrementalDistanceMode = true; implemented = false; break; + case 911: arcIncrementalDistanceMode = true; break; case 920: setGlobalOffsets(vars); break; case 921: resetGlobalOffsets(true); break; @@ -491,8 +491,8 @@ void Controller::execute(const Code &code, int vars) { break; case 970: spinMode = MachineInterface::REVOLUTIONS_PER_MINUTE; break; - case 980: returnMode = RETURN_TO_OLD_Z; break; - case 990: returnMode = RETURN_TO_R; break; + case 980: returnMode = RETURN_TO_R; break; + case 990: returnMode = RETURN_TO_OLD_Z; break; default: implemented = false; } @@ -540,17 +540,18 @@ void Controller::moveAxis(char axis, double value, bool rapid) { void Controller::arc(int vars, bool clockwise) { - // TODO Handle Arc Incremental Distance Mode + // TODO Handle Arc Absolute Mode // TODO Affected by cutter radius compensation + // TODO Make sure this is correct for planes XZ and YZ const char *axes = getPlaneAxes(getPlane()); + if (getPlane() == MachineInterface::XZ) clockwise = !clockwise; // Compute start and end points Axes current = getPosition(true); Axes target = getNextPosition(vars); Vector2D start = Vector2D(current.get(axes[0]), current.get(axes[1])); Vector2D finish = Vector2D(target.get(axes[0]), target.get(axes[1])); - Vector2D center; double radius; @@ -609,7 +610,7 @@ void Controller::arc(int vars, bool clockwise) { if (!angle) angle = 2 * M_PI; if ((VT_P & vars) && 1 < getVar('P')) - angle = angle + angle * (getVar('P') - 1); + angle = angle + M_PI * 2 * (getVar('P') - 1) * (angle < 0 ? -1 : 1); // Do arc double deltaZ = target.get(axes[2]) - current.get(axes[2]); From 82c83a2eff9f5019bdb3c77d0c588066bae4f465 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Wed, 11 Feb 2015 13:57:35 -0800 Subject: [PATCH 10/54] Fix DXF vertex read --- src/openscam/dxf/DXFReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openscam/dxf/DXFReader.cpp b/src/openscam/dxf/DXFReader.cpp index ab48f5d7..406b64a1 100644 --- a/src/openscam/dxf/DXFReader.cpp +++ b/src/openscam/dxf/DXFReader.cpp @@ -84,7 +84,7 @@ void DXFReader::addPolyline(const DL_PolylineData &polyline) { void DXFReader::addVertex(const DL_VertexData &vertex) { if (vertex.bulge) LOG_WARNING("Cannot handle vertex with bulge"); - entity->addVertex(Vector3D(vertex.z, vertex.y, vertex.z)); + entity->addVertex(Vector3D(vertex.x, vertex.y, vertex.z)); } From 200598080fa2c1771d7de324cda2ceeae74b6b79 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Thu, 19 Mar 2015 18:00:15 -0700 Subject: [PATCH 11/54] Added --fullscreen option --- src/openscam/qt/QtApp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/openscam/qt/QtApp.cpp b/src/openscam/qt/QtApp.cpp index 10f50989..0bf065e1 100644 --- a/src/openscam/qt/QtApp.cpp +++ b/src/openscam/qt/QtApp.cpp @@ -35,6 +35,7 @@ using namespace OpenSCAM; QtApp::QtApp(QWidget *parent) : OpenSCAM::Application("OpenSCAM") { options.add("qt-style", "Set Qt style"); + options.add("fullscreen", "Start in fullscreen mode")->setDefault(false); // Configure command line cmdLine.setAllowConfigAsFirstArg(false); @@ -82,6 +83,9 @@ void QtApp::run() { QtWin qtWin(*this); qtWin.init(); + if (options["fullscreen"].toBoolean()) + qtWin.setWindowState(qtWin.windowState() | Qt::WindowFullScreen); + if (projectFile.empty()) qtWin.newProject(); else qtWin.openProject(projectFile); From 7ec06967031bdc0ee20677fe325e1e1b2116db98 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Thu, 19 Mar 2015 18:31:25 -0700 Subject: [PATCH 12/54] Added --auto-play option --- src/openscam/qt/QtApp.cpp | 6 +++++- src/openscam/qt/QtWin.cpp | 11 ++++++++++- src/openscam/qt/QtWin.h | 3 +++ src/openscam/qt/SurfaceThread.cpp | 4 ++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/openscam/qt/QtApp.cpp b/src/openscam/qt/QtApp.cpp index 0bf065e1..4da8f712 100644 --- a/src/openscam/qt/QtApp.cpp +++ b/src/openscam/qt/QtApp.cpp @@ -35,7 +35,9 @@ using namespace OpenSCAM; QtApp::QtApp(QWidget *parent) : OpenSCAM::Application("OpenSCAM") { options.add("qt-style", "Set Qt style"); - options.add("fullscreen", "Start in fullscreen mode")->setDefault(false); + options.add("fullscreen", "Start in fullscreen mode.")->setDefault(false); + options.add("auto-play", "Automatically start tool path playback.") + ->setDefault(false); // Configure command line cmdLine.setAllowConfigAsFirstArg(false); @@ -89,6 +91,8 @@ void QtApp::run() { if (projectFile.empty()) qtWin.newProject(); else qtWin.openProject(projectFile); + if (options["auto-play"].toBoolean()) qtWin.setAutoPlay(); + qtWin.show(); qtApp.exec(); } diff --git a/src/openscam/qt/QtWin.cpp b/src/openscam/qt/QtWin.cpp index 70c7655c..42f619a7 100644 --- a/src/openscam/qt/QtWin.cpp +++ b/src/openscam/qt/QtWin.cpp @@ -69,7 +69,8 @@ QtWin::QtWin(Application &app) : connectionManager(new ConnectionManager(options)), view(new View(valueSet)), viewer(new Viewer), toolView(new ToolView), dirty(false), simDirty(false), inUIUpdate(false), lastProgress(0), - lastStatusActive(false), smooth(true), currentUIView(NULL_VIEW) { + lastStatusActive(false), smooth(true), autoPlay(false), + currentUIView(NULL_VIEW) { ui->setupUi(this); ui->simulationView->init(SIMULATION_VIEW, this); @@ -451,6 +452,14 @@ void QtWin::toolPathComplete() { project->getResolution(), view->getTime(), smooth); surfaceThread->start(); + + // Auto play + if (autoPlay) { + autoPlay = false; + view->path->setByRatio(0); + view->setFlag(View::PLAY_FLAG); + view->reverse = false; + } } diff --git a/src/openscam/qt/QtWin.h b/src/openscam/qt/QtWin.h index cbdb43f4..a077e14a 100644 --- a/src/openscam/qt/QtWin.h +++ b/src/openscam/qt/QtWin.h @@ -106,6 +106,7 @@ namespace OpenSCAM { bool lastStatusActive; cb::SmartPointer currentTool; bool smooth; + bool autoPlay; typedef enum { NULL_VIEW, @@ -122,6 +123,8 @@ namespace OpenSCAM { {return connectionManager;} const cb::SmartPointer &getView() const {return view;} + void setAutoPlay(bool x = true) {autoPlay = x;} + void init(); void setUnitLabel(QLabel *label, real value, int precision = 2); diff --git a/src/openscam/qt/SurfaceThread.cpp b/src/openscam/qt/SurfaceThread.cpp index 440d665a..e4c95f25 100644 --- a/src/openscam/qt/SurfaceThread.cpp +++ b/src/openscam/qt/SurfaceThread.cpp @@ -22,11 +22,15 @@ #include +#include + +using namespace std; using namespace OpenSCAM; void SurfaceThread::run() { try { + if (!time) time = numeric_limits::max(); surface = cutSim->computeSurface(path, bounds, resolution, time, smooth); } CATCH_ERROR; done(); From c0b5a927eba81462619263e98ff405905e9adc6b Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Thu, 19 Mar 2015 18:43:00 -0700 Subject: [PATCH 13/54] Added --auto-close and --play-speed options --- src/openscam/qt/QtApp.cpp | 13 ++++++++++++- src/openscam/qt/QtWin.cpp | 6 +++++- src/openscam/qt/QtWin.h | 2 ++ src/openscam/view/View.h | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/openscam/qt/QtApp.cpp b/src/openscam/qt/QtApp.cpp index 4da8f712..873c8599 100644 --- a/src/openscam/qt/QtApp.cpp +++ b/src/openscam/qt/QtApp.cpp @@ -38,6 +38,10 @@ QtApp::QtApp(QWidget *parent) : OpenSCAM::Application("OpenSCAM") { options.add("fullscreen", "Start in fullscreen mode.")->setDefault(false); options.add("auto-play", "Automatically start tool path playback.") ->setDefault(false); + options.add("play-speed", "Set playback speed.")->setDefault(1); + options.add("auto-close", "Automatically exit after tool path playback is " + "complete. Only valid with 'auto-play'") + ->setDefault(false); // Configure command line cmdLine.setAllowConfigAsFirstArg(false); @@ -85,14 +89,21 @@ void QtApp::run() { QtWin qtWin(*this); qtWin.init(); + // Options if (options["fullscreen"].toBoolean()) qtWin.setWindowState(qtWin.windowState() | Qt::WindowFullScreen); if (projectFile.empty()) qtWin.newProject(); else qtWin.openProject(projectFile); - if (options["auto-play"].toBoolean()) qtWin.setAutoPlay(); + qtWin.getView()->setSpeed(options["play-speed"].toInteger()); + + if (options["auto-play"].toBoolean()) { + qtWin.setAutoPlay(); + if (options["auto-close"].toBoolean()) qtWin.setAutoClose(); + } + // Start it up qtWin.show(); qtApp.exec(); } diff --git a/src/openscam/qt/QtWin.cpp b/src/openscam/qt/QtWin.cpp index 42f619a7..61b2775c 100644 --- a/src/openscam/qt/QtWin.cpp +++ b/src/openscam/qt/QtWin.cpp @@ -69,7 +69,7 @@ QtWin::QtWin(Application &app) : connectionManager(new ConnectionManager(options)), view(new View(valueSet)), viewer(new Viewer), toolView(new ToolView), dirty(false), simDirty(false), inUIUpdate(false), lastProgress(0), - lastStatusActive(false), smooth(true), autoPlay(false), + lastStatusActive(false), smooth(true), autoPlay(false), autoClose(false), currentUIView(NULL_VIEW) { ui->setupUi(this); @@ -1211,6 +1211,10 @@ void QtWin::animate() { dirty = connectionManager->update() || dirty; dirty = view->update() || dirty; + // Auto close after auto play + if (!autoPlay &&autoClose && + !view->isFlagSet(View::PLAY_FLAG)) app.requestExit(); + if (dirty) redraw(true); if (simDirty) reload(true); diff --git a/src/openscam/qt/QtWin.h b/src/openscam/qt/QtWin.h index a077e14a..346caf65 100644 --- a/src/openscam/qt/QtWin.h +++ b/src/openscam/qt/QtWin.h @@ -107,6 +107,7 @@ namespace OpenSCAM { cb::SmartPointer currentTool; bool smooth; bool autoPlay; + bool autoClose; typedef enum { NULL_VIEW, @@ -124,6 +125,7 @@ namespace OpenSCAM { const cb::SmartPointer &getView() const {return view;} void setAutoPlay(bool x = true) {autoPlay = x;} + void setAutoClose(bool x = true) {autoClose = x;} void init(); void setUnitLabel(QLabel *label, real value, int precision = 2); diff --git a/src/openscam/view/View.h b/src/openscam/view/View.h index 9535feff..1f691921 100644 --- a/src/openscam/view/View.h +++ b/src/openscam/view/View.h @@ -77,6 +77,7 @@ namespace OpenSCAM { void clearFlag(unsigned flag) {flags &= ~flag; values.updated();} void toggleFlag(unsigned flag) {flags ^= flag; values.updated();} + void setSpeed(unsigned speed) {this->speed = speed;} void incSpeed(); void decSpeed(); void changeDirection() {reverse = !reverse; values.updated();} From 6f28fcf0989f63158fcb68237efb9ab22a21bb0f Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Fri, 20 Mar 2015 13:35:37 -0700 Subject: [PATCH 14/54] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fe4aa99c..66a4d6bc 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Clone the OpenSCAM git repository and build the software using scons: In the OpenSCAM source code directory run: scons package - sudo dpkg -i openscam_*.deb + sudo dpkg -i $(cat package.txt) ## Build Warnings/Errors If you get any build warnings, by default, the build will stop. If you have From 29bd71bde9733afb3415ac3834613bac12fcdd47 Mon Sep 17 00:00:00 2001 From: Joseph Coffland Date: Sun, 5 Apr 2015 14:11:24 -0700 Subject: [PATCH 15/54] Moved Websites to other repos --- doc/tpl/background.png | Bin 2108 -> 0 bytes doc/tpl/images/square.png | Bin 27661 -> 0 bytes doc/tpl/images/squares.png | Bin 90754 -> 0 bytes doc/tpl/images/star.png | Bin 242513 -> 0 bytes doc/tpl/publish.sh | 4 - doc/tpl/rainbow-custom.min.js | 10 - doc/tpl/solarized-light.css | 89 - doc/tpl/tpl.css | 136 - doc/tpl/tpl.html | 521 -- doc/tpl/tpl.js | 82 - doc/www/Makefile | 10 - doc/www/build.sh | 37 - doc/www/config.json | 31 - doc/www/create_menu.sh | 31 - doc/www/create_template.sh | 17 - doc/www/css/main.css | 5891 ----------------- doc/www/css/shadowbox.css | 30 - doc/www/images/banner.png | Bin 48288 -> 0 bytes doc/www/images/bitcoin.svg | 135 - doc/www/images/close.png | Bin 255 -> 0 bytes doc/www/images/debian-128.png | Bin 12001 -> 0 bytes doc/www/images/donate.png | Bin 2288 -> 0 bytes doc/www/images/download.png | Bin 8995 -> 0 bytes doc/www/images/favicon.ico | Bin 31206 -> 0 bytes doc/www/images/help.png | Bin 10140 -> 0 bytes doc/www/images/install.png | Bin 9248 -> 0 bytes doc/www/images/linux-32bit-128.png | Bin 13273 -> 0 bytes doc/www/images/linux-64bit-128.png | Bin 13262 -> 0 bytes doc/www/images/loading.gif | Bin 2545 -> 0 bytes doc/www/images/logo.png | Bin 1791 -> 0 bytes doc/www/images/manual/dialog-export.png | Bin 19441 -> 0 bytes doc/www/images/manual/dock-context-sim.png | Bin 23109 -> 0 bytes doc/www/images/manual/dock-context-tool.png | Bin 14101 -> 0 bytes doc/www/images/manual/dock-estimates.png | Bin 15033 -> 0 bytes doc/www/images/manual/dock-position.png | Bin 11223 -> 0 bytes doc/www/images/manual/dock-project.png | Bin 11993 -> 0 bytes doc/www/images/manual/dock-status.png | Bin 10975 -> 0 bytes .../images/manual/dock-tool-path-bounds.png | Bin 9317 -> 0 bytes .../images/manual/dock-workpiece-bounds.png | Bin 8421 -> 0 bytes doc/www/images/manual/layout-default.png | Bin 172611 -> 0 bytes doc/www/images/manual/layout-full.png | Bin 219663 -> 0 bytes doc/www/images/manual/layout-minimal.png | Bin 160734 -> 0 bytes doc/www/images/manual/menu-examples.png | Bin 84034 -> 0 bytes doc/www/images/manual/menu-file.png | Bin 24465 -> 0 bytes doc/www/images/manual/menu-layout.png | Bin 47099 -> 0 bytes doc/www/images/manual/menu-project.png | Bin 17890 -> 0 bytes doc/www/images/manual/modified.png | Bin 14248 -> 0 bytes doc/www/images/manual/overview.png | Bin 256402 -> 0 bytes doc/www/images/manual/playback-control.png | Bin 8498 -> 0 bytes doc/www/images/manual/playback-position.png | Bin 1874 -> 0 bytes doc/www/images/manual/progressbar.png | Bin 2888 -> 0 bytes doc/www/images/manual/project-units.png | Bin 1701 -> 0 bytes doc/www/images/manual/resolution.png | Bin 6513 -> 0 bytes doc/www/images/manual/simulation-control.png | Bin 6645 -> 0 bytes .../images/manual/thumbs/layout-default.png | Bin 17083 -> 0 bytes doc/www/images/manual/thumbs/layout-full.png | Bin 22557 -> 0 bytes .../images/manual/thumbs/layout-minimal.png | Bin 15736 -> 0 bytes doc/www/images/manual/thumbs/overview.png | Bin 84962 -> 0 bytes .../images/manual/thumbs/view-simulation.png | Bin 40171 -> 0 bytes doc/www/images/manual/thumbs/view-tool.png | Bin 12115 -> 0 bytes doc/www/images/manual/tool-settings.png | Bin 11708 -> 0 bytes doc/www/images/manual/toolbar-perspective.png | Bin 7699 -> 0 bytes doc/www/images/manual/toolbar-project.png | Bin 4825 -> 0 bytes doc/www/images/manual/toolbar-view.png | Bin 6341 -> 0 bytes doc/www/images/manual/tooltable.png | Bin 5005 -> 0 bytes doc/www/images/manual/view-simulation.png | Bin 94285 -> 0 bytes doc/www/images/manual/view-tool.png | Bin 14502 -> 0 bytes doc/www/images/manual/workpiece-automatic.png | Bin 17201 -> 0 bytes doc/www/images/manual/workpiece-manual.png | Bin 15395 -> 0 bytes doc/www/images/manual/workpiece-view.png | Bin 3199 -> 0 bytes doc/www/images/manual/workpiece.png | Bin 5090 -> 0 bytes doc/www/images/mint-128.png | Bin 15189 -> 0 bytes doc/www/images/next.png | Bin 248 -> 0 bytes doc/www/images/openscam-bitcoin-donations.gif | Bin 2375 -> 0 bytes doc/www/images/openscam.png | Bin 27047 -> 0 bytes doc/www/images/osx-128.png | Bin 7512 -> 0 bytes doc/www/images/pause.png | Bin 155 -> 0 bytes doc/www/images/play.png | Bin 211 -> 0 bytes doc/www/images/previous.png | Bin 237 -> 0 bytes doc/www/images/screenshots/full_layout.png | Bin 235702 -> 0 bytes doc/www/images/screenshots/openscam.png | Bin 160734 -> 0 bytes .../images/screenshots/simulation_view.png | Bin 171487 -> 0 bytes .../images/screenshots/thumbs/full_layout.png | Bin 35962 -> 0 bytes .../images/screenshots/thumbs/openscam.png | Bin 23347 -> 0 bytes .../screenshots/thumbs/simulation_view.png | Bin 23754 -> 0 bytes .../screenshots/thumbs/tool_path_view.png | Bin 44545 -> 0 bytes .../images/screenshots/thumbs/tool_view.png | Bin 12177 -> 0 bytes .../screenshots/thumbs/workpiece_view.png | Bin 17764 -> 0 bytes doc/www/images/screenshots/tool_path_view.png | Bin 200520 -> 0 bytes doc/www/images/screenshots/tool_view.png | Bin 73176 -> 0 bytes doc/www/images/screenshots/workpiece_view.png | Bin 99852 -> 0 bytes doc/www/images/subscribe.png | Bin 7005 -> 0 bytes doc/www/images/support_ribbon.png | Bin 26811 -> 0 bytes doc/www/images/ubuntu-128.png | Bin 18209 -> 0 bytes doc/www/images/windows-128.png | Bin 17627 -> 0 bytes doc/www/jade/download/current.jade | 8 - doc/www/jade/download/debug.jade | 13 - doc/www/jade/download/install.jade | 16 - doc/www/jade/download/previous.jade | 24 - doc/www/jade/download/run.jade | 28 - doc/www/jade/download/source.jade | 34 - doc/www/jade/footer.jade | 44 - doc/www/jade/head.jade | 30 - doc/www/jade/header.jade | 51 - doc/www/jade/main/about.jade | 22 - doc/www/jade/main/community.jade | 20 - doc/www/jade/main/contact.jade | 7 - doc/www/jade/main/donate.jade | 29 - doc/www/jade/main/legal.jade | 23 - doc/www/jade/main/menu.jade | 28 - doc/www/jade/main/mission.jade | 26 - doc/www/jade/main/quick-start.jade | 11 - doc/www/jade/main/screenshots.jade | 10 - doc/www/jade/main/status.jade | 117 - doc/www/jade/main/template.jade | 37 - doc/www/jade/manual/docks.jade | 77 - doc/www/jade/manual/export.jade | 55 - doc/www/jade/manual/layout.jade | 30 - doc/www/jade/manual/menu.jade | 108 - doc/www/jade/manual/nc-files.jade | 16 - doc/www/jade/manual/overview.jade | 17 - doc/www/jade/manual/playback.jade | 31 - doc/www/jade/manual/projects.jade | 51 - doc/www/jade/manual/simulation.jade | 94 - doc/www/jade/manual/template.jade | 41 - doc/www/jade/manual/toolbars.jade | 29 - doc/www/jade/manual/tools.jade | 66 - doc/www/jade/manual/workpiece.jade | 40 - doc/www/jade/mixins.jade | 18 - doc/www/jade/notfound.jade | 6 - doc/www/jade/template_head.jade | 15 - doc/www/jade/template_tail.jade | 1 - doc/www/js/main.js | 74 - doc/www/js/shadowbox.js | 17 - 134 files changed, 8388 deletions(-) delete mode 100644 doc/tpl/background.png delete mode 100644 doc/tpl/images/square.png delete mode 100644 doc/tpl/images/squares.png delete mode 100644 doc/tpl/images/star.png delete mode 100755 doc/tpl/publish.sh delete mode 100644 doc/tpl/rainbow-custom.min.js delete mode 100644 doc/tpl/solarized-light.css delete mode 100644 doc/tpl/tpl.css delete mode 100644 doc/tpl/tpl.html delete mode 100644 doc/tpl/tpl.js delete mode 100644 doc/www/Makefile delete mode 100755 doc/www/build.sh delete mode 100644 doc/www/config.json delete mode 100755 doc/www/create_menu.sh delete mode 100755 doc/www/create_template.sh delete mode 100644 doc/www/css/main.css delete mode 100644 doc/www/css/shadowbox.css delete mode 100644 doc/www/images/banner.png delete mode 100644 doc/www/images/bitcoin.svg delete mode 100644 doc/www/images/close.png delete mode 100644 doc/www/images/debian-128.png delete mode 100644 doc/www/images/donate.png delete mode 100644 doc/www/images/download.png delete mode 100644 doc/www/images/favicon.ico delete mode 100644 doc/www/images/help.png delete mode 100644 doc/www/images/install.png delete mode 100644 doc/www/images/linux-32bit-128.png delete mode 100644 doc/www/images/linux-64bit-128.png delete mode 100644 doc/www/images/loading.gif delete mode 100644 doc/www/images/logo.png delete mode 100644 doc/www/images/manual/dialog-export.png delete mode 100644 doc/www/images/manual/dock-context-sim.png delete mode 100644 doc/www/images/manual/dock-context-tool.png delete mode 100644 doc/www/images/manual/dock-estimates.png delete mode 100644 doc/www/images/manual/dock-position.png delete mode 100644 doc/www/images/manual/dock-project.png delete mode 100644 doc/www/images/manual/dock-status.png delete mode 100644 doc/www/images/manual/dock-tool-path-bounds.png delete mode 100644 doc/www/images/manual/dock-workpiece-bounds.png delete mode 100644 doc/www/images/manual/layout-default.png delete mode 100644 doc/www/images/manual/layout-full.png delete mode 100644 doc/www/images/manual/layout-minimal.png delete mode 100644 doc/www/images/manual/menu-examples.png delete mode 100644 doc/www/images/manual/menu-file.png delete mode 100644 doc/www/images/manual/menu-layout.png delete mode 100644 doc/www/images/manual/menu-project.png delete mode 100644 doc/www/images/manual/modified.png delete mode 100644 doc/www/images/manual/overview.png delete mode 100644 doc/www/images/manual/playback-control.png delete mode 100644 doc/www/images/manual/playback-position.png delete mode 100644 doc/www/images/manual/progressbar.png delete mode 100644 doc/www/images/manual/project-units.png delete mode 100644 doc/www/images/manual/resolution.png delete mode 100644 doc/www/images/manual/simulation-control.png delete mode 100644 doc/www/images/manual/thumbs/layout-default.png delete mode 100644 doc/www/images/manual/thumbs/layout-full.png delete mode 100644 doc/www/images/manual/thumbs/layout-minimal.png delete mode 100644 doc/www/images/manual/thumbs/overview.png delete mode 100644 doc/www/images/manual/thumbs/view-simulation.png delete mode 100644 doc/www/images/manual/thumbs/view-tool.png delete mode 100644 doc/www/images/manual/tool-settings.png delete mode 100644 doc/www/images/manual/toolbar-perspective.png delete mode 100644 doc/www/images/manual/toolbar-project.png delete mode 100644 doc/www/images/manual/toolbar-view.png delete mode 100644 doc/www/images/manual/tooltable.png delete mode 100644 doc/www/images/manual/view-simulation.png delete mode 100644 doc/www/images/manual/view-tool.png delete mode 100644 doc/www/images/manual/workpiece-automatic.png delete mode 100644 doc/www/images/manual/workpiece-manual.png delete mode 100644 doc/www/images/manual/workpiece-view.png delete mode 100644 doc/www/images/manual/workpiece.png delete mode 100644 doc/www/images/mint-128.png delete mode 100644 doc/www/images/next.png delete mode 100644 doc/www/images/openscam-bitcoin-donations.gif delete mode 100644 doc/www/images/openscam.png delete mode 100644 doc/www/images/osx-128.png delete mode 100644 doc/www/images/pause.png delete mode 100644 doc/www/images/play.png delete mode 100644 doc/www/images/previous.png delete mode 100644 doc/www/images/screenshots/full_layout.png delete mode 100644 doc/www/images/screenshots/openscam.png delete mode 100644 doc/www/images/screenshots/simulation_view.png delete mode 100644 doc/www/images/screenshots/thumbs/full_layout.png delete mode 100644 doc/www/images/screenshots/thumbs/openscam.png delete mode 100644 doc/www/images/screenshots/thumbs/simulation_view.png delete mode 100644 doc/www/images/screenshots/thumbs/tool_path_view.png delete mode 100644 doc/www/images/screenshots/thumbs/tool_view.png delete mode 100644 doc/www/images/screenshots/thumbs/workpiece_view.png delete mode 100644 doc/www/images/screenshots/tool_path_view.png delete mode 100644 doc/www/images/screenshots/tool_view.png delete mode 100644 doc/www/images/screenshots/workpiece_view.png delete mode 100644 doc/www/images/subscribe.png delete mode 100644 doc/www/images/support_ribbon.png delete mode 100644 doc/www/images/ubuntu-128.png delete mode 100644 doc/www/images/windows-128.png delete mode 100644 doc/www/jade/download/current.jade delete mode 100644 doc/www/jade/download/debug.jade delete mode 100644 doc/www/jade/download/install.jade delete mode 100644 doc/www/jade/download/previous.jade delete mode 100644 doc/www/jade/download/run.jade delete mode 100644 doc/www/jade/download/source.jade delete mode 100644 doc/www/jade/footer.jade delete mode 100644 doc/www/jade/head.jade delete mode 100644 doc/www/jade/header.jade delete mode 100644 doc/www/jade/main/about.jade delete mode 100644 doc/www/jade/main/community.jade delete mode 100644 doc/www/jade/main/contact.jade delete mode 100644 doc/www/jade/main/donate.jade delete mode 100644 doc/www/jade/main/legal.jade delete mode 100644 doc/www/jade/main/menu.jade delete mode 100644 doc/www/jade/main/mission.jade delete mode 100644 doc/www/jade/main/quick-start.jade delete mode 100644 doc/www/jade/main/screenshots.jade delete mode 100644 doc/www/jade/main/status.jade delete mode 100644 doc/www/jade/main/template.jade delete mode 100644 doc/www/jade/manual/docks.jade delete mode 100644 doc/www/jade/manual/export.jade delete mode 100644 doc/www/jade/manual/layout.jade delete mode 100644 doc/www/jade/manual/menu.jade delete mode 100644 doc/www/jade/manual/nc-files.jade delete mode 100644 doc/www/jade/manual/overview.jade delete mode 100644 doc/www/jade/manual/playback.jade delete mode 100644 doc/www/jade/manual/projects.jade delete mode 100644 doc/www/jade/manual/simulation.jade delete mode 100644 doc/www/jade/manual/template.jade delete mode 100644 doc/www/jade/manual/toolbars.jade delete mode 100644 doc/www/jade/manual/tools.jade delete mode 100644 doc/www/jade/manual/workpiece.jade delete mode 100644 doc/www/jade/mixins.jade delete mode 100644 doc/www/jade/notfound.jade delete mode 100644 doc/www/jade/template_head.jade delete mode 100644 doc/www/jade/template_tail.jade delete mode 100644 doc/www/js/main.js delete mode 100644 doc/www/js/shadowbox.js diff --git a/doc/tpl/background.png b/doc/tpl/background.png deleted file mode 100644 index 90ee6934dd8d0c334ea38a0a74e32bdec2b7dba0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2108 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

lchSbxukK6TfwHoq)iEtP zMSQ|szWS*F4&X`U%h{&Zr1s)Vt%xw-x;lCUCznH%UYukfboq(I zc4o@3T#&qeHJtFHtz3@TB~$rLz~``cH|_t{57y0&G%)$yGFH3PC^XZ?Z z)-$Wg#srza<472%TV$C9hYz(k9ZE6ZW!ptXUMn!jsSE6G^Fn|Yg{#&1@=oom(nuJ* ze5IT%$tKZ&M@@}Iao%hFV5r)U@jGt!{d~~({qlOJXs@uoRJ6R7!u+yS)|a0)m=+oZ zm_g^DRR6te8?@pBe9xO4bbjEQB8%D63VH5T=93yYH(12ga#}{8*^EyTVdX8RHl>pb zo&Y8~FvVHSWt;EdH|Lxfkc66eM~_q!%oV$kr^B<$t5oXh!W@dX9%c6FY|)stlxxr@ zW0n{X2(aM5=q#`=IH}c_M3fKIk?5idhI}0rrGR0OIopXey3ZKfHaw!YY z4vW~J+}5TWrWdB1D0?_+?@rHp+i+O^^a*sTToxjI-zML+8#o}D)m`x#(-xIekh>Gr zg!ZNY!o6JgGfc3=IjUVBp-ZTy4wi`2+grDrC~2P~U*D;~Ebm`zB!0c&CZNMheb5jH zz0yLW51{q!YehoUXGZqkLyV?SHSA??t_BshLX+&ItkqU5p?Ozsr=N&Z znlsQ0P-3NVfDJ^{75Z?&ql!OXp?xCY)sX{5hXD&n0O88^8B;C4W7e0hWw{(LJ5)&u zG99XO$axhwVc(%z@}tsn9_&>0q#XWlK`OFev8}HH>vrw1NDIAC$dI{)l*qV3jX!&S z25&D4`tUmW7k61RH32;dP0VoA^QCD5h<1SpD}dW+^4mbjFmZh&h|Hcgeq~G2!T+&E z)1`i5_w}a|s{p)OPs2Jq?3RanwfBSu`$vW3dU=R|lMNf^b6LUpgag!v1@Ig684lOvZ+}&5v8>nT;pgA_0GV53z2W z%&cAe0&aiC_tM^fF|=Q<8+&gJD0jcrriNjgj1H|j*MPW5V(}hzVlBdCW;$78e8@=#;GB33##r2B<#>S*2vCBV;1Nj>B zQr&plA&>BRwWQYAm>mA{Z;G!;$O=$(&|ZR<*FIFYPC`0Ow+HUL$fv66;NHFnGsveT zg}UFEC{>;uq2~cILD`Ov17=-Wx#6GQTqT0o%m1p$$uaY11S&Ky@8#=+Mt)%48h@Cp ze=(;wb5GBz3G;56+#G^(w_qkzQv}61H)Z!epNSC(I-OsD0VMNnYoCkYaV__=(1@@` z3r}`Act6f*S^te2s+QWVaGoG}Yo*yaJT~lkta(U};P#DI+H<}Q5jGB#;=et7H*3~? z+)lFo)3DP-mPL+EXH|G_2g~w~%^lY&hK0mbrulf1y1(>l@PjQ3sxKrd_p^eh>A1*N zjI|AI_C?+0nAswXFfLnpfvatIar}5H_I)BvN0=trzRU|&{B%tR4g?Bf|9SyxXuJYWmYVp0D2gQf`-)k~&!!KNY-kTk z1g)fq`sk9oJBeMx3T;_K4+X5TXbBI8)xF9V`eu1MyP4s0g zG(~5B5ufM2JyW^qUYNz8%OS&{tGJvMtiOFWxm$XvggZVoG?s`zG--KkGplw}xF2e% zty5(=y!jZ&bSPqS^T*vDfguCN0NE~vg3?lMKn0cCb=)FNf0ti&ypBX!lxuTB=#$w# zsgUUzu8lu!zHzYGhx&=D1qxDz*FmcY70~{hZVKm~-kc<>oi}-;UwTBtjG2K%Zxzb` z7O|ITCt|{$$>Wv1-$^+c)X79pI@AjXjzk*9WyoZNmaA<&#hVqJgqD5<>Xp-+pfude z)D{(LbXnv86&7N|qvOv zzo|3Kql@wVAlZHQOIt5r5*t7U@z=f?nf&--gLn_HzW9Wyxi=%&qOvt3i^&f0a74la7+gs$wi1gD^(|Y%jEi{&b1>6}-hpcvbya z`2E)arn4ydU^eP)l0vl7*o_WD*Bq*B%MAHvifkyappv8VU{TrA64B${=o3l#f+x5k zABWdFruf7aDw-?G_ro-Ktp-xavrznksMf_iZn<3*f#bZ37m zog1zAtrtMna`BXF9yd3f9Rq!6zC&%?`>1}vVb&|sZKA{i94<0n*Z%ug^9w7B7j(W0 z`J7&X%8P>xl*t8_=F6{)Ii~-dzq<;g`FI@#tnvpVc;b7Vrr{1VsC-cKF=b8^e%8En zD)}Un6}0dzMIB~~9NxZY*QtU+(flP&6V(<6B=n>y245AJ;xwQ?&t9K6G{|VCBQ&$m zD))TG27>**8aFp2Lm=Av^EPaL=1JP1Ph}w_k{W>=v_SMl-q^|t7^_nithG_>3Yr7E zWh49uvy8bj!QPC^GO>S<4J0sRiyRK%rhJ(&htwDRu-eeymqUZZFjEsZ*vD<%E z>8A8im`)N}*r-!Jhn**)gvo$=`ZY*9=ky7XxMn&N3ql8egKy08Cc_#8?+HNe!SJ4R z9;=>o74X41+kK{_A&=G2y_{+C39z7=jg3vtlxzioVJ2L5d~+9_;_hJT$PeSsHnT zFubFN4G*{Z`EAsaJtB>(n&BAN3OGW zByA&{NKytrNWWp{!Y4LbIL>n9ue@^wjWB?^+iLGqyso?G>uwp#M6z=XMpFQm4Z(0b zYU*`r_3y=O6|qa5XeCvFxC2s}RbiUY2Ko|sfpGmbclTkwZgn%ltgOYHA}-YrwB3#$ zpw`?6Sy8X0Alpecp>gRikGEKE@dtmQyLlaS7Y*OgDu>DW(Cov@a1WHTKBTkrM03lP zq~hFnmM?J+&Q;K_OVjyv%~aTFhqb#XqtkO~LbrtUB!pqPrj*FhwS*{4$d}TwYWODJC!(1O-G^W*0%2Wv}{e^oj|{` z(~Cnoc`94XEoPOG0r(}o*BAYvxSX>LUh}&IkVI~F%z8)mWoOfI+0VIq@>8RLng9zX*W{Dd3!^bDz%`&RYfaQASrY^d{rln?=cV(j18U;4K0rr@ z9cx<3A@j+*b1Y>1mkj)O`MleR((gp!%-+oW0z)>O%~E2EF1+stx=p-mKi^;NJ&YY2 z5R{cFlgC!K?#1(-eh$_?iw1u$4I}-j3tvjT-XP_fMJLDQ%dhPC9h%2hm>keDSIqVd z(hryG^$8YkIzu$QsH-E4zJ*j{N;gDyOYje>Nl->x_IzW;(v3G$jxH@<$Q`qcE?GAj zm|p%EYS70tb1xn){|LLS2IPmfwd0AsymKRrc~uS7+9=g%Ng=k&(7=hc{w&(2A(v-2 z_$=Fg{%L74gh-X>>~qoR#eG|a<7V@pZnV*DUHTs5E)Tkf&PX&KhydySpZi9YZpp6E zPpqNOy6O8?DRV1RCs41Ra2bM-Kj`MPVX?Hg5vR8xy_|CCbC#5(bW}=PcB$n};{05O zQ81N8=Bd)ZT@kW*%eGpS$5D%;dUIV z>V)?${(6=w+pczEmDvk0kd9@`N_u2xrEN0!{0Bipt7`9fc~PxD?1HuvP#Y32F<)g< z7-O$-Q(L_SYPTY@HEPgY97r{NB8P<;r8i-2pqi{2ZN<|~qS}u9QL9_=ngF?xPf>q@ zYoNWYgk*y7GLDOF*o#g1s=bd1BMsBsN=Z{`d_iWKMHg+OJ)p-=ID0f~TXm*Hnl1fv zJ2A;BGR$CfID0-ubgT7?%-QEufoNhRr-cMrJybVZ?@nWIfEpz!&yC#aDp$8TdIVf@ zf%g_25CNw6eRY=Ni}n*pT<^c^O{For&wT!}eObz7BYZx{uIFyQ$@@0Lp@8g?A)st) z>sarlX3c#=?+yqfIzz4JLw)g-|1Ln$_xBKZkb~gHJJ_!^g8*~bj9o^|zC{nsQ_Oao zq1JiBbf7Z^I_7XFnuUHp2-vE{Q4SDKH;h2gNM>@pN~bf29x2%%5KoNU8K3l{{S=~x9OaS#yt2^^kD@^p)#O~glypSm z@F4$pTs$-5^fyR}HcNa9TSE;u)O0;Zgk zZ-+(!36YTs$IuTq=}E7HGW&9>_r;1+sChM{xKgvKvQK{tPz;zS`Ir^-(ukK@JVU60 z25Kf??E20+&^t!dD6Oq0zxLZDlsJ95CX$Jl2O&aG8N)emebcu(_iq^A&361?Inui$8KlUqtl2DHo-_G3@G5ftc6Ic@zW1KADBn{{yCjD@ zj>(m}fpsU|j1+82JKfavW`H6KpA4!GI9lo^-%`WR@|Fm80#V3`NcPH zI<{m4cpe54!j9Epn#^5YT4#65?*U+KvqI^teoMfLQBLE%^T?#C=JvAD0x2_=3b|A3PX~;Y@N!!e{(2R+mB{?3KW$$C!}pDnckb=j zAXIj8*l0=K0!XNWB`S1l8a{vpuSV)4Vd3tkAl0Y@V23<6dX^ke912CG5g8(>Xm)xx zJYnB)gU|#6-RFLTZ&^5OR`iE zw3VFNNu=rj>SjICGhY5)8i<E0_vSe>@+DgwkRfi&urw?UnCm9KI zyQx`_|E`@{JXE`V74Mm{jpVgRqk*)a)?pN3GVvI_VL+Ot*^ylmFS5kVoR6ia;@p5p zZhgn*e3k-RU(}wF?!324VEgn5@b4?%ui_PbACh|ga!^2U>p(NqB^LZK=;FQ(Ru3eLb zJFqTs20d*(XKVuh7!OhEX!x7A=B3}ha?8=B&sIpFv^DS;tt&f^qS1SmJwSrQv(`4q zWK7-?zt&Pa5dyIW>2M~0Q&%V-=_%vpfMcuZLa&KZtG!1Vj5<8%tukaqZV?Cy7zwnq zxY7;;k(hv2O)q7_w%QDggCvS_igIdO!sOAq)tCwowm~tLP(WHi)bB#V20k~R@o=WG zfH}d=$4r=CKNxTA_u6L2;1?wizdK&fwC>t9n5%BLb&Q6NSUwsw0?nALe?kMvfiNkz zrujD+sV^PINrgp`o^sTvpXaT)lTX~b0G;h^<~SJ+g$kfN9`1`6C7L;w3DI8h+zEek zdbbZ7?deISU(;Y=zw_22uX}&7?V$@6=)xWJ2yg>h5daB4Q~*m7T6Au=q#)s^8OXR~)yn zn%bG8rR^5xFPq-2|2*{z8+rp-0Ndi59~qup!Il$Dd_v>HIsyXaIxGd&V`ye(r{&wF z0NE3_DvfFYawdE9&LtZxr&E7U%8?HYH%MfSS53*+!-<{R41yU*!(eSuc~;&MGO6Xd zN=Y$*`V$p+ioFKe+b*sRFg0eE28Y^^^lvduV8b4aHR& zW1%IVJ=pLX%_m5E7J3N!wGFsd_Qs&3`A$pN+44~Q{Q2Y3Zi9V5LhJ)t@vA_cg1fa= zyA4b?Zp~q3N@xC0HyE_**9tq9h^~!{&O|7j^9JpL^l+z6Q(!MJq z;FR%hD$dyVlygZ!*+Ey!;)1r?UMPcDgn!{DXXz1u%2LNXOj2-!KKcqHq8=F;U|C24 z1e8(Gq2}DLXi%;BagMs5C3D(a2G`WbK;9zX(mbEXJXCNZ-AMGqhXP%irj*Ar_*};x z*TO_OzKJcjyFNfwkPHPAOh^;xCP9x4gH^f1ArXh(CX5_e=mVIRWnHkX2qHa(IRqUmq0{KYr)k~zasf+Bu7iw2iBsh(@z}RbuYfgUe$~nb zSF}U0ksk(fhkEs(+sqH=Z{RAaS?Laln#7_Re}ry3B3`(7m4_L49N#*n+!?-JNrE?(o()Dk9;zah9M= zL6^RcGx2ecgqK->|EyWYrP1H72Q%R_yT5TcDQs?F3~gs-BEu9gSNMVgk$8GjkB`X2($p5te?Rk;UP z3%1%g$eD^ptJ}d`tR?qfs`B1IsMvx`Ie_PB8K~hb3^m4eC&dN{_B_ZWz<1{tF7q^_ zL~S|N6!2MnzAh?YE@8Hxy@Xh#*?e&e+V&!jSyq4E=uk8)xmU#&nY+mxh7B5i4FZ<#&9gdP_=(pf z1KT2&R@-K=Ln4g~rVOZ+Nr1r*vN!C#obON4_W>C(1%WHW3OOz{lhJ0|`w1k{@Ltt^ zbvz7ZlyJEwRVazL11co8S>3aYugh>l-U3U{69>5Ahy1nu(EfK;n?%vPzNishr7UO# zwAU-?mHtG%oYaAtgv~D`$8O4a{dVhCEz61liKw6MpS1j9?2CeBUlX~mgrvvXu6U7O zygVejx-a5`^ACY$26Jb^=zy?motiWIVlY!MWppwaI~lk?nZh5F&i4R>@I0KM&<-Vb zI`da6t62$Q2htPF?E9KoCtbCz{XSiOlgcNrK}Zs{_iGCtSor9Z=t@m89v8NN7JC+X z*y0~H+P=^>iTgBvsp)R_EsYNpRqqE zb}O==K{<3PsuMrm9V8mOH`yf?RQLRXg296^g*02eK%)Go-2{QtL6W}SzIXZL?nDau z=XX_pyvRnhO2!+cgJAUBBNQ!wxpoTH^1*0!HT$x})83#he&O_Q;9BIMOcJb7n;_#0 zdKXsfboZW$eFe?mx=j}|$l=Ih;{`20z#3>J6|$`)u|Y>6{W`+x0Xq)FAa{@>h+NG0 zZzyW^HIP=_k269SyK<|SHi+s5f4nl8_IEyT-j{DKF1Nz|ebJF*WxUheJ!r1cGItyr ztQ}`Bb~`iU9>#WGG%TlfB}OFOt4npWF&>_9HI$*iw_-eZ5Mq*4ikrUxj5JH}V3v1Y zTYWFIsN$8KsKFDa0lx=ggHYis|HyINe_2dR`W;{Wr$2T|2NO1sJ5*54n#eG+8K2ek3DjQqLY{fSf`=aS4;AbEl`W^dZb8M=O&^rE$I zRFe#=Md)UFgN9{XpET@z-v%jO#whmrF}mxT65t+0KKWPo2 z71$QZRaV}tQubzMZA_B>9(3d4Ip9D7sj8fL)d%DhUz=XGyXSn;?f zaZbwwj_TEJCFIU2No=PP)PvuGdmsj=X-X@B=s1A>{|#hlk0LVz-LYz;!mAoZ8@+%2FuLGm zw)buE13n?~l@w}`Bmfk8ml>@CYT+a|p}%;Tn9?)_`SbChxPb(N(HmlvH6`u0@g42m z+}#c5v;ukeNyW|dt?)uBjucSVgs2=H8d!p}{ob3B`qHlv+b0(n*@WH za&}iP6>dD^t%CO0_q)ek`psA5T;p?Q2=SC?( z2j0?Io4eSjI$(g%mC4v}rC}O0I?yg`%*`Nw3wy=l3G9l4Ib>ihy$u=`(!JEQ@6HcUA zH8a#vK(xnsFO>juZv;M9@C8l>gM9LrLBH;1tGZJCm|<(9Cf&B<0q9R5Z5Z6%%{Eq! zONmDra8w+>&%n9_wMB&JTlP+CpZF>>_M7J*+QE?KRFx#OVx03z(3L`tR+iHZSCaEt zII~55#ZR_SRDHnY;tHQ?UwLSQ^CQ9%nMnIa?cmLnc;@?@6hXy_WLW*SdJR3<*KdMn zRs(@H<{8;A7JIbmlgybB1co03zeam|j$@^(N=SN8h0kl1ls|BJjuJMsIi2Sr6YJgE@UFdz}xlA8HdXd)y`zUmgVNoaAn zIz1CLSuF0lgf0Nvt~)@uCXUWKO)Ep#W$o4s&_9N}dI3RqLMyVFL#hxd|44vy1{F9gpkXgYFC656(0kO z&|9f<4QfKw;11rRMWqGcpD#1@A-9@qDi=67;GsT2z8gb5Q0P6BufBYWLPbX0mqZGu zeF43ur+>?Z{oRzaq)-=%B3XsI?P13h_@T*2?qnr_2fQ5c`+Zfy+RQuGmTqzLt#!)1Y6Trgp$*H7nm;xCu-NGuNq_If)J9C zRw~Q#LWgKrJrGiBD#eNw?E_hIs9=^H zv;(=Kjh|4yL2SX}ze&bnTcn{CeLjVcnfV#`7+0I5W<&799rME4G)p5-wz3^^C0lbs zf%j1V>jg-4=Tz^4l`PJQ$8P1Ht3#EnzlzB%0B_tvT204xbw}G+BO?&7UOFt?kecsUwTIBY|86RbQL#~?y zt%_(f#|dFmQO_Muu;pxpxjC0@@rAj9zTFYEt^35}9#2EV;sE!bpVg)Z1V7>+F5TIY z-xBr@Sf!Y(FKV7V8|=&nIeFz8I>|uz&zL_Icjaj_7>6jr9`=t5K>r?sUVm+AJ%4WP6QSMN#W~WV=!S_$kru=DaaP0| zEb2|91D_l(PeHnxZm0NJjds(NtbN0k>=Z^)Jy+SZPOh`r7QwU7LiLkNQNMMI!JUt&X2s5ce zEq|6bRW}MGT7uNC(Yn46m$j(wH^2ip9J3n&m)JlW;89F*Cvm&S9K0l}_}RCW-fJ~2 z_1ycwOENuL?$Qk3&LvF>poP@@zPXaD1L`ibQi%B+Q4^NGMw92>t9$d@+^5?|e-034 z3+naX2&3PJ(S&|tW=cvo>42Qi>WG9|vvPOqHktwI|L@lM%9=x-k_yaJVY`hxw4nGp zKXT7<>6wRQW&te~9(XWeJ2>f2`cYjvk6)qek#ns0zzrO}3)&B0BDZe1+ z94a7#wvEtPBsv?+Sc6s}%}^&?zX@FOP>fMF=oJh3b!6RT`uv;xt;ZA}i$y^u0}R4W z&l*&hWNKlZ)`9M6;W&o4EJ-VsEOblTx+3rn>j&s&OJAg9Yf7 zd!L0C2Yt&Q58w<_$>r9GT3USAWsn&!^GI|B+w}3qtAl< z|LXega5%TNUuBDpjW@&)682Vt(V~|qDI;ny%;LF-CO z0%#o1V)gkZ=HA9u<>mGYG(t-d_h~{^xnhmjGV46?{#H=Ax$i-X=T0~iUK!fF9~s_s zTn>-;CHQca{1BD+iuhHYta`ZMw=4cjgwn_(BHPCY?=HAoR+KdsN&bW^kNAJTzJ9At zAJ4;pgo$@lo?CKnOPq!cv{!Yl-C|BvfM3l?Qc0@FVnW)f7)2Q5TN<|DaC8s2r*-B} zOk?>zu!#Zph%h;+pBx@IpZl^7jg2&V>*Eik-luUON+mjMRFO@=S<$lTdeYS6xb4$f zH*-jrtDbhgiaC0#{dWGF3Z-YUZ;;LMolF-+@1Ns6HnZmvlO-UGC0CrA=08asq^G@h ziSw;+`n7sBFQ0!6XX6cK4MHEuj(CDIS(ea@TKqt@enc;t!&f)8q|sW&{Vn}VT}{;5 z&Frl;xuA+{oAa^g zSoXk{mG`{0#4I>8^i>F5R?^sh){gG?MLtnwu>09UfeW*XQwik5}cnE_QN8ycS zoH2pxA$%hdqoC;%B;;IhGS~1Xoo?63m;S9bcY|__3HJ+fkCi;3-*Dzv2TaIIh!OYV zD3QNiSbbvV49UVw1Mz56>;S?5*}OYnpCNu_I4)oE$-k_{ApEz2d(5oVOdsbJ%@nwQ za$KU1s3_LBlRxo3Bw3t;?Q6~XQ`F+q#~&r5!jxY0ISkDaBIF4pj>{{5XWzRg5nNoS z`b=&Al>Tme>o4-uS>ufp;`TFZ>x7UFUB*#@!m4o0-FZPyuz`vN&PFufuZFtbNB`J$ zoQ)ACZXm7>oRd@#I9;qm$Lcsip{0Or#5!3e%K71ZWM^w8mg~ui8S!i}P8FX5SzAA` zedoZ0+K+O!zh$JkfZaZw=K5-$BAPm8G zJ>ExczPPdGr3b$wg*tL#KHIm{tx78;L`pqBuAk<6c==&^4_A>9$5%v(bV`Nz1L-#% z81cIs%bMVt!AosnSwo3u6g2^J{k-TEYD}CX<(=9`|5?3YW&qa|eB^C7Jq+_HPjar~ z2245@UfoojXI6c0pc-F2iOB8t&oEGLZJVJNj>2W>Au7m^#2+S?KCmF-$}10g+&wYY zDIp!2>ZU))qwd?y`zMCq==ET*vq@u{c^-zDWq>bfceC=i5Wix1@(n z5yY7boar&krNWb6cdp^0U_Lp__sI_$EuMW|+{@lLo}X*? zuQ&BC4{PQUj&k;8{Z;u5H-A~UNKz)f1FUXrmWp&Vh{KiX^^r*fZz*{@N^|Q6#3e5& z{#eO5EKT^7A%t_yOLCUBL)JP=!jp$!RW({NQO-lm?&rZs-NoBLZql7U0d9jj;dg|g zP(zS+>ti>~Ok;f+-=D@q4avrqW9~MZV)#w>GX?rtp}))<80>@Yp3cbc)ZZ*IUR7innPVa$t0y0&&JV{ zqP_T89~rAt2SsW{Nt`GZ8jz&^)p!RrBhBnbe~A~eFuqiqU=kIVooM!t=vRJG(aFVW zs$PA+26?K{zGf#Z+QzPqGQ^}v-tdziEihDy{^bT|T=eC36sRJ`o5O+Zk zr^V;!iA(oVcj#=JnGUV|!5Ma|c}z_@{_-@@ER^_EmE7YNOrmx-qk&vs4TekGi=sRJ z=q?YJGream$+~^8&`l_kBmax~c3@s>tP`wjh3(lN!o!5vx<2CBk%&{B>Ggx*^C^v@ z!xT4n(Xx>`lCZ9SOvb*bEQGwJ*2|V0b27A#7M1njzt^~xT3HP|t!_WY)M>Er6W@F~ zQ#tF@V7c|>9zOnC!$tjz<&6825fkOE#Flz*9}bfg=z)QQ8WJ6%nQzJ5D4dISL9AvC zjNZjhSA?|)nn1|Dr5jDp)_;1Y4`g_U-}X#*?v0YG(lK)iI5}yE0hiym$lRlj|$oX z8hyi3%}dmYAY4+a7sFNXD_Tq#*Q$dM#64b7Bg05MyV}r2_oGzzsKd-r3niD?G7pSx zgT8}+Y{Pb$f5Ert%}v!uV;~34a=`pZzIQ{kQ8C9r<~8DLVqG$uPQl4!vN5R+k%I|0 z!)YVL@=sPCswv&PMY_5uU!AOr%hKMz%Fe-rLdPQ>AF?|+r<5lg9v1TLgbRZTz4;Dd zPM&v*J^Mv=9p3O37lE8S^XEYt$LmhEXn4?;?y9#@+X^gM!a{lZ0vl36)m;e)^%W;uI-iZv1c<}~dn_^rSD#2DrL9KF^H#6!F8EBo07N(HGZ15X?$_eqh-1`iSu$$I#FCKg4Mi`ccYV?C3-WbJE>5 zhPKB0VNM#lMe#fgC7zZ^mZuOu^ufxdWGM>{wq)ti43R%+ehR_m&4}N%de&Dq#51O< zlg8lp=hZ*<8y^LnOt%-)HvZ6+pEOz=ZQK=ca-Vr|{LhTcI&XQ+A4=yZwWdAn?2%Pr zhldPW>Y0kKoXcczka<_k7v)XS-6dDlWqriB?nos6-%-xV1a-sZz!%wvTT@5tOV!5R zgs|r4PEdCP#gE<|GTXDQnXv_pSN{+fj~>mh#E*`DQ!eAemaTQgKG1j;HC5 zbG1#xx(k)64i=?qxWE{k2IwSoqpL`xi%zkD)9XIC#z>95(n2eqUA?DnPg%u{IGTL> zS%h$y$$Ogl&auCW&OPiEdGtr>g0)U~?ztGGS}>tzBoqufqM%=mi+q3*WHTN1Q&^zf zUKn>H%3dWESBXd@^n3ZKthRDnU7I9jHkTYhr#*7(m4p5PA&CBzndu+3hq|A97pt;l zce4n8uUG{*Yv~^e!sT_gcMEYGLIPv2(K}pN^L#sJXPRp|)E#5l z$nLausq_o?#qnS=11GIhi!ma);&owoVWqIa9J}D4)!>3=@!{4CofMh)CBSN8c`JG> zp*3W&&4hCkmY-xCTy!Vj@^b5ttr)6Z^QGWV(UZ#ulcZFXU@7y<2&me26qR$4~zofTl23?FgUK{6( ztM-*l#Bk$)GQR5fvAWuOJ;9IUgSKMM+86cWBpP%#MN;Jvf7bo%<>42X=uH-Kd2XTB056g=h5BUu~I89vr z-a&VJ;wK2}p0aW&9(53!k=Gg$-%-CeYKh$7+vv+mn3?^%6}wS{C1Mf9Mu zwA&>v0#3EBW=B^IhOy1wWF4)U;o9;ks#<sl@r zZnS1>xuqV|ij{3L25t4f9(dLhhwPPiB1NWz-u_kooOfO6b&p~!;ATRYNyR3@J zkz__9_xM7wqx^OjjsnvE#KGUPm|N3`%i57r-N&cx?PvNHVqX8(THKd9o*gce8D8e4 zbE09F&Xbd8w}xSKmjc~H$~L!~lKV-+F@^{k%~``Fky<+%n>(~@({*@3Iak0K zQPpP4ooR4?EAwTW?LTJUbDO3a#3V1eX`H9I02y7XIwQ2tTg_w^4A>OCgw7(=%=y_i zd`1d%%jTJ9{=%PEWY{M4lQu-o6WrWCmrlEFWErNH>sq z)&o}+^+`o|#dNBaiF6vHz!#>S{Li^f1G1MK>Ba3*3Mce=7?L52913jL;uK#G9b z`_-~jPo*}!h{-da_SIa)h(Uh5FGCTLR5oYwBU;|`hTi@-+Vv8)FI3kdpcPwnYV^l(p()yk8Wk^ zRwpeh;+1W}$8sNwoMvCyic^Wc){PW*&DX7)o1&qCIHy;fZe}VdUCcDS|8eC_-EqI6 zqUH8M8=t{BzwsJ>&vsOizt@HuNlqPgP2yDEufI_I!;WM0SA=Kpo4wD_3nunCuQ}XP z$H{B#r65Nh2Hw(B^xA}vBo2mXMlR`D7ikVO)K_3D)y?n87-}p|#+5X1JV7Vugf*Xz zH3x0md;T@zX`hZuD-t=i&m;9Lx>M}c#DbWFWwiDSyZ%Zob$X&<1C&~ia5FbR1%yd= zo$dMyQ%m8b?4>5oC9%`X5A)~SLkF+pD&41kM6x@17_90>{dH@JDvz8^bDYgv ziyz1_R>@AYLwa6xIlbG~xP^As={E`f8P>Q^%0)Lgq0g$}YJfRDHM7WfJ_77fwv)PC zINyG@XCY@XJ79d&E^|ADxn5O8`d$l7N__FBUjn+(?82rTFEoYS1m)cI$Cq<1$Zv{m zE=$?95r!N~=nPRMmYF>+XfO2{XTWb3u-O4~c84fu%xPDYocXg)&mP3!|5;@;nWA=Y zKGUdS#4H?DHADYO!f{z-$u_pHbO%T`mK-^&HY3_`x!t1qJhD<3xy)mc8Ot zSUMkCR&6;6OvSKWOwa9!OMHLc7(-2;m+>K=qxbH%iL=~aV6P({CAyZ`)=ia7Z2;dJ zzoS^LFP~JT6o27>!8|sQl?JkQ3L7OaT75>D`v};3Y$KpSZo^F?@(75xNmd_TdrFH> zthu1k;K~Qf`k0)3Wf^$4epoZ@jk&iP1|Mz(4JAh!>poR;ATa_SmbZ%+;GvA>L->ye%=`i$at%+hp$I+0B7H~j_UmJ@m8 z$pCJJ$MB8m>Znk(v&A)c!MAS2!u714^)Q z_fBe;Ft%iUv!fHY3Qy++84lq=J32Pg)6X-cW0O+4k1XaJ3LS3^A0_us7O61mMGt~i zxIk{Sn)!V2%p%|UBRp|-wUY=v6<|RuezM=ft1bn^sl$T@wUSwlc2r`{SS%5IReDYzo^KPlQ4{Qofs9VU-?!VN$2EKLXOS$w*? z=w~@Lt(#IzfL0mnEVkv!3u~PSLs|q!hfb zJqWq+7;MG|UUbPJ&Mb~)%S*0tUU(2=+q!1jqps_p@Y!D31!ldop$OstoA;(B5chxn zY{DkF?E(2M+Hu@Z!6p`j#(za*X@^!Vxt`j1kunD;o_3xxgIJE~$aLkIz+wQq*{4?l zg_#`ZgeT`ZpT`CcS*+^ap{P6lo1I|(YAN0F&!6CP(_4md+g-O)4zINDym7#TI=Wg) zgHw5NAT@7g7)Wn9%;#cY`#iIL9@U3FJem46wcGshd_&O!)6-=_ao~E9M?VAJr5^TA zZvpvl!FUVJy~RIX9;dhd3(>&{aTYW%`#vjszUSh2mH`Bc?4txfGX*Y+iwWr}`fO={ zl$6eh;@6#OB$jh!8nDo(V0G1y;>Og8Y^Hl>7r=4Kf8ciUhHFYTwHWu4E(Ikwn-kyN z?Yq^qB(qhGGgOa@u-3OneXB1z0RNgC1#BKp^<|5V4*Q#t!}36 z<`_i%M^;<+bwbRNdKvmZoW4&zTu+3%J8z3|X2|Wcv#VL!wBo`x z9Yssx;BFAz@O8Kjx@~5vk-j4g(JW2uX^(1NNWITUZM-)EZ+Quh5 zNTv5U1|OdWRuDXgr8%c4-uN^DJ8Db{=Fvo(?KA#9TG>kdlrU z9VD=y1DsS8EZYAQ2{d@`?(9qXYw8E?h-j6w)t0?G$@feUR|@y6g%lbfBkpar&l5dS1wciqZo(QqX?s9#If~sDX%j7n;73vVQXG%^OiX_J2ZQ85+h1CJH9TQ2{oE^j$I-rATjVL;LC)lyv999ePRB@EbdEqy*IWXg*ux5 zp9~%xFzOawfrP=>Ck8<3-d~st$IWHo0xO_(yut9Mf2ib{%v&bmUEL(V`T^uov|h01 zGZj&96OKZRY#Jj*3&V)NgxoNm*&H$gr`twl?6VE?6TXi$GK4j6cQPTI@?TiwXgL6f z4-<3y4fmRHVIE^lkX-P39Ipq*b$ol~xd}|r;vik)F*7H*QxJL?e#9exy;1Hk5p3?dBa0Q))5uG@^mBZE;574zaujk_;jD2sIxGU)HCyCX}=-g*9KaS+n&B zD}P2EJ$kbj?HuIM)Rx;P79^}ij}~}x!D@KbkX~})Nb+DMdN79Cyd;E9T;O$|B}G>x zpBlun+)X*<(x)31MR4c^huW;YJp-p1F>JX>Nq*CPW=Ht$EN_?m#P-nEgqfCiz!#&g zdY7H8I*I1}J>Az0JA1qm5E7>jQPBGzdz=G7*nvVu9-Y(|X&u-HD2|636!$sK^o94Y zjL$o%3Wb~y3^4N;2h1l6F{C}_MM9~sz-E@EtH1xE zb(F{?hj3s1i6-~lOjQX9yC5z}y+n9+-aI(a1rvMEl7|~c=NM8q8lRko4rj_VNrFZs`XAB*jE$Q=XjuvvyJS}&yn-QYJq@-bS zXXIvJYhK^R%`=7O?TkixV`;(K z^{#*J4IYLH$-EvGBHTek5CKR))#ANE`Ewgxo@pcp6QyLDkez284b`O&%t*9SvM&}T zO^BkQx(h0Ro7dl-zcXT&)l)|yAcnjAh!93M?tjdxRUMp0CviLpKQVI9D>9+AS?dUg zZY5ITE{JdOP>ufkL-N2(oEb?4xdglwDpNHCb0s=8_<6hfA|uEHpLg*|XImIIpcErJ z4kX#9va2(4(CWkPuFcGMX)u~CuY&1c(JF`((d@n5;TIc| z`cd~O(kWG?N&{d66w9Jly}ByjJk*#kqpurgK!WN*A|tJXkEdr#_!c~))%}uynlDza z*UJuvfa%xmrnxc7wU#fF0xPky5d0T z55s85wFn%(e%J{^1LpBMSBcW~M}ZehG33s@fzvPCry+EYzVe`ZDDDew*A#!>XD zpSc7MI199G?_ViW&8QO%D19?Iq=V{7R)N@n#&gmdk(&qSnw8)0TvR7&%NZ;`qe~Sc zXSb{0A|nq5#`~eyBlY+mH;#&G=ntTX-d(_+4mZywjQoC;ObgL7SMnp}BW+U362hTg zrm4p*uc1v^R8-)T#}-&fElQTcR$MFMdd9VT?J&l+`?-vuceiD&&(=aiGdYKsw_H`z z){23g;f*?EH~^XjU6xZ|YTc#Z%nT;Uw7u3<@CuZ~?2TmtBcr@Y@M0nl-7SU30R2IM zzZlUs)9vHI&sF3)QEaNBA_rh6qtp;hKF0p3kunXH8j=}5zb-DBzC@JSM10oF1x~IF7`x;8sqVmle!0v#C0O&{w>CG!<0M~T8;?@74 z7J)h_I3Az`Xn}(6^8a}>T8f^-Tmh&cnh)sy9~7qF|M0jE{{T$Y%C!Ih diff --git a/doc/tpl/images/squares.png b/doc/tpl/images/squares.png deleted file mode 100644 index 6d3c25837ae7c831628bb2e6b43bec1c87695cce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 90754 zcma&N1yEdD(=I${kdPn)1PBCzySoqW?(Pg8+zA>axVyVUa0~9P!QI`RJ2~fj|EmAJ zb?e@$UB$3!?Pb0C>F%d{hseu{p&;QR0RR9L32|XX004#%0Dx9UfQGbS0x`)Ue_$Ly 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