texlive[49658] Build/source/utils: asy 2.47 sources
commits+karl at tug.org
commits+karl at tug.org
Thu Jan 10 19:49:49 CET 2019
Revision: 49658
http://tug.org/svn/texlive?view=revision&revision=49658
Author: karl
Date: 2019-01-10 19:49:48 +0100 (Thu, 10 Jan 2019)
Log Message:
-----------
asy 2.47 sources
Modified Paths:
--------------
trunk/Build/source/utils/README
trunk/Build/source/utils/asymptote/ChangeLog
trunk/Build/source/utils/asymptote/GUI/UndoRedoStack.py
trunk/Build/source/utils/asymptote/GUI/xasy.py
trunk/Build/source/utils/asymptote/GUI/xasy2asy.py
trunk/Build/source/utils/asymptote/GUI/xasyFile.py
trunk/Build/source/utils/asymptote/GUI/xasyOptions.py
trunk/Build/source/utils/asymptote/Makefile.in
trunk/Build/source/utils/asymptote/README
trunk/Build/source/utils/asymptote/ReleaseNotes
trunk/Build/source/utils/asymptote/arrayop.h
trunk/Build/source/utils/asymptote/asy-keywords.el
trunk/Build/source/utils/asymptote/asy.list
trunk/Build/source/utils/asymptote/asymptote.nsi
trunk/Build/source/utils/asymptote/asymptote.spec
trunk/Build/source/utils/asymptote/base/animation.asy
trunk/Build/source/utils/asymptote/base/asymptote.py
trunk/Build/source/utils/asymptote/base/bsp.asy
trunk/Build/source/utils/asymptote/base/plain.asy
trunk/Build/source/utils/asymptote/base/plain_Label.asy
trunk/Build/source/utils/asymptote/base/plain_boxes.asy
trunk/Build/source/utils/asymptote/base/plain_constants.asy
trunk/Build/source/utils/asymptote/base/plain_pens.asy
trunk/Build/source/utils/asymptote/base/plain_picture.asy
trunk/Build/source/utils/asymptote/base/plain_scaling.asy
trunk/Build/source/utils/asymptote/base/plain_shipout.asy
trunk/Build/source/utils/asymptote/base/rational.asy
trunk/Build/source/utils/asymptote/base/simplex.asy
trunk/Build/source/utils/asymptote/base/slide.asy
trunk/Build/source/utils/asymptote/base/three.asy
trunk/Build/source/utils/asymptote/build-scripts/build-asymptote
trunk/Build/source/utils/asymptote/build-scripts/build-asymptote.dos
trunk/Build/source/utils/asymptote/builtin.cc
trunk/Build/source/utils/asymptote/config.guess
trunk/Build/source/utils/asymptote/config.h.in
trunk/Build/source/utils/asymptote/config.sub
trunk/Build/source/utils/asymptote/configure
trunk/Build/source/utils/asymptote/configure.ac
trunk/Build/source/utils/asymptote/doc/CAD.pdf
trunk/Build/source/utils/asymptote/doc/FAQ/asy-faq.info
trunk/Build/source/utils/asymptote/doc/TeXShopAndAsymptote.pdf
trunk/Build/source/utils/asymptote/doc/asy-latex.pdf
trunk/Build/source/utils/asymptote/doc/asy.1
trunk/Build/source/utils/asymptote/doc/asyRefCard.pdf
trunk/Build/source/utils/asymptote/doc/asymptote.pdf
trunk/Build/source/utils/asymptote/doc/asymptote.texi
trunk/Build/source/utils/asymptote/doc/planes.asy
trunk/Build/source/utils/asymptote/doc/png/asymptote.info
trunk/Build/source/utils/asymptote/drawclipbegin.h
trunk/Build/source/utils/asymptote/drawelement.h
trunk/Build/source/utils/asymptote/drawfill.cc
trunk/Build/source/utils/asymptote/drawfill.h
trunk/Build/source/utils/asymptote/drawimage.h
trunk/Build/source/utils/asymptote/drawlabel.cc
trunk/Build/source/utils/asymptote/drawlabel.h
trunk/Build/source/utils/asymptote/drawlayer.h
trunk/Build/source/utils/asymptote/drawpath.cc
trunk/Build/source/utils/asymptote/drawpath.h
trunk/Build/source/utils/asymptote/drawpath3.h
trunk/Build/source/utils/asymptote/drawsurface.cc
trunk/Build/source/utils/asymptote/drawsurface.h
trunk/Build/source/utils/asymptote/errormsg.h
trunk/Build/source/utils/asymptote/examples/p-orbital.asy
trunk/Build/source/utils/asymptote/exp.cc
trunk/Build/source/utils/asymptote/fileio.h
trunk/Build/source/utils/asymptote/glrender.cc
trunk/Build/source/utils/asymptote/interact.cc
trunk/Build/source/utils/asymptote/main.cc
trunk/Build/source/utils/asymptote/memory.h
trunk/Build/source/utils/asymptote/parser.cc
trunk/Build/source/utils/asymptote/picture.cc
trunk/Build/source/utils/asymptote/picture.h
trunk/Build/source/utils/asymptote/pipestream.cc
trunk/Build/source/utils/asymptote/process.cc
trunk/Build/source/utils/asymptote/process.h
trunk/Build/source/utils/asymptote/psfile.cc
trunk/Build/source/utils/asymptote/psfile.h
trunk/Build/source/utils/asymptote/revision.cc
trunk/Build/source/utils/asymptote/runarray.cc
trunk/Build/source/utils/asymptote/runarray.in
trunk/Build/source/utils/asymptote/runpicture.cc
trunk/Build/source/utils/asymptote/runpicture.in
trunk/Build/source/utils/asymptote/runtime.cc
trunk/Build/source/utils/asymptote/runtime.in
trunk/Build/source/utils/asymptote/settings.cc
trunk/Build/source/utils/asymptote/stack.cc
trunk/Build/source/utils/asymptote/vm.h
Added Paths:
-----------
trunk/Build/source/utils/asymptote/GUI/CustMatTransform.py
trunk/Build/source/utils/asymptote/GUI/DebugFlags.py
trunk/Build/source/utils/asymptote/GUI/GuidesManager.py
trunk/Build/source/utils/asymptote/GUI/InplaceAddObj.py
trunk/Build/source/utils/asymptote/GUI/PrimitiveShape.py
trunk/Build/source/utils/asymptote/GUI/SetCustomAnchor.py
trunk/Build/source/utils/asymptote/GUI/Widg_addLabel.py
trunk/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py
trunk/Build/source/utils/asymptote/GUI/Widg_editBezier.py
trunk/Build/source/utils/asymptote/GUI/Window1.py
trunk/Build/source/utils/asymptote/GUI/__init__.py
trunk/Build/source/utils/asymptote/GUI/configs/
trunk/Build/source/utils/asymptote/GUI/configs/__init__.py
trunk/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson
trunk/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson
trunk/Build/source/utils/asymptote/GUI/icon-list.txt
trunk/Build/source/utils/asymptote/GUI/icons_rc.py
trunk/Build/source/utils/asymptote/GUI/labelEditor.py
trunk/Build/source/utils/asymptote/GUI/locale/
trunk/Build/source/utils/asymptote/GUI/locale/th/
trunk/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/
trunk/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po
trunk/Build/source/utils/asymptote/GUI/pyUIClass/
trunk/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py
trunk/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py
trunk/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py
trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py
trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py
trunk/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py
trunk/Build/source/utils/asymptote/GUI/pyUIClass/window1.py
trunk/Build/source/utils/asymptote/GUI/requirements.txt
trunk/Build/source/utils/asymptote/GUI/res/
trunk/Build/source/utils/asymptote/GUI/res/icons/
trunk/Build/source/utils/asymptote/GUI/res/icons/anchor.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-camera.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-close.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-delete.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-done.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-expand.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-hand.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-locate.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.asy
trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/center.asy
trunk/Build/source/utils/asymptote/GUI/res/icons/center.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy
trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/check.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/circle.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/close-round.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy
trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy
trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/code.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/edit.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/eye.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/grid.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy
trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy
trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/plus-round.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/save.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/social-python.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/text.svg
trunk/Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg
trunk/Build/source/utils/asymptote/GUI/res/icons.qrc
trunk/Build/source/utils/asymptote/GUI/setup.py
trunk/Build/source/utils/asymptote/GUI/windows/
trunk/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui
trunk/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui
trunk/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui
trunk/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui
trunk/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui
trunk/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui
trunk/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui
trunk/Build/source/utils/asymptote/GUI/windows/window1.ui
trunk/Build/source/utils/asymptote/GUI/xasyArgs.py
trunk/Build/source/utils/asymptote/GUI/xasyBezierInterface.py
trunk/Build/source/utils/asymptote/GUI/xasyStrings.py
trunk/Build/source/utils/asymptote/GUI/xasySvg.py
trunk/Build/source/utils/asymptote/GUI/xasyTransform.py
trunk/Build/source/utils/asymptote/GUI/xasyUtils.py
trunk/Build/source/utils/asymptote/GUI/xasyValidator.py
trunk/Build/source/utils/asymptote/Pipfile
trunk/Build/source/utils/asymptote/base/rationalSimplex.asy
trunk/Build/source/utils/asymptote/examples/slope.asy
Removed Paths:
-------------
trunk/Build/source/utils/asymptote/GUI/CubicBezier.py
trunk/Build/source/utils/asymptote/GUI/xasyActions.py
trunk/Build/source/utils/asymptote/GUI/xasyBezierEditor.py
trunk/Build/source/utils/asymptote/GUI/xasyCodeEditor.py
trunk/Build/source/utils/asymptote/GUI/xasyColorPicker.py
trunk/Build/source/utils/asymptote/GUI/xasyExample.asy
trunk/Build/source/utils/asymptote/GUI/xasyGUIIcons.py
trunk/Build/source/utils/asymptote/GUI/xasyMainWin.py
trunk/Build/source/utils/asymptote/GUI/xasyOptionsDialog.py
trunk/Build/source/utils/asymptote/base/plain_xasy.asy
trunk/Build/source/utils/asymptote/builtin.symbols.h
trunk/Build/source/utils/asymptote/gsl.symbols.h
trunk/Build/source/utils/asymptote/runarray.symbols.h
trunk/Build/source/utils/asymptote/runbacktrace.symbols.h
trunk/Build/source/utils/asymptote/runfile.symbols.h
trunk/Build/source/utils/asymptote/runhistory.symbols.h
trunk/Build/source/utils/asymptote/runlabel.symbols.h
trunk/Build/source/utils/asymptote/runmath.symbols.h
trunk/Build/source/utils/asymptote/runpair.symbols.h
trunk/Build/source/utils/asymptote/runpath.symbols.h
trunk/Build/source/utils/asymptote/runpath3d.symbols.h
trunk/Build/source/utils/asymptote/runpicture.symbols.h
trunk/Build/source/utils/asymptote/runstring.symbols.h
trunk/Build/source/utils/asymptote/runsystem.symbols.h
trunk/Build/source/utils/asymptote/runtime.symbols.h
trunk/Build/source/utils/asymptote/runtriple.symbols.h
trunk/Build/source/utils/asymptote/types.symbols.h
Modified: trunk/Build/source/utils/README
===================================================================
--- trunk/Build/source/utils/README 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/README 2019-01-10 18:49:48 UTC (rev 49658)
@@ -4,7 +4,7 @@
Extra utilities we (optionally) compile for TeX Live.
See comments in ../texk/README.
-asymptote 2.44 - checked 8apr18
+asymptote 2.47 - checked 10jan19
update to TL from CTAN, to include prebuilt doc.
see http://tug.org/texlive/build.html#asymptote
and tlpkg/bin/tl-update-asy
Modified: trunk/Build/source/utils/asymptote/ChangeLog
===================================================================
--- trunk/Build/source/utils/asymptote/ChangeLog 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/ChangeLog 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,3 +1,2172 @@
+commit 67f0c4b2d24adc346d7b616b13298903433c5910
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 23:23:47 2018 +0200
+
+ Minor optimization.
+
+commit 541b4014c2ad7fd63d845c3ffb6a33a6459c12eb
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 23:07:55 2018 +0200
+
+ Fix scaling (allow second variable in Simplex method to be negative).
+
+commit 28bc9c75a1393cceb0cb719881804615ec09f05f
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 11:23:04 2018 +0200
+
+ Generate EPS only for single-page documents.
+
+commit 89d2c88c2945096e5d765e3d9fe76163f8f553e2
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 10:02:53 2018 +0200
+
+ Remove .vscode from releases.
+
+commit 39454327d81d169aa48fc25f6397afa0bba83be4
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 09:57:43 2018 +0200
+
+ Remove unused files.
+
+commit 2157692a4b640473b188cdee545a431fea67e15b
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 05:42:26 2018 +0200
+
+ Fix uptodate flag; remove spurious directory.
+
+commit aba57e58c0292a3298bc132298671814aeb67fc4
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 04:42:23 2018 +0200
+
+ Fix URL in README.
+
+commit fa2aa36e9cea341aad6ab0e3bf49db93001069c5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 30 04:33:10 2018 +0200
+
+ Fix bsp module.
+
+commit 22d2b8d37da35bf1d0d6a1ddf75e1db32885ede0
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 29 13:22:04 2018 -0600
+
+ Increment version to 2.47.
+
+commit 4eee33bc01e444c03242eefbce091bed40d3f835
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 29 11:29:27 2018 -0600
+
+ Fix relative alignment under picture rotation.
+
+commit 9edc023b2c37d0ea50972c1ab784ee9e1e100d55
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 29 01:42:29 2018 -0600
+
+ Fix commit 451a260ae50d02867c1e54726a68d8af2c55761d.
+
+commit 451a260ae50d02867c1e54726a68d8af2c55761d
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 28 09:35:16 2018 -0600
+
+ Fix shipout issues.
+
+commit ae6d9d312ab21212216960f56122ffe8e0c7fa2a
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 28 06:24:46 2018 -0600
+
+ Account for pen width in bbox.
+
+commit 3ea27282e2a79139cd5600ee31b8e1b451eb2d03
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jul 27 02:02:17 2018 -0600
+
+ Don't use defaultGhostscriptLibrary location in MSWindows registry since TeXLive dvisvgm requires 32-bit version, even on 64-bit platforms.
+
+commit 3b49296799c14832747db90150d23067f946683a
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 21 18:00:11 2018 -0600
+
+ Increment version to 2.46.
+
+commit 19dd6cc8027597d5e2ca25b07db2851d9771f03c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 21 15:37:27 2018 -0600
+
+ Revert "Update path."
+
+ This reverts commit f63df996a86c935c51e09c47fe9c0aa2a8d7dc2d.
+
+commit f63df996a86c935c51e09c47fe9c0aa2a8d7dc2d
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jul 20 23:09:03 2018 -0600
+
+ Update path.
+
+commit 1734e7af6a018f27240fddd4e7bf14f569a09522
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jul 20 21:33:54 2018 -0600
+
+ Improve error message when rsvg-convert is missing.
+
+commit abd6347aea2faaa2862e3ebe34c7f85dd820c77d
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 19 15:10:59 2018 -0600
+
+ Remove obsolete uuid code.
+
+commit b46eed584fea0e625f2cde3dab23c2522d3d2486
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 19 15:09:10 2018 -0600
+
+ Fix saveLocation.
+
+commit 87c39ea72263c68d5548da4941eda639f37fce22
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 14:59:32 2018 -0600
+
+ Use class instead of instance on item not existing.
+
+commit 721cc5cc84abe2351211262670f5091e66f33b7c
+Merge: ec53a266 5f95aa82
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 14:56:15 2018 -0600
+
+ Merge branch 'master' of github.com:vectorgraphics/asymptote
+
+commit ec53a266a170edcd94c8a070f4d5b4a028eba964
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 14:56:11 2018 -0600
+
+ Revert venn.
+
+commit b88d3d9df356db299150e59d4ee0ef0f5adf82bb
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 14:55:10 2018 -0600
+
+ Fix script not updating.
+
+commit 5f95aa8246f7976dfc17a522b66da4a4179833c1
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 19 14:52:25 2018 -0600
+
+ Simplify build script.
+
+commit 779b1b60d7b7fcfa35d48a946fa421db1be54a82
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 14:37:25 2018 -0600
+
+ Only write transformation if the rest of transf is not Id.
+
+commit 63f054012ad1716c8c0de04521ac0e66b81afadb
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 19 14:28:51 2018 -0600
+
+ Remove 'x' key prefix.
+
+commit 0e351c95efca60034ec5d9397ab7924bf415f6ca
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 19 14:13:42 2018 -0600
+
+ Don't apply xmap without an explicit corresponding key.
+
+commit a7026b70bb0793696075d53f1a0dd683073acf82
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 19 14:01:43 2018 -0600
+
+ Update xasy documentation.
+
+commit 7e9954d1ab1043f03b5082266b1cef7a44091c89
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 13:58:41 2018 -0600
+
+ Fix zooming sign inversion.
+
+commit bd333b65cf24379797188e00c961cda229727e0e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 13:39:10 2018 -0600
+
+ Add zooming on arrow keys.
+
+commit 183b47c0f305f829cacaff28222bd1cf40523130
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 19 13:10:15 2018 -0600
+
+ Hook up/down to selection.
+
+commit 7a49eda58677c8d26fa8efbd8f946d80ac560c1a
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 18 14:58:59 2018 -0600
+
+ Transform directly from asy to image coordinates.
+
+commit 65f66b98a91f4dff78c1f6e769005c20b53e926c
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jul 16 15:01:00 2018 -0600
+
+ Disable fill on open curve.
+
+commit 98d364235fdf5073c1dcf2f51c478f21e492de56
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jul 16 14:26:53 2018 -0600
+
+ Fix repeated asyfying.
+
+commit 0ad7327a11094d336057f6d21d99e1385e685c6c
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 22:30:36 2018 -0600
+
+ Fix line shift by xmap.
+
+commit 360e165e00f0c304600a2371af6b5ffefeff89f8
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 21:00:02 2018 -0600
+
+ Revert venn.
+
+commit 42b192057a798825b8e1f5cf0939072cb4f2c116
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 20:58:31 2018 -0600
+
+ Only do change of basis if transform is not Id.
+
+commit ef89f277409805f8a7e65ba7b735b9ddb9bee93d
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 20:49:13 2018 -0600
+
+ Fix transf on different basis.
+
+commit 76d1e66db7ecc1a550c73326b4ea34e65a2e4630
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 20:40:36 2018 -0600
+
+ Fix key load bug.
+
+commit 574c0d96364ccbea81810fcda44cff5b68a35dc6
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 20:23:50 2018 -0600
+
+ Fix add label not working.
+
+commit 7d6cff54d91e978bd700188d09af2e3da1d66ead
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 17:20:15 2018 -0600
+
+ Force cleanup asy.
+
+commit 815e72d73eaa2af714ce157dc8cbc3363ad92cd5
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 15 17:14:41 2018 -0600
+
+ Fix duplicate key problem.
+
+commit b85a7d3b9e8ab18806ceb0ef39cc4f983a55f348
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 15 14:28:34 2018 -0600
+
+ Fix array bounds.
+
+commit 2c15d93e8ca19ea73ed1fb4186b3b3fc93520050
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 15 14:28:16 2018 -0600
+
+ Remove duplicate option.
+
+commit a070e8a6f9e3a3bef91a09fb0b9e192541a2a6bb
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 15 12:33:42 2018 -0600
+
+ Force dvisvgm to be silent.
+
+commit a8a7fea89b9ad8f7dbd02dac898301cfb0592257
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 14 11:31:58 2018 -0600
+
+ Don't resize 3D pictures.
+
+commit c928c92f88c8b3b0942dc9c12bc8244233045e11
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 14 10:38:34 2018 -0600
+
+ Finish xasy port to MSDOS.
+
+commit cd700b4bb9db2b80f77aae8a316a99dd3476c7b4
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 14 10:38:06 2018 -0600
+
+ Redirect cerr to cout again when outpipe=2.
+
+commit f0bc292dd796329fdd39679b1852a6bff1159335
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 14 10:34:17 2018 -0600
+
+ Fix segmentation fault.
+
+commit e1f68286465d275a5677860950e266288ade44a1
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 12 15:13:59 2018 -0600
+
+ Port xasy to MSDOS.
+
+commit 7133ef53816e97ddb3b8e0870ffbfba9b95423b7
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 17:05:36 2018 -0600
+
+ Enable cycle control points.
+
+commit 1c444f8695301ae16bd8beb20778bd7fc14cc9cf
+Merge: 92d1e727 93a679de
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 11 16:13:33 2018 -0600
+
+ Merge branch 'master' of github.com:vectorgraphics/asymptote
+
+commit 93a679de2f2902618546bf86884217c4e8da9041
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 16:13:20 2018 -0600
+
+ Set line width inversely proportional to mag.
+
+commit 92d1e7272842f751bd3952f13efb365e2d100121
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 11 16:12:30 2018 -0600
+
+ Rename config files and commandPalette default keymap.
+
+commit cc93cbe1e79774062ab9fd741469c41e39600959
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 16:04:13 2018 -0600
+
+ Correctly fixes scaling with zoom.
+
+commit afad348e03eaf2e73cd606e4f008d7316bc52627
+Merge: 7f2a28a6 ad6faf30
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 16:02:35 2018 -0600
+
+ Merge branch 'master' of github.com:vectorgraphics/asymptote
+
+commit 7f2a28a6042a401e314b2d865a16d03f02e91687
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 16:02:32 2018 -0600
+
+ Make selection scale with magnification.
+
+commit ad6faf30e81d3ea2f58c92536b967f8d7491c4e8
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 11 15:55:52 2018 -0600
+
+ Fix spelling.
+
+commit 1f383b4b5301c358b4867b692a26a2c3076e6268
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 15:51:31 2018 -0600
+
+ Fix typo again.
+
+commit 893f7fc2ee2e044395ead6215e1e53f195c8d82a
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 15:51:20 2018 -0600
+
+ Fix spelling error.
+
+commit 38f428fa9fe837bca5a00df56b94dbf2f842c235
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 15:49:34 2018 -0600
+
+ Make filename a little more clear.
+
+commit a3f98621376f1c45988dff32191e6da5ad1b53b7
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 15:37:32 2018 -0600
+
+ Fix segfault again (?).
+
+commit ecb5b2db65438e7ba9c626014925ac291f5c1941
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 15:33:59 2018 -0600
+
+ Fix segfault (?).
+
+commit ab12f523ac4e6e52e312cd66e9f869c762779e46
+Merge: 2d24c9aa feefafd6
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jul 11 15:29:04 2018 -0600
+
+ Merge in changes.
+
+commit feefafd64fdd5abdff99fdbdad523a1687ca34f1
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 11 13:55:32 2018 -0600
+
+ Fix asymptote.spec.
+
+commit 935f81064cf10fa83ad49303b0d74ad50cf9856b
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 11 13:49:33 2018 -0600
+
+ Fix asymptote.spec.
+
+commit e65e004ca8c75e168c6c1ac3a44c609a34754f73
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 11 13:45:59 2018 -0600
+
+ Use install-notexhash for building RPMs.
+
+commit bb1cf672f4d99dc1ecdad8826adefd916f1cc9f7
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 11 12:09:12 2018 -0600
+
+ Clean up icons; fix installation problems; port asymptote.py to Python 3.
+
+commit 2d24c9aadb12e6a35e7a840b07f20ced68c8e4a6
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue Jul 10 14:34:39 2018 -0600
+
+ Remove even more unnessecary code.
+
+commit 3cd990f8d5f9bea582c34cb36eaf8da538046ab0
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue Jul 10 14:19:08 2018 -0600
+
+ Generate -- instead of.. when using polygon.
+
+commit 7edcc2f34fcb7551d23a272d7f1bd0b03d940ee7
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue Jul 10 00:56:06 2018 -0600
+
+ Fix duplicate QPainter warning.
+
+commit d1dfb2a8af1c4c5a186a5e622cdc2e2fd9c0b90e
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 9 17:29:42 2018 -0600
+
+ Reset fileChanged on erase.
+
+commit bff496158e93e677e7839e056f5da52129e11e55
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jul 9 17:19:43 2018 -0600
+
+ Add check before reopening file.
+
+commit 2ecb76750fe0ebc120684a076ac3a5b4ab9ce810
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 21:32:22 2018 -0600
+
+ Fix asymptote.spec.
+
+commit d67ec7242352fd97059022795846394ae36f5cbf
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 21:09:06 2018 -0600
+
+ Specify python3 explicitly.
+
+commit a2f95654b4deb7cbf779e8068090f201aa3468b5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 20:46:48 2018 -0600
+
+ Read in xasy version.
+
+commit 94d4cd52647d433b1d13e5a96641c89f07203ebe
+Merge: de430749 770eea72
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 17:06:00 2018 -0600
+
+ Merge branch 'qthup'.
+
+commit 770eea7237d039ee13b9f4b5adaa4a61e8e9297f
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 15:27:45 2018 -0600
+
+ Erase canvas before opening new file.
+
+commit 6dba36575965266b3783f5a2bde8f5a65ab32451
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 8 13:06:47 2018 -0600
+
+ Automatically determine recomputation mode.
+
+commit 869d617084192cf799f0ec033b9ea31f74d6e07a
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 8 12:59:14 2018 -0600
+
+ Preserve Edit Bezier Mode.
+
+commit e8bc45d003f489ccc50fc4461aa19d56da314421
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 8 12:55:02 2018 -0600
+
+ Update .gitignore
+
+commit eed85abcd5e3c2347d4ad1ab86a3d8e550cd3f72
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 12:40:09 2018 -0600
+
+ Improve informational messages.
+
+commit d5de0e972bf7242d2572c2a5a7ff0ded40f85a1e
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 11:08:24 2018 -0600
+
+ Remove unused code.
+
+commit 63be5fe78ea461d3350277799528a78d01069189
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 11:01:25 2018 -0600
+
+ Standardize labels.
+
+commit 618439764c892c9b9b3b0ecbfc52358d3e0a2646
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 02:39:58 2018 -0600
+
+ Add missing actions; remove obsolete code; adjust layout.
+
+commit c2a3daa2e8a95ce104f7a8d828a4237274bd0188
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 8 00:11:27 2018 -0600
+
+ Add remaining icons.
+
+commit 2f894a654d48bf5479331dfb7b176605b8df0eb5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 7 17:30:04 2018 -0600
+
+ Add fill bucket icons.
+
+commit ae34291ff7f91f19a5b29e8d145600096c1d186f
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jul 7 10:49:30 2018 -0600
+
+ Rerender only when dpi exceeds previous maximum dpi.
+
+commit 326766200c3deffe4392d737a92dadbf9591b0d3
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jul 6 16:38:38 2018 -0600
+
+ Fix clip flag.
+
+commit 1797d5f89eaa554d94d34d908e86858ae0d0fdb9
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jul 6 16:29:02 2018 -0600
+
+ Make rsvg-convert read directly from file.
+
+commit 4fdad9b276f93f32164d1ff4da30164720e97b11
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jul 6 15:54:11 2018 -0600
+
+ Remove unused code.
+
+commit cde402ba0d3a491f235b75390fa6232d019eaada
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jul 6 15:47:13 2018 -0600
+
+ Switch from cairo to rsvg.
+
+commit 365189781fe14a3b74662a24d7c37424648893f2
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jul 6 15:16:39 2018 -0600
+
+ Reset current position when click.
+
+commit 8d89b3ad95c45507ab958eee08e50cb7a71d6de1
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jul 6 14:25:35 2018 -0600
+
+ Add more icons.
+
+commit e52e4040874c315a50baeaee22858527197e758e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 21:02:59 2018 -0600
+
+ Fix recenter not recognizing magnification.
+
+commit 54ad8477ed4821a59a8cd08eac741554152f124e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 20:53:48 2018 -0600
+
+ Fix zooming transform.
+
+commit 9f52c34396577ced844734728ac67278ea2dd21e
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jul 5 17:18:41 2018 -0600
+
+ Fix tooltips.
+
+commit c961cabc5ec05e7b0475d54557f298feae6b8dca
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 17:00:26 2018 -0600
+
+ Remove add widget upon addmode deletion.
+
+commit 8543e26542f78f2d334b0eb6580d80cca3bca45e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 16:55:29 2018 -0600
+
+ Add remaining icons.
+
+commit 2ac5c23f2e1b32103ab49eae7b6797aaa5017512
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 15:32:49 2018 -0600
+
+ Enable pan-sensitive zooming.
+
+commit bf3cc0b9f763f4bf40cdc569db4d61d3f96a4f35
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 14:51:07 2018 -0600
+
+ Enables math mode detection in label.
+
+commit b8c2663e0fa1f0b0dc4c6cf41aec6af7aa9cc89e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 14:34:54 2018 -0600
+
+ Add centering pan.
+
+commit 388907330408dae455768900739219e4a9b3b42f
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jul 5 13:48:16 2018 -0600
+
+ Add svg files.
+
+commit 7e9efcd61dcbe7cd0f45f437610e376fa9b4e2f3
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jul 4 19:36:24 2018 -0600
+
+ Add index entries integral and integration.
+
+commit 405ee9a7bc6eb61e0268fc23177eacbcf6563154
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 23:40:02 2018 -0600
+
+ Enable centering pan option.
+
+commit 046b50a837798f4fa406adb434e2794f5c260a5f
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 23:33:57 2018 -0600
+
+ Add fuzz to small bounding boxes.
+
+commit 15e7d80a69049825de0a8e0c5f88e0aac2076462
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 23:24:57 2018 -0600
+
+ Copy text to advanced editor.
+
+commit ddc3fd7c15507fa42a9aea8ef0ea4a5d95776b6c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue Jul 3 16:40:36 2018 -0600
+
+ Improve and enable Cairo clip-path bug workaround.
+
+commit af49fa9dd676f2453ed65aefe6fa6106eab2de9e
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 15:08:38 2018 -0600
+
+ Round points to 10e6 precision.
+
+commit a1086f1f2141a0ed5ca1ee23c0c982cca50d0a50
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 14:58:15 2018 -0600
+
+ Add fontsize for label.
+
+commit ccc3b79d26559b18d86a95e5bcf02478c1051f33
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 14:24:51 2018 -0600
+
+ Enable removal of unneeded clips.
+
+commit b6a25e25e9f586a39d9af6b287b0373a4b703dd1
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 14:01:18 2018 -0600
+
+ Remove unnessecary braces from label editor.
+
+commit b0b8525c6e71cb2643e0c3a96aaea35f2df6ed1d
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jul 3 13:57:46 2018 -0600
+
+ Improve scaling on small labels.
+
+commit d21d7c005dee4968a3af58a1de68bb26e0e4ead6
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jul 2 15:21:02 2018 -0600
+
+ Only insert non-identity keys.
+
+commit bd259097ea0c45835110d7d627a0eea174c0d38a
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jul 2 14:59:31 2018 -0600
+
+ Fix label location and more QoL improvments.
+
+commit a8c22de51d598fff1b008b8b89ae702d8e0dfd15
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 2 11:35:44 2018 -0600
+
+ Switch xmap to asy coordinates.
+
+commit 9ec81262cff36972c91e523dfdc0fdc5a529e3c5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jul 2 08:52:24 2018 -0600
+
+ Fix comment.
+
+commit 5a0588a23082a406cd718a71c6267d78cb9b4a0b
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 21:33:03 2018 -0600
+
+ Fix missing KEYs.
+
+commit 89ecbf116ccee69453179cdab48b0b633a5ff8bb
+Merge: 4463b94c 67c86cd4
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 19:08:33 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 4463b94c5c887de3f8c1f269c33d2bc60dfa1979
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 17:12:32 2018 -0600
+
+ Resize to initial xasy transform.
+
+commit 67c86cd4113f13b275c87d890f5ab48f457808a7
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sun Jul 1 14:11:25 2018 -0600
+
+ Should fix key not writing.
+
+commit 716f8065bfb6d5ce0f0b52f3956df0f92787bb99
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 10:38:24 2018 -0600
+
+ Make SaveAs default to current directory. Add Save action.
+
+commit 9763a3e172d35b1cb7c093695fcaededd29ca391
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 10:38:24 2018 -0600
+
+ Make SaveAs default to current directory. Add Save action.
+
+commit 7a2ff7f7017abf753579216bfa1ecd4b429e6576
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 02:52:17 2018 -0600
+
+ Handle empty objects.
+
+commit 1f35ec3deb126f3e3d4e4b7bbea823336ecd958e
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 02:43:25 2018 -0600
+
+ Remove obsolete redirection.
+
+commit 81d9ab652ce2eb7fb052d0a96f9ea63acc55d21a
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 02:39:26 2018 -0600
+
+ Update bsp.
+
+commit 44ba3d7a149ff97144335ef13a53741a51107272
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jul 1 02:30:33 2018 -0600
+
+ Handle null simplex problems.
+
+commit 943110ab88bb0af227c85cc906777908876888c0
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sat Jun 30 21:10:45 2018 -0600
+
+ More QoL fixes.
+
+commit 6701d59cda39aba6ac5e228401e31b8e2879ab91
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sat Jun 30 21:07:07 2018 -0600
+
+ Delete Icon
+
+commit 5077b81969160b377b0af26f711350531ef19edf
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sat Jun 30 21:06:59 2018 -0600
+
+ Delete Icon
+
+commit 97f26873569db365d0f9e5127d362580bbcdabb3
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sat Jun 30 21:06:50 2018 -0600
+
+ Delete Icon
+
+commit be93a35d25f89a4ca801527912a6b21bb24759bb
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 30 20:16:41 2018 -0600
+
+ Suppress dvisvgm warnings; use dvisvgm --pdf when available.
+
+commit 3bbab66ea27fe2aeecca64b53abd150ab787dee1
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 30 18:22:54 2018 -0600
+
+ Use direct conversion to svg for proper bounding box.
+
+commit 92d74369e228512b2270616f79562741856e0b85
+Merge: ea4fed15 25fab655
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 30 15:42:20 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 25fab655437d0128451bae9506d15052fb9a2394
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Sat Jun 30 14:39:58 2018 -0600
+
+ Enable right clicking for ending curve.
+
+commit c911d8acd1eb4bb21c452838f3ee7249c80b0e63
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Sat Jun 30 13:53:16 2018 -0600
+
+ Fix Undo/Redo buttons not consistent.
+
+commit 11ba4c2c0bcd2938aea757afc10ea5056745f2e4
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Sat Jun 30 13:48:32 2018 -0600
+
+ Update mouse coordinate label unconditionally.
+
+commit f92a2da0266970f12e785e07f27a4add2f067850
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Sat Jun 30 13:45:06 2018 -0600
+
+ Hide anchor when not using custom anchor.
+
+commit ea4fed159acd44095bce42fc306e64550a42eac6
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 30 12:30:59 2018 -0600
+
+ Remove obsolete code.
+
+commit bdb83475c13af0e41909f97af0389148757558b0
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 30 09:46:40 2018 -0600
+
+ Rename _fout to _outpipe and move declaration to plain_shipout.asy.
+
+commit 2d49cb19dbbbd5cac38260a32c2df75cd4d2fd10
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Fri Jun 29 22:21:51 2018 -0600
+
+ Fix bezier edit not resetting.
+
+commit ede9f4906ed0c82e39833f9d57562c3c9c8b6d25
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Fri Jun 29 22:08:11 2018 -0600
+
+ Save file with asy coords.
+
+commit 79c2ce6d847f470760faa70fd5a2e211dcfd5033
+Merge: f0d35d4f 731251c7
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Fri Jun 29 21:57:28 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 731251c7301c1f65f4daa50e75e69aec75a150a1
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 29 18:32:13 2018 -0600
+
+ Use ctrl-D to terminate xasy-to-asy communication.
+
+commit f0d35d4fbbf46572baf776b2667e7856c87c8d25
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Fri Jun 29 17:39:53 2018 -0600
+
+ Fix key count missing.
+
+commit 14a9a432836617d7282cd6f4aff7b7bb883d35dd
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Fri Jun 29 17:35:49 2018 -0600
+
+ Other QoL improvements.
+
+commit a8c22c228fdd82347c55a260b38a56ca97d26159
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Fri Jun 29 17:12:35 2018 -0600
+
+ Save file as asy coords instead of postscript.
+
+commit 21981780fa0e5237b1b92b7ec39ac8da8f8711ea
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 28 15:45:55 2018 -0600
+
+ Add option for editing settings.
+
+commit 00347340d591d11e386bf42eadc3496b5d5b2b53
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 28 15:06:10 2018 -0600
+
+ Add experimental antialiasing (may not work at all).
+
+commit 36df0f26c942fa3aa994541b6e6c0fdc2748eef0
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 28 14:33:37 2018 -0600
+
+ Add legacy xasy bezier mode.
+
+commit 905f58f2c64703371a72641d78465179671c919a
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 28 14:07:24 2018 -0600
+
+ Fix cairo dpi bug.
+
+commit f2601b75e126b6ee659b75cdd78f12d369d51b7a
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 28 13:53:02 2018 -0600
+
+ Make the default linewidth 0.5.
+
+commit de430749dfa385b81ad457ed8a3390dad28cf952
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jun 28 12:46:35 2018 -0600
+
+ Avoid modifying input arrays in rationalSimplex.asy.
+
+commit 06aee1b86106f39835889a72a2248ab7c02d3cd7
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jun 28 12:45:39 2018 -0600
+
+ Overload operator !=.
+
+commit 1e39a91779ea25645acb1f6fc20f2b1480e5c8e7
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jun 28 11:22:33 2018 -0600
+
+ Avoid modifying input arrays.
+
+commit ee333cb2e837962b26305dc9e65e306e232c9d3f
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Wed Jun 27 17:30:26 2018 -0600
+
+ Add workaround for bounding box flip.
+
+commit 6e91ddbe19f4b01649b33dfb4a05c36e029f57a6
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Wed Jun 27 17:20:51 2018 -0600
+
+ Change clip detection to asy.
+
+commit 1dedb3885815058ee3067f6402529b6b93a4e0a7
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 27 16:57:25 2018 -0600
+
+ Detect clip; invert images.
+
+commit 1b55335147fc4eebe9676c864c9e5e2937c57d67
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Wed Jun 27 16:28:25 2018 -0600
+
+ Enable DPI checking for magnification.
+
+commit bfbfafbc406d8e93166468f1058e57a8a7891086
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Wed Jun 27 13:14:17 2018 -0600
+
+ Add custom dpi support.
+
+commit b1d540c919da0ec7cb53616e22f84f3de723f997
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Wed Jun 27 12:43:26 2018 -0600
+
+ Add temporary workaround for svg noclip.
+
+commit 6c12f7777edb0a2064ae206ea37661461e96a0ec
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Wed Jun 27 02:08:51 2018 -0600
+
+ Remove debug messages.
+
+commit 999210c14c41ba6737ea31fa03a7c7e003940997
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Wed Jun 27 02:07:47 2018 -0600
+
+ Add svg support dependent on QtSvg.
+
+commit 19efab230370f14552d1d17930dd33373f59220d
+Merge: 96031ea2 50fb809f
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 27 00:19:54 2018 -0600
+
+ Merge branch 'master' into qthup.
+
+commit 50fb809fdaf2383385f09884174262964a046156
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 27 00:17:35 2018 -0600
+
+ Use system ghostscript library by default for dvisvgm.
+
+commit 96031ea2614dee2a470525ba87d921fbe0291056
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue Jun 26 17:56:19 2018 -0600
+
+ Deconstruct to svg format.
+
+commit f07fc294bfcf278d72c4cbe14ee95b9c13e22768
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jun 26 15:23:09 2018 -0600
+
+ Add scrolling functionality.
+
+commit c27d0994645a395185aad3cdeb85579e830f45c0
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Tue Jun 26 13:50:31 2018 -0600
+
+ Terminate asy on exit.
+
+commit e1f540d4a86fc432b091cff538703a4e2d1eb180
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 17:37:55 2018 -0600
+
+ No longer uses asy for zoom.
+
+commit a13447f744ec9677e62e5ec09626ec84865068c8
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 16:49:42 2018 -0600
+
+ Fix Custom Anchor inconsistency.
+
+commit 91c0c648ea8e2384be530380836edd6a0fc563ae
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 14:37:10 2018 -0600
+
+ Add undo for object creation.
+
+commit 4fe6ebb5f7b263aa97358a11d9f24d5f0c6432ac
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 12:52:11 2018 -0600
+
+ Add Scale mode to bezier editing.
+
+commit 0c1a59da64db42d1d961210f9e464cab24ebd6b9
+Merge: 4b55a597 cf2e8c9d
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 12:12:57 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 4b55a597110461af90b9082a8e1a1caa1dd40b7b
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 12:12:54 2018 -0600
+
+ More QoL improvements for bezier editor.
+
+commit db447ef6ae109bd7c6f3f6b8c74d0513fec7969d
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 12:12:43 2018 -0600
+
+ Simplify string management.
+
+commit cf2e8c9df1b1665b48b85815028b8990d2cc97f3
+Merge: 5e612b5d b757219e
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jun 25 11:19:56 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 5e612b5dc66928fa4c9f5152e3a47d3544ed1196
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jun 25 11:19:51 2018 -0600
+
+ Remove unused prompt.
+
+commit b757219e235127134448516c47ad3104e86dc100
+Merge: f01a9f11 aa4ee7b7
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 11:03:26 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup.
+
+commit f01a9f11564532c05d21ac131d4ada7bfff723e1
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Mon Jun 25 11:00:26 2018 -0600
+
+ Change spacing to one for each object.
+
+commit aa4ee7b78186e49b35a3a1ed0417f2695be88c1a
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sat Jun 23 16:11:02 2018 -0600
+
+ Delete unneeded files.
+
+commit bf52e9ef5c6b2d2bfc34b7f4a3d86d9e4895a6b5
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sat Jun 23 16:10:54 2018 -0600
+
+ Add early bezier editing mode button.
+
+commit 92c3d17e2a059014ddb13ce8ef50a626f396bfe7
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sat Jun 23 16:10:25 2018 -0600
+
+ Add setup.py file.
+
+commit 068d75ce11365caf064cc5e2c8a76e7a3c7a15bf
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sat Jun 23 15:24:24 2018 -0600
+
+ Edit some build files.
+
+commit 8f7217ac8df4d721127b6f7487874396f5843c6f
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Sat Jun 23 15:24:15 2018 -0600
+
+ Add icon files for easier editing.
+
+commit e70d99640450c984344c605a35dae157a58ed264
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 23 01:33:36 2018 -0600
+
+ Remove bounding box in example until xasy support is implemented.
+
+commit 3abe5e672a6f9255f382a09b16ed1ee29769ccdd
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 23 01:21:36 2018 -0600
+
+ Detect xasy with settings.xasy; reinstate bounding box in example.
+
+commit 401cf60f89dcddfb6993f7bd25a86b144ec5f3ad
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 23 00:33:18 2018 -0600
+
+ Replace restricted simplex method with general simplex solver.
+
+commit 77c3c2bbc8496a1b53bf3b0e5af27501be05b50c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 22 16:48:33 2018 -0600
+
+ Fix xasy mode and keys.
+
+commit 0e31fa8c29737941d559bf4e42162212f5f85bb5
+Merge: 10d30131 60a35767
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 22 15:04:58 2018 -0600
+
+ Merge branch 'master' into qthup.
+
+commit 5ff20563472ab9361826bea32cd4a2635a346550
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 22 14:53:17 2018 -0600
+
+ Force make clean to remove GSL symbols.
+
+commit 10d30131851c3e8936f4c0fe62097d6dccaa3b64
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Fri Jun 22 13:59:59 2018 -0600
+
+ Allow for new key replacement.
+
+commit febc76cb94e3de54b8f3d01da29f6eb71bf76e25
+Merge: 8aeec7ce 69aaf4fc
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 22 11:36:36 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 8aeec7ce7debb2469d2e21efd237123e9943c3b6
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 22 11:09:14 2018 -0600
+
+ Implement interactive xasy mode.
+
+commit 728f50856129f4cdcc8f2d30b253aeee243ed6ac
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 22 08:31:54 2018 -0600
+
+ Test new xasy mode.
+
+commit 69aaf4fca1d01254a43d78b9bed4755990c052a7
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 21 22:47:48 2018 -0600
+
+ Add more bezier editing features.
+
+commit a890ec75dd31b8aacc4adcea8f138fafe0b9d504
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 21 16:51:19 2018 -0600
+
+ Add control point editing.
+
+commit 7ce567731e2eab843ef2ea5789435d82dc65c69c
+Author: Supakorn <rassamee at ualberta.ca>
+Date: Thu Jun 21 16:26:57 2018 -0600
+
+ Allow saving of edited beziers.
+
+commit 60a35767c5becaf6f8a5fcd72584a9d3d316b028
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jun 21 00:42:08 2018 -0600
+
+ Force dvips to respect EPS requirements.
+
+commit d36d513b7e060ad476208f2ab9552b4323c45a05
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 20 15:49:30 2018 -0600
+
+ Add early bezier editing.
+
+commit b2c25d8ae46ce3ccf9c5e9689dc682ec647780ab
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue Jun 19 13:13:49 2018 -0600
+
+ Update keydata.
+
+commit c6b4d4b1ef81305d4973e3848673f2a77e476c4c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue Jun 19 11:20:11 2018 -0600
+
+ Add a flag to identify a user-specified key.
+
+commit 88de674b7daeb9efc3e59a1300e4cd3928f22ceb
+Merge: 3040e29d 74393725
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jun 18 23:41:42 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 743937250a7c67dc414ddbd60ee8e2f59c62147d
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jun 18 23:41:30 2018 -0600
+
+ Revert to using interactive mode for xasy.
+
+commit 0f044019bdc7c7947c6f58db9ba7d34703c49048
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 18 23:24:59 2018 -0600
+
+ Remove unnessecary icon residues.
+
+commit 3040e29d15c97e526faeba5bbbad00f1ec436c17
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon Jun 18 17:05:05 2018 -0600
+
+ Revert "Remove obsolete code."
+
+ This reverts commit 28e91cfec416a135e1a9ba5a32486507e59bf5ec.
+
+commit 97ab025569e6cc765d7c4f88a96e49f2628d2930
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 18 15:21:37 2018 -0600
+
+ Unify asymptote process.
+
+commit 5e2123d1358e2e34a3149d3d281365c2e43c8dec
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 18 13:37:01 2018 -0600
+
+ Add initial bezier curve detailed view.
+
+commit c049ce0c2f21c4c9eb86ffaa7bb5b6b163cbc0a8
+Merge: e4a169a5 9d0f460a
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 18 12:50:47 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit e4a169a5a79b7e6499b61ecc852551246a38869e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 18 12:45:44 2018 -0600
+
+ Fix moveMove.
+
+commit 9d0f460a251cbad4a2a5ebebf33ebc68633ffcac
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 15 18:25:34 2018 -0600
+
+ Fix mouse interaction.
+
+commit 3f6584a1fe2f71c754f2e5b8f34f1f2db9b81f24
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 15 16:44:55 2018 -0600
+
+ Minor type hinting.
+
+commit 91410b0bb179411ca1245f3f82056f1b4e3eae0f
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 15 16:18:28 2018 -0600
+
+ Move export option to menu.
+
+commit 8be30f41855c222604a20e771b16d737e907c279
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 15 15:02:19 2018 -0600
+
+ Set fill to disable open buttons.
+
+commit 8369f1d2552ca0739444b071804c55d4930d497b
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 15 14:55:46 2018 -0600
+
+ Add More modes.
+
+commit 2feb57922220320c2167f42cb6194b6fb4daaea6
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 15 14:21:27 2018 -0600
+
+ Fix labels adding.
+
+commit fa522058317c2a685b4983dc243319c6a87b33a5
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 15 13:33:47 2018 -0600
+
+ Fix anchor not updating.
+
+commit 1fc16f12cabf5a3cec16a6899676b5fd1ead61f0
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 17:52:09 2018 -0600
+
+ Add custom anchor.
+
+commit bbfb89044d5e4b2e8d5d86e1bddac594e35e72ad
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 17:04:12 2018 -0600
+
+ Check for mouse down first.
+
+commit 6fb39b6dac1ea61f053d98273cf1dd11e984f74a
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 16:53:04 2018 -0600
+
+ Add hover delete.
+
+commit c106bffce3b1c034a251b6a53745b16ddb7bc431
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 16:46:27 2018 -0600
+
+ Add hover deletion.
+
+commit 2cffe89eaff1b30b797dac3e267b65c60cca94c8
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 16:34:51 2018 -0600
+
+ Even more xasy changes.
+
+commit ad33e4b69f848af0e4cbaaacfe81b9006a3fd5cb
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 15:44:47 2018 -0600
+
+ Recompute control points for all nodes.
+
+commit 01ac796f6a9ff2ae89622e3faa050c8bcb386549
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 14:04:53 2018 -0600
+
+ Other minor bug changes.
+
+commit eeba4902c2fc1425351d6a53bd129c67c616fb6c
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 14 13:39:15 2018 -0600
+
+ Add more anchor mode.
+
+commit 6df104d6060fe5400e9d7618462026f11767bbd8
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 18:13:56 2018 -0600
+
+ Add support for hard deletion undo.
+
+commit 100ac43d7b9d762e7c5f2b732f7fb47529e666b2
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 16:57:17 2018 -0600
+
+ Remove closed path option.
+
+commit 0c2b40391218e0923f145d50aacc834fd575fde5
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 16:45:00 2018 -0600
+
+ Add some bezier keymaps.
+
+commit d6c70960f272c439d6f8e2220e12756194878875
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 15:55:39 2018 -0600
+
+ Make code objects a little more informative.
+
+commit 86b8a207600a33d509002f6cae016e5551316e53
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 15:42:35 2018 -0600
+
+ Update Editor argument system.
+
+commit ddb1a2c604eacd69509685e228d4e487ffe48a4e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 15:05:20 2018 -0600
+
+ Restore venn.
+
+commit c74ca307377f24073973137830bfbb064125ee67
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 15:05:00 2018 -0600
+
+ Put back shipout.
+
+commit 19e31f55e7f12bcee0b584d21d47e3e4b3e52243
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 15:04:22 2018 -0600
+
+ Change arguments to old xasy.
+
+commit c8d73f5f33c4c94ccee4397a876906c8eb1558cf
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 14:52:33 2018 -0600
+
+ Bind delete to delete object.
+
+commit b9f5e41419d978c5084870beed3efa21a2a9e09d
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 14:43:10 2018 -0600
+
+ Update .gitignore
+
+commit 9d59dca9b470251e336d63f6df7fa7a2d64603f9
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 13 14:42:26 2018 -0600
+
+ Revamp options system.
+
+commit c2827f039043d9077aed43d15604d451a0f79b81
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue Jun 12 22:51:09 2018 -0600
+
+ Change deletion mode.
+
+commit bd6d4cf68a80d4e335274b2caa32f7045f7591c0
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue Jun 12 16:59:37 2018 -0600
+
+ Omit deleted objects on deconstruction.
+
+commit 8fcb2b769bf595380360ad7a3aebe1680da53ef1
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue Jun 12 15:37:58 2018 -0600
+
+ Ignore EINTR on read from pipe.
+
+commit 97f7d0ca87d4d2db1c522a59532cc2b0f7758630
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 11 18:16:23 2018 -0600
+
+ Optimize deletion and options.
+
+commit 5a7a08e173fff7a77727aa3236b323a5069c2af3
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 11 16:39:36 2018 -0600
+
+ Add CSON support and basic deletion.
+
+commit c639a6b9b0142e5bea61d087a9c22a7eb38bb335
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Jun 9 13:33:22 2018 -0600
+
+ Update three and slide modules.
+
+commit ae8f7b0bc3a001fb6dc8a72598f4342979117eb8
+Merge: 6cb432ef de2c27e0
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 8 22:23:39 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit 6cb432ef307bb52184196bc95a386f960a392aa5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 8 22:23:32 2018 -0600
+
+ Rename map to xmap.
+
+commit de2c27e042780e860e4848995241484b2c255602
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 8 22:15:53 2018 -0600
+
+ Allow for top-layer draw for selected objects.
+
+commit 55b9c779cf36d7757eb145f2028bb8c328a4ce1e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 8 17:25:34 2018 -0600
+
+ Add map/xmap switching and key counter.
+
+commit f54e57e5b8a05da8ddfa1b5a8eb4aa1f939768f9
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Jun 8 16:42:57 2018 -0600
+
+ Add mouse wheel selection modifying.
+
+commit 01db5e39b2969fb10142a3b9b9e90c1a9f8826d5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 8 15:15:10 2018 -0600
+
+ Add identity and zero transform constants.
+
+commit 9b065e65c5b42b9fb0aba00ff2874e92d2ae368f
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Jun 8 14:38:16 2018 -0600
+
+ Implement RGB(int,int,int) function.
+
+commit e3dc24a6810bf35c7a5ae1fb176961b873ed92fd
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jun 7 21:42:37 2018 -0600
+
+ Renenable object deletion.
+
+commit 018e17a2e1caeec6552eefd94737b1e24715ee5f
+Merge: 7b06be2c 594473ef
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jun 7 21:20:50 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup.
+
+commit 7b06be2c7e0334081b5540e80e29248afa81cfd3
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu Jun 7 21:20:44 2018 -0600
+
+ Support bbox in xasy mode again.
+
+commit 594473ef65e616be969e0e212f7c24b201c9aec2
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jun 7 14:28:38 2018 -0600
+
+ Remove writing of identity transformations.
+
+commit dab676e5a6d8182e8958e8d705ce01f90d542d6f
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 6 21:03:56 2018 -0600
+
+ Fix KEY order.
+
+commit b2197a0e1c094e16b7d06c5cd1492b5898af57ac
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 6 19:16:34 2018 -0600
+
+ Remove unwanted spaces.
+
+commit 7cef83b715c5dca65178b6f64c717a066c45f981
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 6 16:25:50 2018 -0600
+
+ Cleanup code and add terminal option.
+
+commit 027cfb6ebdeeb4af66567a06d2490ce3ae506d27
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Jun 6 15:42:35 2018 -0600
+
+ Change mapping behavior when save.
+
+commit 356ec304168863f178e37314cbcca272d8eb3f0e
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 6 14:21:32 2018 -0600
+
+ Add default transform to map.
+
+commit 9f4c4c60239faa7da04fa177f5dd5e3ec97974a5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 6 14:04:12 2018 -0600
+
+ Draw xasy objects onto currentpicture in PostScript coordinates.
+
+commit 0645b41d5f88085b16f0ba1814e85dd60dce445c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Jun 6 11:04:22 2018 -0600
+
+ Draw xasy objects on a separate frame.
+
+commit 8b006fb0b29c6a9da2ac0bc53c03fdd51223f634
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue Jun 5 17:14:43 2018 -0600
+
+ Add support for exporting files and other changes.
+
+commit 30bd410fad4be3b71ab26e4eddbc64f39b49773f
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 4 17:26:19 2018 -0600
+
+ Add early magnification support.
+
+commit 41613fa98512a44487c6b5ac687b88f3852e9102
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 4 13:44:57 2018 -0600
+
+ Fix selection issue.
+
+commit 3d1ca05ccaaf934a42df038e5b8c5ab098a299b8
+Merge: cf276195 93f367bb
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 4 13:32:05 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit cf27619534b2f5eec07fda1ec58110ea2d8c11a9
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon Jun 4 13:31:04 2018 -0600
+
+ Move transforms to dict[list] model.
+
+commit 93f367bba491d01706e656821ccb748067ad2773
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Jun 3 20:32:07 2018 -0600
+
+ Finish passing KEY to transformed elements.
+
+commit 34ce667325ce323de441d0bea58b47c0f05751d2
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 31 19:31:45 2018 -0600
+
+ Show key in status bar message (for debug).
+
+commit 75397a5488c0ec3de9d9d24f75e8479b91cc3a14
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 31 19:28:01 2018 -0600
+
+ Groups objects with the same key.
+
+commit 761e3f3275da938a83c7c2ff4c6cd164dd47b134
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu May 31 17:50:19 2018 -0600
+
+ Begin passing KEY to transformed elements.
+
+commit 221fda26e204542d88a2df73f4392adbaec29f54
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 31 16:49:38 2018 -0600
+
+ Fix tuple loading of xasy2asy.
+
+commit 771bd937375c8a6888873c0acb68b337bea744f9
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 31 14:44:31 2018 -0600
+
+ Add more functionality for toggle visibility, code adding.
+
+commit 308fceb60033262814b6fa843a46f3580f2a4d02
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 30 17:27:51 2018 -0600
+
+ Add functionality for delete, change order.
+
+commit 0a05fccf9e9035568247d3e628d373d9b245ccc0
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 30 16:45:42 2018 -0600
+
+ Update add bezier mode and file loading.
+
+commit 0b08348102fd6be4c4a2b62945b17c46aeb5f978
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue May 29 13:13:07 2018 -0600
+
+ Add key support on asy side.
+
+commit aed03a1f8db344aa133b3abd7a7d6a386e6f31f3
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue May 29 11:17:10 2018 -0600
+
+ Add more bezier options.
+
+commit d10a4f89efc4c3a7cf2552425a19cb62a1861491
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 28 16:00:55 2018 -0600
+
+ Add in-place bezier curve interface.
+
+commit 90f82d4a91d7eabf3e13bd034a95df14cfd85fa9
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 28 15:32:19 2018 -0600
+
+ Update .gitignore.
+
+commit 99155d3edc967ce06cfbd7c6c8d892502b2eee82
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 28 12:52:57 2018 -0600
+
+ Add filling to circles and polygons.
+
+commit d04cac4bf67abb52bde752204d76cecec1f3a422
+Merge: c489474d 560f683d
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 25 18:52:52 2018 -0600
+
+ Merge branch 'qthup' of github.com:vectorgraphics/asymptote into qthup
+
+commit c489474da753207bad06b414df2a36d41efa62c3
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 25 18:52:39 2018 -0600
+
+ Modify xasyFillShape for qt.
+
+commit 560f683d7d089a25ea21bb9b240f7cb34650d878
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 25 17:12:47 2018 -0600
+
+ Remove obsolete code.
+
+commit 17c40ba170f7c359fd6ae3943b6d2a17b4baffd6
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 25 14:44:52 2018 -0600
+
+ Fix add shape transform bug.
+
+commit ac69fc4d0deab73dbfeef21fb88a6e0007b2fec1
+Merge: baf37589 f01b1baf
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 25 14:24:58 2018 -0600
+
+ Merge branch 'master' into qthup.
+
+commit f01b1baf546ed20bf49e5fd56aac4b43b4a1a5e7
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 25 14:24:19 2018 -0600
+
+ Fix quiet flag.
+
+commit baf37589eed095c896099e7cd51e4dfdc1c916a2
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 25 04:27:17 2018 -0600
+
+ Fix outpipe communication by turning off quiet mode.
+
+commit 4deafa3b4a9368d2a8463917eb009bd29b5d5658
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu May 24 18:09:46 2018 -0600
+
+ Handshake via pipe.
+
+commit 5016356832b2b5939bd45711ae48b95113f27489
+Author: John Bowman <bowman at ualberta.ca>
+Date: Thu May 24 16:58:31 2018 -0600
+
+ Clean up initial hand shake.
+
+commit f78ac62b79949992271c7f893f559ce4b7b77f39
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 24 15:38:44 2018 -0600
+
+ Change drawing backend to use ordered lists.
+
+commit 4f947b99fe88f5e0fc2fed4b42d73a5f914c2a7e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 23 15:06:54 2018 -0600
+
+ Manually add back labelEditor changes.
+
+commit 0bd402f7ffc30fc1f3dd4979965ced0b36c29499
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 23 14:22:59 2018 -0600
+
+ Manually merge back xasy2asy.py.
+
+commit 5caafee6c63ee66473663038ed2bea655dc304b3
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 23 14:02:22 2018 -0600
+
+ Add back xasyUtils.py.
+
+commit fe3482ec33738e7f6d89fda409082d05f6b585cc
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 23 12:58:33 2018 -0600
+
+ Get xasy to wait for asy to start.
+
+commit 82cb3f48c6ed3c81af5d62e870adbc6cda27e9d5
+Merge: fb2bd13e 4425e5c5
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed May 23 11:22:07 2018 -0600
+
+ Merge branch 'master' into qthup.
+
+commit fb2bd13e326e9a040bc578b533a36f23b64ed33c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Mon May 21 15:09:11 2018 -0600
+
+ Remove obsolete code.
+
+commit 2d72f98a9316dc49cd55737e8a9b23fc91d5736d
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun May 20 22:27:42 2018 -0600
+
+ Implement xasyKEY for 3D objects.
+
+commit b137bfb6c542ecc1d0341475511e02b8a67849ff
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun May 20 22:17:09 2018 -0600
+
+ Fix key generation.
+
+commit b3e1dc3c0d5fe2bd19936fe1f25e815c0203d2ba
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun May 20 10:57:05 2018 -0600
+
+ Simplify code.
+
+commit 4425e5c5aca12f87fc3f90151913733f8b771834
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat May 19 23:44:45 2018 -0600
+
+ Transition from rpc to tirpc library.
+
+commit 1c46c6547e63006cfaa49ad9b70846a12b44ea8e
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat May 19 11:36:12 2018 -0600
+
+ Inhibit exit on pipe EOF only when inpipe is specified (for xasy).
+
+commit 28e91cfec416a135e1a9ba5a32486507e59bf5ec
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat May 19 11:26:34 2018 -0600
+
+ Remove obsolete code.
+
+commit a0b453d97991205a8b9a78b0f44b2aa9c10c63b8
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat May 19 06:00:26 2018 -0600
+
+ Simplify code.
+
+commit 697537dee813ce9523382e4b44a6941b7d55f091
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat May 19 05:57:49 2018 -0600
+
+ Use SIGHUP to signal EOF.
+
+commit 8c982663371957021be663d6796bbf0db52317c0
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 18 23:48:49 2018 -0600
+
+ Use a direct pipe read for xasy instead of interactive mode.
+
+commit 6082601320a25abd0a9976550707b9eaf67cf9c6
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 18 13:48:29 2018 -0600
+
+ Preserve pan translation in resize.
+
+commit df4c903e109a9ef2a812605526bb93d118921f03
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 18 12:30:34 2018 -0600
+
+ Allow for flexible resizing.
+
+commit a05bdea1a260b0fe86c46e55731ed561d7f6eaae
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 17 19:27:54 2018 -0600
+
+ Fix a critical output dir bug.
+
+commit ff19d78558783ec53ac2ba2aaacd0d3916866dbc
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 17 17:19:33 2018 -0600
+
+ Add early label editor preview.
+
+commit 442a81ca4147a98535507b097e38bc587bb34ce4
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 17 12:46:59 2018 -0600
+
+ Migrate asymptote process engine to a contained class.
+
+commit 6a6bb0e1126dd02ac45603a75db1f642570d7c48
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 17 12:18:01 2018 -0600
+
+ Add early translation foundation.
+
+commit 0971e4dd2d12705bf92adff52e326246fa65a4cf
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 16 15:27:07 2018 -0600
+
+ Fix align mode in label widget.
+
+commit f698e26621b500d06d46731dc8c9865b06a247c2
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 16 14:50:17 2018 -0600
+
+ Add advanced label editor.
+
+commit d03660d2fbcff4dc1ed48b99ea1353db2c3e1db3
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue May 15 17:34:23 2018 -0600
+
+ Optimize string concatenation to use mutable string.
+
+commit 46b7b040f0a0d00f99da26718f7d3cc797826e05
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue May 15 16:09:59 2018 -0600
+
+ Add early label adding.
+
+commit d0860eb41adf13170079ae0f60da21f9f0ea58e4
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue May 15 14:34:03 2018 -0600
+
+ Add test label support.
+
+commit 14e8314dd7425874f36780e4109626cec2589b72
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 14 18:56:13 2018 -0600
+
+ Early migration to key-based transform (incomplete).
+
+commit cb034388031e39a6e7aeb07f31fb8744a5406b74
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 11 16:15:10 2018 -0600
+
+ Add argument support.
+
+commit 37f670816e7fc8ba23ea041d7ce18ebf16d35d8f
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 11 14:43:37 2018 -0600
+
+ Disable startScript and endScript.
+
+commit 436b50fe3b73a5191f0679a9666d899da35697d2
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 11 14:41:26 2018 -0600
+
+ Revert test code.
+
+commit 4acdd9ab9a524ec148c7fa8d75edf3652f354de4
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 11 13:51:41 2018 -0600
+
+ Update .gitignore.
+
+commit 05287cec1a12e77fd35a58a7dc534798add32735
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 11 13:51:06 2018 -0600
+
+ Remove asydev.
+
+commit 872ceac1642c01f3fe9370170bdaee654c1113cc
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 11 13:50:15 2018 -0600
+
+ Update .gitignore.
+
+commit de30993530af475d8fde3484d5bbe4f7c1dce339
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 11 13:42:44 2018 -0600
+
+ Remove unwanted file.
+
+commit 198d8589a70618071340969ae76d0c2c9534ea12
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri May 11 00:38:26 2018 -0600
+
+ Simplify code; move global variables to processDataStruct.
+
+commit f718e5eaaeca1a0938068b0dcfc97af2bc5cc912
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 10 16:52:51 2018 -0600
+
+ Adding some testing flags.
+
+commit fae1d6192b61f3c5a2e5dca553d5b45dd240e030
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 10 16:03:15 2018 -0600
+
+ Add preliminary trasnform migration to key.
+
+commit f0d593d9953ee3fa69f3fee6a2336a56a5cd02e9
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 10 15:21:01 2018 -0600
+
+ Add basic key recognition.
+
+commit 9ebbcfaa7cc3f57d18432ef11c6746569f057754
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed May 9 19:19:01 2018 -0600
+
+ Write KEY to outpipe.
+
+commit db66c57b242c83541abea7eb0201f87d13a648dc
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 9 17:34:09 2018 -0600
+
+ Add preliminary key support (Still a hot mess...)
+
+commit c46f5b3886e0285a5eb535ffa2d3ebf44644dd89
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed May 9 14:44:05 2018 -0600
+
+ Add virtual KEY argument to all functions for xasy.
+
+commit 0103b665ebdca12c348886c18eafd751fe6901b4
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 7 16:35:13 2018 -0600
+
+ More Quality of life improvements for color dialog.
+
+commit 345ba41986af818577cf60dc61e8aeb26a35bc1b
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 7 15:30:11 2018 -0600
+
+ Update gitignore.
+
+commit 67cbfd41508f79b79a91f2fca693e1ec5cdd95e0
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 7 15:19:20 2018 -0600
+
+ Add pen support.
+
+commit ab412a711d8836fb47399fd4380665288502de8f
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 7 14:52:21 2018 -0600
+
+ Add color support.
+
+commit b52cf9dc210c9d48fd1d20182d667a11dc013c47
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Mon May 7 13:26:33 2018 -0600
+
+ Fix inscribed polygon mode.
+
+commit d86e0ad3ec666f2d0516b97d72c0b5e7710dd3ca
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 4 18:24:35 2018 -0600
+
+ Add preliminary options for Polygon adding.
+
+commit 234483ccc8a13b8d318b7d09c3e38dfe353f696f
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 4 15:27:08 2018 -0600
+
+ Update UI for more options.
+
+commit 82cdb14e492e428b3e83c3aa489a448f31a8a746
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri May 4 14:56:44 2018 -0600
+
+ Add in-place preliminary polygon adding.
+
+commit 51bd11364219e7503622704ae297e3f7f0643cac
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 3 16:39:23 2018 -0600
+
+ Add interface for polygon adding.
+
+commit 3b1f8f08d7404b2143015468b0b0bcdd51bae93b
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu May 3 15:38:11 2018 -0600
+
+ Add preliminary in-screen object creation.
+
+commit 003d2fa4b41bb1c12c9de1503083267395d4ff5e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 2 16:25:43 2018 -0600
+
+ Add exscribed (right word?) polygon handling
+
+commit 27470ffb04cc5b446e906e327dab976713c94309
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 2 15:43:09 2018 -0600
+
+ Add support for primtive polygons.
+
+commit 34a182db3e5f611f794319ef6c2485594f3487a6
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed May 2 15:10:29 2018 -0600
+
+ Add adding circles.
+
+commit 8258bb93752a2d888e583f307d13bb4ef727aee6
+Merge: 7c18f2ea d09e7fce
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed May 2 08:28:05 2018 -0600
+
+ Merge pull request #70 from rgxgr/patch-1
+
+ Correct words order to avoid confusing
+
+commit d09e7fce20722e2e7d65692b915c4cef9a33bb2c
+Author: rgxgr <33611071+rgxgr at users.noreply.github.com>
+Date: Wed May 2 20:08:14 2018 +0800
+
+ Correct words order to avoid confusing
+
+commit 7f758672b3c9d39707379d030f9d8c7bc33a48cc
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue May 1 17:09:33 2018 -0600
+
+ Merge settings management into original Shardt code.
+
+commit b9754484ce5ef55fb9415731512362615a431778
+Merge: 75b22704 7c18f2ea
+Author: John Bowman <bowman at ualberta.ca>
+Date: Tue May 1 12:03:43 2018 -0600
+
+ Merge branch 'master' into qt.
+
+commit 7c18f2ea15c289fbdd6e4f91c69110f5a0c159b8
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Apr 28 12:08:11 2018 -0600
+
+ Rename i386 to i386_32 to give preference to 64-bit binary.
+
+commit 9079934b3424157942736bbe1a15afd1dbf5836c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Apr 28 11:39:48 2018 -0600
+
+ Do not modify system path.
+
+commit 799bf2dfc67869606056633c3a8ce4313b45d058
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Apr 28 11:10:47 2018 -0600
+
+ Revert "Workaround NSIS EnvVarUpdate bug that truncates long paths."
+
+ This reverts commit 8e932eb10a822d4e927b3b9dbecb313e135ee267.
+
+commit 8e932eb10a822d4e927b3b9dbecb313e135ee267
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Apr 27 16:22:08 2018 -0600
+
+ Workaround NSIS EnvVarUpdate bug that truncates long paths.
+
+commit 21e497260a55dbe4e4b111198aa26115564669ce
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Apr 14 08:31:47 2018 -0600
+
+ Fix sort.
+
+commit 2bfec3147f4308fa6e206ec624574e3156f43fd2
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Apr 13 10:11:31 2018 -0600
+
+ Add option to use unstable sort in favour of less(T i, T j) ordering.
+
+commit 20ff31c0444c901c2b0486127f3c4df2b9832df8
+Merge: 1a50ee63 2fd03c66
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Apr 11 17:51:11 2018 -0600
+
+ Merge branch 'master' of github.com:vectorgraphics/asymptote
+
+commit 1a50ee634cb58dbb4d9395ba90d7a795e63512d1
+Author: John Bowman <bowman at ualberta.ca>
+Date: Wed Apr 11 17:49:52 2018 -0600
+
+ Update README
+
+commit 2fd03c6695627387db19f993ac93e926b9b63eb7
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Apr 8 12:26:42 2018 -0600
+
+ Fix uninitialized counter.
+
+commit 4d0771442074af020b7fc929e929629e0bcbbdee
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Apr 7 23:51:06 2018 -0600
+
+ Increment version to 2.45.
+
commit 878f944b9ee540c77c83f2cc61d6a97c22298553
Author: John Bowman <bowman at ualberta.ca>
Date: Sat Apr 7 20:56:45 2018 -0600
@@ -334,6 +2503,48 @@
Update CYGWIN port for 64-bit build.
+commit 75b227048bf39a8f2bd9288d1a4e076119d0e612
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Thu Jan 4 15:07:17 2018 -0700
+
+ Add Polar Grid Form.
+
+commit 77ba04a37dd8affd267a267df256326fb42f6f1b
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Tue Jan 2 15:03:01 2018 -0700
+
+ Add basic guide drawing system.
+
+commit 109a43611f3e2f9da5f5dae5502d8a5b8b299a6a
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Dec 29 21:10:25 2017 -0700
+
+ Add basic grid snapping.
+
+commit aefccb8c568f772feb2bc59f009da9da3e8a3ff3
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Dec 29 16:13:31 2017 -0700
+
+ Add basic grid toggling
+
+commit 0fa0e5ca0c3709c3d3e0722c35ae45a412ea10d4
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Dec 27 16:53:51 2017 -0700
+
+ Add basic grid rendering.
+
+commit 6f6b6b1f7ef8393096a57c8c0b370275c11b2270
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Wed Dec 27 15:22:28 2017 -0700
+
+ Update deletion of Bezier points.
+
+commit 187e6113e92669d0cb724971694eaa8d7768178e
+Author: Supakorn Rassameemasmuang <rassamee at ualberta.ca>
+Date: Fri Dec 22 21:44:13 2017 -0700
+
+ Fix rotationBug - xasy2 now checks if custom anchor is defined or not.
+
commit 005aef0a8c45c8625910363e1159fedcd9fa31b6
Author: John Bowman <bowman at ualberta.ca>
Date: Mon Dec 18 14:51:43 2017 -0700
@@ -450,6 +2661,188 @@
Implement findall.
+commit 1d87c4b421c6e1950280eb26681ad229fe98313c
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Mon Sep 4 16:23:21 2017 -0600
+
+ Add preliminary keymap & settings support.
+
+commit 8e8a2349800a1d245779e023ecc5ede7da38b239
+Merge: c4aa7ded e9584ed2
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Sep 1 15:28:23 2017 -0600
+
+ Merge branch 'qt' of github.com:vectorgraphics/asymptote into qt
+
+commit c4aa7dedffc4a7782a75416c787dc7f607a308ea
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Sep 1 15:28:18 2017 -0600
+
+ Fix Beizer -> Bezier spelling
+
+commit e9584ed2fbaa6ba2bbf98fe78166c4e91a139da4
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Sep 1 15:27:42 2017 -0600
+
+ Update Makefile.
+
+commit e76d689c599a22a4441ae7111164bae7ac8f4f60
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Sep 1 15:27:11 2017 -0600
+
+ Update GUI.
+
+commit c5e57f4d961d136c4b547ea63026795790bd125e
+Merge: 355f99d4 15fe0eb7
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Sep 1 15:26:49 2017 -0600
+
+ Merge branch 'qt' of github.com:vectorgraphics/asymptote into qt
+
+commit 355f99d469f725e0086313bb27ab66b66d4d48cd
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Sep 1 15:26:43 2017 -0600
+
+ Fix merge conflict.
+
+commit 15fe0eb716b5f0d92ab8fe7063ca55124a623260
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Sep 1 15:16:29 2017 -0600
+
+ Update.
+
+commit 65e540f590ae0a9b552d31fec8eef5980e0f59c9
+Merge: 7be28a23 093568e2
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Sep 1 15:09:10 2017 -0600
+
+ Fix merge conflict.
+
+commit 7be28a23c991a0356792adf6304a5e58e0d8f492
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Sep 1 15:06:29 2017 -0600
+
+ Add Point Editor.
+
+commit 093568e25e61c860b896497264b19ea4f078c0ac
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Sep 1 15:04:39 2017 -0600
+
+ Fix spelling.
+
+commit fa2c10cf89b3b2564ee53bc48d46dd6919ba6105
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Sep 1 14:33:27 2017 -0600
+
+ Remove obsolete file.
+
+commit 7404f0bca98908521bccdfe9fe5fc84582869deb
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Sep 1 14:31:47 2017 -0600
+
+ Add ui entry.
+
+commit 0ea7b7aca30f5f0b2e0c17bac97093c797ff3397
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 29 13:00:50 2017 -0600
+
+ Add Beizer Curve Editor.
+
+commit 8fde617cc64cdfe44f61e6cc5ef6197ef2cc633c
+Merge: d664d887 f1092a70
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 29 13:00:01 2017 -0600
+
+ Merge remote-tracking branch 'origin/qt' into qt
+
+commit d664d887042bdbf4fd0a38d34834c6d4282acfd3
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 29 12:59:42 2017 -0600
+
+ Add undo/redo stack.
+
+commit f1092a70a211994ddf6bafe488427628e71341a0
+Merge: 1ed21e9e 1eafa765
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Aug 26 23:39:00 2017 -0600
+
+ Merge branch 'qt' of github.com:vectorgraphics/asymptote into qt
+
+commit 1ed21e9e55effe8fb917d4a3c9903f07cdd6e228
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sat Aug 26 23:38:43 2017 -0600
+
+ Add pyUIClass support to Makefile.
+
+commit 1eafa765e69ddb869237532ec7e9e828b30993c6
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sat Aug 26 23:14:43 2017 -0600
+
+ Add Custom Anchor dialog.
+
+commit d4e29b99c50c481bd67a46de08da95598730c72f
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sat Aug 26 23:13:24 2017 -0600
+
+ Add panning, added screen transformation layer, custom commands
+ input dialog.
+
+commit ade0b6c36cbca1bce9bfc51edefc7657e46d31c6
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Aug 25 12:58:54 2017 -0600
+
+ De-Asyfy transformation, fix local coordinates (temporary),
+ updated matrix dialog.
+
+commit 477fdd587d86bb57d8a8080a5a89401f80e6e128
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Wed Aug 23 14:16:58 2017 -0600
+
+ Add icon resource files, Matrix Transform Dialog.
+
+commit c460dce5689f9c992e0a80b150b2c67238a39c2e
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 22 17:10:59 2017 -0600
+
+ Add quick rendering, toggling of grids, more tooltips.
+
+commit 64d74954ef499b36329c5fb958dab4a38c932b52
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 22 15:54:52 2017 -0600
+
+ Add custom Transformation.
+
+commit 2f9674524c1d2231b58252b4daafd14aee478b27
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Mon Aug 21 16:45:27 2017 -0600
+
+ Fix translation & Update README.
+
+commit fd330a08614549c1497bd969f230837abcec8d7e
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Mon Aug 21 16:40:56 2017 -0600
+
+ Transition to final UI, add basic translation, scaling, rotation.
+
+commit ab2c346a05cd13fcc6e5c36ec2e9b0a100779e23
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sat Aug 19 16:40:07 2017 -0600
+
+ Move to new, Final User interface.
+
+commit efc9a0013f20fcc39872bbf42b8b1cbdbec91d35
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sat Aug 19 15:32:34 2017 -0600
+
+ Temporarily remove preCanvasPixmap (as mainCanvas
+ transparency is not wokring for some reason), add grid outline.
+
+commit 8988458f8d4f14bfb7b5e85074e7dd18d90fdc31
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Fri Aug 18 21:32:58 2017 -0600
+
+ Add mouse detection, drag translation & deferred buffers.
+
commit f7231be3e560fa40f43e298e4b69b5c03ca0a141
Author: John Bowman <bowman at ualberta.ca>
Date: Fri Aug 18 14:31:44 2017 -0600
@@ -456,6 +2849,67 @@
Remove redundant vbox.
+commit 7c5ba009606fe64da1757bdfebed51f0776a9941
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Wed Aug 16 15:42:29 2017 -0600
+
+ Change PIL to QImage.
+
+commit b69b6093485c4b42f03c26134099f54f02b497f8
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 15 14:42:19 2017 -0600
+
+ Rename xasyQt to xasy and original xasy to xasyTk.
+
+commit 52b8a33a6129219acb608abcc36248f27596965e
+Merge: fd134d02 67fe29eb
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 15 14:40:50 2017 -0600
+
+ Merge branch 'qt' of github.com:vectorgraphics/asymptote into qt
+
+commit fd134d02224c30893fc99a993643b641a6025999
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 15 14:40:44 2017 -0600
+
+ added final ui draft
+
+commit 27beaff43db806d9169f27ad0e10dd41f2a61299
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Mon Aug 14 01:00:36 2017 -0600
+
+ Add generalized Affine Transform.
+
+commit 67fe29eb902d87a6f34b6fbdd01c2a302a6b028c
+Author: John Bowman <bowman at ualberta.ca>
+Date: Sun Aug 13 21:51:17 2017 -0600
+
+ Fix xasyQt.
+
+commit c66360fc91837ac6b226ccef33c5bb95bff31bc3
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sun Aug 13 16:31:59 2017 -0600
+
+ Refractor to have the raw image flipped (for native asy coordinates).
+
+commit ad49f711ce684ef85b260cb02c0f51b0558e55ec
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Sun Aug 13 15:56:30 2017 -0600
+
+ Add rotation and translation.
+
+commit 81434d3f20caec72ebad1ac758958c3ca2d13481
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Wed Aug 9 00:11:55 2017 -0600
+
+ Update .gitignore and move generated files to a separate folder
+
+commit 03617244274132af1cad89cf8c3b1617cd2d1f91
+Author: Supakorn Rassameemasmuang <mistersupakorn at gmail.com>
+Date: Tue Aug 8 16:06:18 2017 -0600
+
+ Add initial qt xasy.
+
commit 84f4ea3ff0a564698282af8eeb1afae14907e2fe
Author: John Bowman <bowman at ualberta.ca>
Date: Fri Aug 4 15:33:03 2017 -0600
@@ -462,6 +2916,12 @@
Improve equation support in module slide.
+commit da7e0f8adee99fadb59623bc3065acae4c523e9b
+Author: John Bowman <bowman at ualberta.ca>
+Date: Fri Aug 4 16:25:15 2017 -0600
+
+ Test of Qt5.
+
commit 1b9692fae4a4f7bd58ea09f37178f7ed598f277d
Author: John Bowman <bowman at ualberta.ca>
Date: Tue Jun 13 15:40:12 2017 -0600
Deleted: trunk/Build/source/utils/asymptote/GUI/CubicBezier.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/CubicBezier.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/CubicBezier.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,104 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# Convert a Bezier curve to a polyline
-#
-# Once Tk supports "RawCurves" this will not be needed.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-import math
-
-def norm(vector):
- """Return the norm of a vector"""
- return math.sqrt(vector[0]**2+vector[1]**2)
-
-def splitLine(end0,end1,t):
- """Split a line at the distance t, with t in (0,1)"""
- return (end0[0]+t*(end1[0]-end0[0]),end0[1]+t*(end1[1]-end0[1]))
-
-def splitBezier(node0,control0,control1,node1,t):
- """Find the nodes and control points for the segments of a Bezier curve split at t"""
- a = splitLine(node0,control0,t)
- b = splitLine(control0,control1,t)
- c = splitLine(control1,node1,t)
- d = splitLine(a,b,t)
- e = splitLine(b,c,t)
- f = splitLine(d,e,t)#this is the point on the curve at t
- return ([node0,a,d,f],[f,e,c,node1])
-
-def BezierWidth(node0,control0,control1,node1):
- """Compute the distance of the control points from the node-node axis"""
- deltax = node1[0] - node0[0]
- deltay = node1[1] - node0[1]
- length = norm((deltax,deltay))
- if length == 0:
- y1 = control0[1]-node0[1]
- y2 = control1[1]-node0[1]
- else:
- cosine = deltax/length
- sine = deltay/length
- y1 = cosine*(control0[1]-node0[1])-sine*(control0[0]-node0[0])
- y2 = cosine*(control1[1]-node0[1])-sine*(control1[0]-node0[0])
- if y1*y2 >= 0:
- #same sign
- return max(abs(y1),abs(y2))
- else:
- #opposite sign
- return abs(y1)+abs(y2)
-
-#If the above algorithm fails, this one will work, but it is far from elegant
-#def computeIntermediates(steps,node0,control0,control1,node1):
- #pointList = []
- #for a in range(0,100,100/steps)+[100]:
- #t = a/100.0
- #t1 = 1-t
- #x = node0[0]*t1**3+3*control0[0]*t*t1**2+3*control1[0]*t**2*t1+node1[0]*t**3
- #y = node0[1]*t1**3+3*control0[1]*t*t1**2+3*control1[1]*t**2*t1+node1[1]*t**3
- #pointList.append((x,y))
- #return pointList
-#def makeBezier(steps,node0,control0,control1,node1):
- #if len(node0)!=2 or len(control0)!=2 or len(control1)!=2 or len(node1)!=2:
- #return -1
- #else:
- #return [node0]+computeIntermediates(steps,node0,control0,control1,node1)+[node1]
-
-def makeBezierIntermediates(node0,control0,control1,node1,epsilon):
- """Find the points, excluding node0, to be used as the line segment endpoints"""
- if(BezierWidth(node0,control0,control1,node1) <= epsilon):
- return [node1]
- else:
- splitUp = splitBezier(node0,control0,control1,node1,0.5)
- return makeBezierIntermediates(*splitUp[0]+[epsilon])+makeBezierIntermediates(*splitUp[1]+[epsilon])
-
-def makeBezier(node0,control0,control1,node1,epsilon=1):
- """Return the vertices to be used in the polyline representation of a Bezier curve"""
- return [node0]+makeBezierIntermediates(node0,control0,control1,node1,epsilon)
-
-if __name__ == '__main__':
- pointList = makeBezier((-80,0),(-150,40),(150,120),(80,0),0.5)
- from timeit import Timer
- t = Timer('makeBezier((-80,0),(-40,-40),(40,120),(80,0),1)','from __main__ import makeBezier')
- print (pointList)
- print (len(pointList))
- iterations = 1000
- time = t.timeit(iterations)
- print ("{:d} iterations took {:f} seconds ({:f} ms for each).".format(iterations,time,1000.0*time/iterations))
- points = []
- for point in pointList:
- points.append(point[0])
- points.append(-point[1])
- if sys.version_info >= (3, 0):
- from tkinter import *
- else:
- from Tkinter import *
- root = Tk()
- canv = Canvas(root,scrollregion=(-100,-100,100,100))
- canv.pack()
- canv.create_line(points)
- for point in pointList:
- canv.create_oval(point[0],-point[1],point[0],-point[1],fill='red',outline='red')
- root.mainloop()
Added: trunk/Build/source/utils/asymptote/GUI/CustMatTransform.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/CustMatTransform.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/CustMatTransform.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import numpy as np
+import xasy2asy as x2a
+from pyUIClass.custMatTransform import Ui_Dialog
+
+
+class CustMatTransform(Qw.QDialog):
+ def __init__(self):
+ super().__init__()
+ self.ui = Ui_Dialog()
+ self.ui.setupUi(self)
+
+ self.ui.btnAccept.clicked.connect(self.accept)
+ self.ui.btnCancel.clicked.connect(self.reject)
+ self.ui.btnReset.clicked.connect(self.resetDialog)
+
+ self.mainTransformation = Qg.QTransform()
+ self.mainTransformation.scale(1, -1)
+
+ self.matrixLineInputs = [
+ self.ui.lineMat00, self.ui.lineMat01, self.ui.lineMatTx,
+ self.ui.lineMat10, self.ui.lineMat11, self.ui.lineMatTy]
+
+ validator = Qg.QDoubleValidator()
+ for lineInput in self.matrixLineInputs:
+ lineInput.setValidator(validator)
+ lineInput.textChanged.connect(self.handleUpdateText)
+
+ def show(self):
+ super().show()
+ self.createCanvas()
+ self.updatePreview()
+
+ def createCanvas(self):
+ self.canvSize = self.ui.imgPreview.size()
+ self.previewPixmap = Qg.QPixmap(self.canvSize)
+ tx, ty = self.canvSize.width() / 2, self.canvSize.height() / 2
+ self.mainTransformation.translate(tx, -ty)
+
+ def handleUpdateText(self, text):
+ if str(text) not in {'.', '-', '.-', '-.'} and str(text):
+ self.updatePreview()
+ self.ui.btnAccept.setEnabled(True)
+ else:
+ self.previewPixmap.fill()
+ self.ui.imgPreview.setPixmap(self.previewPixmap)
+ self.ui.btnAccept.setEnabled(False)
+
+ def updatePreview(self):
+ self.previewPixmap.fill()
+ canvas = Qg.QPainter(self.previewPixmap)
+ if not canvas.isActive():
+ return
+ canvas.setTransform(self.mainTransformation)
+
+ canvas.save()
+ canvas.setPen(Qc.Qt.lightGray)
+ self.drawBasicGrid(canvas)
+ transform = x2a.asyTransform.fromNumpyMatrix(self.getTransformationMatrix())
+ canvTransform = transform.toQTransform()
+ canvas.setTransform(canvTransform, True)
+
+ canvas.setPen(Qc.Qt.black)
+
+ if canvTransform.isInvertible():
+ self.drawBasicGrid(canvas, False)
+
+ if canvTransform.determinant() <= 0:
+ canvas.setPen(Qc.Qt.red)
+
+ canvas.drawRect(Qc.QRect(Qc.QPoint(0, 0), Qc.QSize(20, 20)))
+
+ self.ui.imgPreview.setPixmap(self.previewPixmap)
+
+ def resetDialog(self):
+ self.ui.lineMatTx.setText('0')
+ self.ui.lineMatTx.setText('0')
+
+ self.ui.lineMat00.setText('1')
+ self.ui.lineMat01.setText('0')
+ self.ui.lineMat10.setText('0')
+ self.ui.lineMat11.setText('1')
+
+ def drawBasicGrid(self, canvas, grid=True):
+ canvas.drawLine(Qc.QLine(-9999, 0, 9999, 0))
+ canvas.drawLine(Qc.QLine(0, -9999, 0, 9999))
+
+ fromIter, toIter = -7, 7
+ gridSize = 20
+ if grid:
+ for iterIndex in range(fromIter, toIter + 1):
+ canvas.drawLine(Qc.QLine(-9999, iterIndex * gridSize, 9999, iterIndex * gridSize))
+ canvas.drawLine(Qc.QLine(iterIndex * gridSize, -9999, iterIndex * gridSize, 9999))
+
+ def getTransformationMatrix(self):
+ rawMatrixNum = [float(lineInput.text()) for lineInput in self.matrixLineInputs]
+ rawMatrixNum.extend([0, 0, 1])
+ return np.matrix(rawMatrixNum).reshape((3, 3))
Property changes on: trunk/Build/source/utils/asymptote/GUI/CustMatTransform.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/DebugFlags.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/DebugFlags.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/DebugFlags.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+keepFiles = False
+printFoutTranscript = False
+printDeconstTranscript = False
+forceRasterizationSVG = False
Property changes on: trunk/Build/source/utils/asymptote/GUI/DebugFlags.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/GuidesManager.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/GuidesManager.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/GuidesManager.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import numpy as np
+
+class Guide:
+ def __init__(self, pen=None):
+ if pen is None:
+ pen = Qg.QPen()
+ assert isinstance(pen, Qg.QPen)
+ self.pen = pen
+
+ def drawShape(self, pen):
+ assert isinstance(pen, Qg.QPainter)
+ pen.save()
+ pen.setPen(self.pen)
+
+class LineGuide(Guide):
+ def __init__(self, origin, direction, pen=None):
+ super().__init__(pen)
+ self.origin = origin
+ self.direction = direction
+
+ def drawShape(self, pen):
+ super().drawShape(pen)
+ p1 = self.origin + (9999 * Qc.QPointF(np.cos(self.direction), np.sin(self.direction)))
+ p2 = self.origin - (9999 * Qc.QPointF(np.cos(self.direction), np.sin(self.direction)))
+ pen.drawLine(Qc.QLineF(p1, p2))
+ pen.restore()
+
+class ArcGuide(Guide):
+ @classmethod
+ def radTo16Deg(cls, radians):
+ return int(round(np.rad2deg(radians) * 16))
+
+ def __init__(self, center=None, radius=1, startAng=0, endAng=(2*np.pi), pen=None):
+ if center is None:
+ center = Qc.QPointF(0, 0)
+ super().__init__(pen)
+ self.center = center
+ self.radius = int(radius)
+ self.startAng = startAng
+ self.endAng = endAng
+
+ def drawShape(self, pen):
+ super().drawShape(pen)
+ assert isinstance(pen, Qg.QPainter)
+ x, y = int(round(self.center.x())), int(round(self.center.y()))
+ pen.drawArc(x - self.radius, y - self.radius, 2 * self.radius, 2 * self.radius, ArcGuide.radTo16Deg(self.startAng),
+ -ArcGuide.radTo16Deg(self.endAng - self.startAng))
+ pen.restore()
Property changes on: trunk/Build/source/utils/asymptote/GUI/GuidesManager.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/InplaceAddObj.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/InplaceAddObj.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/InplaceAddObj.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,356 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtCore as Qc
+import PyQt5.QtGui as Qg
+import xasy2asy as x2a
+
+import PrimitiveShape
+import math
+
+import Widg_addPolyOpt
+import Widg_addLabel
+
+
+class InplaceObjProcess(Qc.QObject):
+ objectCreated = Qc.pyqtSignal(Qc.QObject)
+ objectUpdated = Qc.pyqtSignal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self._active = False
+ pass
+
+ @property
+ def active(self):
+ return self._active
+
+ def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+ raise NotImplementedError
+
+ def mouseMove(self, pos, event: Qg.QMouseEvent):
+ raise NotImplementedError
+
+ def mouseRelease(self):
+ raise NotImplementedError
+
+ def forceFinalize(self):
+ raise NotImplementedError
+
+ def getPreview(self):
+ return None
+
+ def getObject(self):
+ raise NotImplementedError
+
+ def getXasyObject(self):
+ raise NotImplementedError
+
+ def postDrawPreview(self, canvas: Qg.QPainter):
+ pass
+
+ def createOptWidget(self, info):
+ return None
+
+
+class AddCircle(InplaceObjProcess):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.center = Qc.QPointF(0, 0)
+ self.radius = 0
+
+ def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+ self.radius = 0
+ self.center.setX(x)
+ self.center.setY(y)
+ self.fill = info['fill']
+ self._active = True
+
+ def mouseMove(self, pos, event):
+ self.radius = PrimitiveShape.PrimitiveShape.euclideanNorm(pos, self.center)
+
+ def mouseRelease(self):
+ self.objectCreated.emit(self.getXasyObject())
+ self._active = False
+
+ def getPreview(self):
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.center)
+ boundRect = Qc.QRectF(x - self.radius, y - self.radius, 2 * self.radius, 2 * self.radius)
+ # because the internal image is flipped...
+ newPath = Qg.QPainterPath()
+ newPath.addEllipse(boundRect)
+ # newPath.addRect(boundRect)
+ return newPath
+
+ def getObject(self):
+ return PrimitiveShape.PrimitiveShape.circle(self.center, self.radius)
+
+ def getXasyObject(self):
+ if self.fill:
+ newObj = x2a.xasyFilledShape(self.getObject(), None)
+ else:
+ newObj = x2a.xasyShape(self.getObject(), None)
+ return newObj
+
+ def forceFinalize(self):
+ self.mouseRelease()
+
+
+class AddLabel(InplaceObjProcess):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.alignMode = None
+ self.opt = None
+ self.text = None
+ self.anchor = Qc.QPointF(0, 0)
+ self._active = False
+
+ def createOptWidget(self, info):
+ self.opt = Widg_addLabel.Widg_addLabel(info)
+ return self.opt
+
+ def getPreview(self):
+ return None
+
+ def mouseRelease(self):
+ self.objectCreated.emit(self.getXasyObject())
+ self._active = False
+
+ def mouseMove(self, pos, event):
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+ self.anchor.setX(x)
+ self.anchor.setY(y)
+
+ def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+ if self.opt is not None:
+ self.text = self.opt.labelText
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+ self.anchor.setX(x)
+ self.anchor.setY(y)
+
+ self.alignMode = info['align']
+ self.fontSize = info['fontSize']
+ self._active = True
+
+ def getObject(self):
+ finalTuple = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.anchor)
+ return {'txt': self.text, 'align': str(self.alignMode), 'anchor': finalTuple}
+
+ def getXasyObject(self):
+ text = self.text
+ align = str(self.alignMode)
+ anchor = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.anchor)
+ newLabel = x2a.xasyText(text=text, location=anchor, pen=None,
+ align=align, asyengine=None, fontsize=self.fontSize)
+ newLabel.asyfied = False
+ return newLabel
+
+ def forceFinalize(self):
+ self.mouseRelease()
+
+
+class AddBezierShape(InplaceObjProcess):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.asyengine = None
+ self.basePath = None
+ self.basePathPreview = None
+ self.closedPath = None
+ self.info = None
+ self.fill = False
+ self.opt = None
+
+ # list of "committed" points with Linkage information.
+ # Linkmode should be to the last point.
+ # (x, y, linkmode), (u, v, lm2) <==> (x, y) <=lm2=> (u, v)
+ self.pointsList = []
+ self.currentPoint = Qc.QPointF(0, 0)
+ self.pendingPoint = None
+ self.useLegacy = False
+
+ def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+ self.currentPoint.setX(x)
+ self.currentPoint.setY(y)
+ self.info = info
+
+ if not self._active:
+ self._active = True
+ self.fill = info['fill']
+ self.asyengine = info['asyengine']
+ self.closedPath = info['closedPath']
+ self.useBezierBase = info['useBezier']
+ self.useLegacy = self.info['options']['useLegacyDrawMode']
+ self.pointsList.clear()
+ self.pointsList.append((x, y, None))
+ else:
+ # see http://doc.qt.io/archives/qt-4.8/qt.html#MouseButton-enum
+ if (int(mouseEvent.buttons()) if mouseEvent is not None else 0) & 0x2 and self.useLegacy:
+ self.forceFinalize()
+
+ def _getLinkType(self):
+ if self.info['useBezier']:
+ return '..'
+ else:
+ return '--'
+
+ def mouseMove(self, pos, event):
+ # in postscript coords.
+ if self._active:
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+
+ if self.useLegacy or int(event.buttons()) != 0:
+ self.currentPoint.setX(x)
+ self.currentPoint.setY(y)
+ else:
+ self.forceFinalize()
+
+
+ def createOptWidget(self, info):
+ return None
+ # self.opt = Widg_addBezierInPlace.Widg_addBezierInplace(info)
+ # return self.opt
+
+ def finalizeClosure(self):
+ if self.active:
+ self.closedPath = True
+ self.forceFinalize()
+
+ def mouseRelease(self):
+ x, y = self.currentPoint.x(), self.currentPoint.y()
+ self.pointsList.append((x, y, self._getLinkType()))
+ # self.updateBasePath()
+
+ def updateBasePath(self):
+ self.basePath = x2a.asyPath(asyengine=self.asyengine, forceCurve=self.useBezierBase)
+ newNode = [(x, y) for x, y, _ in self.pointsList]
+ newLink = [lnk for *args, lnk in self.pointsList[1:]]
+ if self.useLegacy:
+ newNode += [(self.currentPoint.x(), self.currentPoint.y())]
+ newLink += [self._getLinkType()]
+ if self.closedPath:
+ newNode.append('cycle')
+ newLink.append(self._getLinkType())
+ self.basePath.initFromNodeList(newNode, newLink)
+
+ if self.useBezierBase:
+ self.basePath.computeControls()
+
+ def updateBasePathPreview(self):
+ self.basePathPreview = x2a.asyPath(
+ asyengine=self.asyengine, forceCurve=self.useBezierBase)
+ newNode = [(x, y) for x, y, _ in self.pointsList] + [(self.currentPoint.x(), self.currentPoint.y())]
+ newLink = [lnk for *args, lnk in self.pointsList[1:]] + [self._getLinkType()]
+ if self.closedPath:
+ newNode.append('cycle')
+ newLink.append(self._getLinkType())
+ self.basePathPreview.initFromNodeList(newNode, newLink)
+
+ if self.useBezierBase:
+ self.basePathPreview.computeControls()
+
+ def forceFinalize(self):
+ self.updateBasePath()
+ self._active = False
+ self.pointsList.clear()
+ self.objectCreated.emit(self.getXasyObject())
+ self.basePath = None
+
+ def getObject(self):
+ if self.basePath is None:
+ raise RuntimeError('BasePath is None')
+ self.basePath.asyengine = self.asyengine
+ return self.basePath
+
+ def getPreview(self):
+ if self._active:
+ if self.pointsList:
+ self.updateBasePathPreview()
+ newPath = self.basePathPreview.toQPainterPath()
+ return newPath
+
+ def getXasyObject(self):
+ if self.fill:
+ return x2a.xasyFilledShape(self.getObject(), None)
+ else:
+ return x2a.xasyShape(self.getObject(), None)
+
+
+class AddPoly(InplaceObjProcess):
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.center = Qc.QPointF(0, 0)
+ self.currPos = Qc.QPointF(0, 0)
+ self.sides = None
+ self.inscribed = None
+ self.centermode = None
+ self.asyengine = None
+ self.fill = None
+ self.opt = None
+
+ def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+ self._active = True
+ self.sides = info['sides']
+ self.inscribed = info['inscribed']
+ self.centermode = info['centermode']
+ self.fill = info['fill']
+
+
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+ self.center.setX(x)
+ self.center.setY(y)
+ self.currPos = Qc.QPointF(self.center)
+
+ def mouseMove(self, pos, event):
+ x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+ self.currPos.setX(x)
+ self.currPos.setY(y)
+
+ def mouseRelease(self):
+ if self.active:
+ self.objectCreated.emit(self.getXasyObject())
+ self._active = False
+
+ def forceFinalize(self):
+ self.mouseRelease()
+
+ def getObject(self):
+ if self.inscribed:
+ return PrimitiveShape.PrimitiveShape.inscribedRegPolygon(self.sides, self.center, self._rad(),
+ self._angle())
+ else:
+ return PrimitiveShape.PrimitiveShape.exscribedRegPolygon(self.sides, self.center, self._rad(),
+ self._angle())
+
+ def getPreview(self):
+ if self.inscribed:
+ poly = PrimitiveShape.PrimitiveShape.inscribedRegPolygon(self.sides, self.center, self._rad(),
+ self._angle(), qpoly=True)
+ else:
+ poly = PrimitiveShape.PrimitiveShape.exscribedRegPolygon(self.sides, self.center, self._rad(),
+ self._angle(), qpoly=True)
+ newPath = Qg.QPainterPath()
+ newPath.addPolygon(poly)
+ return newPath
+
+ def createOptWidget(self, info):
+ self.opt = Widg_addPolyOpt.Widg_addPolyOpt(info)
+ return self.opt
+
+ def _rad(self):
+ return PrimitiveShape.PrimitiveShape.euclideanNorm(self.currPos, self.center)
+
+ def _angle(self):
+ dist_x = self.currPos.x() - self.center.x()
+ dist_y = self.currPos.y() - self.center.y()
+ if dist_x == 0 and dist_y == 0:
+ return 0
+ else:
+ return math.atan2(dist_y, dist_x)
+
+ def getXasyObject(self):
+ if self.fill:
+ newObj = x2a.xasyFilledShape(self.getObject(), None)
+ else:
+ newObj = x2a.xasyShape(self.getObject(), None)
+ return newObj
Property changes on: trunk/Build/source/utils/asymptote/GUI/InplaceAddObj.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/PrimitiveShape.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/PrimitiveShape.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/PrimitiveShape.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+import xasy2asy as x2a
+import numpy as np
+import math
+import PyQt5.QtCore as Qc
+import PyQt5.QtGui as Qg
+
+
+class PrimitiveShape:
+ # The magic number.
+ # see https://www.desmos.com/calculator/lw6j7khikj for unitcircle
+ # optimal_ctl_pt = 0.5447
+
+ @staticmethod
+ def pos_to_tuple(pos):
+ if isinstance(pos, tuple) or isinstance(pos, np.ndarray):
+ return pos
+ elif isinstance(pos, Qc.QPoint) or isinstance(pos, Qc.QPointF):
+ return pos.x(), pos.y()
+ else:
+ raise TypeError("Position must be a valid type!")
+
+ @staticmethod
+ def euclideanNorm(p1, p2):
+ x1, y1 = PrimitiveShape.pos_to_tuple(p1)
+ x2, y2 = PrimitiveShape.pos_to_tuple(p2)
+
+ normSq = ((x1 - x2) ** 2) + ((y1 - y2) ** 2)
+ return math.sqrt(normSq)
+
+ @classmethod
+ def circle(cls, position, radius):
+ pos_x, pos_y = PrimitiveShape.pos_to_tuple(position)
+ newCircle = x2a.asyPath()
+ ptsList = [(pos_x + radius, pos_y), (pos_x, pos_y + radius), (pos_x - radius, pos_y), (pos_x, pos_y - radius),
+ 'cycle']
+ # cycle doesn't work for now.
+ lkList = ['..', '..', '..', '..']
+ newCircle.initFromNodeList(ptsList, lkList)
+ return newCircle
+
+ @classmethod
+ def inscribedRegPolygon(cls, sides, position, radius, starting_rad, qpoly=False):
+ pos_x, pos_y = PrimitiveShape.pos_to_tuple(position)
+ lkList = ['--'] * sides
+ ptsList = []
+ for ang in np.linspace(starting_rad, starting_rad + math.tau, sides, endpoint=False):
+ ptsList.append((pos_x + radius * math.cos(ang), pos_y + radius * math.sin(ang)))
+
+ if qpoly:
+ ptsList.append((pos_x + radius * math.cos(starting_rad), pos_y + radius * math.sin(starting_rad)))
+ qpoints = [Qc.QPointF(x, y) for (x, y) in ptsList]
+ return Qg.QPolygonF(qpoints)
+ else:
+ ptsList.append('cycle')
+ newPoly = x2a.asyPath()
+ newPoly.initFromNodeList(ptsList, lkList)
+ return newPoly
+
+ @classmethod
+ def exscribedRegPolygon(cls, sides, position, length, starting_rad, qpoly=False):
+ ang = math.tau/sides
+ # see notes
+ adjusted_radius = length / math.cos(ang/2)
+ return cls.inscribedRegPolygon(sides, position, adjusted_radius, starting_rad - ang/2, qpoly)
Property changes on: trunk/Build/source/utils/asymptote/GUI/PrimitiveShape.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/SetCustomAnchor.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/SetCustomAnchor.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/SetCustomAnchor.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+from pyUIClass.setCustomAnchor import Ui_Dialog
+
+
+class CustomAnchorDialog(Qw.QDialog):
+
+ def __init__(self):
+ super().__init__()
+ self.ui = Ui_Dialog()
+ self.ui.setupUi(self)
+ self.ui.buttonBox.button(Qw.QDialogButtonBox.Reset).clicked.connect(self.resetDialog)
+
+ validator = Qg.QDoubleValidator()
+
+ self.ui.lineEditX.setValidator(validator)
+ self.ui.lineEditY.setValidator(validator)
+
+ self.ui.lineEditX.textChanged.connect(self.checkTextChanged)
+ self.ui.lineEditY.textChanged.connect(self.checkTextChanged)
+
+ def checkTextChanged(self, text):
+ if str(text) not in {'.', '-', '.-', '-.'} and str(text):
+ self.ui.buttonBox.button(Qw.QDialogButtonBox.Ok).setEnabled(True)
+ else:
+ self.ui.buttonBox.button(Qw.QDialogButtonBox.Ok).setEnabled(False)
+
+ def getPoint(self):
+ xPoint = float(self.ui.lineEditX.text())
+ yPoint = float(self.ui.lineEditY.text())
+
+ return Qc.QPointF(xPoint, yPoint)
+
+ def handleBtnBoxClick(self, button):
+ assert isinstance(button, Qw.QAbstractButton)
+ if button.text() == 'Reset':
+ self.resetDialog()
+
+ def resetDialog(self):
+ self.ui.lineEditX.setText('0')
+ self.ui.lineEditY.setText('0')
Property changes on: trunk/Build/source/utils/asymptote/GUI/SetCustomAnchor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Build/source/utils/asymptote/GUI/UndoRedoStack.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/UndoRedoStack.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/UndoRedoStack.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
###########################################################################
#
# UndoRedoStack implements the usual undo/redo capabilities of a GUI
@@ -8,110 +8,125 @@
#
###########################################################################
+
class action:
- def __init__(self,act,inv):
- self.act = act
- self.inv = inv
- def undo(self):
- #print ("Undo:",self)
- self.inv()
- def redo(self):
- #print ("Redo:",self)
- self.act()
- def __str__(self):
- return "A generic action"
+ def __init__(self, actions):
+ act, inv = actions
+ self.act = act
+ self.inv = inv
+ def undo(self):
+ # print ("Undo:",self)
+ self.inv()
+
+ def redo(self):
+ # print ("Redo:",self)
+ self.act()
+
+ def __str__(self):
+ return "A generic action"
+
+
class beginActionGroup:
- pass
+ pass
+
class endActionGroup:
- pass
+ pass
+
class actionStack:
- def __init__(self):
- self.clear()
+ def __init__(self):
+ self.clear()
- def add(self,action):
- self.undoStack.append(action)
- #print ("Added",action)
- self.redoStack = []
+ def add(self, action):
+ self.undoStack.append(action)
+ # print ("Added",action)
+ self.redoStack = []
- def undo(self):
- if len(self.undoStack) > 0:
- op = self.undoStack.pop()
- if op is beginActionGroup:
- level = 1
- self.redoStack.append(endActionGroup)
- while level > 0:
- op=self.undoStack.pop()
- if op is endActionGroup:
- level -= 1
- self.redoStack.append(beginActionGroup)
- elif op is beginActionGroup:
- level += 1
- self.redoStack.append(endActionGroup)
- else:
- op.undo()
- self.redoStack.append(op)
- elif op is endActionGroup:
- raise Exception("endActionGroup without previous beginActionGroup")
- else:
- self.redoStack.append(op)
- op.undo()
- #print ("undid",op)
- else:
- pass #print ("nothing to undo")
+ def undo(self):
+ if len(self.undoStack) > 0:
+ op = self.undoStack.pop()
+ if op is beginActionGroup:
+ level = 1
+ self.redoStack.append(endActionGroup)
+ while level > 0:
+ op = self.undoStack.pop()
+ if op is endActionGroup:
+ level -= 1
+ self.redoStack.append(beginActionGroup)
+ elif op is beginActionGroup:
+ level += 1
+ self.redoStack.append(endActionGroup)
+ else:
+ op.undo()
+ self.redoStack.append(op)
+ elif op is endActionGroup:
+ raise Exception("endActionGroup without previous beginActionGroup")
+ else:
+ self.redoStack.append(op)
+ op.undo()
+ # print ("undid",op)
+ else:
+ pass # print ("nothing to undo")
- def redo(self):
- if len(self.redoStack) > 0:
- op = self.redoStack.pop()
- if op is beginActionGroup:
- level = 1
- self.undoStack.append(endActionGroup)
- while level > 0:
- op = self.redoStack.pop()
- if op is endActionGroup:
- level -= 1
- self.undoStack.append(beginActionGroup)
- elif op is beginActionGroup:
- level += 1
- self.undoStack.append(endActionGroup)
- else:
- op.redo()
- self.undoStack.append(op)
- elif op is endActionGroup:
- raise Exception("endActionGroup without previous beginActionGroup")
- else:
- self.undoStack.append(op)
- op.redo()
- #print ("redid",op)
- else:
- pass #print ("nothing to redo")
+ def redo(self):
+ if len(self.redoStack) > 0:
+ op = self.redoStack.pop()
+ if op is beginActionGroup:
+ level = 1
+ self.undoStack.append(endActionGroup)
+ while level > 0:
+ op = self.redoStack.pop()
+ if op is endActionGroup:
+ level -= 1
+ self.undoStack.append(beginActionGroup)
+ elif op is beginActionGroup:
+ level += 1
+ self.undoStack.append(endActionGroup)
+ else:
+ op.redo()
+ self.undoStack.append(op)
+ elif op is endActionGroup:
+ raise Exception("endActionGroup without previous beginActionGroup")
+ else:
+ self.undoStack.append(op)
+ op.redo()
+ # print ("redid",op)
+ else:
+ pass # print ("nothing to redo")
- def setCommitLevel(self):
- self.commitLevel = len(self.undoStack)
+ def setCommitLevel(self):
+ self.commitLevel = len(self.undoStack)
- def changesMade(self):
- if len(self.undoStack) != self.commitLevel:
- return True
- else:
- return False
+ def changesMade(self):
+ if len(self.undoStack) != self.commitLevel:
+ return True
+ else:
+ return False
- def clear(self):
- self.redoStack = []
- self.undoStack = []
- self.commitLevel = 0
+ def clear(self):
+ self.redoStack = []
+ self.undoStack = []
+ self.commitLevel = 0
-if __name__=='__main__':
- import sys
- def opq():
- print ("action1")
- def unopq():
- print ("inverse1")
- q = action(opq,unopq)
- w = action(lambda:sys.stdout.write("action2\n"),lambda:sys.stdout.write("inverse2\n"))
- e = action(lambda:sys.stdout.write("action3\n"),lambda:sys.stdout.write("inverse3\n"))
- s = actionStack()
- s.add(q)
- s.add(w)
- s.add(e)
+
+if __name__ == '__main__':
+ import sys
+
+
+ def opq():
+ print("action1")
+
+
+ def unopq():
+ print("inverse1")
+
+
+ q = action(opq, unopq)
+ w = action(lambda: sys.stdout.write("action2\n"), lambda: sys.stdout.write("inverse2\n"))
+ e = action(lambda: sys.stdout.write("action3\n"), lambda: sys.stdout.write("inverse3\n"))
+ s = actionStack()
+ s.add(q)
+ s.add(w)
+ s.add(e)
Added: trunk/Build/source/utils/asymptote/GUI/Widg_addLabel.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/Widg_addLabel.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/Widg_addLabel.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+
+from pyUIClass.widg_addLabel import Ui_Form
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+
+import labelEditor
+import xasyUtils as xu
+
+
+class Widg_addLabel(Qw.QWidget):
+ def __init__(self, info):
+ super().__init__()
+ self.ui = Ui_Form()
+ self.info = info
+ self.ui.setupUi(self)
+ self.setFixedSize(self.size())
+
+ if 'alignIndex' not in self.info.keys():
+ self.info['alignIndex'] = 0
+
+ if 'shift_x' not in self.info.keys():
+ self.info['shift_x'] = None
+
+ if 'shift_y' not in self.info.keys():
+ self.info['shift_y'] = None
+
+ if 'align' not in self.info.keys():
+ self.info['align'] = (0, 0)
+
+ if self.info['shift_x'] is not None:
+ self.ui.txtShiftX.setText(str(self.info['shift_x']))
+
+ if self.info['shift_y'] is not None:
+ self.ui.txtShiftY.setText(str(self.info['shift_y']))
+
+
+ self.ui.cmbFontSize.setCurrentText(str(self.info['fontSize']) if self.info['fontSize'] is not None else '-')
+ self.ui.cmbAlign.setCurrentIndex(self.info['alignIndex'])
+
+ validator = Qg.QDoubleValidator()
+
+ self.ui.txtShiftX.setValidator(validator)
+ self.ui.txtShiftY.setValidator(validator)
+ self.ui.cmbFontSize.setValidator(validator)
+
+ self.ui.cmbAlign.currentTextChanged.connect(self.updateCheck)
+ self.ui.cmbAlign.currentIndexChanged.connect(self.cmbIndexUpdate)
+ self.ui.txtShiftX.textEdited.connect(self.shftXUpdate)
+ self.ui.txtShiftY.textEdited.connect(self.shftYUpdate)
+ self.ui.btnAdvancedEdit.clicked.connect(self.btnAdvancedEditClicked)
+ self.ui.cmbFontSize.currentTextChanged.connect(self.cmbFontSizeTextChanged)
+
+ self.updateCheck(self.ui.cmbAlign.currentText())
+
+ def cmbFontSizeTextChanged(self, text: str):
+ tryParseVal = xu.tryParse(text, float)
+ self.info['fontSize'] = tryParseVal
+
+ def btnAdvancedEditClicked(self):
+ advancedEditDialog = labelEditor.labelEditor(self.ui.txtLabelText.text())
+ advancedEditDialog.show()
+ result = advancedEditDialog.exec_()
+ if result == Qw.QDialog.Accepted:
+ self.ui.txtLabelText.setText(advancedEditDialog.getText())
+
+ @property
+ def labelText(self):
+ return self.ui.txtLabelText.text()
+
+ def updateCheck(self, a0):
+ self.ui.txtShiftX.setEnabled(a0 == 'Custom')
+ self.ui.txtShiftY.setEnabled(a0 == 'Custom')
+
+ def shftXUpdate(self, text):
+ if text:
+ self.info['shift_x'] = float(text)
+ self.updateAlign()
+
+ def shftYUpdate(self, text):
+ if text:
+ self.info['shift_y'] = float(text)
+ self.updateAlign()
+
+ def updateAlign(self):
+ index = self.ui.cmbAlign.currentIndex()
+ self.info['alignIndex'] = index
+ if self.ui.cmbAlign.currentText() == 'Custom':
+ self.info['align'] = (self.info['shift_x'], self.info['shift_y'])
+ elif self.ui.cmbAlign.currentText() == 'None':
+ self.info['align'] = (0, 0)
+ else:
+ self.info['align'] = self.ui.cmbAlign.currentText()
+
+ def cmbIndexUpdate(self, index):
+ self.updateAlign()
Property changes on: trunk/Build/source/utils/asymptote/GUI/Widg_addLabel.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+from pyUIClass.widg_addPolyOpt import Ui_Form
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+
+import sys
+
+
+class Widg_addPolyOpt(Qw.QWidget):
+ def __init__(self, info):
+ super().__init__()
+ self.ui = Ui_Form()
+ self.info = info
+ self.ui.setupUi(self)
+ self.setFixedSize(self.size())
+
+ self.ui.chkInscribed.setChecked(self.info['inscribed'])
+ self.ui.txtSides.setText(str(self.info['sides']))
+ self.ui.txtSides.setValidator(Qg.QIntValidator())
+
+ self.ui.chkInscribed.stateChanged.connect(self.chkInscribedUpdate)
+ self.ui.txtSides.textChanged.connect(self.txtSidesUpdate)
+
+ def chkInscribedUpdate(self, checked):
+ self.info['inscribed'] = checked
+
+ def txtSidesUpdate(self, text):
+ if text:
+ self.info['sides'] = int(text)
Property changes on: trunk/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/Widg_editBezier.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/Widg_editBezier.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/Widg_editBezier.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+from pyUIClass.widg_editBezier import Ui_Form
+
+import PyQt5.QtCore as Qc
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+
+class LockMode:
+ noLock = 0
+ angleLock = 1
+ angleAndScaleLock = 2
+
+class Widg_editBezier(Qw.QWidget):
+ def __init__(self, info: dict, enableCurveFeatures: bool=True):
+ super().__init__()
+ self.ui = Ui_Form()
+ self.ui.setupUi(self)
+ self.info = info
+
+ self.ui.chkRecompute.setChecked(self.info['autoRecompute'])
+ self.ui.cmbLockMode.setCurrentIndex(self.info['editBezierlockMode'])
+
+ self.ui.cmbLockMode.currentIndexChanged[int].connect(self.cmbLockIndexChange)
+ self.ui.chkRecompute.stateChanged.connect(self.chkRecomputeChanged)
+
+ self.disableOnAutoRecompute = {self.ui.cmbLockMode, self.ui.btnForceRecompute}
+ self.curveBtnsOnly = {self.ui.cmbLockMode, self.ui.btnForceRecompute, self.ui.chkRecompute}
+
+ for elem in self.curveBtnsOnly:
+ elem.setEnabled(enableCurveFeatures)
+
+ @property
+ def autoRecompute(self) -> bool:
+ return self.ui.chkRecompute.isChecked()
+
+ @property
+ def lockMode(self) -> int:
+ return self.ui.cmbLockMode.currentIndex()
+
+ @Qc.pyqtSlot(int)
+ def cmbLockIndexChange(self, index: int):
+ self.info['editBezierlockMode'] = index
+
+ @Qc.pyqtSlot(int)
+ def chkRecomputeChanged(self, checked: int):
+ isChecked = (checked == 2)
+ for obj in self.disableOnAutoRecompute:
+ obj.setEnabled(not checked)
+ self.info['autoRecompute'] = checked
+
+ if isChecked:
+ self.ui.btnForceRecompute.clicked.emit()
Property changes on: trunk/Build/source/utils/asymptote/GUI/Widg_editBezier.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/Window1.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/Window1.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/Window1.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,1890 @@
+#!/usr/bin/env python3
+
+from pyUIClass.window1 import Ui_MainWindow
+
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import xasyVersion
+
+import numpy as np
+import os
+import json
+import io
+import pathlib
+import webbrowser
+import subprocess
+import tempfile
+import datetime
+import string
+import atexit
+
+import xasyUtils as xu
+import xasy2asy as x2a
+import xasyFile as xf
+import xasyOptions as xo
+import UndoRedoStack as Urs
+import xasyArgs as xa
+import xasyBezierInterface as xbi
+from xasyTransform import xasyTransform as xT
+import xasyStrings as xs
+
+import PrimitiveShape
+import InplaceAddObj
+
+import CustMatTransform
+import SetCustomAnchor
+import GuidesManager
+
+
+class ActionChanges:
+ pass
+
+
+# State Invariance: When ActionChanges is at the top, all state of the program & file
+# is exactly like what it was the event right after that ActionChanges was created.
+
+class TransformationChanges(ActionChanges):
+ def __init__(self, objIndex, transformation, isLocal=False):
+ self.objIndex = objIndex
+ self.transformation = transformation
+ self.isLocal = isLocal
+
+
+class ObjCreationChanges(ActionChanges):
+ def __init__(self, obj):
+ self.object = obj
+
+class HardDeletionChanges(ActionChanges):
+ def __init__(self, obj, pos):
+ self.item = obj
+ self.objIndex = pos
+
+class AnchorMode:
+ origin = 0
+ center = 1
+ topLeft = 2
+ topRight = 3
+ bottomRight = 4
+ bottomLeft = 5
+ customAnchor = 6
+
+
+class GridMode:
+ cartesian = 0
+ polar = 1
+
+
+class SelectionMode:
+ select = 0
+ pan = 1
+ translate = 2
+ rotate = 3
+ scale = 4
+ delete = 5
+ setAnchor = 6
+ selectEdit = 7
+
+class AddObjectMode:
+ Circle = 0
+ Arc = 1
+ Polygon = 2
+
+class MainWindow1(Qw.QMainWindow):
+ defaultFrameStyle = """
+ QFrame{{
+ padding: 4.0;
+ border-radius: 3.0;
+ background: rgb({0}, {1}, {2})
+ }}
+ """
+
+ def __init__(self):
+ super().__init__()
+ self.ui = Ui_MainWindow()
+ self.ui.setupUi(self)
+
+ self.settings = xo.BasicConfigs.defaultOpt
+ self.keyMaps = xo.BasicConfigs.keymaps
+
+ self.raw_args = Qc.QCoreApplication.arguments()
+ self.args = xa.parseArgs(self.raw_args)
+
+ self.strings = xs.xasyString(self.args.language)
+ self.asy2psmap = x2a.identity()
+
+ if self.settings['asyBaseLocation'] is not None:
+ os.environ['ASYMPTOTE_DIR'] = self.settings['asyBaseLocation']
+
+ if self.args.asypath is not None:
+ asyPath = self.args.asypath
+ else:
+ asyPath = self.settings['asyPath']
+
+ self.asyPath = asyPath
+ self.asyEngine = x2a.AsymptoteEngine(self.asyPath)
+
+ try:
+ self.asyEngine.start()
+ finally:
+ atexit.register(self.asyEngine.cleanup)
+
+ # For initialization purposes
+ self.canvSize = Qc.QSize()
+ self.filename = None
+ self.currDir = None
+ self.mainCanvas = None
+ self.dpi = 300
+ self.canvasPixmap = None
+
+ # Actions
+ # <editor-fold> Connecting Actions
+ self.ui.txtLineWidth.setValidator(Qg.QDoubleValidator())
+
+ self.connectActions()
+ self.connectButtons()
+
+ self.ui.txtLineWidth.returnPressed.connect(self.btnTerminalCommandOnClick)
+ # </editor-fold>
+
+ # Base Transformations
+
+ self.mainTransformation = Qg.QTransform()
+ self.mainTransformation.scale(1, 1)
+ self.localTransform = Qg.QTransform()
+ self.screenTransformation = Qg.QTransform()
+ self.panTranslation = Qg.QTransform()
+
+ # Internal Settings
+ self.magnification = self.args.mag
+ self.inMidTransformation = False
+ self.addMode = None
+ self.currentlySelectedObj = {'key': None, 'allSameKey': set(), 'selectedIndex': None, 'keyIndex': None}
+ self.pendingSelectedObjList = []
+ self.pendingSelectedObjIndex = -1
+
+ self.savedMousePosition = None
+ self.currentBoundingBox = None
+ self.selectionDelta = None
+ self.newTransform = None
+ self.origBboxTransform = None
+ self.deltaAngle = 0
+ self.scaleFactor = 1
+ self.panOffset = [0, 0]
+
+ super().setMouseTracking(True)
+ # setMouseTracking(True)
+
+ self.undoRedoStack = Urs.actionStack()
+
+ self.lockX = False
+ self.lockY = False
+ self.anchorMode = AnchorMode.center
+ self.currentAnchor = Qc.QPointF(0, 0)
+ self.customAnchor = None
+ self.useGlobalCoords = True
+ self.drawAxes = True
+ self.drawGrid = False
+ self.gridSnap = False # TODO: for now. turn it on later
+
+ self.fileChanged = False
+
+ self.terminalPythonMode = self.ui.btnTogglePython.isChecked()
+
+ self.savedWindowMousePos = None
+
+ self.finalPixmap = None
+ self.preCanvasPixmap = None
+ self.postCanvasPixmap = None
+ self.previewCurve = None
+ self.mouseDown = False
+
+ self.globalObjectCounter = 0
+
+ self.fileItems = []
+ self.drawObjects = []
+ self.xasyDrawObj = {'drawDict': self.drawObjects}
+
+ self.modeButtons = {
+ self.ui.btnTranslate, self.ui.btnRotate, self.ui.btnScale, # self.ui.btnSelect,
+ self.ui.btnPan, self.ui.btnDeleteMode, self.ui.btnAnchor,
+ self.ui.btnSelectEdit
+ }
+
+ self.objButtons = {self.ui.btnCustTransform, self.ui.actionTransform, self.ui.btnSendForwards,
+ self.ui.btnSendBackwards, self.ui.btnToggleVisible
+ }
+
+ self.globalTransformOnlyButtons = (self.ui.comboAnchor, self.ui.btnAnchor)
+
+ self.ui.txtTerminalPrompt.setFont(Qg.QFont(self.settings['terminalFont']))
+
+ self.currAddOptionsWgt = None
+ self.currAddOptions = {
+ 'options': self.settings,
+ 'inscribed': True,
+ 'sides': 3,
+ 'centermode': True,
+ 'fontSize': None,
+ 'asyengine': self.asyEngine,
+ 'fill': self.ui.btnFill.isChecked(),
+ 'closedPath': False,
+ 'useBezier': True,
+ 'magnification': self.magnification,
+ 'editBezierlockMode': xbi.Web.LockMode.angleLock,
+ 'autoRecompute': False
+ }
+
+
+ self.currentModeStack = [SelectionMode.translate]
+ self.drawGridMode = GridMode.cartesian
+ self.setAllInSetEnabled(self.objButtons, False)
+ self._currentPen = x2a.asyPen()
+ self.currentGuides = []
+ self.selectAsGroup = self.settings['groupObjDefault']
+
+ # commands switchboard
+ self.commandsFunc = {
+ 'quit': Qc.QCoreApplication.quit,
+ 'undo': self.btnUndoOnClick,
+ 'redo': self.btnRedoOnClick,
+ 'manual': self.actionManual,
+ 'about': self.actionAbout,
+ 'loadFile': self.btnLoadFileonClick,
+ 'save': self.actionSave,
+ 'saveAs': self.actionSaveAs,
+ 'transform': self.btnCustTransformOnClick,
+ 'commandPalette': self.enterCustomCommand,
+ 'clearGuide': self.clearGuides,
+ 'finalizeAddObj': self.finalizeAddObj,
+ 'finalizeCurve': self.finalizeCurve,
+ 'finalizeCurveClosed': self.finalizeCurveClosed,
+ 'setMag': self.setMagPrompt,
+ 'deleteObject': self.btnSelectiveDeleteOnClick,
+ 'anchorMode': self.switchToAnchorMode,
+ 'moveUp': lambda: self.arrowButtons(0, 1, False),
+ 'moveDown': lambda: self.arrowButtons(0, -1, False),
+
+ 'scrollLeft': lambda: self.arrowButtons(-1, 0, True),
+ 'scrollRight': lambda: self.arrowButtons(1, 0, True),
+ 'scrollUp': lambda: self.arrowButtons(0, 1, True),
+ 'scrollDown': lambda: self.arrowButtons(0, -1, True),
+
+ 'zoomIn': lambda: self.arrowButtons(0, 1, False, True),
+ 'zoomOut': lambda: self.arrowButtons(0, -1, False, True)
+ }
+
+ self.hiddenKeys = set()
+
+ # Coordinates Label
+
+ self.coordLabel = Qw.QLabel(self.ui.statusbar)
+ self.ui.statusbar.addPermanentWidget(self.coordLabel)
+
+ # Settings Initialization
+ # from xasyoptions config file
+ self.loadKeyMaps()
+ self.setupXasyOptions()
+
+ self.colorDialog = Qw.QColorDialog(x2a.asyPen.convertToQColor(self._currentPen.color), self)
+ self.initPenInterface()
+
+ def arrowButtons(self, x:int , y:int, shift: bool=False, ctrl: bool=False):
+ "x, y indicates update button orientation on the cartesian plane."
+ if not (shift or ctrl):
+ self.changeSelection(y)
+ elif not (shift and ctrl):
+ self.mouseWheel(30*x, 30*y)
+ self.quickUpdate()
+
+ def cleanup(self):
+ self.asyengine.cleanup()
+
+ def getScrsTransform(self):
+ # pipeline:
+ # assuming origin <==> top left
+ # (Pan) * (Translate) * (Flip the images) * (Zoom) * (Obj transform) * (Base Information)
+
+ # pipeline --> let x, y be the postscript point
+ # p = (mx + cx + panoffset, -ny + cy + panoffset)
+ cx, cy = self.canvSize.width() / 2, self.canvSize.height() / 2
+
+ newTransf = Qg.QTransform()
+ newTransf.translate(*self.panOffset)
+ newTransf.translate(cx, cy)
+ newTransf.scale(1, 1)
+ newTransf.scale(self.magnification, self.magnification)
+
+ return newTransf
+
+ def finalizeCurve(self):
+ if self.addMode is not None:
+ if self.addMode.active and isinstance(self.addMode, InplaceAddObj.AddBezierShape):
+ self.addMode.forceFinalize()
+ self.fileChanged = True
+
+ def finalizeCurveClosed(self):
+ if self.addMode is not None:
+ if self.addMode.active and isinstance(self.addMode, InplaceAddObj.AddBezierShape):
+ self.addMode.finalizeClosure()
+ self.fileChanged = True
+
+ def getAllBoundingBox(self) -> Qc.QRectF:
+ newRect = Qc.QRectF()
+ for majitem in self.drawObjects:
+ for minitem in majitem:
+ newRect = newRect.united(minitem.boundingBox)
+ return newRect
+
+ def finalizeAddObj(self):
+ if self.addMode is not None:
+ if self.addMode.active:
+ self.addMode.forceFinalize()
+ self.fileChanged = True
+
+ def openAndReloadSettings(self):
+ settingsFile = self.settings.settingsFileLocation()
+ subprocess.run(args=self.getExternalEditor(asypath=settingsFile))
+ self.settings.load()
+ self.quickUpdate()
+
+ def setMagPrompt(self):
+ commandText, result = Qw.QInputDialog.getText(self, '', 'Enter magnification:')
+ if result:
+ self.magnification = float(commandText)
+ self.currAddOptions['magnification'] = self.magnification
+ self.quickUpdate()
+
+ def btnTogglePythonOnClick(self, checked):
+ self.terminalPythonMode = checked
+
+ def internationalize(self):
+ self.ui.btnRotate.setToolTip(self.strings.rotate)
+
+ def handleArguments(self):
+ if self.args.filename is not None:
+ self.loadFile(self.args.filename)
+ else:
+ self.initializeEmptyFile()
+
+ if self.args.language != 'en':
+ self.internationalize()
+
+ def initPenInterface(self):
+ self.ui.txtLineWidth.setText(str(self._currentPen.width))
+ self.updateFrameDispColor()
+
+ def updateFrameDispColor(self):
+ r, g, b = [int(x * 255) for x in self._currentPen.color]
+ self.ui.frameCurrColor.setStyleSheet(MainWindow1.defaultFrameStyle.format(r, g, b))
+
+ def initDebug(self):
+ debugFunc = {
+ }
+ self.commandsFunc = {**self.commandsFunc, **debugFunc}
+
+ def dbgRecomputeCtrl(self):
+ if isinstance(self.addMode, xbi.InteractiveBezierEditor):
+ self.addMode.recalculateCtrls()
+ self.quickUpdate()
+
+ def objectUpdated(self):
+ self.removeAddMode()
+ self.clearSelection()
+ self.asyfyCanvas()
+
+ def connectActions(self):
+ self.ui.actionQuit.triggered.connect(lambda: self.execCustomCommand('quit'))
+ self.ui.actionUndo.triggered.connect(lambda: self.execCustomCommand('undo'))
+ self.ui.actionRedo.triggered.connect(lambda: self.execCustomCommand('redo'))
+ self.ui.actionTransform.triggered.connect(lambda: self.execCustomCommand('transform'))
+
+ self.ui.actionOpen.triggered.connect(self.actionOpen)
+ self.ui.actionSave.triggered.connect(self.actionSave)
+ self.ui.actionSaveAs.triggered.connect(self.actionSaveAs)
+ self.ui.actionManual.triggered.connect(self.actionManual)
+ self.ui.actionAbout.triggered.connect(self.actionAbout)
+ self.ui.actionSettings.triggered.connect(self.openAndReloadSettings)
+ self.ui.actionEnterCommand.triggered.connect(self.enterCustomCommand)
+ self.ui.actionExportAsymptote.triggered.connect(self.btnExportAsyOnClick)
+
+ def setupXasyOptions(self):
+ if self.settings['debugMode']:
+ self.initDebug()
+ newColor = Qg.QColor(self.settings['defaultPenColor'])
+ newWidth = self.settings['defaultPenWidth']
+
+ self._currentPen.setColorFromQColor(newColor)
+ self._currentPen.setWidth(newWidth)
+
+ def connectButtons(self):
+ # Button initialization
+ self.ui.btnUndo.clicked.connect(self.btnUndoOnClick)
+ self.ui.btnRedo.clicked.connect(self.btnRedoOnClick)
+ self.ui.btnLoadFile.clicked.connect(self.btnLoadFileonClick)
+ self.ui.btnSave.clicked.connect(self.btnSaveonClick)
+ self.ui.btnQuickScreenshot.clicked.connect(self.btnQuickScreenshotOnClick)
+
+ # self.ui.btnExportAsy.clicked.connect(self.btnExportAsyOnClick)
+
+ self.ui.btnDrawAxes.clicked.connect(self.btnDrawAxesOnClick)
+# self.ui.btnAsyfy.clicked.connect(lambda: self.asyfyCanvas(True))
+ self.ui.btnSetZoom.clicked.connect(self.setMagPrompt)
+ self.ui.btnResetPan.clicked.connect(self.resetPan)
+ self.ui.btnPanCenter.clicked.connect(self.btnPanCenterOnClick)
+
+ self.ui.btnTranslate.clicked.connect(self.btnTranslateonClick)
+ self.ui.btnRotate.clicked.connect(self.btnRotateOnClick)
+ self.ui.btnScale.clicked.connect(self.btnScaleOnClick)
+ # self.ui.btnSelect.clicked.connect(self.btnSelectOnClick)
+ self.ui.btnPan.clicked.connect(self.btnPanOnClick)
+
+ # self.ui.btnDebug.clicked.connect(self.pauseBtnOnClick)
+ self.ui.btnAlignX.clicked.connect(self.btnAlignXOnClick)
+ self.ui.btnAlignY.clicked.connect(self.btnAlignYOnClick)
+ self.ui.comboAnchor.currentIndexChanged.connect(self.handleAnchorComboIndex)
+ self.ui.btnCustTransform.clicked.connect(self.btnCustTransformOnClick)
+ self.ui.btnViewCode.clicked.connect(self.btnLoadEditorOnClick)
+
+ self.ui.btnAnchor.clicked.connect(self.btnAnchorModeOnClick)
+
+ self.ui.btnSelectColor.clicked.connect(self.btnColorSelectOnClick)
+ self.ui.txtLineWidth.textEdited.connect(self.txtLineWithEdited)
+
+ # self.ui.btnCreateCurve.clicked.connect(self.btnCreateCurveOnClick)
+ self.ui.btnDrawGrid.clicked.connect(self.btnDrawGridOnClick)
+
+ self.ui.btnAddCircle.clicked.connect(self.btnAddCircleOnClick)
+ self.ui.btnAddPoly.clicked.connect(self.btnAddPolyOnClick)
+ self.ui.btnAddLabel.clicked.connect(self.btnAddLabelOnClick)
+ # self.ui.btnAddBezierInplace.clicked.connect(self.btnAddBezierInplaceOnClick)
+ self.ui.btnClosedCurve.clicked.connect(self.btnAddClosedCurveOnClick)
+ self.ui.btnOpenCurve.clicked.connect(self.btnAddOpenCurveOnClick)
+ self.ui.btnClosedPoly.clicked.connect(self.btnAddClosedLineOnClick)
+ self.ui.btnOpenPoly.clicked.connect(self.btnAddOpenLineOnClick)
+
+ self.ui.btnFill.clicked.connect(self.btnFillOnClick)
+
+ self.ui.btnSendBackwards.clicked.connect(self.btnSendBackwardsOnClick)
+ self.ui.btnSendForwards.clicked.connect(self.btnSendForwardsOnClick)
+ # self.ui.btnDelete.clicked.connect(self.btnSelectiveDeleteOnClick)
+ self.ui.btnDeleteMode.clicked.connect(self.btnDeleteModeOnClick)
+ # self.ui.btnSoftDelete.clicked.connect(self.btnSoftDeleteOnClick)
+ self.ui.btnToggleVisible.clicked.connect(self.btnSetVisibilityOnClick)
+
+ self.ui.btnEnterCommand.clicked.connect(self.btnTerminalCommandOnClick)
+ self.ui.btnTogglePython.clicked.connect(self.btnTogglePythonOnClick)
+ self.ui.btnSelectEdit.clicked.connect(self.btnSelectEditOnClick)
+
+ def btnDeleteModeOnClick(self):
+ self.currentModeStack = [SelectionMode.delete]
+ self.ui.statusbar.showMessage('Delete Mode')
+ self.clearSelection()
+ self.updateChecks()
+
+ def btnTerminalCommandOnClick(self):
+ if self.terminalPythonMode:
+ exec(self.ui.txtTerminalPrompt.text())
+ self.fileChanged = True
+ else:
+ pass
+ # TODO: How to handle this case?
+ # Like AutoCAD?
+ self.ui.txtTerminalPrompt.clear()
+
+ def btnFillOnClick(self, checked):
+ self.currAddOptions['fill'] = checked
+ self.ui.btnOpenCurve.setEnabled(not checked)
+ self.ui.btnOpenPoly.setEnabled(not checked)
+
+ def btnSelectEditOnClick(self):
+ self.ui.statusbar.showMessage('Edit mode')
+ self.currentModeStack = [SelectionMode.selectEdit]
+ self.updateChecks()
+
+ @property
+ def currentPen(self):
+ return x2a.asyPen.fromAsyPen(self._currentPen)
+ pass
+ def debug(self):
+ print('Put a breakpoint here.')
+
+ def execPythonCmd(self):
+ commandText, result = Qw.QInputDialog.getText(self, '', 'enter python cmd')
+ if result:
+ exec(commandText)
+
+ def deleteAddOptions(self):
+ if self.currAddOptionsWgt is not None:
+ self.currAddOptionsWgt.hide()
+ self.ui.addOptionLayout.removeWidget(self.currAddOptionsWgt)
+ self.currAddOptionsWgt = None
+
+ def updateOptionWidget(self):
+ try:
+ self.addMode.objectCreated.disconnect()
+ except Exception:
+ pass
+
+ self.currentModeStack[-1] = None
+ self.addMode.objectCreated.connect(self.addInPlace)
+ self.updateModeBtnsOnly()
+
+
+ self.deleteAddOptions()
+
+ self.currAddOptionsWgt = self.addMode.createOptWidget(self.currAddOptions)
+ if self.currAddOptionsWgt is not None:
+ self.ui.addOptionLayout.addWidget(self.currAddOptionsWgt)
+
+ def addInPlace(self, obj):
+ obj.asyengine = self.asyEngine
+ obj.pen = self.currentPen
+ obj.onCanvas = self.xasyDrawObj
+ obj.setKey(str(self.globalObjectCounter))
+ self.globalObjectCounter = self.globalObjectCounter + 1
+
+ self.fileItems.append(obj)
+ self.fileChanged = True
+ self.addObjCreationUrs(obj)
+ self.asyfyCanvas()
+
+ def addObjCreationUrs(self, obj):
+ newAction = self.createAction(ObjCreationChanges(obj))
+ self.undoRedoStack.add(newAction)
+ self.checkUndoRedoButtons()
+
+ def clearGuides(self):
+ self.currentGuides.clear()
+ self.quickUpdate()
+
+ def btnAddCircleOnClick(self):
+ self.addMode = InplaceAddObj.AddCircle(self)
+ self.ui.statusbar.showMessage('')
+ self.updateOptionWidget()
+
+ LegacyHint='Click and drag to draw; right click or space bar to finalize'
+ Hint='Click and drag to draw; release and click in place to add node; continue dragging'
+ HintClose=' or c to close.'
+
+ def drawHint(self):
+ if self.settings['useLegacyDrawMode']:
+ self.ui.statusbar.showMessage(self.LegacyHint+'.')
+ else:
+ self.ui.statusbar.showMessage(self.Hint+'.')
+
+ def drawHintOpen(self):
+ if self.settings['useLegacyDrawMode']:
+ self.ui.statusbar.showMessage(self.LegacyHint+self.HintClose)
+ else:
+ self.ui.statusbar.showMessage(self.Hint+self.HintClose)
+
+ def btnAddBezierInplaceOnClick(self):
+ self.addMode = InplaceAddObj.AddBezierShape(self)
+ self.updateOptionWidget()
+
+ def btnAddOpenLineOnClick(self):
+ self.currAddOptions['useBezier'] = False
+ self.currAddOptions['closedPath'] = False
+ self.drawHintOpen()
+ self.btnAddBezierInplaceOnClick()
+
+ def btnAddClosedLineOnClick(self):
+ self.currAddOptions['useBezier'] = False
+ self.currAddOptions['closedPath'] = True
+ self.drawHint()
+ self.btnAddBezierInplaceOnClick()
+
+ def btnAddOpenCurveOnClick(self):
+ self.currAddOptions['useBezier'] = True
+ self.currAddOptions['closedPath'] = False
+ self.drawHintOpen()
+ self.btnAddBezierInplaceOnClick()
+
+ def btnAddClosedCurveOnClick(self):
+ self.currAddOptions['useBezier'] = True
+ self.currAddOptions['closedPath'] = True
+ self.drawHint()
+ self.btnAddBezierInplaceOnClick()
+
+ def btnAddPolyOnClick(self):
+ self.addMode = InplaceAddObj.AddPoly(self)
+ self.ui.statusbar.showMessage('')
+ self.updateOptionWidget()
+
+ def btnAddLabelOnClick(self):
+ self.addMode = InplaceAddObj.AddLabel(self)
+ self.ui.statusbar.showMessage('')
+ self.updateOptionWidget()
+
+ def updateCurve(self, valid, newCurve):
+ self.previewCurve = newCurve
+ self.quickUpdate()
+
+ def addTransformationChanges(self, objIndex, transform, isLocal=False):
+ self.undoRedoStack.add(self.createAction(TransformationChanges(objIndex,
+ transform, isLocal)))
+ self.checkUndoRedoButtons()
+
+ def btnSendForwardsOnClick(self):
+ if self.currentlySelectedObj['selectedIndex'] is not None:
+ maj, minor = self.currentlySelectedObj['selectedIndex']
+ selectedObj = self.drawObjects[maj][minor]
+ index = self.fileItems.index(selectedObj.parent())
+
+ self.clearSelection()
+ if index == len(self.fileItems) - 1:
+ return
+ else:
+ self.fileItems[index], self.fileItems[index + 1] = self.fileItems[index + 1], self.fileItems[index]
+ self.asyfyCanvas()
+
+ def btnSelectiveDeleteOnClick(self):
+ if self.currentlySelectedObj['selectedIndex'] is not None:
+ maj, minor = self.currentlySelectedObj['selectedIndex']
+ selectedObj = self.drawObjects[maj][minor]
+
+ parent = selectedObj.parent()
+
+ if isinstance(parent, x2a.xasyScript):
+ self.hiddenKeys.add((selectedObj.key, selectedObj.keyIndex))
+ self.softDeleteObj((maj, minor))
+ else:
+ index = self.fileItems.index(selectedObj.parent())
+
+ self.undoRedoStack.add(self.createAction(
+ HardDeletionChanges(selectedObj.parent(), index)
+ ))
+ self.checkUndoRedoButtons()
+
+ self.fileItems.remove(selectedObj.parent())
+
+ self.fileChanged = True
+ self.clearSelection()
+ self.asyfyCanvas()
+ else:
+ result = self.selectOnHover()
+ if result:
+ self.btnSelectiveDeleteOnClick()
+
+ def btnSetVisibilityOnClick(self):
+ if self.currentlySelectedObj['selectedIndex'] is not None:
+ maj, minor = self.currentlySelectedObj['selectedIndex']
+ selectedObj = self.drawObjects[maj][minor]
+
+ self.hiddenKeys.symmetric_difference_update({(selectedObj.key, selectedObj.keyIndex)})
+ self.clearSelection()
+ self.quickUpdate()
+
+ def btnSendBackwardsOnClick(self):
+ if self.currentlySelectedObj['selectedIndex'] is not None:
+ maj, minor = self.currentlySelectedObj['selectedIndex']
+ selectedObj = self.drawObjects[maj][minor]
+ index = self.fileItems.index(selectedObj.parent())
+
+ self.clearSelection()
+ if index == 0:
+ return
+ else:
+ self.fileItems[index], self.fileItems[index - 1] = self.fileItems[index - 1], self.fileItems[index]
+ self.asyfyCanvas()
+
+
+ def btnUndoOnClick(self):
+ self.undoRedoStack.undo()
+ self.checkUndoRedoButtons()
+
+ def btnRedoOnClick(self):
+ self.undoRedoStack.redo()
+ self.checkUndoRedoButtons()
+
+ def checkUndoRedoButtons(self):
+ self.ui.btnUndo.setEnabled(self.undoRedoStack.changesMade())
+ self.ui.actionUndo.setEnabled(self.undoRedoStack.changesMade())
+
+ self.ui.btnRedo.setEnabled(len(self.undoRedoStack.redoStack) > 0)
+ self.ui.actionRedo.setEnabled(len(self.undoRedoStack.redoStack) > 0)
+
+ def handleUndoChanges(self, change):
+ assert isinstance(change, ActionChanges)
+ if isinstance(change, TransformationChanges):
+ self.transformObject(change.objIndex, change.transformation.inverted(), change.isLocal)
+ elif isinstance(change, ObjCreationChanges):
+ self.fileItems.pop()
+ elif isinstance(change, HardDeletionChanges):
+ self.fileItems.insert(change.objIndex, change.item)
+ self.asyfyCanvas()
+
+ def handleRedoChanges(self, change):
+ assert isinstance(change, ActionChanges)
+ if isinstance(change, TransformationChanges):
+ self.transformObject(
+ change.objIndex, change.transformation, change.isLocal)
+ elif isinstance(change, ObjCreationChanges):
+ self.fileItems.append(change.object)
+ elif isinstance(change, HardDeletionChanges):
+ self.fileItems.remove(change.item)
+ self.asyfyCanvas()
+
+ # is this a "pythonic" way?
+ def createAction(self, changes):
+ def _change():
+ return self.handleRedoChanges(changes)
+
+ def _undoChange():
+ return self.handleUndoChanges(changes)
+
+ return Urs.action((_change, _undoChange))
+
+ def execCustomCommand(self, command):
+ if command in self.commandsFunc:
+ self.commandsFunc[command]()
+ else:
+ self.ui.statusbar.showMessage('Command {0} not found'.format(command))
+
+ def enterCustomCommand(self):
+ commandText, result = Qw.QInputDialog.getText(self, 'Enter Custom Command', 'Enter Custom Command')
+ if result:
+ self.execCustomCommand(commandText)
+
+ def addItemFromPath(self, path):
+ newItem = x2a.xasyShape(path, self.asyEngine, pen=self.currentPen)
+ self.fileItems.append(newItem)
+ self.fileChanged = True
+ self.asyfyCanvas()
+
+ def actionManual(self):
+ asyManualURL = 'http://asymptote.sourceforge.net/asymptote.pdf'
+ webbrowser.open_new(asyManualURL)
+
+ def actionAbout(self):
+ Qw.QMessageBox.about(self,"xasy","This is xasy "+xasyVersion.xasyVersion+"; a graphical front end to the Asymptote vector graphics language: http://asymptote.sourceforge.net/")
+
+ def btnExportAsyOnClick(self):
+ diag = Qw.QFileDialog(self)
+ diag.setAcceptMode(Qw.QFileDialog.AcceptSave)
+
+ formatId = {
+ 'pdf': {
+ 'name': 'PDF Files',
+ 'ext': ['*.pdf']
+ },
+ 'svg': {
+ 'name': 'Scalable Vector Graphics',
+ 'ext': ['*.svg']
+ },
+ 'eps': {
+ 'name': 'Postscript Files',
+ 'ext': ['*.eps']
+ },
+ 'png': {
+ 'name': 'Portable Network Graphics',
+ 'ext': ['*.png']
+ },
+ '*': {
+ 'name': 'Any Files',
+ 'ext': ['*.*']
+ }
+ }
+
+ formats = ['pdf', 'svg', 'eps', 'png', '*']
+
+ formatText = ';;'.join('{0:s} ({1:s})'.format(formatId[form]['name'], ' '.join(formatId[form]['ext']))
+ for form in formats)
+
+ if self.currDir is not None:
+ diag.setDirectory(self.currDir)
+ rawFile = os.path.splitext(os.path.basename(self.filename))[0] + '.pdf'
+ diag.selectFile(rawFile)
+
+ diag.setNameFilter(formatText)
+ diag.show()
+ result = diag.exec_()
+
+ if result != diag.Accepted:
+ return
+
+ finalFiles = diag.selectedFiles()
+
+ with io.StringIO() as finalCode:
+ xf.saveFile(finalCode, self.fileItems, self.asy2psmap)
+ finalString = finalCode.getvalue()
+
+ for file in finalFiles:
+ ext = os.path.splitext(file)
+ if len(ext) < 2:
+ ext = 'pdf'
+ else:
+ ext = ext[1][1:]
+
+ with subprocess.Popen(args=[self.asyPath, '-f{0}'.format(ext), '-o{0}'.format(file), '-'], encoding='utf-8',
+ stdin=subprocess.PIPE) as asy:
+ print('test:', finalString)
+ asy.stdin.write(finalString)
+ asy.stdin.close()
+ asy.wait(timeout=35)
+
+
+ def loadKeyMaps(self):
+ """Inverts the mapping of the key
+ Input map is in format 'Action' : 'Key Sequence' """
+ for action, key in self.keyMaps.options.items():
+ shortcut = Qw.QShortcut(self)
+ shortcut.setKey(Qg.QKeySequence(key))
+
+ # hate doing this, but python doesn't have explicit way to pass a
+ # string to a lambda without an identifier
+ # attached to it.
+ exec('shortcut.activated.connect(lambda: self.execCustomCommand("{0}"))'.format(action),
+ {'self': self, 'shortcut': shortcut})
+
+ def initializeButtons(self):
+ self.ui.btnDrawAxes.setChecked(self.settings['defaultShowAxes'])
+ self.btnDrawAxesOnClick(self.settings['defaultShowAxes'])
+
+ self.ui.btnDrawGrid.setChecked(self.settings['defaultShowGrid'])
+ self.btnDrawGridOnClick(self.settings['defaultShowGrid'])
+
+ def erase(self):
+ self.fileItems.clear()
+ self.fileChanged = False
+
+ def actionOpen(self):
+ if self.fileChanged:
+ save="Save current file?"
+ reply=Qw.QMessageBox.question(self,'Message',save,Qw.QMessageBox.Yes,
+ Qw.QMessageBox.No)
+ if reply == Qw.QMessageBox.Yes:
+ self.actionSave()
+
+ filename = Qw.QFileDialog.getOpenFileName(self, 'Open Asymptote File','', '*.asy')
+ if filename[0]:
+ self.loadFile(filename[0])
+
+ def actionSave(self):
+ if self.filename is None:
+ self.actionSaveAs()
+ else:
+ saveFile = io.open(self.filename, 'w')
+ xf.saveFile(saveFile, self.fileItems, self.asy2psmap)
+ saveFile.close()
+ self.updateScript()
+
+ def updateScript(self):
+ for item in self.fileItems:
+ if isinstance(item, x2a.xasyScript):
+ if item.updatedCode:
+ item.setScript(item.updatedCode)
+ item.updatedCode = None
+
+ def actionSaveAs(self):
+ saveLocation = Qw.QFileDialog.getSaveFileName(self, 'Save File')[0]
+ if saveLocation:
+ saveFile = io.open(saveLocation, 'w')
+ xf.saveFile(saveFile, self.fileItems, self.asy2psmap)
+ saveFile.close()
+ self.filename = saveLocation
+ self.updateScript()
+
+
+ def btnQuickScreenshotOnClick(self):
+ saveLocation = Qw.QFileDialog.getSaveFileName(self, 'Save Screenshot','')
+ if saveLocation[0]:
+ self.ui.imgLabel.pixmap().save(saveLocation[0])
+
+ def btnLoadFileonClick(self):
+ self.actionOpen()
+
+ def btnSaveonClick(self):
+ self.actionSave()
+
+ @Qc.pyqtSlot(int)
+ def handleAnchorComboIndex(self, index: int):
+ self.anchorMode = index
+ if self.anchorMode == AnchorMode.customAnchor:
+ if self.customAnchor is not None:
+ self.anchorMode = AnchorMode.customAnchor
+ else:
+ self.ui.comboAnchor.setCurrentIndex(AnchorMode.center)
+ self.anchorMode = AnchorMode.center
+ self.quickUpdate()
+ def btnColorSelectOnClick(self):
+ self.colorDialog.show()
+ result = self.colorDialog.exec()
+ if result == Qw.QDialog.Accepted:
+ self._currentPen.setColorFromQColor(self.colorDialog.selectedColor())
+ self.updateFrameDispColor()
+
+ def txtLineWithEdited(self, text):
+ new_val = xu.tryParse(text, float)
+ if new_val is not None:
+ if new_val > 0:
+ self._currentPen.setWidth(new_val)
+
+ def isReady(self):
+ return self.mainCanvas is not None
+
+ def resizeEvent(self, resizeEvent):
+ # super().resizeEvent(resizeEvent)
+ assert isinstance(resizeEvent, Qg.QResizeEvent)
+
+ if self.isReady():
+ if self.mainCanvas.isActive():
+ self.mainCanvas.end()
+ self.canvSize = self.ui.imgFrame.size()
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+ self.canvasPixmap = Qg.QPixmap(self.canvSize)
+ # self.canvasPixmap.setDevicePixelRatio(3)
+ self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
+
+ self.quickUpdate()
+
+ def show(self):
+ super().show()
+ self.createMainCanvas() # somehow, the coordinates doesn't get updated until after showing.
+ self.initializeButtons()
+ self.postShow()
+
+ def postShow(self):
+ self.handleArguments()
+
+ def roundPositionSnap(self, oldPoint):
+ minorGridSize = self.settings['gridMajorAxesSpacing'] / (self.settings['gridMinorAxesCount'] + 1)
+ if isinstance(oldPoint, list) or isinstance(oldPoint, tuple):
+ return [round(val / minorGridSize) * minorGridSize for val in oldPoint]
+ elif isinstance(oldPoint, Qc.QPoint) or isinstance(oldPoint, Qc.QPointF):
+ x, y = oldPoint.x(), oldPoint.y()
+ x = round(x / minorGridSize) * minorGridSize
+ y = round(y / minorGridSize) * minorGridSize
+ return Qc.QPointF(x, y)
+ else:
+ raise Exception
+
+ def getAsyCoordinates(self):
+ canvasPosOrig = self.getCanvasCoordinates()
+ return canvasPosOrig, canvasPosOrig
+
+ def mouseMoveEvent(self, mouseEvent: Qg.QMouseEvent): # TODO: Actually refine grid snapping...
+ if not self.ui.imgLabel.underMouse() and not self.mouseDown:
+ return
+
+ self.updateMouseCoordLabel()
+ asyPos, canvasPos = self.getAsyCoordinates()
+
+ # add mode
+ if self.addMode is not None:
+ if self.addMode.active:
+ self.addMode.mouseMove(asyPos, mouseEvent)
+ self.quickUpdate()
+ return
+
+ # pan mode
+ if self.currentModeStack[-1] == SelectionMode.pan and int(mouseEvent.buttons()) and self.savedWindowMousePos is not None:
+ mousePos = self.getWindowCoordinates()
+ newPos = mousePos - self.savedWindowMousePos
+
+ tx, ty = newPos.x(), newPos.y()
+
+ if self.lockX:
+ tx = 0
+ if self.lockY:
+ ty = 0
+
+ self.panOffset[0] += tx
+ self.panOffset[1] += ty
+
+ self.savedWindowMousePos = self.getWindowCoordinates()
+ self.quickUpdate()
+ return
+
+ # otherwise, in transformation
+ if self.inMidTransformation:
+ if self.currentModeStack[-1] == SelectionMode.translate:
+ newPos = canvasPos - self.savedMousePosition
+ if self.gridSnap:
+ newPos = self.roundPositionSnap(newPos) # actually round to the nearest minor grid afterwards...
+
+ self.tx, self.ty = newPos.x(), newPos.y()
+
+ if self.lockX:
+ self.tx = 0
+ if self.lockY:
+ self.ty = 0
+ self.newTransform = Qg.QTransform.fromTranslate(self.tx, self.ty)
+
+ elif self.currentModeStack[-1] == SelectionMode.rotate:
+ if self.gridSnap:
+ canvasPos = self.roundPositionSnap(canvasPos)
+
+ adjustedSavedMousePos = self.savedMousePosition - self.currentAnchor
+ adjustedCanvasCoords = canvasPos - self.currentAnchor
+
+ origAngle = np.arctan2(adjustedSavedMousePos.y(), adjustedSavedMousePos.x())
+ newAng = np.arctan2(adjustedCanvasCoords.y(), adjustedCanvasCoords.x())
+ self.deltaAngle = newAng - origAngle
+ self.newTransform = xT.makeRotTransform(self.deltaAngle, self.currentAnchor).toQTransform()
+
+ elif self.currentModeStack[-1] == SelectionMode.scale:
+ if self.gridSnap:
+ canvasPos = self.roundPositionSnap(canvasPos)
+ x, y = int(round(canvasPos.x())), int(round(canvasPos.y())) # otherwise it crashes...
+ canvasPos = Qc.QPoint(x, y)
+
+ originalDeltaPts = self.savedMousePosition - self.currentAnchor
+ scaleFactor = Qc.QPointF.dotProduct(canvasPos - self.currentAnchor, originalDeltaPts) /\
+ (xu.twonorm((originalDeltaPts.x(), originalDeltaPts.y())) ** 2)
+ if not self.lockX:
+ self.scaleFactorX = scaleFactor
+ else:
+ self.scaleFactorX = 1
+
+ if not self.lockY:
+ self.scaleFactorY = scaleFactor
+ else:
+ self.scaleFactorY = 1
+
+ self.newTransform = xT.makeScaleTransform(self.scaleFactorX, self.scaleFactorY, self.currentAnchor).\
+ toQTransform()
+
+ self.quickUpdate()
+ return
+
+ # otherwise, select a candinate for selection
+
+ if self.currentlySelectedObj['selectedIndex'] is None:
+ selectedIndex, selKeyList = self.selectObject()
+ if selectedIndex is not None:
+ if self.pendingSelectedObjList != selKeyList:
+ self.pendingSelectedObjList = selKeyList
+ self.pendingSelectedObjIndex = -1
+ else:
+ self.pendingSelectedObjList.clear()
+ self.pendingSelectedObjIndex = -1
+ self.quickUpdate()
+ return
+
+
+ def mouseReleaseEvent(self, mouseEvent):
+ assert isinstance(mouseEvent, Qg.QMouseEvent)
+ if not self.mouseDown:
+ return
+
+ self.mouseDown = False
+ if self.addMode is not None:
+ self.addMode.mouseRelease()
+ if self.inMidTransformation:
+ self.clearSelection()
+ self.inMidTransformation = False
+ self.quickUpdate()
+
+ def clearSelection(self):
+ if self.currentlySelectedObj['selectedIndex'] is not None:
+ self.releaseTransform()
+ self.setAllInSetEnabled(self.objButtons, False)
+ self.currentlySelectedObj['selectedIndex'] = None
+ self.currentlySelectedObj['key'] = None
+
+ self.currentlySelectedObj['allSameKey'].clear()
+ self.newTransform = Qg.QTransform()
+ self.currentBoundingBox = None
+ self.quickUpdate()
+
+ def changeSelection(self, offset):
+ if self.pendingSelectedObjList:
+ if offset > 0:
+ if self.pendingSelectedObjIndex + offset <= -1:
+ self.pendingSelectedObjIndex = self.pendingSelectedObjIndex + offset
+ else:
+ if self.pendingSelectedObjIndex + offset >= -len(self.pendingSelectedObjList):
+ self.pendingSelectedObjIndex = self.pendingSelectedObjIndex + offset
+
+ def mouseWheel(self, rawAngleX: float, rawAngle: float, defaultModifiers: int=0):
+ keyModifiers = int(Qw.QApplication.keyboardModifiers())
+ keyModifiers = keyModifiers | defaultModifiers
+ if keyModifiers & int(Qc.Qt.ControlModifier):
+ oldMag = self.magnification
+
+ cx, cy = self.canvSize.width() / 2, self.canvSize.height() / 2
+ centerPoint = Qc.QPointF(cx, cy) * self.getScrsTransform().inverted()[0]
+
+ self.magnification += (rawAngle/100)
+
+ if self.magnification < self.settings['minimumMagnification']:
+ self.magnification = self.settings['minimumMagnification']
+ elif self.magnification > self.settings['maximumMagnification']:
+ self.magnification = self.settings['maximumMagnification']
+
+ # set the new pan. Let c be the fixed point (center point),
+ # Let m the old mag, n the new mag
+
+ # find t2 such that
+ # mc + t1 = nc + t2 ==> t2 = (m - n)c + t1
+
+ centerPoint = (oldMag - self.magnification) * centerPoint
+
+ self.panOffset = [
+ self.panOffset[0] + centerPoint.x(),
+ self.panOffset[1] + centerPoint.y()
+ ]
+
+ self.currAddOptions['magnification'] = self.magnification
+
+ if self.addMode is xbi.InteractiveBezierEditor:
+ self.addMode.setSelectionBoundaries()
+
+ elif keyModifiers & (int(Qc.Qt.ShiftModifier) | int(Qc.Qt.AltModifier)):
+ self.panOffset[1] += rawAngle/1
+ self.panOffset[0] -= rawAngleX/1
+ # handle scrolling
+ else:
+ # process selection layer change
+ if rawAngle >= 15:
+ self.changeSelection(1)
+ elif rawAngle <= -15:
+ self.changeSelection(-1)
+ self.quickUpdate()
+
+ def wheelEvent(self, event: Qg.QWheelEvent):
+ rawAngle = event.angleDelta().y() / 8
+ rawAngleX = event.angleDelta().x() / 8
+ self.mouseWheel(rawAngleX, rawAngle)
+
+ def selectOnHover(self):
+ """Returns True if selection happened, False otherwise.
+ """
+ if self.pendingSelectedObjList:
+ selectedIndex = self.pendingSelectedObjList[self.pendingSelectedObjIndex]
+ self.pendingSelectedObjList.clear()
+
+ maj, minor = selectedIndex
+
+ self.currentlySelectedObj['selectedIndex'] = selectedIndex
+ self.currentlySelectedObj['key'], self.currentlySelectedObj['allSameKey'] = self.selectObjectSet(
+ )
+
+ self.currentBoundingBox = self.drawObjects[maj][minor].boundingBox
+
+ if self.selectAsGroup:
+ for selItems in self.currentlySelectedObj['allSameKey']:
+ obj = self.drawObjects[selItems[0]][selItems[1]]
+ self.currentBoundingBox = self.currentBoundingBox.united(obj.boundingBox)
+
+ self.origBboxTransform = self.drawObjects[maj][minor].transform.toQTransform()
+ self.newTransform = Qg.QTransform()
+ return True
+ else:
+ return False
+
+ def mousePressEvent(self, mouseEvent: Qg.QMouseEvent):
+ # we make an exception for bezier curve
+ bezierException = False
+ if self.addMode is not None:
+ if self.addMode.active and isinstance(self.addMode, InplaceAddObj.AddBezierShape):
+ bezierException = True
+
+ if not self.ui.imgLabel.underMouse() and not bezierException:
+ return
+
+ self.mouseDown = True
+ asyPos, self.savedMousePosition = self.getAsyCoordinates()
+
+ if self.addMode is not None:
+ self.addMode.mouseDown(asyPos, self.currAddOptions, mouseEvent)
+ elif self.currentModeStack[-1] == SelectionMode.pan:
+ self.savedWindowMousePos = self.getWindowCoordinates()
+ elif self.currentModeStack[-1] == SelectionMode.setAnchor:
+ self.customAnchor = self.savedMousePosition
+ self.currentModeStack.pop()
+
+ self.anchorMode = AnchorMode.customAnchor
+ self.ui.comboAnchor.setCurrentIndex(AnchorMode.customAnchor)
+ self.updateChecks()
+ self.quickUpdate()
+ elif self.inMidTransformation:
+ pass
+ elif self.pendingSelectedObjList:
+ self.selectOnHover()
+
+ if self.currentModeStack[-1] in {SelectionMode.translate, SelectionMode.rotate, SelectionMode.scale}:
+ self.setAllInSetEnabled(self.objButtons, False)
+ self.inMidTransformation = True
+ self.setAnchor()
+ elif self.currentModeStack[-1] == SelectionMode.delete:
+ self.btnSelectiveDeleteOnClick()
+ elif self.currentModeStack[-1] == SelectionMode.selectEdit:
+ self.setupSelectEdit()
+ else:
+ self.setAllInSetEnabled(self.objButtons, True)
+ self.inMidTransformation = False
+ self.setAnchor()
+
+ else:
+ self.setAllInSetEnabled(self.objButtons, False)
+ self.currentBoundingBox = None
+ self.inMidTransformation = False
+ self.clearSelection()
+
+ self.quickUpdate()
+
+ def removeAddMode(self):
+ self.addMode = None
+ self.deleteAddOptions()
+
+ def editFinalized(self):
+ self.addMode.forceFinalize()
+ self.removeAddMode()
+ self.fileChanged = True
+ self.quickUpdate()
+
+ def editRejected(self):
+ self.addMode.resetObj()
+ self.editFinalized()
+
+ def setupSelectEdit(self):
+ """For Select-Edit mode. For now, if the object selected is a bezier curve, opens up a bezier editor"""
+ maj, minor = self.currentlySelectedObj['selectedIndex']
+ obj = self.fileItems[maj]
+ if isinstance(obj, x2a.xasyDrawnItem):
+ # bezier path
+ self.addMode = xbi.InteractiveBezierEditor(self, obj, self.currAddOptions)
+ self.addMode.objectUpdated.connect(self.objectUpdated)
+ self.addMode.editAccepted.connect(self.editFinalized)
+ self.addMode.editRejected.connect(self.editRejected)
+ self.updateOptionWidget()
+ self.currentModeStack[-1] = SelectionMode.selectEdit
+ self.fileChanged = True
+ else:
+ self.clearSelection()
+ self.quickUpdate()
+
+ def setAnchor(self):
+ if self.anchorMode == AnchorMode.center:
+ self.currentAnchor = self.currentBoundingBox.center()
+ elif self.anchorMode == AnchorMode.topLeft:
+ self.currentAnchor = self.currentBoundingBox.bottomLeft() # due to internal image being flipped
+ elif self.anchorMode == AnchorMode.topRight:
+ self.currentAnchor = self.currentBoundingBox.bottomRight()
+ elif self.anchorMode == AnchorMode.bottomLeft:
+ self.currentAnchor = self.currentBoundingBox.topLeft()
+ elif self.anchorMode == AnchorMode.bottomRight:
+ self.currentAnchor = self.currentBoundingBox.topRight()
+ elif self.anchorMode == AnchorMode.customAnchor:
+ self.currentAnchor = self.customAnchor
+ else:
+ self.currentAnchor = Qc.QPointF(0, 0)
+
+ if self.anchorMode != AnchorMode.origin:
+ pass
+ # TODO: Record base points/bbox before hand and use that for
+ # anchor?
+ # adjTransform =
+ # self.drawObjects[selectedIndex].transform.toQTransform()
+ # self.currentAnchor = adjTransform.map(self.currentAnchor)
+
+
+ def releaseTransform(self):
+ if self.newTransform.isIdentity():
+ return
+ newTransform = x2a.asyTransform.fromQTransform(self.newTransform)
+ objKey = self.currentlySelectedObj['selectedIndex']
+ self.addTransformationChanges(objKey, newTransform, not self.useGlobalCoords)
+ self.transformObject(objKey, newTransform, not self.useGlobalCoords)
+
+ def adjustTransform(self, appendTransform):
+ self.screenTransformation = self.screenTransformation * appendTransform
+
+ def createMainCanvas(self):
+ self.canvSize = self.ui.imgFrame.size()
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+ x, y = self.canvSize.width() / 2, self.canvSize.height() / 2
+
+ self.canvasPixmap = Qg.QPixmap(self.canvSize)
+ self.canvasPixmap.fill()
+
+ self.finalPixmap = Qg.QPixmap(self.canvSize)
+
+ self.preCanvasPixmap = Qg.QPixmap(self.canvSize)
+ self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
+
+ self.mainCanvas = Qg.QPainter(self.canvasPixmap)
+ self.mainCanvas.setRenderHint(Qg.QPainter.Antialiasing)
+ self.mainCanvas.setRenderHint(Qg.QPainter.SmoothPixmapTransform)
+ self.mainCanvas.setRenderHint(Qg.QPainter.HighQualityAntialiasing)
+ self.xasyDrawObj['canvas'] = self.mainCanvas
+
+ self.mainTransformation = Qg.QTransform()
+ self.mainTransformation.scale(1, 1)
+ self.mainTransformation.translate(x, y)
+
+ self.mainCanvas.setTransform(self.getScrsTransform(), True)
+
+ self.ui.imgLabel.setPixmap(self.canvasPixmap)
+
+ def resetPan(self):
+ self.panOffset = [0, 0]
+ self.quickUpdate()
+
+ def btnPanCenterOnClick(self):
+ newCenter = self.getAllBoundingBox().center()
+
+ # adjust to new magnification
+ # technically, doable through getscrstransform()
+ # and subtract pan offset and center points
+ # but it's much more work...
+ newCenter = self.magnification * newCenter
+ self.panOffset = [-newCenter.x(), newCenter.y()]
+
+ self.quickUpdate()
+
+ def selectObject(self):
+ if not self.ui.imgLabel.underMouse():
+ return None, []
+ canvasCoords = self.getCanvasCoordinates()
+ highestDrawPriority = -np.inf
+ collidedObjKey = None
+ rawObjNumList = []
+ for objKeyMaj in range(len(self.drawObjects)):
+ for objKeyMin in range(len(self.drawObjects[objKeyMaj])):
+ obj = self.drawObjects[objKeyMaj][objKeyMin]
+ if obj.collide(canvasCoords) and (obj.key, obj.keyIndex) not in self.hiddenKeys:
+ rawObjNumList.append(((objKeyMaj, objKeyMin), obj.drawOrder))
+ if obj.drawOrder > highestDrawPriority:
+ collidedObjKey = (objKeyMaj, objKeyMin)
+ if collidedObjKey is not None:
+ rawKey = self.drawObjects[collidedObjKey[0]][collidedObjKey[1]].key
+# self.ui.statusbar.showMessage('Collide with {0}, Key is {1}'.format(str(collidedObjKey), rawKey), 2500)
+ self.ui.statusbar.showMessage('Key: {0}'.format(rawKey), 2500)
+ return collidedObjKey, [rawObj[0] for rawObj in sorted(rawObjNumList, key=lambda ordobj: ordobj[1])]
+ else:
+ return None, []
+
+ def selectObjectSet(self):
+ objKey = self.currentlySelectedObj['selectedIndex']
+ if objKey is None:
+ return set()
+ assert isinstance(objKey, (tuple, list)) and len(objKey) == 2
+ rawObj = self.drawObjects[objKey[0]][objKey[1]]
+ rawKey = rawObj.key
+ rawSet = {objKey}
+ for objKeyMaj in range(len(self.drawObjects)):
+ for objKeyMin in range(len(self.drawObjects[objKeyMaj])):
+ obj = self.drawObjects[objKeyMaj][objKeyMin]
+ if obj.key == rawKey:
+ rawSet.add((objKeyMaj, objKeyMin))
+ return rawKey, rawSet
+
+ def getCanvasCoordinates(self):
+ # assert self.ui.imgLabel.underMouse()
+ uiPos = self.mapFromGlobal(Qg.QCursor.pos())
+ canvasPos = self.ui.imgLabel.mapFrom(self, uiPos)
+
+ # Issue: For magnification, should xasy treats this at xasy level, or asy level?
+ return canvasPos * self.getScrsTransform().inverted()[0]
+
+ def getWindowCoordinates(self):
+ # assert self.ui.imgLabel.underMouse()
+ return self.mapFromGlobal(Qg.QCursor.pos())
+
+ def refreshCanvas(self):
+ if self.mainCanvas.isActive():
+ self.mainCanvas.end()
+ self.mainCanvas.begin(self.canvasPixmap)
+ self.mainCanvas.setTransform(self.getScrsTransform())
+
+ def asyfyCanvas(self, force=False):
+ self.drawObjects = []
+ self.populateCanvasWithItems(force)
+ self.quickUpdate()
+ if self.currentModeStack[-1] == SelectionMode.translate:
+ self.ui.statusbar.showMessage(self.strings.asyfyComplete)
+
+ def updateMouseCoordLabel(self):
+ *args, canvasPos = self.getAsyCoordinates()
+ nx, ny = self.asy2psmap.inverted() * (canvasPos.x(), canvasPos.y())
+ self.coordLabel.setText('{0:.2f}, {1:.2f} '.format(nx, ny))
+
+ def quickUpdate(self):
+ self.updateMouseCoordLabel()
+ self.refreshCanvas()
+
+ self.preDraw(self.mainCanvas)
+ self.quickDraw()
+
+ self.mainCanvas.end()
+ self.postDraw()
+ self.updateScreen()
+
+ def quickDraw(self):
+ assert self.isReady()
+ dpi = self.magnification * self.dpi
+ activeItem = None
+ for majorItem in self.drawObjects:
+ for item in majorItem:
+ # hidden objects - toggleable
+ if (item.key, item.keyIndex) in self.hiddenKeys:
+ continue
+ isSelected = item.key == self.currentlySelectedObj['key']
+ if not self.selectAsGroup and isSelected and self.currentlySelectedObj['selectedIndex'] is not None:
+ maj, min_ = self.currentlySelectedObj['selectedIndex']
+ isSelected = isSelected and item is self.drawObjects[maj][min_]
+ if isSelected and self.settings['enableImmediatePreview']:
+ activeItem = item
+ if self.useGlobalCoords:
+ item.draw(self.newTransform, canvas=self.mainCanvas, dpi=dpi)
+ else:
+ item.draw(self.newTransform, applyReverse=True, canvas=self.mainCanvas, dpi=dpi)
+ else:
+ item.draw(canvas=self.mainCanvas, dpi=dpi)
+
+ if self.settings['drawSelectedOnTop']:
+ if self.pendingSelectedObjList:
+ maj, minor = self.pendingSelectedObjList[self.pendingSelectedObjIndex]
+ self.drawObjects[maj][minor].draw(canvas=self.mainCanvas, dpi=dpi)
+ # and apply the preview too...
+ elif activeItem is not None:
+ if self.useGlobalCoords:
+ activeItem.draw(self.newTransform, canvas=self.mainCanvas, dpi=dpi)
+ else:
+ activeItem.draw(self.newTransform, applyReverse=True, canvas=self.mainCanvas, dpi=dpi)
+ activeItem = None
+
+ def updateScreen(self):
+ self.finalPixmap = Qg.QPixmap(self.canvSize)
+ self.finalPixmap.fill(Qc.Qt.black)
+ with Qg.QPainter(self.finalPixmap) as finalPainter:
+ drawPoint = Qc.QPoint(0, 0)
+ # finalPainter.drawPixmap(drawPoint, self.preCanvasPixmap)
+ finalPainter.drawPixmap(drawPoint, self.canvasPixmap)
+ finalPainter.drawPixmap(drawPoint, self.postCanvasPixmap)
+ self.ui.imgLabel.setPixmap(self.finalPixmap)
+
+ def drawCartesianGrid(self, preCanvas):
+ majorGrid = self.settings['gridMajorAxesSpacing'] * self.asy2psmap.xx
+ minorGridCount = self.settings['gridMinorAxesCount']
+
+ majorGridCol = Qg.QColor(self.settings['gridMajorAxesColor'])
+ minorGridCol = Qg.QColor(self.settings['gridMinorAxesColor'])
+
+ panX, panY = self.panOffset
+
+ x_range = (self.canvSize.width() / 2 + (2 * abs(panX)))/self.magnification
+ y_range = (self.canvSize.height() / 2 + (2 * abs(panY)))/self.magnification
+
+ for x in np.arange(0, 2 * x_range + 1, majorGrid): # have to do
+ # this in two stages...
+ preCanvas.setPen(minorGridCol)
+ for xMinor in range(1, minorGridCount + 1):
+ xCoord = x + ((xMinor / (minorGridCount + 1)) * majorGrid)
+ preCanvas.drawLine(Qc.QLine(xCoord, -9999, xCoord, 9999))
+ preCanvas.drawLine(Qc.QLine(-xCoord, -9999, -xCoord, 9999))
+
+ for y in np.arange(0, 2 * y_range + 1, majorGrid):
+ preCanvas.setPen(minorGridCol)
+ for yMinor in range(1, minorGridCount + 1):
+ yCoord = y + ((yMinor / (minorGridCount + 1)) * majorGrid)
+ preCanvas.drawLine(Qc.QLine(-9999, yCoord, 9999, yCoord))
+ preCanvas.drawLine(Qc.QLine(-9999, -yCoord, 9999, -yCoord))
+
+ preCanvas.setPen(majorGridCol)
+ preCanvas.drawLine(Qc.QLine(-9999, y, 9999, y))
+ preCanvas.drawLine(Qc.QLine(-9999, -y, 9999, -y))
+
+ for x in np.arange(0, 2 * x_range + 1, majorGrid):
+ preCanvas.setPen(majorGridCol)
+ preCanvas.drawLine(Qc.QLine(x, -9999, x, 9999))
+ preCanvas.drawLine(Qc.QLine(-x, -9999, -x, 9999))
+
+ def drawPolarGrid(self, preCanvas):
+ center = Qc.QPointF(0, 0)
+ majorGridCol = Qg.QColor(self.settings['gridMajorAxesColor'])
+ minorGridCol = Qg.QColor(self.settings['gridMinorAxesColor'])
+ majorGrid = self.settings['gridMajorAxesSpacing']
+ minorGridCount = self.settings['gridMinorAxesCount']
+
+ majorAxisAng = (np.pi/4) # 45 degrees - for now.
+ minorAxisCount = 2 # 15 degrees each
+
+ subRadiusSize = int(round((majorGrid / (minorGridCount + 1))))
+ subAngleSize = majorAxisAng / (minorAxisCount + 1)
+
+ for radius in range(majorGrid, 9999 + 1, majorGrid):
+ preCanvas.setPen(majorGridCol)
+ preCanvas.drawEllipse(center, radius, radius)
+
+ preCanvas.setPen(minorGridCol)
+
+ for minorRing in range(minorGridCount):
+ subRadius = round(radius - (subRadiusSize * (minorRing + 1)))
+ preCanvas.drawEllipse(center, subRadius, subRadius)
+
+ currAng = majorAxisAng
+ while currAng <= (2 * np.pi):
+ preCanvas.setPen(majorGridCol)
+ p1 = center + (9999 * Qc.QPointF(np.cos(currAng), np.sin(currAng)))
+ preCanvas.drawLine(Qc.QLineF(center, p1))
+
+ preCanvas.setPen(minorGridCol)
+ for minorAngLine in range(minorAxisCount):
+ newAng = currAng - (subAngleSize * (minorAngLine + 1))
+ p1 = center + (9999 * Qc.QPointF(np.cos(newAng), np.sin(newAng)))
+ preCanvas.drawLine(Qc.QLineF(center, p1))
+
+ currAng = currAng + majorAxisAng
+
+ def preDraw(self, painter):
+ # self.preCanvasPixmap.fill(Qc.Qt.white)
+ self.canvasPixmap.fill()
+ preCanvas = painter
+
+ # preCanvas = Qg.QPainter(self.preCanvasPixmap)
+ preCanvas.setTransform(self.getScrsTransform())
+
+ if self.drawAxes:
+ preCanvas.setPen(Qc.Qt.gray)
+ preCanvas.drawLine(Qc.QLine(-9999, 0, 9999, 0))
+ preCanvas.drawLine(Qc.QLine(0, -9999, 0, 9999))
+
+ if self.drawGrid:
+ if self.drawGridMode == GridMode.cartesian:
+ self.drawCartesianGrid(painter)
+ elif self.drawGridMode == GridMode.polar:
+ self.drawPolarGrid(painter)
+
+ if self.currentGuides:
+ for guide in self.currentGuides:
+ guide.drawShape(preCanvas)
+ # preCanvas.end()
+
+ def drawAddModePreview(self, painter):
+ if self.addMode is not None:
+ if self.addMode.active:
+ # Preview Object
+ if self.addMode.getPreview() is not None:
+ painter.setPen(self.currentPen.toQPen())
+ painter.drawPath(self.addMode.getPreview())
+ self.addMode.postDrawPreview(painter)
+
+
+ def drawTransformPreview(self, painter):
+ if self.currentBoundingBox is not None and self.currentlySelectedObj['selectedIndex'] is not None:
+ painter.save()
+ maj, minor = self.currentlySelectedObj['selectedIndex']
+ selObj = self.drawObjects[maj][minor]
+ if not self.useGlobalCoords:
+ painter.save()
+ painter.setTransform(
+ selObj.transform.toQTransform(), True)
+ # painter.setTransform(selObj.baseTransform.toQTransform(), True)
+ painter.setPen(Qc.Qt.gray)
+ painter.drawLine(Qc.QLine(-9999, 0, 9999, 0))
+ painter.drawLine(Qc.QLine(0, -9999, 0, 9999))
+ painter.setPen(Qc.Qt.black)
+ painter.restore()
+
+ painter.setTransform(selObj.getInteriorScrTransform(
+ self.newTransform).toQTransform(), True)
+ painter.drawRect(selObj.localBoundingBox)
+ else:
+ painter.setTransform(self.newTransform, True)
+ painter.drawRect(self.currentBoundingBox)
+ painter.restore()
+
+ def postDraw(self):
+ self.postCanvasPixmap.fill(Qc.Qt.transparent)
+ with Qg.QPainter(self.postCanvasPixmap) as postCanvas:
+ postCanvas.setRenderHints(self.mainCanvas.renderHints())
+ postCanvas.setTransform(self.getScrsTransform())
+
+ self.drawTransformPreview(postCanvas)
+
+ if self.pendingSelectedObjList:
+ maj, minor = self.pendingSelectedObjList[self.pendingSelectedObjIndex]
+ postCanvas.drawRect(self.drawObjects[maj][minor].boundingBox)
+
+ self.drawAddModePreview(postCanvas)
+
+ if self.customAnchor is not None and self.anchorMode == AnchorMode.customAnchor:
+ self.drawAnchorCursor(postCanvas)
+
+ # postCanvas.drawRect(self.getAllBoundingBox())
+
+ def drawAnchorCursor(self, painter):
+ painter.drawEllipse(self.customAnchor, 6, 6)
+ newCirclePath = Qg.QPainterPath()
+ newCirclePath.addEllipse(self.customAnchor, 2, 2)
+
+ painter.fillPath(newCirclePath, Qg.QColor.fromRgb(0, 0, 0))
+
+ def updateModeBtnsOnly(self):
+ if self.currentModeStack[-1] == SelectionMode.translate:
+ activeBtn = self.ui.btnTranslate
+ elif self.currentModeStack[-1] == SelectionMode.rotate:
+ activeBtn = self.ui.btnRotate
+ elif self.currentModeStack[-1] == SelectionMode.scale:
+ activeBtn = self.ui.btnScale
+ elif self.currentModeStack[-1] == SelectionMode.pan:
+ activeBtn = self.ui.btnPan
+ elif self.currentModeStack[-1] == SelectionMode.setAnchor:
+ activeBtn = self.ui.btnAnchor
+ elif self.currentModeStack[-1] == SelectionMode.delete:
+ activeBtn = self.ui.btnDeleteMode
+ elif self.currentModeStack[-1] == SelectionMode.selectEdit:
+ activeBtn = self.ui.btnSelectEdit
+ else:
+ activeBtn = None
+
+
+ disableFill = isinstance(self.addMode, InplaceAddObj.AddBezierShape) and not self.currAddOptions['closedPath']
+ self.ui.btnFill.setEnabled(not disableFill)
+ if disableFill and self.ui.btnFill.isEnabled():
+ self.ui.btnFill.setChecked(not disableFill)
+
+
+ for button in self.modeButtons:
+ button.setChecked(button is activeBtn)
+
+ def updateChecks(self):
+ self.removeAddMode()
+ self.updateModeBtnsOnly()
+ self.quickUpdate()
+
+ def btnAlignXOnClick(self, checked):
+ self.lockY = checked
+ if self.lockX:
+ self.lockX = False
+ self.ui.btnAlignY.setChecked(False)
+
+ def btnAlignYOnClick(self, checked):
+ self.lockX = checked
+ if self.lockY:
+ self.lockY = False
+ self.ui.btnAlignX.setChecked(False)
+
+ def btnAnchorModeOnClick(self):
+ if self.currentModeStack[-1] != SelectionMode.setAnchor:
+ self.currentModeStack.append(SelectionMode.setAnchor)
+ self.updateChecks()
+
+ def switchToAnchorMode(self):
+ if self.currentModeStack[-1] != SelectionMode.setAnchor:
+ self.currentModeStack.append(SelectionMode.setAnchor)
+ self.updateChecks()
+
+ def btnTranslateonClick(self):
+ self.currentModeStack = [SelectionMode.translate]
+ self.ui.statusbar.showMessage('Translate mode')
+ self.clearSelection()
+ self.updateChecks()
+
+ def btnRotateOnClick(self):
+ self.currentModeStack = [SelectionMode.rotate]
+ self.ui.statusbar.showMessage('Rotate mode')
+ self.clearSelection()
+ self.updateChecks()
+
+ def btnScaleOnClick(self):
+ self.currentModeStack = [SelectionMode.scale]
+ self.ui.statusbar.showMessage('Scale mode')
+ self.clearSelection()
+ self.updateChecks()
+
+ def btnPanOnClick(self):
+ self.currentModeStack = [SelectionMode.pan]
+ self.ui.statusbar.showMessage('Pan mode')
+ self.clearSelection()
+ self.updateChecks()
+
+ def btnWorldCoordsOnClick(self, checked):
+ self.useGlobalCoords = checked
+ if not self.useGlobalCoords:
+ self.ui.comboAnchor.setCurrentIndex(AnchorMode.origin)
+ self.setAllInSetEnabled(self.globalTransformOnlyButtons, checked)
+
+ def setAllInSetEnabled(self, widgetSet, enabled):
+ for widget in widgetSet:
+ widget.setEnabled(enabled)
+
+ def btnDrawAxesOnClick(self, checked):
+ self.drawAxes = checked
+ self.quickUpdate()
+
+ def btnDrawGridOnClick(self, checked):
+ self.drawGrid = checked
+ self.quickUpdate()
+
+ def btnCustTransformOnClick(self):
+ matrixDialog = CustMatTransform.CustMatTransform()
+ matrixDialog.show()
+ result = matrixDialog.exec_()
+ if result == Qw.QDialog.Accepted:
+ objKey = self.currentlySelectedObj['selectedIndex']
+ self.transformObject(objKey,
+ matrixDialog.getTransformationMatrix(), not
+ self.useGlobalCoords)
+
+ # for now, unless we update the bouding box transformation.
+ self.clearSelection()
+ self.quickUpdate()
+
+ def btnLoadEditorOnClick(self):
+ if self.fileChanged:
+ save = "Save current file?"
+ reply = Qw.QMessageBox.question(self, 'Message', save, Qw.QMessageBox.Yes,
+ Qw.QMessageBox.No)
+ if reply == Qw.QMessageBox.Yes:
+ self.actionSave()
+
+ rawExternalEditor = self.settings['externalEditor']
+ rawExtEditorArgs = self.settings['externalEditorArgs']
+ execEditor = [rawExternalEditor]
+
+ for arg in rawExtEditorArgs:
+ execEditor.append(string.Template(
+ arg).substitute(asypath=(self.filename)))
+
+ subprocess.Popen(args=execEditor)
+
+ def btnAddCodeOnClick(self):
+ header = """
+// xasy object created at $time
+// Object Number: $uid
+// This header is automatically generated by xasy.
+// Your code here
+"""
+ header = string.Template(header).substitute(time=str(datetime.datetime.now()), uid=str(self.globalObjectCounter))
+
+ with tempfile.TemporaryDirectory() as tmpdir:
+ newPath = os.path.join(tmpdir, 'tmpcode.asy')
+ f = io.open(newPath, 'w')
+ f.write(header)
+ f.close()
+
+ subprocess.run(args=self.getExternalEditor(asypath=newPath))
+
+ f = io.open(newPath, 'r')
+ newItem = x2a.xasyScript(engine=self.asyEngine, canvas=self.xasyDrawObj)
+ newItem.setScript(f.read())
+ f.close()
+
+ # newItem.replaceKey(str(self.globalObjectCounter) + ':')
+ self.fileItems.append(newItem)
+ self.addObjCreationUrs(newItem)
+ self.asyfyCanvas()
+
+ self.globalObjectCounter = self.globalObjectCounter + 1
+ def softDeleteObj(self, objKey):
+ maj, minor = objKey
+ drawObj = self.drawObjects[maj][minor]
+ item = drawObj.originalObj
+ key = drawObj.key
+ keyIndex = drawObj.keyIndex
+
+
+ item.transfKeymap[key][keyIndex].deleted = True
+ # item.asyfied = False
+
+ def getSelectedObjInfo(self, objIndex):
+ maj, minor = objIndex
+ drawObj = self.drawObjects[maj][minor]
+ item = drawObj.originalObj
+ key = drawObj.key
+ keyIndex = drawObj.keyIndex
+
+ return item, key, keyIndex
+
+ def transformObjKey(self, item, key, keyIndex, transform, applyFirst=False, drawObj=None):
+ if isinstance(transform, np.ndarray):
+ obj_transform = x2a.asyTransform.fromNumpyMatrix(transform)
+ elif isinstance(transform, Qg.QTransform):
+ assert transform.isAffine()
+ obj_transform = x2a.asyTransform.fromQTransform(transform)
+ else:
+ obj_transform = transform
+
+ scr_transform = obj_transform
+
+ if not applyFirst:
+ item.transfKeymap[key][keyIndex] = obj_transform * \
+ item.transfKeymap[key][keyIndex]
+ if drawObj is not None:
+ drawObj.transform = scr_transform * drawObj.transform
+ else:
+ item.transfKeymap[key][keyIndex] = item.transfKeymap[key][keyIndex] * obj_transform
+ if drawObj is not None:
+ drawObj.transform = drawObj.transform * scr_transform
+
+ if self.selectAsGroup:
+ for (maj2, min2) in self.currentlySelectedObj['allSameKey']:
+ if (maj2, min2) == (maj, minor):
+ continue
+ obj = self.drawObjects[maj2][min2]
+ newIndex = obj.keyIndex
+ if not applyFirst:
+ item.transfKeymap[key][newIndex] = obj_transform * \
+ item.transfKeymap[key][newIndex]
+ obj.transform = scr_transform * obj.transform
+ else:
+ item.transfKeymap[key][newIndex] = item.transfKeymap[key][newIndex] * obj_transform
+ obj.transform = obj.transform * scr_transform
+
+ self.fileChanged = True
+ self.quickUpdate()
+
+ def transformObject(self, objKey, transform, applyFirst=False):
+ maj, minor = objKey
+ drawObj = self.drawObjects[maj][minor]
+ item, key, keyIndex = self.getSelectedObjInfo(objKey)
+ self.transformObjKey(item, key, keyIndex, transform, applyFirst, drawObj)
+
+ def initializeEmptyFile(self):
+ pass
+
+ def getExternalEditor(self, **kwargs) -> str:
+ rawExternalEditor = self.settings['externalEditor']
+ rawExtEditorArgs = self.settings['externalEditorArgs']
+ execEditor = [rawExternalEditor]
+
+ for arg in rawExtEditorArgs:
+ execEditor.append(string.Template(arg).substitute(**kwargs))
+
+ return execEditor
+
+
+ def loadFile(self, name):
+ filename = os.path.abspath(name)
+ if not os.path.isfile(filename):
+ filename = filename + '.asy'
+
+ if not os.path.isfile(filename):
+ self.ui.statusbar.showMessage('File {0} not found'.format(filename))
+ return
+
+ self.ui.statusbar.showMessage('Load {0}'.format(filename))
+ self.filename = filename
+ self.currDir = os.path.dirname(self.filename)
+
+ self.erase()
+
+ f = open(self.filename, 'rt')
+ try:
+ rawFileStr = f.read()
+ except IOError:
+ Qw.QMessageBox.critical(self, self.strings.fileOpenFailed, self.strings.fileOpenFailedText)
+ else:
+ rawText, transfDict, maxKey = xf.extractTransformsFromFile(rawFileStr)
+ item = x2a.xasyScript(canvas=self.xasyDrawObj, engine=self.asyEngine, transfKeyMap=transfDict)
+
+ item.setScript(rawText)
+ self.fileItems.append(item)
+ self.asyfyCanvas(True)
+
+ maxKey2 = item.getMaxKeyCounter()
+ self.asy2psmap = item.asy2psmap
+ self.globalObjectCounter = max(maxKey + 1, maxKey2)
+ finally:
+ f.close()
+
+ def populateCanvasWithItems(self, forceUpdate=False):
+ self.itemCount = 0
+ for item in self.fileItems:
+ self.drawObjects.append(item.generateDrawObjects(forceUpdate))
Property changes on: trunk/Build/source/utils/asymptote/GUI/Window1.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/__init__.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/__init__.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/__init__.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1 @@
+#!/usr/bin/env python3
\ No newline at end of file
Property changes on: trunk/Build/source/utils/asymptote/GUI/__init__.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/configs/__init__.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/configs/__init__.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/configs/__init__.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1 @@
+#!/usr/bin/env python3
\ No newline at end of file
Property changes on: trunk/Build/source/utils/asymptote/GUI/configs/__init__.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,57 @@
+# Default Options for xasy
+
+# External editor. $asypath will be replaced by the current file.
+externalEditor: "emacs"
+externalEditorArgs: ["$asypath"]
+
+# Path to Asymptote executable
+asyPath: "asy"
+
+# Overwrites the ASYMPTOTE_DIR Environment variable if set. Otherwise, leaves asymptote to decide.
+asyBaseLocation: null
+
+# Show Debugging Information
+showDebug: false
+
+# Default Pen Options
+defaultPenOptions: ""
+
+# Default Pen Color
+defaultPenColor: "#000000"
+
+#
+defaultPenWidth: 0.5
+useLegacyDrawMode: false
+enableImmediatePreview: true
+useDegrees: false
+groupObjDefault: false
+
+#
+terminalFont: "Courier"
+terminalFontSize: 9
+
+#
+defaultShowAxes: true
+defaultShowGrid: false
+defaultGridSnap: false
+
+# Draw Selected Objects on top of the frame
+drawSelectedOnTop: true
+
+# Grid Settings
+
+gridMajorAxesColor: "#858585"
+gridMinorAxesColor: "#dddddd"
+gridMajorAxesSpacing: 5
+gridMinorAxesCount: 9
+
+# Magnification Settings
+minimumMagnification: 0.01
+maximumMagnification: 100
+
+# Debug Mode
+debugMode: true
+
+# Settings Override for Windows
+windows:
+ externalEditor: "notepad.exe"
Added: trunk/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,24 @@
+# Default Keymaps for xasy
+
+commandPalette: "Ctrl+P"
+quit: "Ctrl+Q"
+deleteObject: "Del"
+
+finalizeCurve: "Space"
+finalizeCurveClosed: "c"
+
+anchorMode: "Ctrl+A"
+
+undo: 'Ctrl+Z'
+redo: 'Ctrl+Y'
+
+moveUp: 'Up'
+moveDown: 'Down'
+
+scrollUp: 'Shift+Up'
+scrollDown: 'Shift+Down'
+scrollLeft: 'Shift+Left'
+scrollRight: 'Shift+Right'
+
+zoomIn: 'Ctrl+Up'
+zoomOut: 'Ctrl+Down'
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/icon-list.txt
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/icon-list.txt (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/icon-list.txt 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1 @@
+https://superdevresources.com/free-svg-icons/
\ No newline at end of file
Property changes on: trunk/Build/source/utils/asymptote/GUI/icon-list.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/icons_rc.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/icons_rc.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/icons_rc.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,2680 @@
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created by: The Resource Compiler for PyQt5 (Qt v5.10.1)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x04\x10\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\x76\x65\x72\x73\
+\x69\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\
+\x38\x33\x20\x31\x38\x2e\x37\x35\x20\x31\x38\x2e\x37\x35\x27\x20\
+\x77\x69\x64\x74\x68\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\
+\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x27\x3e\x0a\x3c\
+\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\
+\x20\x36\x33\x2e\x32\x33\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\
+\x68\x20\x64\x3d\x27\x4d\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x20\
+\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\x34\
+\x20\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\
+\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\x38\x2e\x36\
+\x35\x37\x33\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\
+\x38\x2e\x36\x35\x37\x33\x34\x20\x38\x2e\x36\x35\x37\x33\x34\x5a\
+\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\
+\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\
+\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\
+\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\
+\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x35\x30\x35\x36\x32\x27\
+\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\
+\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\
+\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\x20\x36\x33\x2e\x32\x33\
+\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\
+\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x20\x2d\x30\x4c\x20\x38\x2e\
+\x36\x35\x37\x33\x34\x20\x30\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\
+\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\
+\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\
+\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\
+\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\
+\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\
+\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\
+\x2e\x35\x30\x35\x36\x32\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\
+\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\
+\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\
+\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x37\x38\x34\
+\x34\x20\x36\x33\x2e\x32\x33\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\
+\x74\x68\x20\x64\x3d\x27\x4d\x20\x30\x20\x38\x2e\x36\x35\x37\x33\
+\x34\x4c\x20\x30\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x27\x20\x66\
+\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\
+\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\
+\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\
+\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\
+\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\
+\x64\x74\x68\x3d\x27\x31\x2e\x35\x30\x35\x36\x32\x27\x2f\x3e\x0a\
+\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\xc9\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\
+\x3d\x22\x34\x38\x30\x2c\x32\x35\x36\x20\x33\x38\x34\x2c\x31\x36\
+\x30\x20\x33\x38\x34\x2c\x32\x33\x36\x20\x32\x37\x36\x2c\x32\x33\
+\x36\x20\x32\x37\x36\x2c\x31\x32\x38\x20\x33\x35\x32\x2c\x31\x32\
+\x38\x20\x32\x35\x36\x2c\x33\x32\x20\x31\x36\x30\x2c\x31\x32\x38\
+\x20\x32\x33\x36\x2c\x31\x32\x38\x20\x32\x33\x36\x2c\x32\x33\x36\
+\x20\x31\x32\x38\x2c\x32\x33\x36\x20\x31\x32\x38\x2c\x31\x36\x30\
+\x20\x33\x32\x2c\x32\x35\x36\x20\x31\x32\x38\x2c\x33\x35\x32\x20\
+\x0d\x0a\x09\x31\x32\x38\x2c\x32\x37\x36\x20\x32\x33\x36\x2c\x32\
+\x37\x36\x20\x32\x33\x36\x2c\x33\x38\x34\x20\x31\x36\x30\x2c\x33\
+\x38\x34\x20\x32\x35\x36\x2c\x34\x38\x30\x20\x33\x35\x32\x2c\x33\
+\x38\x34\x20\x32\x37\x35\x2e\x38\x2c\x33\x38\x34\x20\x32\x37\x35\
+\x2e\x34\x2c\x32\x37\x35\x2e\x35\x20\x33\x38\x34\x2c\x32\x37\x35\
+\x2e\x38\x20\x33\x38\x34\x2c\x33\x35\x32\x20\x22\x2f\x3e\x0d\x0a\
+\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x93\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4d\x61\x67\x6e\x69\x66\x79\x69\x6e\x67\x5f\x67\x6c\x61\
+\x73\x73\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x79\x3d\x22\
+\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\
+\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\x62\x6c\x65\x2d\
+\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\x6e\x65\x77\x20\
+\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\x6d\x6c\x3a\x73\
+\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\
+\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x37\x2e\x35\
+\x34\x35\x2c\x31\x35\x2e\x34\x36\x37\x6c\x2d\x33\x2e\x37\x37\x39\
+\x2d\x33\x2e\x37\x37\x39\x63\x30\x2e\x35\x37\x2d\x30\x2e\x39\x33\
+\x35\x2c\x30\x2e\x38\x39\x38\x2d\x32\x2e\x30\x33\x35\x2c\x30\x2e\
+\x38\x39\x38\x2d\x33\x2e\x32\x31\x63\x30\x2d\x33\x2e\x34\x31\x37\
+\x2d\x32\x2e\x39\x36\x31\x2d\x36\x2e\x33\x37\x37\x2d\x36\x2e\x33\
+\x37\x38\x2d\x36\x2e\x33\x37\x37\x0d\x0a\x09\x43\x34\x2e\x38\x36\
+\x39\x2c\x32\x2e\x31\x2c\x32\x2e\x31\x2c\x34\x2e\x38\x37\x2c\x32\
+\x2e\x31\x2c\x38\x2e\x32\x38\x37\x63\x30\x2c\x33\x2e\x34\x31\x36\
+\x2c\x32\x2e\x39\x36\x31\x2c\x36\x2e\x33\x37\x37\x2c\x36\x2e\x33\
+\x37\x37\x2c\x36\x2e\x33\x37\x37\x63\x31\x2e\x31\x33\x37\x2c\x30\
+\x2c\x32\x2e\x32\x2d\x30\x2e\x33\x30\x39\x2c\x33\x2e\x31\x31\x35\
+\x2d\x30\x2e\x38\x34\x34\x6c\x33\x2e\x37\x39\x39\x2c\x33\x2e\x38\
+\x30\x31\x0d\x0a\x09\x63\x30\x2e\x33\x37\x32\x2c\x30\x2e\x33\x37\
+\x31\x2c\x30\x2e\x39\x37\x35\x2c\x30\x2e\x33\x37\x31\x2c\x31\x2e\
+\x33\x34\x36\x2c\x30\x6c\x30\x2e\x39\x34\x33\x2d\x30\x2e\x39\x34\
+\x33\x43\x31\x38\x2e\x30\x35\x31\x2c\x31\x36\x2e\x33\x30\x37\x2c\
+\x31\x37\x2e\x39\x31\x36\x2c\x31\x35\x2e\x38\x33\x38\x2c\x31\x37\
+\x2e\x35\x34\x35\x2c\x31\x35\x2e\x34\x36\x37\x7a\x20\x4d\x34\x2e\
+\x30\x30\x34\x2c\x38\x2e\x32\x38\x37\x0d\x0a\x09\x63\x30\x2d\x32\
+\x2e\x33\x36\x36\x2c\x31\x2e\x39\x31\x37\x2d\x34\x2e\x32\x38\x33\
+\x2c\x34\x2e\x32\x38\x32\x2d\x34\x2e\x32\x38\x33\x63\x32\x2e\x33\
+\x36\x36\x2c\x30\x2c\x34\x2e\x34\x37\x34\x2c\x32\x2e\x31\x30\x37\
+\x2c\x34\x2e\x34\x37\x34\x2c\x34\x2e\x34\x37\x34\x63\x30\x2c\x32\
+\x2e\x33\x36\x35\x2d\x31\x2e\x39\x31\x38\x2c\x34\x2e\x32\x38\x33\
+\x2d\x34\x2e\x32\x38\x33\x2c\x34\x2e\x32\x38\x33\x0d\x0a\x09\x43\
+\x36\x2e\x31\x31\x31\x2c\x31\x32\x2e\x37\x36\x2c\x34\x2e\x30\x30\
+\x34\x2c\x31\x30\x2e\x36\x35\x32\x2c\x34\x2e\x30\x30\x34\x2c\x38\
+\x2e\x32\x38\x37\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x0d\x0a\
+\x00\x00\x03\x46\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x33\x37\x2e\x35\
+\x2c\x33\x38\x36\x2e\x36\x4c\x33\x30\x36\x2e\x39\x2c\x32\x35\x36\
+\x6c\x31\x33\x30\x2e\x36\x2d\x31\x33\x30\x2e\x36\x63\x31\x34\x2e\
+\x31\x2d\x31\x34\x2e\x31\x2c\x31\x34\x2e\x31\x2d\x33\x36\x2e\x38\
+\x2c\x30\x2d\x35\x30\x2e\x39\x63\x2d\x31\x34\x2e\x31\x2d\x31\x34\
+\x2e\x31\x2d\x33\x36\x2e\x38\x2d\x31\x34\x2e\x31\x2d\x35\x30\x2e\
+\x39\x2c\x30\x4c\x32\x35\x36\x2c\x32\x30\x35\x2e\x31\x4c\x31\x32\
+\x35\x2e\x34\x2c\x37\x34\x2e\x35\x0d\x0a\x09\x63\x2d\x31\x34\x2e\
+\x31\x2d\x31\x34\x2e\x31\x2d\x33\x36\x2e\x38\x2d\x31\x34\x2e\x31\
+\x2d\x35\x30\x2e\x39\x2c\x30\x63\x2d\x31\x34\x2e\x31\x2c\x31\x34\
+\x2e\x31\x2d\x31\x34\x2e\x31\x2c\x33\x36\x2e\x38\x2c\x30\x2c\x35\
+\x30\x2e\x39\x4c\x32\x30\x35\x2e\x31\x2c\x32\x35\x36\x4c\x37\x34\
+\x2e\x35\x2c\x33\x38\x36\x2e\x36\x63\x2d\x31\x34\x2e\x31\x2c\x31\
+\x34\x2e\x31\x2d\x31\x34\x2e\x31\x2c\x33\x36\x2e\x38\x2c\x30\x2c\
+\x35\x30\x2e\x39\x0d\x0a\x09\x63\x31\x34\x2e\x31\x2c\x31\x34\x2e\
+\x31\x2c\x33\x36\x2e\x38\x2c\x31\x34\x2e\x31\x2c\x35\x30\x2e\x39\
+\x2c\x30\x4c\x32\x35\x36\x2c\x33\x30\x36\x2e\x39\x6c\x31\x33\x30\
+\x2e\x36\x2c\x31\x33\x30\x2e\x36\x63\x31\x34\x2e\x31\x2c\x31\x34\
+\x2e\x31\x2c\x33\x36\x2e\x38\x2c\x31\x34\x2e\x31\x2c\x35\x30\x2e\
+\x39\x2c\x30\x43\x34\x35\x31\x2e\x35\x2c\x34\x32\x33\x2e\x34\x2c\
+\x34\x35\x31\x2e\x35\x2c\x34\x30\x30\x2e\x36\x2c\x34\x33\x37\x2e\
+\x35\x2c\x33\x38\x36\x2e\x36\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\
+\x76\x67\x3e\x0d\x0a\
+\x00\x00\x00\xdd\
+\x3c\
+\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x38\x22\
+\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x38\x22\x20\x76\x69\x65\x77\
+\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x38\x20\x38\x22\x3e\x0a\x20\
+\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x30\x20\x30\x76\x32\
+\x68\x2e\x35\x63\x30\x2d\x2e\x35\x35\x2e\x34\x35\x2d\x31\x20\x31\
+\x2d\x31\x68\x31\x2e\x35\x76\x35\x2e\x35\x63\x30\x20\x2e\x32\x38\
+\x2d\x2e\x32\x32\x2e\x35\x2d\x2e\x35\x2e\x35\x68\x2d\x2e\x35\x76\
+\x31\x68\x34\x76\x2d\x31\x68\x2d\x2e\x35\x63\x2d\x2e\x32\x38\x20\
+\x30\x2d\x2e\x35\x2d\x2e\x32\x32\x2d\x2e\x35\x2d\x2e\x35\x76\x2d\
+\x35\x2e\x35\x68\x31\x2e\x35\x63\x2e\x35\x35\x20\x30\x20\x31\x20\
+\x2e\x34\x35\x20\x31\x20\x31\x68\x2e\x35\x76\x2d\x32\x68\x2d\x38\
+\x7a\x22\x20\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\x7f\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\
+\x3d\x22\x32\x38\x38\x2c\x39\x36\x20\x33\x33\x37\x2e\x39\x2c\x31\
+\x34\x35\x2e\x39\x20\x32\x37\x34\x2c\x32\x30\x39\x2e\x37\x20\x32\
+\x37\x34\x2c\x32\x30\x39\x2e\x37\x20\x31\x34\x35\x2e\x39\x2c\x33\
+\x33\x37\x2e\x39\x20\x39\x36\x2c\x32\x38\x38\x20\x39\x36\x2c\x34\
+\x31\x36\x20\x32\x32\x34\x2c\x34\x31\x36\x20\x31\x37\x34\x2e\x31\
+\x2c\x33\x36\x36\x2e\x31\x20\x33\x35\x37\x2e\x34\x2c\x31\x38\x32\
+\x2e\x39\x20\x33\x36\x36\x2e\x31\x2c\x31\x37\x34\x2e\x31\x20\x0d\
+\x0a\x09\x34\x31\x36\x2c\x32\x32\x34\x20\x34\x31\x36\x2c\x39\x36\
+\x20\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x22\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x4c\x20\x2d\x36\x2e\x36\x34\x30\x35\x37\
+\x20\x2d\x31\x32\x2e\x30\x34\x35\x4c\x20\x38\x2e\x36\x37\x36\x33\
+\x32\x20\x2d\x36\x2e\x35\x31\x38\x37\x31\x4c\x20\x33\x2e\x33\x32\
+\x30\x32\x38\x20\x36\x2e\x30\x32\x32\x35\x27\x20\x66\x69\x6c\x6c\
+\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\
+\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\
+\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\
+\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\
+\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
+\x3d\x27\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\
+\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\
+\x39\x31\x31\x38\x27\x20\x63\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\
+\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\
+\x35\x37\x27\x20\x63\x79\x3d\x27\x2d\x31\x32\x2e\x30\x34\x35\x27\
+\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\
+\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\
+\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\
+\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\
+\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\
+\x2e\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\
+\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\
+\x37\x36\x33\x32\x27\x20\x63\x79\x3d\x27\x2d\x36\x2e\x35\x31\x38\
+\x37\x31\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\
+\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\
+\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\
+\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\
+\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\
+\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\
+\x33\x2e\x33\x32\x30\x32\x38\x27\x20\x63\x79\x3d\x27\x36\x2e\x30\
+\x32\x32\x35\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\
+\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\
+\x3e\x0a\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\
+\x3e\
+\x00\x00\x03\xb5\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x68\x65\x76\x72\x6f\x6e\x5f\x63\x69\x72\x63\x6c\x65\
+\x64\x5f\x72\x69\x67\x68\x74\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x0d\x0a\x09\x20\x78\x3d\x22\x30\x70\x78\
+\x22\x20\x79\x3d\x22\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\
+\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\
+\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\
+\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\
+\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x4d\x31\x31\x2c\x31\x30\x4c\x38\x2e\x36\x39\x38\x2c\x37\x2e\x34\
+\x39\x34\x63\x2d\x30\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x38\x2d\
+\x30\x2e\x31\x39\x36\x2d\x30\x2e\x35\x31\x39\x2c\x30\x2d\x30\x2e\
+\x37\x31\x38\x63\x30\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2c\
+\x30\x2e\x35\x31\x35\x2d\x30\x2e\x31\x39\x37\x2c\x30\x2e\x37\x31\
+\x2c\x30\x6c\x32\x2e\x38\x30\x37\x2c\x32\x2e\x38\x36\x34\x0d\x0a\
+\x09\x63\x30\x2e\x31\x39\x36\x2c\x30\x2e\x31\x39\x39\x2c\x30\x2e\
+\x31\x39\x36\x2c\x30\x2e\x35\x32\x2c\x30\x2c\x30\x2e\x37\x31\x37\
+\x6c\x2d\x32\x2e\x38\x30\x37\x2c\x32\x2e\x38\x36\x34\x63\x2d\x30\
+\x2e\x31\x39\x35\x2c\x30\x2e\x31\x39\x39\x2d\x30\x2e\x35\x31\x34\
+\x2c\x30\x2e\x31\x39\x38\x2d\x30\x2e\x37\x31\x2c\x30\x63\x2d\x30\
+\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2d\x30\x2e\x31\x39\x36\
+\x2d\x30\x2e\x35\x31\x38\x2c\x30\x2d\x30\x2e\x37\x31\x37\x4c\x31\
+\x31\x2c\x31\x30\x7a\x20\x4d\x31\x30\x2c\x30\x2e\x34\x0d\x0a\x09\
+\x63\x35\x2e\x33\x30\x32\x2c\x30\x2c\x39\x2e\x36\x2c\x34\x2e\x32\
+\x39\x38\x2c\x39\x2e\x36\x2c\x39\x2e\x36\x63\x30\x2c\x35\x2e\x33\
+\x30\x33\x2d\x34\x2e\x32\x39\x38\x2c\x39\x2e\x36\x2d\x39\x2e\x36\
+\x2c\x39\x2e\x36\x53\x30\x2e\x34\x2c\x31\x35\x2e\x33\x30\x33\x2c\
+\x30\x2e\x34\x2c\x31\x30\x43\x30\x2e\x34\x2c\x34\x2e\x36\x39\x38\
+\x2c\x34\x2e\x36\x39\x38\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\
+\x34\x7a\x20\x4d\x31\x30\x2c\x31\x38\x2e\x33\x35\x34\x0d\x0a\x09\
+\x63\x34\x2e\x36\x31\x33\x2c\x30\x2c\x38\x2e\x33\x35\x34\x2d\x33\
+\x2e\x37\x34\x2c\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\
+\x30\x2d\x34\x2e\x36\x31\x34\x2d\x33\x2e\x37\x34\x31\x2d\x38\x2e\
+\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\
+\x2d\x34\x2e\x36\x31\x35\x2c\x30\x2d\x38\x2e\x33\x35\x34\x2c\x33\
+\x2e\x37\x34\x2d\x38\x2e\x33\x35\x34\x2c\x38\x2e\x33\x35\x34\x0d\
+\x0a\x09\x43\x31\x2e\x36\x34\x35\x2c\x31\x34\x2e\x36\x31\x34\x2c\
+\x35\x2e\x33\x38\x35\x2c\x31\x38\x2e\x33\x35\x34\x2c\x31\x30\x2c\
+\x31\x38\x2e\x33\x35\x34\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\
+\x67\x3e\x0d\x0a\
+\x00\x00\x02\x79\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x31\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x67\x3e\x0d\x0a\x09\x09\x09\x3c\x70\x6f\x6c\
+\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\x31\x38\x36\
+\x2e\x33\x30\x31\x2c\x33\x33\x39\x2e\x38\x39\x33\x20\x39\x36\x2c\
+\x32\x34\x39\x2e\x34\x36\x31\x20\x36\x34\x2c\x32\x37\x39\x2e\x39\
+\x36\x38\x20\x31\x38\x36\x2e\x33\x30\x31\x2c\x34\x30\x32\x20\x34\
+\x34\x38\x2c\x31\x34\x30\x2e\x35\x30\x36\x20\x34\x31\x36\x2c\x31\
+\x31\x30\x20\x09\x09\x09\x22\x2f\x3e\x0d\x0a\x09\x09\x3c\x2f\x67\
+\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\
+\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x79\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x6f\x64\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\
+\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\
+\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\
+\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\x79\x3d\
+\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\
+\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\
+\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\
+\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\
+\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\
+\x35\x2e\x37\x31\x39\x2c\x31\x34\x2e\x37\x35\x63\x2d\x30\x2e\x32\
+\x33\x36\x2c\x30\x2d\x30\x2e\x34\x37\x34\x2d\x30\x2e\x30\x38\x33\
+\x2d\x30\x2e\x36\x36\x34\x2d\x30\x2e\x32\x35\x32\x4c\x2d\x30\x2e\
+\x30\x30\x35\x2c\x31\x30\x6c\x35\x2e\x33\x34\x31\x2d\x34\x2e\x37\
+\x34\x38\x43\x35\x2e\x37\x34\x38\x2c\x34\x2e\x38\x38\x37\x2c\x36\
+\x2e\x33\x38\x2c\x34\x2e\x39\x32\x32\x2c\x36\x2e\x37\x34\x37\x2c\
+\x35\x2e\x33\x33\x35\x0d\x0a\x09\x63\x30\x2e\x33\x36\x37\x2c\x30\
+\x2e\x34\x31\x33\x2c\x30\x2e\x33\x33\x2c\x31\x2e\x30\x34\x35\x2d\
+\x30\x2e\x30\x38\x33\x2c\x31\x2e\x34\x31\x32\x4c\x33\x2e\x30\x30\
+\x35\x2c\x31\x30\x6c\x33\x2e\x33\x37\x38\x2c\x33\x2e\x30\x30\x32\
+\x63\x30\x2e\x34\x31\x33\x2c\x30\x2e\x33\x36\x37\x2c\x30\x2e\x34\
+\x35\x2c\x30\x2e\x39\x39\x39\x2c\x30\x2e\x30\x38\x33\x2c\x31\x2e\
+\x34\x31\x32\x0d\x0a\x09\x43\x36\x2e\x32\x36\x39\x2c\x31\x34\x2e\
+\x36\x33\x37\x2c\x35\x2e\x39\x39\x34\x2c\x31\x34\x2e\x37\x35\x2c\
+\x35\x2e\x37\x31\x39\x2c\x31\x34\x2e\x37\x35\x7a\x20\x4d\x31\x34\
+\x2e\x36\x36\x34\x2c\x31\x34\x2e\x37\x34\x38\x4c\x32\x30\x2e\x30\
+\x30\x35\x2c\x31\x30\x6c\x2d\x35\x2e\x30\x36\x2d\x34\x2e\x34\x39\
+\x38\x63\x2d\x30\x2e\x34\x31\x33\x2d\x30\x2e\x33\x36\x37\x2d\x31\
+\x2e\x30\x34\x35\x2d\x30\x2e\x33\x33\x2d\x31\x2e\x34\x31\x31\x2c\
+\x30\x2e\x30\x38\x33\x0d\x0a\x09\x63\x2d\x30\x2e\x33\x36\x37\x2c\
+\x30\x2e\x34\x31\x33\x2d\x30\x2e\x33\x33\x2c\x31\x2e\x30\x34\x35\
+\x2c\x30\x2e\x30\x38\x33\x2c\x31\x2e\x34\x31\x32\x4c\x31\x36\x2e\
+\x39\x39\x35\x2c\x31\x30\x6c\x2d\x33\x2e\x36\x35\x39\x2c\x33\x2e\
+\x32\x35\x32\x63\x2d\x30\x2e\x34\x31\x33\x2c\x30\x2e\x33\x36\x37\
+\x2d\x30\x2e\x34\x35\x2c\x30\x2e\x39\x39\x39\x2d\x30\x2e\x30\x38\
+\x33\x2c\x31\x2e\x34\x31\x32\x43\x31\x33\x2e\x34\x35\x2c\x31\x34\
+\x2e\x38\x38\x37\x2c\x31\x33\x2e\x37\x32\x35\x2c\x31\x35\x2c\x31\
+\x34\x2c\x31\x35\x0d\x0a\x09\x43\x31\x34\x2e\x32\x33\x36\x2c\x31\
+\x35\x2c\x31\x34\x2e\x34\x37\x34\x2c\x31\x34\x2e\x39\x31\x37\x2c\
+\x31\x34\x2e\x36\x36\x34\x2c\x31\x34\x2e\x37\x34\x38\x7a\x20\x4d\
+\x39\x2e\x39\x38\x36\x2c\x31\x36\x2e\x31\x36\x35\x6c\x32\x2d\x31\
+\x32\x63\x30\x2e\x30\x39\x31\x2d\x30\x2e\x35\x34\x35\x2d\x30\x2e\
+\x32\x37\x37\x2d\x31\x2e\x30\x36\x2d\x30\x2e\x38\x32\x32\x2d\x31\
+\x2e\x31\x35\x31\x0d\x0a\x09\x63\x2d\x30\x2e\x35\x34\x37\x2d\x30\
+\x2e\x30\x39\x32\x2d\x31\x2e\x30\x36\x31\x2c\x30\x2e\x32\x37\x37\
+\x2d\x31\x2e\x31\x35\x2c\x30\x2e\x38\x32\x32\x6c\x2d\x32\x2c\x31\
+\x32\x63\x2d\x30\x2e\x30\x39\x31\x2c\x30\x2e\x35\x34\x35\x2c\x30\
+\x2e\x32\x37\x37\x2c\x31\x2e\x30\x36\x2c\x30\x2e\x38\x32\x32\x2c\
+\x31\x2e\x31\x35\x31\x43\x38\x2e\x38\x39\x32\x2c\x31\x36\x2e\x39\
+\x39\x36\x2c\x38\x2e\x39\x34\x36\x2c\x31\x37\x2c\x39\x2e\x30\x30\
+\x31\x2c\x31\x37\x0d\x0a\x09\x43\x39\x2e\x34\x38\x31\x2c\x31\x37\
+\x2c\x39\x2e\x39\x30\x35\x2c\x31\x36\x2e\x36\x35\x33\x2c\x39\x2e\
+\x39\x38\x36\x2c\x31\x36\x2e\x31\x36\x35\x7a\x22\x2f\x3e\x0d\x0a\
+\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x30\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x4c\x20\x2d\x36\x2e\x36\x34\x30\x35\x37\
+\x20\x2d\x31\x32\x2e\x30\x34\x35\x4c\x20\x38\x2e\x36\x37\x36\x33\
+\x32\x20\x2d\x36\x2e\x35\x31\x38\x37\x31\x4c\x20\x33\x2e\x33\x32\
+\x30\x32\x38\x20\x36\x2e\x30\x32\x32\x35\x4c\x20\x2d\x39\x2e\x33\
+\x39\x31\x31\x38\x20\x2d\x30\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\
+\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\
+\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\
+\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\
+\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\
+\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\x39\x31\
+\x31\x38\x27\x20\x63\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\x27\x33\
+\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\
+\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\
+\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\x35\x37\
+\x27\x20\x63\x79\x3d\x27\x2d\x31\x32\x2e\x30\x34\x35\x27\x20\x72\
+\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\
+\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\
+\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\
+\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\
+\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\
+\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\
+\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\x37\x36\
+\x33\x32\x27\x20\x63\x79\x3d\x27\x2d\x36\x2e\x35\x31\x38\x37\x31\
+\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\
+\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\
+\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\
+\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\
+\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\
+\x38\x2e\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\
+\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\
+\x33\x32\x30\x32\x38\x27\x20\x63\x79\x3d\x27\x36\x2e\x30\x32\x32\
+\x35\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\
+\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\
+\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x07\x80\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x39\x33\x2e\x34\x36\
+\x2c\x32\x34\x39\x2e\x30\x35\x36\x63\x33\x2e\x37\x32\x33\x2d\x30\
+\x2e\x36\x37\x2c\x37\x2e\x35\x38\x39\x2d\x31\x2e\x30\x34\x31\x2c\
+\x31\x31\x2e\x35\x38\x36\x2d\x31\x2e\x30\x34\x31\x4c\x32\x30\x31\
+\x2e\x39\x32\x34\x2c\x32\x34\x38\x68\x31\x30\x33\x2e\x38\x32\x33\
+\x63\x34\x2e\x35\x30\x33\x2c\x30\x2c\x38\x2e\x38\x30\x36\x2d\x30\
+\x2e\x36\x31\x37\x2c\x31\x32\x2e\x39\x30\x38\x2d\x31\x2e\x37\x35\
+\x34\x0d\x0a\x09\x09\x63\x31\x39\x2e\x33\x37\x2d\x35\x2e\x33\x36\
+\x33\x2c\x33\x33\x2e\x33\x34\x35\x2d\x32\x32\x2e\x35\x33\x37\x2c\
+\x33\x33\x2e\x33\x34\x35\x2d\x34\x33\x2e\x36\x36\x33\x76\x2d\x33\
+\x30\x2e\x38\x32\x32\x76\x2d\x35\x36\x2e\x34\x30\x32\x63\x30\x2d\
+\x32\x34\x2e\x38\x33\x32\x2d\x32\x31\x2e\x31\x35\x2d\x34\x33\x2e\
+\x34\x38\x34\x2d\x34\x36\x2e\x32\x38\x39\x2d\x34\x37\x2e\x36\x30\
+\x36\x0d\x0a\x09\x09\x63\x2d\x31\x35\x2e\x39\x33\x31\x2d\x32\x2e\
+\x36\x32\x34\x2d\x33\x39\x2e\x32\x35\x38\x2d\x33\x2e\x38\x32\x37\
+\x2d\x35\x35\x2e\x30\x38\x39\x2d\x33\x2e\x37\x34\x39\x63\x2d\x31\
+\x35\x2e\x38\x32\x39\x2c\x30\x2e\x30\x38\x36\x2d\x33\x30\x2e\x39\
+\x38\x31\x2c\x31\x2e\x34\x30\x34\x2d\x34\x34\x2e\x32\x37\x37\x2c\
+\x33\x2e\x37\x34\x39\x43\x31\x36\x37\x2e\x31\x34\x33\x2c\x37\x34\
+\x2e\x35\x37\x36\x2c\x31\x36\x30\x2c\x38\x38\x2e\x39\x32\x38\x2c\
+\x31\x36\x30\x2c\x31\x31\x35\x2e\x33\x35\x39\x56\x31\x34\x34\x68\
+\x39\x36\x0d\x0a\x09\x09\x76\x31\x36\x48\x31\x32\x38\x2e\x38\x32\
+\x63\x2d\x33\x35\x2e\x36\x32\x38\x2c\x30\x2d\x36\x34\x2e\x35\x33\
+\x38\x2c\x34\x32\x2e\x35\x37\x31\x2d\x36\x34\x2e\x38\x31\x33\x2c\
+\x39\x35\x2e\x32\x34\x32\x43\x36\x34\x2e\x30\x30\x35\x2c\x32\x35\
+\x35\x2e\x34\x39\x35\x2c\x36\x34\x2c\x32\x35\x35\x2e\x37\x34\x37\
+\x2c\x36\x34\x2c\x32\x35\x36\x63\x30\x2c\x39\x2e\x35\x32\x33\x2c\
+\x30\x2e\x39\x34\x2c\x31\x38\x2e\x37\x32\x2c\x32\x2e\x36\x38\x35\
+\x2c\x32\x37\x2e\x34\x30\x34\x0d\x0a\x09\x09\x43\x37\x34\x2e\x36\
+\x34\x38\x2c\x33\x32\x33\x2e\x30\x37\x2c\x39\x39\x2e\x34\x35\x31\
+\x2c\x33\x35\x32\x2c\x31\x32\x38\x2e\x38\x32\x2c\x33\x35\x32\x48\
+\x31\x34\x34\x76\x2d\x32\x2e\x36\x36\x32\x76\x2d\x34\x33\x2e\x32\
+\x37\x33\x43\x31\x34\x34\x2c\x32\x37\x39\x2e\x32\x33\x38\x2c\x31\
+\x36\x34\x2e\x31\x34\x36\x2c\x32\x35\x34\x2e\x33\x33\x32\x2c\x31\
+\x39\x33\x2e\x34\x36\x2c\x32\x34\x39\x2e\x30\x35\x36\x7a\x20\x4d\
+\x32\x30\x33\x2e\x36\x35\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x0d\
+\x0a\x09\x09\x63\x2d\x39\x2e\x35\x39\x32\x2c\x30\x2d\x31\x37\x2e\
+\x33\x38\x34\x2d\x37\x2e\x37\x38\x35\x2d\x31\x37\x2e\x33\x38\x34\
+\x2d\x31\x37\x2e\x34\x30\x33\x63\x30\x2d\x39\x2e\x36\x36\x34\x2c\
+\x37\x2e\x37\x37\x34\x2d\x31\x37\x2e\x35\x32\x2c\x31\x37\x2e\x33\
+\x38\x34\x2d\x31\x37\x2e\x35\x32\x63\x39\x2e\x35\x37\x34\x2c\x30\
+\x2c\x31\x37\x2e\x33\x39\x39\x2c\x37\x2e\x38\x35\x35\x2c\x31\x37\
+\x2e\x33\x39\x39\x2c\x31\x37\x2e\x35\x32\x0d\x0a\x09\x09\x43\x32\
+\x32\x31\x2e\x30\x35\x36\x2c\x31\x31\x39\x2e\x32\x31\x37\x2c\x32\
+\x31\x33\x2e\x32\x34\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x2c\x32\
+\x30\x33\x2e\x36\x35\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x7a\x22\
+\x2f\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\
+\x34\x33\x2e\x39\x35\x31\x2c\x32\x32\x32\x2e\x35\x34\x33\x43\x34\
+\x33\x34\x2e\x37\x38\x2c\x31\x38\x36\x2e\x30\x32\x31\x2c\x34\x31\
+\x31\x2e\x30\x33\x33\x2c\x31\x36\x30\x2c\x33\x38\x33\x2e\x31\x38\
+\x2c\x31\x36\x30\x48\x33\x36\x38\x76\x32\x2e\x36\x32\x36\x76\x33\
+\x38\x2e\x30\x34\x36\x63\x30\x2c\x33\x33\x2e\x39\x31\x35\x2d\x32\
+\x32\x2e\x32\x38\x36\x2c\x35\x38\x2e\x34\x37\x34\x2d\x34\x39\x2e\
+\x34\x38\x39\x2c\x36\x32\x2e\x36\x38\x31\x0d\x0a\x09\x09\x63\x2d\
+\x32\x2e\x37\x33\x37\x2c\x30\x2e\x34\x32\x34\x2d\x35\x2e\x34\x38\
+\x33\x2c\x30\x2e\x36\x34\x36\x2d\x38\x2e\x33\x30\x31\x2c\x30\x2e\
+\x36\x34\x36\x48\x32\x30\x36\x2e\x33\x35\x31\x63\x2d\x34\x2e\x35\
+\x31\x38\x2c\x30\x2d\x38\x2e\x39\x30\x34\x2c\x30\x2e\x35\x38\x34\
+\x2d\x31\x33\x2e\x30\x34\x39\x2c\x31\x2e\x36\x37\x32\x43\x31\x37\
+\x34\x2e\x31\x38\x2c\x32\x37\x30\x2e\x36\x38\x39\x2c\x31\x36\x30\
+\x2c\x32\x38\x36\x2e\x36\x2c\x31\x36\x30\x2c\x33\x30\x37\x2e\x32\
+\x33\x36\x76\x33\x32\x2e\x39\x32\x32\x0d\x0a\x09\x09\x76\x35\x34\
+\x2e\x33\x30\x35\x63\x30\x2c\x32\x34\x2e\x38\x33\x32\x2c\x32\x34\
+\x2e\x39\x37\x37\x2c\x33\x39\x2e\x34\x32\x36\x2c\x34\x39\x2e\x34\
+\x38\x31\x2c\x34\x36\x2e\x35\x35\x31\x63\x32\x39\x2e\x33\x32\x37\
+\x2c\x38\x2e\x35\x33\x31\x2c\x36\x31\x2e\x32\x36\x37\x2c\x31\x30\
+\x2e\x30\x36\x38\x2c\x39\x36\x2e\x33\x36\x36\x2c\x30\x43\x33\x32\
+\x39\x2e\x31\x35\x2c\x34\x33\x34\x2e\x33\x35\x34\x2c\x33\x35\x32\
+\x2c\x34\x32\x30\x2e\x38\x39\x33\x2c\x33\x35\x32\x2c\x33\x39\x34\
+\x2e\x34\x36\x33\x56\x33\x36\x38\x0d\x0a\x09\x09\x68\x2d\x39\x36\
+\x76\x2d\x31\x36\x68\x31\x32\x37\x2e\x31\x38\x63\x32\x35\x2e\x32\
+\x34\x2c\x30\x2c\x34\x37\x2e\x31\x30\x37\x2d\x32\x31\x2e\x33\x36\
+\x35\x2c\x35\x37\x2e\x38\x31\x34\x2d\x35\x32\x2e\x35\x34\x39\x43\
+\x34\x34\x35\x2e\x34\x37\x34\x2c\x32\x38\x36\x2e\x34\x30\x34\x2c\
+\x34\x34\x38\x2c\x32\x37\x31\x2e\x36\x34\x31\x2c\x34\x34\x38\x2c\
+\x32\x35\x36\x0d\x0a\x09\x09\x43\x34\x34\x38\x2c\x32\x34\x34\x2e\
+\x32\x33\x32\x2c\x34\x34\x36\x2e\x35\x36\x37\x2c\x32\x33\x32\x2e\
+\x39\x36\x32\x2c\x34\x34\x33\x2e\x39\x35\x31\x2c\x32\x32\x32\x2e\
+\x35\x34\x33\x7a\x20\x4d\x33\x30\x37\x2e\x38\x36\x37\x2c\x33\x38\
+\x32\x2e\x38\x32\x63\x39\x2e\x35\x39\x2c\x30\x2c\x31\x37\x2e\x33\
+\x38\x31\x2c\x37\x2e\x37\x38\x35\x2c\x31\x37\x2e\x33\x38\x31\x2c\
+\x31\x37\x2e\x34\x0d\x0a\x09\x09\x63\x30\x2c\x39\x2e\x36\x35\x2d\
+\x37\x2e\x37\x39\x31\x2c\x31\x37\x2e\x35\x32\x31\x2d\x31\x37\x2e\
+\x33\x38\x31\x2c\x31\x37\x2e\x35\x32\x31\x63\x2d\x39\x2e\x35\x37\
+\x37\x2c\x30\x2d\x31\x37\x2e\x33\x39\x39\x2d\x37\x2e\x38\x37\x31\
+\x2d\x31\x37\x2e\x33\x39\x39\x2d\x31\x37\x2e\x35\x32\x31\x43\x32\
+\x39\x30\x2e\x34\x36\x38\x2c\x33\x39\x30\x2e\x35\x39\x2c\x32\x39\
+\x38\x2e\x32\x37\x34\x2c\x33\x38\x32\x2e\x38\x32\x2c\x33\x30\x37\
+\x2e\x38\x36\x37\x2c\x33\x38\x32\x2e\x38\x32\x7a\x22\x2f\x3e\x0d\
+\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x05\x27\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x31\x32\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\
+\x3e\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\
+\x35\x36\x2c\x36\x34\x43\x31\x35\x30\x2e\x34\x30\x31\x2c\x36\x34\
+\x2c\x36\x34\x2c\x31\x35\x30\x2e\x34\x30\x31\x2c\x36\x34\x2c\x32\
+\x35\x36\x63\x30\x2c\x31\x30\x35\x2e\x36\x30\x34\x2c\x38\x36\x2e\
+\x34\x30\x31\x2c\x31\x39\x32\x2c\x31\x39\x32\x2c\x31\x39\x32\x63\
+\x31\x38\x2e\x31\x33\x36\x2c\x30\x2c\x33\x32\x2d\x31\x33\x2e\x38\
+\x36\x34\x2c\x33\x32\x2d\x33\x32\x0d\x0a\x09\x09\x09\x63\x30\x2d\
+\x38\x2e\x35\x33\x31\x2d\x33\x2e\x31\x39\x38\x2d\x31\x36\x2d\x38\
+\x2e\x35\x33\x31\x2d\x32\x31\x2e\x33\x33\x33\x63\x2d\x35\x2e\x33\
+\x33\x33\x2d\x35\x2e\x33\x33\x34\x2d\x38\x2e\x35\x33\x31\x2d\x31\
+\x32\x2e\x38\x30\x33\x2d\x38\x2e\x35\x33\x31\x2d\x32\x31\x2e\x33\
+\x33\x34\x63\x30\x2d\x31\x38\x2e\x31\x33\x35\x2c\x31\x33\x2e\x38\
+\x36\x34\x2d\x33\x32\x2c\x33\x32\x2d\x33\x32\x68\x33\x38\x2e\x33\
+\x39\x36\x0d\x0a\x09\x09\x09\x63\x35\x38\x2e\x36\x36\x37\x2c\x30\
+\x2c\x31\x30\x36\x2e\x36\x36\x37\x2d\x34\x38\x2c\x31\x30\x36\x2e\
+\x36\x36\x37\x2d\x31\x30\x36\x2e\x36\x36\x36\x43\x34\x34\x38\x2c\
+\x31\x34\x30\x2e\x38\x30\x32\x2c\x33\x36\x31\x2e\x36\x30\x34\x2c\
+\x36\x34\x2c\x32\x35\x36\x2c\x36\x34\x7a\x20\x4d\x31\x33\x38\x2e\
+\x36\x36\x37\x2c\x32\x35\x36\x63\x2d\x31\x38\x2e\x31\x33\x36\x2c\
+\x30\x2d\x33\x32\x2d\x31\x33\x2e\x38\x36\x34\x2d\x33\x32\x2d\x33\
+\x32\x73\x31\x33\x2e\x38\x36\x34\x2d\x33\x32\x2c\x33\x32\x2d\x33\
+\x32\x0d\x0a\x09\x09\x09\x63\x31\x38\x2e\x31\x33\x35\x2c\x30\x2c\
+\x33\x32\x2c\x31\x33\x2e\x38\x36\x34\x2c\x33\x32\x2c\x33\x32\x53\
+\x31\x35\x36\x2e\x38\x30\x32\x2c\x32\x35\x36\x2c\x31\x33\x38\x2e\
+\x36\x36\x37\x2c\x32\x35\x36\x7a\x20\x4d\x32\x30\x32\x2e\x36\x36\
+\x37\x2c\x31\x37\x30\x2e\x36\x36\x37\x63\x2d\x31\x38\x2e\x31\x33\
+\x36\x2c\x30\x2d\x33\x32\x2d\x31\x33\x2e\x38\x36\x35\x2d\x33\x32\
+\x2d\x33\x32\x63\x30\x2d\x31\x38\x2e\x31\x33\x36\x2c\x31\x33\x2e\
+\x38\x36\x34\x2d\x33\x32\x2c\x33\x32\x2d\x33\x32\x0d\x0a\x09\x09\
+\x09\x63\x31\x38\x2e\x31\x33\x35\x2c\x30\x2c\x33\x32\x2c\x31\x33\
+\x2e\x38\x36\x34\x2c\x33\x32\x2c\x33\x32\x43\x32\x33\x34\x2e\x36\
+\x36\x37\x2c\x31\x35\x36\x2e\x38\x30\x32\x2c\x32\x32\x30\x2e\x38\
+\x30\x32\x2c\x31\x37\x30\x2e\x36\x36\x37\x2c\x32\x30\x32\x2e\x36\
+\x36\x37\x2c\x31\x37\x30\x2e\x36\x36\x37\x7a\x20\x4d\x33\x30\x39\
+\x2e\x33\x33\x33\x2c\x31\x37\x30\x2e\x36\x36\x37\x63\x2d\x31\x38\
+\x2e\x31\x33\x35\x2c\x30\x2d\x33\x32\x2d\x31\x33\x2e\x38\x36\x35\
+\x2d\x33\x32\x2d\x33\x32\x0d\x0a\x09\x09\x09\x63\x30\x2d\x31\x38\
+\x2e\x31\x33\x36\x2c\x31\x33\x2e\x38\x36\x35\x2d\x33\x32\x2c\x33\
+\x32\x2d\x33\x32\x63\x31\x38\x2e\x31\x33\x36\x2c\x30\x2c\x33\x32\
+\x2c\x31\x33\x2e\x38\x36\x34\x2c\x33\x32\x2c\x33\x32\x43\x33\x34\
+\x31\x2e\x33\x33\x33\x2c\x31\x35\x36\x2e\x38\x30\x32\x2c\x33\x32\
+\x37\x2e\x34\x36\x39\x2c\x31\x37\x30\x2e\x36\x36\x37\x2c\x33\x30\
+\x39\x2e\x33\x33\x33\x2c\x31\x37\x30\x2e\x36\x36\x37\x7a\x20\x4d\
+\x33\x37\x33\x2e\x33\x33\x33\x2c\x32\x35\x36\x0d\x0a\x09\x09\x09\
+\x63\x2d\x31\x38\x2e\x31\x33\x35\x2c\x30\x2d\x33\x32\x2d\x31\x33\
+\x2e\x38\x36\x34\x2d\x33\x32\x2d\x33\x32\x73\x31\x33\x2e\x38\x36\
+\x35\x2d\x33\x32\x2c\x33\x32\x2d\x33\x32\x63\x31\x38\x2e\x31\x33\
+\x36\x2c\x30\x2c\x33\x32\x2c\x31\x33\x2e\x38\x36\x34\x2c\x33\x32\
+\x2c\x33\x32\x53\x33\x39\x31\x2e\x34\x36\x39\x2c\x32\x35\x36\x2c\
+\x33\x37\x33\x2e\x33\x33\x33\x2c\x32\x35\x36\x7a\x22\x2f\x3e\x0d\
+\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xa2\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x32\x38\x2c\x34\x30\
+\x35\x2e\x34\x32\x39\x43\x31\x32\x38\x2c\x34\x32\x38\x2e\x38\x34\
+\x36\x2c\x31\x34\x37\x2e\x31\x39\x38\x2c\x34\x34\x38\x2c\x31\x37\
+\x30\x2e\x36\x36\x37\x2c\x34\x34\x38\x68\x31\x37\x30\x2e\x36\x36\
+\x37\x43\x33\x36\x34\x2e\x38\x30\x32\x2c\x34\x34\x38\x2c\x33\x38\
+\x34\x2c\x34\x32\x38\x2e\x38\x34\x36\x2c\x33\x38\x34\x2c\x34\x30\
+\x35\x2e\x34\x32\x39\x56\x31\x36\x30\x48\x31\x32\x38\x56\x34\x30\
+\x35\x2e\x34\x32\x39\x7a\x20\x4d\x34\x31\x36\x2c\x39\x36\x0d\x0a\
+\x09\x09\x68\x2d\x38\x30\x6c\x2d\x32\x36\x2e\x37\x38\x35\x2d\x33\
+\x32\x48\x32\x30\x32\x2e\x37\x38\x36\x4c\x31\x37\x36\x2c\x39\x36\
+\x48\x39\x36\x76\x33\x32\x68\x33\x32\x30\x56\x39\x36\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\
+\x0a\
+\x00\x00\x03\x22\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\x32\x35\x36\x22\
+\x20\x63\x79\x3d\x22\x32\x38\x30\x22\x20\x72\x3d\x22\x36\x33\x22\
+\x2f\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\
+\x34\x30\x2c\x39\x36\x68\x2d\x38\x38\x6c\x2d\x33\x32\x2d\x33\x32\
+\x48\x31\x39\x32\x6c\x2d\x33\x32\x2c\x33\x32\x48\x37\x32\x63\x2d\
+\x32\x32\x2e\x30\x39\x32\x2c\x30\x2d\x34\x30\x2c\x31\x37\x2e\x39\
+\x30\x38\x2d\x34\x30\x2c\x34\x30\x76\x32\x37\x32\x63\x30\x2c\x32\
+\x32\x2e\x30\x39\x32\x2c\x31\x37\x2e\x39\x30\x38\x2c\x34\x30\x2c\
+\x34\x30\x2c\x34\x30\x68\x33\x36\x38\x63\x32\x32\x2e\x30\x39\x32\
+\x2c\x30\x2c\x34\x30\x2d\x31\x37\x2e\x39\x30\x38\x2c\x34\x30\x2d\
+\x34\x30\x0d\x0a\x09\x09\x56\x31\x33\x36\x43\x34\x38\x30\x2c\x31\
+\x31\x33\x2e\x39\x30\x38\x2c\x34\x36\x32\x2e\x30\x39\x32\x2c\x39\
+\x36\x2c\x34\x34\x30\x2c\x39\x36\x7a\x20\x4d\x32\x35\x36\x2c\x33\
+\x39\x32\x63\x2d\x36\x31\x2e\x38\x35\x35\x2c\x30\x2d\x31\x31\x32\
+\x2d\x35\x30\x2e\x31\x34\x35\x2d\x31\x31\x32\x2d\x31\x31\x32\x73\
+\x35\x30\x2e\x31\x34\x35\x2d\x31\x31\x32\x2c\x31\x31\x32\x2d\x31\
+\x31\x32\x73\x31\x31\x32\x2c\x35\x30\x2e\x31\x34\x35\x2c\x31\x31\
+\x32\x2c\x31\x31\x32\x0d\x0a\x09\x09\x53\x33\x31\x37\x2e\x38\x35\
+\x35\x2c\x33\x39\x32\x2c\x32\x35\x36\x2c\x33\x39\x32\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\
+\x0a\
+\x00\x00\x02\x7d\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x38\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x38\x35\
+\x2c\x32\x37\x37\x2e\x33\x37\x35\x68\x32\x35\x39\x2e\x37\x30\x34\
+\x4c\x32\x32\x35\x2e\x30\x30\x32\x2c\x33\x39\x37\x2e\x30\x37\x37\
+\x4c\x32\x35\x36\x2c\x34\x32\x37\x6c\x31\x37\x31\x2d\x31\x37\x31\
+\x4c\x32\x35\x36\x2c\x38\x35\x6c\x2d\x32\x39\x2e\x39\x32\x32\x2c\
+\x32\x39\x2e\x39\x32\x34\x6c\x31\x31\x38\x2e\x36\x32\x36\x2c\x31\
+\x31\x39\x2e\x37\x30\x31\x48\x38\x35\x56\x32\x37\x37\x2e\x33\x37\
+\x35\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x05\xb7\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x31\x38\x2e\x34\x33\x37\x35\x20\x32\x34\x27\x20\x77\x69\x64\x74\
+\x68\x3d\x27\x31\x38\x2e\x34\x33\x37\x35\x70\x74\x27\x20\x78\x6d\
+\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
+\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\
+\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\
+\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x27\x3e\x0a\x3c\x67\x20\
+\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\
+\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\
+\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x36\x32\x38\x32\x20\x37\
+\x34\x2e\x32\x30\x32\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\
+\x3d\x27\x4d\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\
+\x31\x36\x36\x37\x43\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\
+\x32\x2e\x37\x30\x38\x35\x20\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\
+\x31\x33\x2e\x39\x35\x38\x34\x20\x30\x20\x2d\x31\x33\x2e\x39\x35\
+\x38\x34\x43\x20\x2d\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\x31\x33\
+\x2e\x39\x35\x38\x34\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\
+\x31\x32\x2e\x37\x30\x38\x35\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\
+\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x43\x20\x2d\x38\x2e\x33\x37\
+\x35\x30\x34\x20\x2d\x39\x2e\x36\x32\x34\x39\x32\x20\x2d\x34\x2e\
+\x36\x32\x35\x34\x31\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x30\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x43\x20\x34\x2e\x36\x32\x35\
+\x34\x31\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x38\x2e\x33\x37\
+\x35\x30\x34\x20\x2d\x39\x2e\x36\x32\x34\x39\x32\x20\x38\x2e\x33\
+\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x5a\x27\x20\
+\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\
+\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\
+\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\
+\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\
+\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\
+\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\x3e\
+\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\
+\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\
+\x20\x36\x35\x2e\x36\x32\x38\x32\x20\x37\x34\x2e\x32\x30\x32\x29\
+\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x4c\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x30\x4c\x20\x2d\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x2e\x38\x35\x39\x36\x33\x65\
+\x2d\x31\x35\x43\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\
+\x2e\x32\x33\x39\x37\x35\x65\x2d\x31\x35\x20\x2d\x38\x2e\x33\x37\
+\x35\x30\x34\x20\x2d\x36\x2e\x31\x39\x38\x37\x37\x65\x2d\x31\x36\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x30\x43\x20\x2d\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x31\x2e\x35\x34\x31\x38\x20\x2d\x34\
+\x2e\x36\x32\x35\x34\x31\x20\x32\x2e\x37\x39\x31\x36\x38\x20\x30\
+\x20\x32\x2e\x37\x39\x31\x36\x38\x43\x20\x34\x2e\x36\x32\x35\x34\
+\x31\x20\x32\x2e\x37\x39\x31\x36\x38\x20\x38\x2e\x33\x37\x35\x30\
+\x34\x20\x31\x2e\x35\x34\x31\x38\x20\x38\x2e\x33\x37\x35\x30\x34\
+\x20\x30\x4c\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x30\x4c\x20\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x27\
+\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\
+\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\
+\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\
+\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\
+\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\
+\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\
+\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\
+\x34\x20\x36\x35\x2e\x36\x32\x38\x32\x20\x37\x34\x2e\x32\x30\x32\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x43\
+\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x35\x2e\x37\x39\x32\
+\x31\x20\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\x31\x39\x2e\x35\x34\
+\x31\x38\x20\x30\x20\x2d\x31\x39\x2e\x35\x34\x31\x38\x43\x20\x2d\
+\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\x31\x39\x2e\x35\x34\x31\x38\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x35\x2e\x37\x39\
+\x32\x31\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\
+\x31\x36\x36\x37\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\
+\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\
+\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\
+\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\
+\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x03\x26\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x35\x36\x2c\x33\x38\
+\x38\x63\x2d\x37\x32\x2e\x35\x39\x37\x2c\x30\x2d\x31\x33\x32\x2d\
+\x35\x39\x2e\x34\x30\x35\x2d\x31\x33\x32\x2d\x31\x33\x32\x63\x30\
+\x2d\x37\x32\x2e\x36\x30\x31\x2c\x35\x39\x2e\x34\x30\x33\x2d\x31\
+\x33\x32\x2c\x31\x33\x32\x2d\x31\x33\x32\x63\x33\x36\x2e\x33\x2c\
+\x30\x2c\x36\x39\x2e\x32\x39\x39\x2c\x31\x35\x2e\x34\x2c\x39\x32\
+\x2e\x34\x30\x36\x2c\x33\x39\x2e\x36\x30\x31\x4c\x32\x37\x38\x2c\
+\x32\x33\x34\x68\x31\x35\x34\x56\x38\x30\x0d\x0a\x09\x09\x6c\x2d\
+\x35\x31\x2e\x36\x39\x38\x2c\x35\x31\x2e\x37\x30\x32\x43\x33\x34\
+\x38\x2e\x34\x30\x36\x2c\x39\x39\x2e\x37\x39\x38\x2c\x33\x30\x34\
+\x2e\x34\x30\x36\x2c\x38\x30\x2c\x32\x35\x36\x2c\x38\x30\x63\x2d\
+\x39\x36\x2e\x37\x39\x37\x2c\x30\x2d\x31\x37\x36\x2c\x37\x39\x2e\
+\x32\x30\x33\x2d\x31\x37\x36\x2c\x31\x37\x36\x73\x37\x38\x2e\x30\
+\x39\x34\x2c\x31\x37\x36\x2c\x31\x37\x36\x2c\x31\x37\x36\x0d\x0a\
+\x09\x09\x63\x38\x31\x2e\x30\x34\x35\x2c\x30\x2c\x31\x34\x38\x2e\
+\x32\x38\x37\x2d\x35\x34\x2e\x31\x33\x34\x2c\x31\x36\x39\x2e\x34\
+\x30\x31\x2d\x31\x32\x38\x48\x33\x37\x38\x2e\x38\x35\x43\x33\x36\
+\x30\x2e\x31\x30\x35\x2c\x33\x35\x33\x2e\x35\x36\x31\x2c\x33\x31\
+\x31\x2e\x37\x31\x32\x2c\x33\x38\x38\x2c\x32\x35\x36\x2c\x33\x38\
+\x38\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\
+\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x0c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x68\x65\x63\x6b\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\x79\
+\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\
+\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\
+\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\
+\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\
+\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x4d\x38\x2e\x32\x39\x34\x2c\x31\x36\x2e\x39\x39\x38\x63\x2d\x30\
+\x2e\x34\x33\x35\x2c\x30\x2d\x30\x2e\x38\x34\x37\x2d\x30\x2e\x32\
+\x30\x33\x2d\x31\x2e\x31\x31\x31\x2d\x30\x2e\x35\x35\x33\x4c\x33\
+\x2e\x36\x31\x2c\x31\x31\x2e\x37\x32\x34\x63\x2d\x30\x2e\x34\x36\
+\x35\x2d\x30\x2e\x36\x31\x33\x2d\x30\x2e\x33\x34\x34\x2d\x31\x2e\
+\x34\x38\x36\x2c\x30\x2e\x32\x37\x2d\x31\x2e\x39\x35\x31\x0d\x0a\
+\x09\x63\x30\x2e\x36\x31\x35\x2d\x30\x2e\x34\x36\x37\x2c\x31\x2e\
+\x34\x38\x38\x2d\x30\x2e\x33\x34\x34\x2c\x31\x2e\x39\x35\x33\x2c\
+\x30\x2e\x32\x37\x6c\x32\x2e\x33\x35\x31\x2c\x33\x2e\x31\x30\x34\
+\x6c\x35\x2e\x39\x31\x31\x2d\x39\x2e\x34\x39\x32\x63\x30\x2e\x34\
+\x30\x37\x2d\x30\x2e\x36\x35\x32\x2c\x31\x2e\x32\x36\x37\x2d\x30\
+\x2e\x38\x35\x32\x2c\x31\x2e\x39\x32\x31\x2d\x30\x2e\x34\x34\x35\
+\x0d\x0a\x09\x63\x30\x2e\x36\x35\x33\x2c\x30\x2e\x34\x30\x36\x2c\
+\x30\x2e\x38\x35\x34\x2c\x31\x2e\x32\x36\x36\x2c\x30\x2e\x34\x34\
+\x36\x2c\x31\x2e\x39\x32\x4c\x39\x2e\x34\x37\x38\x2c\x31\x36\x2e\
+\x33\x34\x63\x2d\x30\x2e\x32\x34\x32\x2c\x30\x2e\x33\x39\x31\x2d\
+\x30\x2e\x36\x36\x31\x2c\x30\x2e\x36\x33\x35\x2d\x31\x2e\x31\x32\
+\x2c\x30\x2e\x36\x35\x36\x43\x38\x2e\x33\x33\x36\x2c\x31\x36\x2e\
+\x39\x39\x38\x2c\x38\x2e\x33\x31\x36\x2c\x31\x36\x2e\x39\x39\x38\
+\x2c\x38\x2e\x32\x39\x34\x2c\x31\x36\x2e\x39\x39\x38\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xfc\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x32\x30\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\
+\x3e\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\
+\x35\x36\x2c\x34\x38\x43\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\
+\x2c\x34\x38\x2c\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\x2c\x32\
+\x35\x36\x73\x39\x33\x2e\x36\x30\x31\x2c\x32\x30\x38\x2c\x32\x30\
+\x38\x2c\x32\x30\x38\x73\x32\x30\x38\x2d\x39\x33\x2e\x36\x30\x31\
+\x2c\x32\x30\x38\x2d\x32\x30\x38\x53\x33\x37\x30\x2e\x33\x39\x39\
+\x2c\x34\x38\x2c\x32\x35\x36\x2c\x34\x38\x7a\x20\x4d\x32\x35\x36\
+\x2c\x34\x32\x32\x2e\x33\x39\x39\x0d\x0a\x09\x09\x09\x63\x2d\x39\
+\x31\x2e\x35\x31\x38\x2c\x30\x2d\x31\x36\x36\x2e\x33\x39\x39\x2d\
+\x37\x34\x2e\x38\x38\x32\x2d\x31\x36\x36\x2e\x33\x39\x39\x2d\x31\
+\x36\x36\x2e\x33\x39\x39\x53\x31\x36\x34\x2e\x34\x38\x32\x2c\x38\
+\x39\x2e\x36\x2c\x32\x35\x36\x2c\x38\x39\x2e\x36\x53\x34\x32\x32\
+\x2e\x34\x2c\x31\x36\x34\x2e\x34\x38\x32\x2c\x34\x32\x32\x2e\x34\
+\x2c\x32\x35\x36\x53\x33\x34\x37\x2e\x35\x31\x38\x2c\x34\x32\x32\
+\x2e\x33\x39\x39\x2c\x32\x35\x36\x2c\x34\x32\x32\x2e\x33\x39\x39\
+\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x4c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x32\x31\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\
+\x3e\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\
+\x35\x36\x2c\x31\x35\x32\x63\x2d\x35\x37\x2e\x32\x2c\x30\x2d\x31\
+\x30\x34\x2c\x34\x36\x2e\x38\x2d\x31\x30\x34\x2c\x31\x30\x34\x73\
+\x34\x36\x2e\x38\x2c\x31\x30\x34\x2c\x31\x30\x34\x2c\x31\x30\x34\
+\x73\x31\x30\x34\x2d\x34\x36\x2e\x38\x2c\x31\x30\x34\x2d\x31\x30\
+\x34\x53\x33\x31\x33\x2e\x32\x2c\x31\x35\x32\x2c\x32\x35\x36\x2c\
+\x31\x35\x32\x7a\x20\x4d\x32\x35\x36\x2c\x34\x38\x0d\x0a\x09\x09\
+\x09\x43\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\x2c\x34\x38\x2c\
+\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\x2c\x32\x35\x36\x73\x39\
+\x33\x2e\x36\x30\x31\x2c\x32\x30\x38\x2c\x32\x30\x38\x2c\x32\x30\
+\x38\x73\x32\x30\x38\x2d\x39\x33\x2e\x36\x30\x31\x2c\x32\x30\x38\
+\x2d\x32\x30\x38\x53\x33\x37\x30\x2e\x33\x39\x39\x2c\x34\x38\x2c\
+\x32\x35\x36\x2c\x34\x38\x7a\x20\x4d\x32\x35\x36\x2c\x34\x32\x32\
+\x2e\x34\x0d\x0a\x09\x09\x09\x63\x2d\x39\x31\x2e\x35\x31\x38\x2c\
+\x30\x2d\x31\x36\x36\x2e\x34\x2d\x37\x34\x2e\x38\x38\x33\x2d\x31\
+\x36\x36\x2e\x34\x2d\x31\x36\x36\x2e\x34\x53\x31\x36\x34\x2e\x34\
+\x38\x32\x2c\x38\x39\x2e\x36\x2c\x32\x35\x36\x2c\x38\x39\x2e\x36\
+\x53\x34\x32\x32\x2e\x34\x2c\x31\x36\x34\x2e\x34\x38\x32\x2c\x34\
+\x32\x32\x2e\x34\x2c\x32\x35\x36\x53\x33\x34\x37\x2e\x35\x31\x38\
+\x2c\x34\x32\x32\x2e\x34\x2c\x32\x35\x36\x2c\x34\x32\x32\x2e\x34\
+\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x64\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\x0d\x0a\x09\
+\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x35\x36\x2c\x31\
+\x37\x36\x63\x2d\x34\x34\x2e\x30\x30\x34\x2c\x30\x2d\x38\x30\x2e\
+\x30\x30\x31\x2c\x33\x36\x2d\x38\x30\x2e\x30\x30\x31\x2c\x38\x30\
+\x63\x30\x2c\x34\x34\x2e\x30\x30\x34\x2c\x33\x35\x2e\x39\x39\x37\
+\x2c\x38\x30\x2c\x38\x30\x2e\x30\x30\x31\x2c\x38\x30\x63\x34\x34\
+\x2e\x30\x30\x35\x2c\x30\x2c\x37\x39\x2e\x39\x39\x39\x2d\x33\x35\
+\x2e\x39\x39\x36\x2c\x37\x39\x2e\x39\x39\x39\x2d\x38\x30\x0d\x0a\
+\x09\x09\x09\x43\x33\x33\x35\x2e\x39\x39\x39\x2c\x32\x31\x32\x2c\
+\x33\x30\x30\x2e\x30\x30\x35\x2c\x31\x37\x36\x2c\x32\x35\x36\x2c\
+\x31\x37\x36\x7a\x20\x4d\x34\x34\x36\x2e\x39\x33\x38\x2c\x32\x33\
+\x34\x2e\x36\x36\x37\x63\x2d\x39\x2e\x36\x30\x35\x2d\x38\x38\x2e\
+\x35\x33\x31\x2d\x38\x31\x2e\x30\x37\x34\x2d\x31\x36\x30\x2d\x31\
+\x36\x39\x2e\x36\x30\x35\x2d\x31\x36\x39\x2e\x35\x39\x39\x56\x33\
+\x32\x68\x2d\x34\x32\x2e\x36\x36\x36\x76\x33\x33\x2e\x30\x36\x37\
+\x0d\x0a\x09\x09\x09\x63\x2d\x38\x38\x2e\x35\x33\x31\x2c\x39\x2e\
+\x35\x39\x39\x2d\x31\x36\x30\x2c\x38\x31\x2e\x30\x36\x38\x2d\x31\
+\x36\x39\x2e\x36\x30\x34\x2c\x31\x36\x39\x2e\x35\x39\x39\x48\x33\
+\x32\x76\x34\x32\x2e\x36\x36\x37\x68\x33\x33\x2e\x30\x36\x32\x63\
+\x39\x2e\x36\x30\x34\x2c\x38\x38\x2e\x35\x33\x31\x2c\x38\x31\x2e\
+\x30\x37\x32\x2c\x31\x36\x30\x2c\x31\x36\x39\x2e\x36\x30\x34\x2c\
+\x31\x36\x39\x2e\x36\x30\x34\x56\x34\x38\x30\x68\x34\x32\x2e\x36\
+\x36\x36\x76\x2d\x33\x33\x2e\x30\x36\x32\x0d\x0a\x09\x09\x09\x63\
+\x38\x38\x2e\x35\x33\x31\x2d\x39\x2e\x36\x30\x34\x2c\x31\x36\x30\
+\x2d\x38\x31\x2e\x30\x37\x33\x2c\x31\x36\x39\x2e\x36\x30\x35\x2d\
+\x31\x36\x39\x2e\x36\x30\x34\x48\x34\x38\x30\x76\x2d\x34\x32\x2e\
+\x36\x36\x37\x48\x34\x34\x36\x2e\x39\x33\x38\x7a\x20\x4d\x32\x35\
+\x36\x2c\x34\x30\x35\x2e\x33\x33\x33\x63\x2d\x38\x32\x2e\x31\x33\
+\x37\x2c\x30\x2d\x31\x34\x39\x2e\x33\x33\x34\x2d\x36\x37\x2e\x31\
+\x39\x38\x2d\x31\x34\x39\x2e\x33\x33\x34\x2d\x31\x34\x39\x2e\x33\
+\x33\x33\x0d\x0a\x09\x09\x09\x63\x30\x2d\x38\x32\x2e\x31\x33\x36\
+\x2c\x36\x37\x2e\x31\x39\x37\x2d\x31\x34\x39\x2e\x33\x33\x33\x2c\
+\x31\x34\x39\x2e\x33\x33\x34\x2d\x31\x34\x39\x2e\x33\x33\x33\x63\
+\x38\x32\x2e\x31\x33\x35\x2c\x30\x2c\x31\x34\x39\x2e\x33\x33\x32\
+\x2c\x36\x37\x2e\x31\x39\x38\x2c\x31\x34\x39\x2e\x33\x33\x32\x2c\
+\x31\x34\x39\x2e\x33\x33\x33\x43\x34\x30\x35\x2e\x33\x33\x32\x2c\
+\x33\x33\x38\x2e\x31\x33\x35\x2c\x33\x33\x38\x2e\x31\x33\x35\x2c\
+\x34\x30\x35\x2e\x33\x33\x33\x2c\x32\x35\x36\x2c\x34\x30\x35\x2e\
+\x33\x33\x33\x7a\x0d\x0a\x09\x09\x09\x22\x2f\x3e\x0d\x0a\x09\x3c\
+\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\
+\x3e\x0d\x0a\
+\x00\x00\x03\x36\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\x3d\
+\x22\x33\x39\x36\x2e\x37\x39\x35\x2c\x33\x39\x36\x2e\x38\x20\x33\
+\x32\x30\x2c\x33\x39\x36\x2e\x38\x20\x33\x32\x30\x2c\x34\x34\x38\
+\x20\x34\x34\x38\x2c\x34\x34\x38\x20\x34\x34\x38\x2c\x33\x32\x30\
+\x20\x33\x39\x36\x2e\x37\x39\x35\x2c\x33\x32\x30\x20\x09\x22\x2f\
+\x3e\x0d\x0a\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\
+\x6e\x74\x73\x3d\x22\x33\x39\x36\x2e\x38\x2c\x31\x31\x35\x2e\x32\
+\x30\x35\x20\x33\x39\x36\x2e\x38\x2c\x31\x39\x32\x20\x34\x34\x38\
+\x2c\x31\x39\x32\x20\x34\x34\x38\x2c\x36\x34\x20\x33\x32\x30\x2c\
+\x36\x34\x20\x33\x32\x30\x2c\x31\x31\x35\x2e\x32\x30\x35\x20\x09\
+\x22\x2f\x3e\x0d\x0a\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\
+\x6f\x69\x6e\x74\x73\x3d\x22\x31\x31\x35\x2e\x32\x30\x35\x2c\x31\
+\x31\x35\x2e\x32\x20\x31\x39\x32\x2c\x31\x31\x35\x2e\x32\x20\x31\
+\x39\x32\x2c\x36\x34\x20\x36\x34\x2c\x36\x34\x20\x36\x34\x2c\x31\
+\x39\x32\x20\x31\x31\x35\x2e\x32\x30\x35\x2c\x31\x39\x32\x20\x09\
+\x22\x2f\x3e\x0d\x0a\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\
+\x6f\x69\x6e\x74\x73\x3d\x22\x31\x31\x35\x2e\x32\x2c\x33\x39\x36\
+\x2e\x37\x39\x35\x20\x31\x31\x35\x2e\x32\x2c\x33\x32\x30\x20\x36\
+\x34\x2c\x33\x32\x30\x20\x36\x34\x2c\x34\x34\x38\x20\x31\x39\x32\
+\x2c\x34\x34\x38\x20\x31\x39\x32\x2c\x33\x39\x36\x2e\x37\x39\x35\
+\x20\x09\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\
+\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xf7\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x31\x37\x2e\x34\
+\x2c\x32\x32\x34\x48\x32\x38\x38\x56\x39\x34\x2e\x36\x63\x30\x2d\
+\x31\x36\x2e\x39\x2d\x31\x34\x2e\x33\x2d\x33\x30\x2e\x36\x2d\x33\
+\x32\x2d\x33\x30\x2e\x36\x63\x2d\x31\x37\x2e\x37\x2c\x30\x2d\x33\
+\x32\x2c\x31\x33\x2e\x37\x2d\x33\x32\x2c\x33\x30\x2e\x36\x56\x32\
+\x32\x34\x48\x39\x34\x2e\x36\x43\x37\x37\x2e\x37\x2c\x32\x32\x34\
+\x2c\x36\x34\x2c\x32\x33\x38\x2e\x33\x2c\x36\x34\x2c\x32\x35\x36\
+\x0d\x0a\x09\x63\x30\x2c\x31\x37\x2e\x37\x2c\x31\x33\x2e\x37\x2c\
+\x33\x32\x2c\x33\x30\x2e\x36\x2c\x33\x32\x48\x32\x32\x34\x76\x31\
+\x32\x39\x2e\x34\x63\x30\x2c\x31\x36\x2e\x39\x2c\x31\x34\x2e\x33\
+\x2c\x33\x30\x2e\x36\x2c\x33\x32\x2c\x33\x30\x2e\x36\x63\x31\x37\
+\x2e\x37\x2c\x30\x2c\x33\x32\x2d\x31\x33\x2e\x37\x2c\x33\x32\x2d\
+\x33\x30\x2e\x36\x56\x32\x38\x38\x68\x31\x32\x39\x2e\x34\x63\x31\
+\x36\x2e\x39\x2c\x30\x2c\x33\x30\x2e\x36\x2d\x31\x34\x2e\x33\x2c\
+\x33\x30\x2e\x36\x2d\x33\x32\x0d\x0a\x09\x43\x34\x34\x38\x2c\x32\
+\x33\x38\x2e\x33\x2c\x34\x33\x34\x2e\x33\x2c\x32\x32\x34\x2c\x34\
+\x31\x37\x2e\x34\x2c\x32\x32\x34\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x52\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\
+\x64\x3d\x22\x4d\x34\x33\x37\x2e\x33\x33\x34\x2c\x31\x34\x34\x48\
+\x32\x35\x36\x2e\x30\x30\x36\x6c\x2d\x34\x32\x2e\x36\x36\x38\x2d\
+\x34\x38\x48\x37\x34\x2e\x36\x36\x36\x43\x35\x31\x2e\x31\x39\x37\
+\x2c\x39\x36\x2c\x33\x32\x2c\x31\x31\x35\x2e\x31\x39\x38\x2c\x33\
+\x32\x2c\x31\x33\x38\x2e\x36\x36\x37\x76\x32\x33\x34\x2e\x36\x36\
+\x36\x43\x33\x32\x2c\x33\x39\x36\x2e\x38\x30\x32\x2c\x35\x31\x2e\
+\x31\x39\x37\x2c\x34\x31\x36\x2c\x37\x34\x2e\x36\x36\x36\x2c\x34\
+\x31\x36\x68\x33\x36\x32\x2e\x36\x36\x38\x0d\x0a\x09\x43\x34\x36\
+\x30\x2e\x38\x30\x33\x2c\x34\x31\x36\x2c\x34\x38\x30\x2c\x33\x39\
+\x36\x2e\x38\x30\x32\x2c\x34\x38\x30\x2c\x33\x37\x33\x2e\x33\x33\
+\x33\x56\x31\x38\x36\x2e\x36\x36\x37\x43\x34\x38\x30\x2c\x31\x36\
+\x33\x2e\x31\x39\x38\x2c\x34\x36\x30\x2e\x38\x30\x33\x2c\x31\x34\
+\x34\x2c\x34\x33\x37\x2e\x33\x33\x34\x2c\x31\x34\x34\x7a\x20\x4d\
+\x34\x34\x38\x2c\x33\x37\x33\x2e\x33\x33\x33\x0d\x0a\x09\x63\x30\
+\x2c\x35\x2e\x37\x38\x32\x2d\x34\x2e\x38\x38\x35\x2c\x31\x30\x2e\
+\x36\x36\x37\x2d\x31\x30\x2e\x36\x36\x36\x2c\x31\x30\x2e\x36\x36\
+\x37\x48\x37\x34\x2e\x36\x36\x36\x43\x36\x38\x2e\x38\x38\x34\x2c\
+\x33\x38\x34\x2c\x36\x34\x2c\x33\x37\x39\x2e\x31\x31\x35\x2c\x36\
+\x34\x2c\x33\x37\x33\x2e\x33\x33\x33\x56\x31\x37\x36\x68\x33\x37\
+\x33\x2e\x33\x33\x34\x63\x35\x2e\x37\x38\x31\x2c\x30\x2c\x31\x30\
+\x2e\x36\x36\x36\x2c\x34\x2e\x38\x38\x35\x2c\x31\x30\x2e\x36\x36\
+\x36\x2c\x31\x30\x2e\x36\x36\x37\x0d\x0a\x09\x56\x33\x37\x33\x2e\
+\x33\x33\x33\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\
+\x0a\
+\x00\x00\x05\xca\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\
+\x64\x3d\x22\x4d\x34\x35\x30\x2e\x36\x37\x39\x2c\x32\x37\x33\x2e\
+\x35\x63\x2d\x31\x34\x2e\x35\x38\x35\x2d\x31\x34\x2e\x35\x37\x37\
+\x2d\x33\x36\x2e\x30\x35\x34\x2d\x31\x35\x2e\x38\x39\x2d\x35\x30\
+\x2e\x36\x33\x39\x2d\x31\x2e\x33\x31\x32\x6c\x2d\x34\x31\x2e\x36\
+\x38\x37\x2c\x34\x31\x2e\x36\x36\x34\x63\x2d\x31\x30\x2e\x38\x35\
+\x32\x2c\x31\x30\x2e\x38\x33\x36\x2d\x32\x33\x2e\x39\x33\x2c\x31\
+\x30\x2e\x38\x35\x39\x2d\x33\x31\x2e\x35\x36\x34\x2c\x31\x2e\x38\
+\x35\x32\x0d\x0a\x09\x63\x2d\x35\x2e\x30\x35\x37\x2d\x35\x2e\x39\
+\x36\x38\x2d\x33\x2e\x30\x36\x31\x2d\x32\x34\x2e\x33\x37\x34\x2d\
+\x31\x2e\x36\x34\x34\x2d\x33\x36\x2e\x30\x34\x39\x6c\x32\x30\x2e\
+\x39\x30\x37\x2d\x31\x37\x31\x2e\x38\x34\x39\x63\x31\x2e\x38\x36\
+\x37\x2d\x31\x35\x2e\x33\x35\x33\x2d\x39\x2e\x30\x37\x2d\x33\x30\
+\x2e\x31\x38\x35\x2d\x32\x34\x2e\x34\x33\x2d\x33\x32\x2e\x30\x35\
+\x31\x0d\x0a\x09\x63\x2d\x31\x35\x2e\x33\x35\x38\x2d\x31\x2e\x38\
+\x36\x37\x2d\x32\x39\x2e\x33\x32\x32\x2c\x39\x2e\x39\x33\x39\x2d\
+\x33\x31\x2e\x31\x39\x31\x2c\x32\x35\x2e\x32\x38\x39\x4c\x32\x36\
+\x37\x2e\x33\x37\x2c\x32\x33\x36\x2e\x30\x32\x31\x63\x2d\x31\x2e\
+\x32\x30\x35\x2c\x33\x2e\x33\x35\x38\x2d\x33\x2e\x37\x39\x2c\x33\
+\x2e\x39\x33\x38\x2d\x34\x2e\x30\x38\x31\x2d\x30\x2e\x35\x38\x32\
+\x4c\x32\x35\x35\x2e\x34\x34\x2c\x36\x30\x0d\x0a\x09\x63\x30\x2d\
+\x31\x35\x2e\x34\x36\x35\x2d\x31\x32\x2e\x35\x34\x32\x2d\x32\x38\
+\x2d\x32\x38\x2e\x30\x31\x34\x2d\x32\x38\x63\x2d\x31\x35\x2e\x34\
+\x37\x33\x2c\x30\x2d\x32\x38\x2e\x30\x31\x35\x2c\x31\x32\x2e\x35\
+\x33\x35\x2d\x32\x38\x2e\x30\x31\x35\x2c\x32\x38\x6c\x2d\x30\x2e\
+\x35\x35\x32\x2c\x31\x37\x36\x2e\x37\x35\x32\x63\x30\x2e\x31\x34\
+\x36\x2c\x32\x2e\x30\x34\x2d\x31\x2e\x36\x30\x34\x2c\x32\x2e\x36\
+\x32\x34\x2d\x31\x2e\x39\x32\x2c\x30\x2e\x32\x39\x34\x4c\x31\x37\
+\x32\x2e\x30\x31\x36\x2c\x39\x39\x2e\x30\x37\x37\x0d\x0a\x09\x63\
+\x2d\x32\x2e\x37\x35\x2d\x31\x35\x2e\x32\x31\x39\x2d\x31\x37\x2e\
+\x33\x32\x33\x2d\x32\x36\x2e\x32\x30\x33\x2d\x33\x32\x2e\x35\x34\
+\x38\x2d\x32\x33\x2e\x34\x35\x33\x63\x2d\x31\x35\x2e\x32\x32\x37\
+\x2c\x32\x2e\x37\x34\x38\x2d\x32\x35\x2e\x33\x33\x39\x2c\x31\x38\
+\x2e\x31\x38\x37\x2d\x32\x32\x2e\x35\x39\x31\x2c\x33\x33\x2e\x34\
+\x30\x33\x6c\x32\x32\x2e\x31\x39\x33\x2c\x31\x36\x31\x2e\x34\x35\
+\x35\x0d\x0a\x09\x63\x30\x2e\x30\x32\x33\x2c\x32\x2e\x38\x37\x32\
+\x2d\x30\x2e\x39\x34\x31\x2c\x34\x2e\x35\x31\x33\x2d\x32\x2e\x33\
+\x30\x38\x2c\x30\x2e\x38\x33\x31\x6c\x2d\x33\x33\x2e\x31\x30\x39\
+\x2d\x38\x38\x2e\x35\x31\x37\x63\x2d\x35\x2e\x31\x38\x2d\x31\x34\
+\x2e\x35\x37\x32\x2d\x32\x31\x2e\x31\x39\x36\x2d\x32\x33\x2e\x30\
+\x36\x35\x2d\x33\x35\x2e\x37\x37\x36\x2d\x31\x37\x2e\x38\x38\x39\
+\x0d\x0a\x09\x63\x2d\x31\x34\x2e\x35\x37\x39\x2c\x35\x2e\x31\x37\
+\x37\x2d\x32\x32\x2e\x32\x30\x31\x2c\x32\x32\x2e\x30\x36\x31\x2d\
+\x31\x37\x2e\x30\x32\x33\x2c\x33\x36\x2e\x36\x33\x31\x6c\x35\x38\
+\x2e\x30\x34\x32\x2c\x31\x38\x39\x2e\x36\x32\x35\x63\x30\x2e\x33\
+\x30\x33\x2c\x31\x2e\x30\x34\x36\x2c\x30\x2e\x36\x32\x34\x2c\x32\
+\x2e\x30\x38\x35\x2c\x30\x2e\x39\x35\x33\x2c\x33\x2e\x31\x31\x38\
+\x6c\x30\x2e\x31\x32\x31\x2c\x30\x2e\x33\x39\x0d\x0a\x09\x63\x30\
+\x2e\x30\x31\x31\x2c\x30\x2e\x30\x33\x31\x2c\x30\x2e\x30\x32\x35\
+\x2c\x30\x2e\x30\x35\x38\x2c\x30\x2e\x30\x33\x35\x2c\x30\x2e\x30\
+\x38\x38\x43\x31\x32\x36\x2e\x30\x37\x39\x2c\x34\x34\x34\x2e\x32\
+\x33\x33\x2c\x31\x37\x32\x2e\x35\x37\x2c\x34\x38\x30\x2c\x32\x32\
+\x37\x2e\x34\x32\x37\x2c\x34\x38\x30\x63\x33\x35\x2e\x31\x31\x36\
+\x2c\x30\x2c\x37\x31\x2e\x35\x39\x31\x2d\x31\x32\x2e\x33\x37\x38\
+\x2c\x39\x39\x2e\x33\x35\x37\x2d\x33\x33\x2e\x36\x37\x32\x0d\x0a\
+\x09\x63\x30\x2e\x30\x30\x31\x2c\x30\x2c\x30\x2e\x30\x30\x33\x2d\
+\x30\x2e\x30\x30\x32\x2c\x30\x2e\x30\x30\x33\x2d\x30\x2e\x30\x30\
+\x32\x63\x32\x39\x2e\x39\x39\x2d\x31\x38\x2e\x30\x35\x31\x2c\x31\
+\x32\x36\x2e\x30\x37\x31\x2d\x31\x32\x31\x2e\x33\x34\x37\x2c\x31\
+\x32\x36\x2e\x30\x37\x31\x2d\x31\x32\x31\x2e\x33\x34\x37\x43\x34\
+\x36\x37\x2e\x34\x34\x35\x2c\x33\x31\x30\x2e\x34\x30\x32\x2c\x34\
+\x36\x35\x2e\x32\x36\x36\x2c\x32\x38\x38\x2e\x30\x38\x2c\x34\x35\
+\x30\x2e\x36\x37\x39\x2c\x32\x37\x33\x2e\x35\x7a\x22\x2f\x3e\x0d\
+\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\xbd\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x39\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x43\x20\x2d\x39\x2e\x39\x36\x38\x36\x31\
+\x20\x2d\x33\x2e\x38\x33\x30\x30\x34\x20\x2d\x38\x2e\x35\x35\x37\
+\x30\x36\x20\x2d\x37\x2e\x35\x31\x39\x34\x34\x20\x2d\x36\x2e\x36\
+\x34\x30\x35\x37\x20\x2d\x31\x30\x2e\x32\x31\x37\x31\x43\x20\x2d\
+\x30\x2e\x34\x39\x31\x30\x38\x39\x20\x2d\x31\x38\x2e\x38\x37\x33\
+\x33\x20\x38\x2e\x33\x35\x36\x37\x36\x20\x2d\x31\x35\x2e\x31\x39\
+\x30\x36\x20\x38\x2e\x36\x37\x36\x33\x32\x20\x2d\x35\x2e\x35\x32\
+\x39\x34\x38\x43\x20\x38\x2e\x38\x33\x36\x20\x2d\x30\x2e\x37\x30\
+\x32\x30\x30\x38\x20\x36\x2e\x32\x33\x39\x36\x38\x20\x32\x2e\x39\
+\x34\x32\x30\x37\x20\x33\x2e\x33\x32\x30\x32\x38\x20\x35\x2e\x31\
+\x30\x38\x35\x37\x43\x20\x2d\x31\x2e\x39\x36\x38\x39\x31\x20\x39\
+\x2e\x30\x33\x33\x37\x31\x20\x2d\x38\x2e\x32\x36\x38\x39\x35\x20\
+\x37\x2e\x34\x34\x33\x37\x20\x2d\x39\x2e\x33\x39\x31\x31\x38\x20\
+\x2d\x30\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\
+\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\
+\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\
+\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
+\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\x36\
+\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\
+\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\
+\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x39\
+\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\
+\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\x39\x31\x31\x38\x27\x20\x63\
+\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\
+\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\
+\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\
+\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\
+\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\
+\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x39\x2e\x37\
+\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\
+\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\x35\x37\x27\x20\x63\x79\x3d\
+\x27\x2d\x31\x30\x2e\x32\x31\x37\x31\x27\x20\x72\x3d\x27\x33\x2e\
+\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\
+\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\
+\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\
+\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\
+\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\
+\x36\x39\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\
+\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\x37\x36\x33\x32\x27\x20\
+\x63\x79\x3d\x27\x2d\x35\x2e\x35\x32\x39\x34\x38\x27\x20\x72\x3d\
+\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x39\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x33\x32\x30\x32\
+\x38\x27\x20\x63\x79\x3d\x27\x35\x2e\x31\x30\x38\x35\x37\x27\x20\
+\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\
+\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\
+\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x04\xca\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\x72\
+\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\x75\
+\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x39\x2e\x32\x2e\x31\x2c\x20\
+\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\x2d\
+\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\x6e\
+\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\x20\
+\x20\x2d\x2d\x3e\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x73\
+\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\
+\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\x2f\x2f\
+\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
+\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\x73\x2f\
+\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\x67\x31\
+\x31\x2e\x64\x74\x64\x22\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\
+\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x0a\x09\x20\x69\x64\x3d\
+\x22\x73\x76\x67\x34\x36\x31\x39\x22\x20\x69\x6e\x6b\x73\x63\x61\
+\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x39\x31\
+\x2b\x64\x65\x76\x65\x6c\x2b\x6f\x73\x78\x6d\x65\x6e\x75\x20\x72\
+\x31\x32\x39\x31\x31\x22\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
+\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x74\x72\x69\x61\x6e\x67\x6c\
+\x65\x2d\x73\x74\x72\x6f\x6b\x65\x64\x2d\x31\x35\x2e\x73\x76\x67\
+\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\x65\x63\x6f\x6d\x6d\x6f\
+\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\x22\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\
+\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\
+\x73\x2f\x31\x2e\x31\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\
+\x6e\x61\x6d\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\
+\x61\x70\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\
+\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\
+\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\
+\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\
+\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\
+\x30\x30\x2f\x73\x76\x67\x22\x0a\x09\x20\x78\x6d\x6c\x6e\x73\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\
+\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\
+\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\
+\x79\x3d\x22\x30\x70\x78\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\
+\x35\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\x35\x70\
+\x78\x22\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\
+\x30\x20\x31\x35\x20\x31\x35\x22\x20\x73\x74\x79\x6c\x65\x3d\x22\
+\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\
+\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\x31\x35\x20\x31\x35\x3b\
+\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\
+\x73\x65\x72\x76\x65\x22\x3e\x0a\x3c\x70\x61\x74\x68\x20\x69\x64\
+\x3d\x22\x72\x65\x63\x74\x33\x33\x33\x38\x22\x20\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\
+\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x73\x6f\x64\
+\x69\x70\x6f\x64\x69\x3a\x6e\x6f\x64\x65\x74\x79\x70\x65\x73\x3d\
+\x22\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x22\x20\x64\
+\x3d\x22\x4d\x37\x2e\x35\x32\x34\x33\x2c\x31\x2e\x35\x30\x30\x34\
+\x0a\x09\x43\x37\x2e\x32\x34\x32\x39\x2c\x31\x2e\x34\x39\x31\x33\
+\x2c\x36\x2e\x39\x37\x38\x37\x2c\x31\x2e\x36\x34\x32\x33\x2c\x36\
+\x2e\x38\x33\x33\x36\x2c\x31\x2e\x38\x39\x35\x32\x6c\x2d\x35\x2e\
+\x35\x2c\x39\x2e\x38\x36\x39\x32\x43\x31\x2e\x30\x32\x31\x38\x2c\
+\x31\x32\x2e\x33\x30\x37\x38\x2c\x31\x2e\x33\x39\x35\x2c\x31\x32\
+\x2e\x39\x39\x39\x39\x2c\x32\x2c\x31\x33\x68\x31\x31\x0a\x09\x63\
+\x30\x2e\x36\x30\x35\x2d\x30\x2e\x30\x30\x30\x31\x2c\x30\x2e\x39\
+\x37\x38\x32\x2d\x30\x2e\x36\x39\x32\x32\x2c\x30\x2e\x36\x36\x36\
+\x34\x2d\x31\x2e\x32\x33\x35\x35\x6c\x2d\x35\x2e\x35\x2d\x39\x2e\
+\x38\x36\x39\x32\x43\x38\x2e\x30\x33\x30\x32\x2c\x31\x2e\x36\x35\
+\x37\x39\x2c\x37\x2e\x37\x38\x38\x34\x2c\x31\x2e\x35\x30\x39\x32\
+\x2c\x37\x2e\x35\x32\x34\x33\x2c\x31\x2e\x35\x30\x30\x34\x7a\x20\
+\x4d\x37\x2e\x35\x2c\x33\x2e\x38\x39\x39\x33\x6c\x34\x2e\x31\x32\
+\x36\x37\x2c\x37\x2e\x34\x37\x30\x34\x0a\x09\x48\x33\x2e\x33\x37\
+\x33\x33\x4c\x37\x2e\x35\x2c\x33\x2e\x38\x39\x39\x33\x7a\x22\x2f\
+\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\
+\x00\x00\x04\x8d\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x43\x20\x2d\x39\x2e\x33\x32\x32\x35\x37\
+\x20\x2d\x33\x2e\x37\x37\x37\x38\x33\x20\x2d\x38\x2e\x33\x34\x33\
+\x32\x34\x20\x2d\x37\x2e\x33\x38\x34\x34\x34\x20\x2d\x36\x2e\x36\
+\x34\x30\x35\x37\x20\x2d\x31\x30\x2e\x31\x32\x39\x38\x43\x20\x2d\
+\x31\x2e\x32\x36\x32\x31\x39\x20\x2d\x31\x38\x2e\x38\x30\x31\x37\
+\x20\x37\x2e\x36\x38\x39\x37\x31\x20\x2d\x31\x35\x2e\x35\x33\x35\
+\x31\x20\x38\x2e\x36\x37\x36\x33\x32\x20\x2d\x35\x2e\x34\x38\x32\
+\x32\x43\x20\x39\x2e\x31\x38\x36\x37\x39\x20\x2d\x30\x2e\x32\x38\
+\x30\x38\x37\x37\x20\x36\x2e\x37\x34\x39\x33\x37\x20\x34\x2e\x35\
+\x31\x38\x38\x37\x20\x33\x2e\x33\x32\x30\x32\x38\x20\x35\x2e\x30\
+\x36\x34\x38\x39\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\
+\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\
+\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\
+\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\
+\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\
+\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\
+\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\
+\x65\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\x39\x31\x31\x38\x27\x20\
+\x63\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\
+\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\
+\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\
+\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\
+\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x39\x2e\
+\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\
+\x63\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\x35\x37\x27\x20\x63\x79\
+\x3d\x27\x2d\x31\x30\x2e\x31\x32\x39\x38\x27\x20\x72\x3d\x27\x33\
+\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\
+\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\
+\x20\x36\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\x37\x36\x33\x32\x27\
+\x20\x63\x79\x3d\x27\x2d\x35\x2e\x34\x38\x32\x32\x27\x20\x72\x3d\
+\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x33\x32\x30\x32\
+\x38\x27\x20\x63\x79\x3d\x27\x35\x2e\x30\x36\x34\x38\x39\x27\x20\
+\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\
+\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\
+\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x03\xeb\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x67\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x4d\x32\x35\x36\x2c\x31\x32\x38\x63\x2d\x38\x31\x2e\x39\x2c\x30\
+\x2d\x31\x34\x35\x2e\x37\x2c\x34\x38\x2e\x38\x2d\x32\x32\x34\x2c\
+\x31\x32\x38\x63\x36\x37\x2e\x34\x2c\x36\x37\x2e\x37\x2c\x31\x32\
+\x34\x2c\x31\x32\x38\x2c\x32\x32\x34\x2c\x31\x32\x38\x63\x39\x39\
+\x2e\x39\x2c\x30\x2c\x31\x37\x33\x2e\x34\x2d\x37\x36\x2e\x34\x2c\
+\x32\x32\x34\x2d\x31\x32\x36\x2e\x36\x0d\x0a\x09\x09\x43\x34\x32\
+\x38\x2e\x32\x2c\x31\x39\x38\x2e\x36\x2c\x33\x35\x34\x2e\x38\x2c\
+\x31\x32\x38\x2c\x32\x35\x36\x2c\x31\x32\x38\x7a\x20\x4d\x32\x35\
+\x36\x2c\x33\x34\x37\x2e\x33\x63\x2d\x34\x39\x2e\x34\x2c\x30\x2d\
+\x38\x39\x2e\x36\x2d\x34\x31\x2d\x38\x39\x2e\x36\x2d\x39\x31\x2e\
+\x33\x63\x30\x2d\x35\x30\x2e\x34\x2c\x34\x30\x2e\x32\x2d\x39\x31\
+\x2e\x33\x2c\x38\x39\x2e\x36\x2d\x39\x31\x2e\x33\x73\x38\x39\x2e\
+\x36\x2c\x34\x31\x2c\x38\x39\x2e\x36\x2c\x39\x31\x2e\x33\x0d\x0a\
+\x09\x09\x43\x33\x34\x35\x2e\x36\x2c\x33\x30\x36\x2e\x34\x2c\x33\
+\x30\x35\x2e\x34\x2c\x33\x34\x37\x2e\x33\x2c\x32\x35\x36\x2c\x33\
+\x34\x37\x2e\x33\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x67\x3e\x0d\x0a\
+\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x35\x36\x2c\
+\x32\x32\x34\x63\x30\x2d\x37\x2e\x39\x2c\x32\x2e\x39\x2d\x31\x35\
+\x2e\x31\x2c\x37\x2e\x36\x2d\x32\x30\x2e\x37\x63\x2d\x32\x2e\x35\
+\x2d\x30\x2e\x34\x2d\x35\x2d\x30\x2e\x36\x2d\x37\x2e\x36\x2d\x30\
+\x2e\x36\x63\x2d\x32\x38\x2e\x38\x2c\x30\x2d\x35\x32\x2e\x33\x2c\
+\x32\x33\x2e\x39\x2d\x35\x32\x2e\x33\x2c\x35\x33\x2e\x33\x63\x30\
+\x2c\x32\x39\x2e\x34\x2c\x32\x33\x2e\x35\x2c\x35\x33\x2e\x33\x2c\
+\x35\x32\x2e\x33\x2c\x35\x33\x2e\x33\x0d\x0a\x09\x09\x09\x73\x35\
+\x32\x2e\x33\x2d\x32\x33\x2e\x39\x2c\x35\x32\x2e\x33\x2d\x35\x33\
+\x2e\x33\x63\x30\x2d\x32\x2e\x33\x2d\x30\x2e\x32\x2d\x34\x2e\x36\
+\x2d\x30\x2e\x34\x2d\x36\x2e\x39\x63\x2d\x35\x2e\x35\x2c\x34\x2e\
+\x33\x2d\x31\x32\x2e\x33\x2c\x36\x2e\x39\x2d\x31\x39\x2e\x38\x2c\
+\x36\x2e\x39\x43\x32\x37\x30\x2e\x33\x2c\x32\x35\x36\x2c\x32\x35\
+\x36\x2c\x32\x34\x31\x2e\x37\x2c\x32\x35\x36\x2c\x32\x32\x34\x7a\
+\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\
+\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x6c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x0d\x0a\x09\x09\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x31\x37\x38\
+\x2e\x38\x34\x36\x22\x20\x79\x3d\x22\x39\x32\x2e\x30\x38\x37\x22\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
+\x69\x78\x28\x2d\x30\x2e\x37\x30\x37\x31\x20\x2d\x30\x2e\x37\x30\
+\x37\x31\x20\x30\x2e\x37\x30\x37\x31\x20\x2d\x30\x2e\x37\x30\x37\
+\x31\x20\x32\x32\x34\x2e\x33\x34\x37\x36\x20\x36\x33\x31\x2e\x31\
+\x34\x39\x38\x29\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\
+\x2e\x30\x38\x35\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x35\
+\x34\x2e\x30\x34\x39\x22\x2f\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\
+\x20\x64\x3d\x22\x4d\x34\x37\x31\x2e\x37\x32\x33\x2c\x38\x38\x2e\
+\x33\x39\x33\x6c\x2d\x34\x38\x2e\x31\x31\x35\x2d\x34\x38\x2e\x31\
+\x31\x34\x63\x2d\x31\x31\x2e\x37\x32\x33\x2d\x31\x31\x2e\x37\x32\
+\x34\x2d\x33\x31\x2e\x35\x35\x38\x2d\x31\x30\x2e\x38\x39\x36\x2d\
+\x34\x34\x2e\x33\x30\x34\x2c\x31\x2e\x38\x35\x6c\x2d\x34\x35\x2e\
+\x32\x30\x32\x2c\x34\x35\x2e\x32\x30\x33\x6c\x39\x30\x2e\x35\x36\
+\x39\x2c\x39\x30\x2e\x35\x36\x38\x6c\x34\x35\x2e\x32\x30\x32\x2d\
+\x34\x35\x2e\x32\x30\x32\x0d\x0a\x09\x09\x43\x34\x38\x32\x2e\x36\
+\x31\x36\x2c\x31\x31\x39\x2e\x39\x35\x32\x2c\x34\x38\x33\x2e\x34\
+\x34\x35\x2c\x31\x30\x30\x2e\x31\x31\x36\x2c\x34\x37\x31\x2e\x37\
+\x32\x33\x2c\x38\x38\x2e\x33\x39\x33\x7a\x22\x2f\x3e\x0d\x0a\x09\
+\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\x3d\
+\x22\x36\x34\x2e\x30\x32\x31\x2c\x33\x36\x33\x2e\x32\x35\x32\x20\
+\x33\x32\x2c\x34\x38\x30\x20\x31\x34\x38\x2e\x37\x33\x37\x2c\x34\
+\x34\x37\x2e\x39\x37\x39\x20\x09\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\x7d\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x38\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x32\
+\x37\x2c\x32\x33\x34\x2e\x36\x32\x35\x48\x31\x36\x37\x2e\x32\x39\
+\x36\x6c\x31\x31\x39\x2e\x37\x30\x32\x2d\x31\x31\x39\x2e\x37\x30\
+\x32\x4c\x32\x35\x36\x2c\x38\x35\x4c\x38\x35\x2c\x32\x35\x36\x6c\
+\x31\x37\x31\x2c\x31\x37\x31\x6c\x32\x39\x2e\x39\x32\x32\x2d\x32\
+\x39\x2e\x39\x32\x34\x4c\x31\x36\x37\x2e\x32\x39\x36\x2c\x32\x37\
+\x37\x2e\x33\x37\x35\x48\x34\x32\x37\x56\x32\x33\x34\x2e\x36\x32\
+\x35\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\xc4\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x68\x65\x76\x72\x6f\x6e\x5f\x63\x69\x72\x63\x6c\x65\
+\x64\x5f\x6c\x65\x66\x74\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\
+\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\
+\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\
+\x6c\x69\x6e\x6b\x22\x0d\x0a\x09\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\
+\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\
+\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\
+\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\
+\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\
+\x31\x31\x2e\x33\x30\x32\x2c\x36\x2e\x37\x37\x36\x63\x2d\x30\x2e\
+\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2d\x30\x2e\x35\x31\x35\x2d\
+\x30\x2e\x31\x39\x37\x2d\x30\x2e\x37\x31\x2c\x30\x4c\x37\x2e\x37\
+\x38\x35\x2c\x39\x2e\x36\x34\x31\x63\x2d\x30\x2e\x31\x39\x36\x2c\
+\x30\x2e\x31\x39\x39\x2d\x30\x2e\x31\x39\x36\x2c\x30\x2e\x35\x32\
+\x2c\x30\x2c\x30\x2e\x37\x31\x37\x6c\x32\x2e\x38\x30\x37\x2c\x32\
+\x2e\x38\x36\x34\x0d\x0a\x09\x63\x30\x2e\x31\x39\x35\x2c\x30\x2e\
+\x31\x39\x39\x2c\x30\x2e\x35\x31\x34\x2c\x30\x2e\x31\x39\x38\x2c\
+\x30\x2e\x37\x31\x2c\x30\x63\x30\x2e\x31\x39\x36\x2d\x30\x2e\x31\
+\x39\x37\x2c\x30\x2e\x31\x39\x36\x2d\x30\x2e\x35\x31\x38\x2c\x30\
+\x2d\x30\x2e\x37\x31\x37\x4c\x39\x2c\x31\x30\x6c\x32\x2e\x33\x30\
+\x32\x2d\x32\x2e\x35\x30\x36\x43\x31\x31\x2e\x34\x39\x38\x2c\x37\
+\x2e\x32\x39\x36\x2c\x31\x31\x2e\x34\x39\x38\x2c\x36\x2e\x39\x37\
+\x36\x2c\x31\x31\x2e\x33\x30\x32\x2c\x36\x2e\x37\x37\x36\x7a\x0d\
+\x0a\x09\x20\x4d\x31\x30\x2c\x30\x2e\x34\x63\x2d\x35\x2e\x33\x30\
+\x32\x2c\x30\x2d\x39\x2e\x36\x2c\x34\x2e\x32\x39\x38\x2d\x39\x2e\
+\x36\x2c\x39\x2e\x36\x63\x30\x2c\x35\x2e\x33\x30\x33\x2c\x34\x2e\
+\x32\x39\x38\x2c\x39\x2e\x36\x2c\x39\x2e\x36\x2c\x39\x2e\x36\x73\
+\x39\x2e\x36\x2d\x34\x2e\x32\x39\x37\x2c\x39\x2e\x36\x2d\x39\x2e\
+\x36\x43\x31\x39\x2e\x36\x2c\x34\x2e\x36\x39\x38\x2c\x31\x35\x2e\
+\x33\x30\x32\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\x34\x7a\x20\
+\x4d\x31\x30\x2c\x31\x38\x2e\x33\x35\x34\x0d\x0a\x09\x63\x2d\x34\
+\x2e\x36\x31\x35\x2c\x30\x2d\x38\x2e\x33\x35\x34\x2d\x33\x2e\x37\
+\x34\x2d\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x30\x2d\
+\x34\x2e\x36\x31\x34\x2c\x33\x2e\x37\x33\x39\x2d\x38\x2e\x33\x35\
+\x34\x2c\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x34\x2e\
+\x36\x31\x33\x2c\x30\x2c\x38\x2e\x33\x35\x34\x2c\x33\x2e\x37\x34\
+\x2c\x38\x2e\x33\x35\x34\x2c\x38\x2e\x33\x35\x34\x0d\x0a\x09\x43\
+\x31\x38\x2e\x33\x35\x34\x2c\x31\x34\x2e\x36\x31\x34\x2c\x31\x34\
+\x2e\x36\x31\x33\x2c\x31\x38\x2e\x33\x35\x34\x2c\x31\x30\x2c\x31\
+\x38\x2e\x33\x35\x34\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\
+\x3e\x0d\x0a\
+\x00\x00\x00\x6c\
+\x3c\
+\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\
+\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x3e\x3c\x70\x61\x74\x68\
+\x20\x64\x3d\x22\x4d\x31\x38\x20\x31\x32\x76\x31\x48\x38\x76\x35\
+\x6c\x2d\x36\x2d\x36\x20\x36\x2d\x36\x76\x35\x68\x38\x56\x32\x68\
+\x32\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\xb7\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x35\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\
+\x6e\x74\x73\x3d\x22\x34\x30\x35\x2c\x31\x33\x36\x2e\x37\x39\x38\
+\x20\x33\x37\x35\x2e\x32\x30\x32\x2c\x31\x30\x37\x20\x32\x35\x36\
+\x2c\x32\x32\x36\x2e\x32\x30\x32\x20\x31\x33\x36\x2e\x37\x39\x38\
+\x2c\x31\x30\x37\x20\x31\x30\x37\x2c\x31\x33\x36\x2e\x37\x39\x38\
+\x20\x32\x32\x36\x2e\x32\x30\x32\x2c\x32\x35\x36\x20\x31\x30\x37\
+\x2c\x33\x37\x35\x2e\x32\x30\x32\x20\x31\x33\x36\x2e\x37\x39\x38\
+\x2c\x34\x30\x35\x20\x32\x35\x36\x2c\x32\x38\x35\x2e\x37\x39\x38\
+\x20\x0d\x0a\x09\x09\x09\x33\x37\x35\x2e\x32\x30\x32\x2c\x34\x30\
+\x35\x20\x34\x30\x35\x2c\x33\x37\x35\x2e\x32\x30\x32\x20\x32\x38\
+\x35\x2e\x37\x39\x38\x2c\x32\x35\x36\x20\x09\x09\x22\x2f\x3e\x0d\
+\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x01\xdd\
+\x00\
+\x00\x06\xe4\x78\x9c\xcd\x54\x4d\x6f\x9b\x40\x10\x3d\x13\x29\xff\
+\x61\xba\xb7\x4a\xec\x17\xc4\xd4\xa6\xa6\x51\xfd\x21\xcb\x52\x9a\
+\x58\x6a\xea\xaa\xa7\x0a\xc3\x16\x50\x28\x20\x58\xc0\xce\xaf\xef\
+\xee\x92\x54\x51\x95\xfa\x18\xfb\xb0\x33\xda\x79\x6f\xde\xbc\x65\
+\x24\xa6\xd7\xfb\xdf\x39\x74\xa2\x6e\xb2\xb2\x08\x10\x27\x0c\x81\
+\x28\xa2\x32\xce\x8a\x24\x40\xad\xfc\x85\xc7\xe8\xfa\xd3\xe5\xc5\
+\xf4\x1d\xc6\xb0\x12\x85\xa8\x43\x59\xd6\x3e\x7c\x8e\xcb\x9d\x80\
+\x75\x9e\xb7\x8d\x34\x25\xe0\x1e\x71\x08\xb7\xe1\xeb\x76\x05\xcb\
+\x7d\x55\xd6\x12\x36\x79\x9b\xe0\x75\x01\xc4\x14\xb7\xc3\x10\x1f\
+\x3c\xc2\x18\xcc\xda\x2c\x8f\x81\xbd\x07\xc0\xd8\xe8\x2f\xee\xe6\
+\xf7\x3f\x36\x4b\x68\xba\x04\x36\xdf\x66\x37\xeb\x39\x20\x4c\xe9\
+\x77\x77\x4e\xe9\xe2\x7e\x61\x24\x38\xe1\x94\x2e\x6f\x11\xa0\x54\
+\xca\xca\xa7\xb4\xef\x7b\xd2\xbb\xa4\xac\x13\xba\xaa\xc3\x2a\xcd\
+\xa2\x86\x2a\x22\xd5\x44\xd5\x44\x95\x18\xe7\x24\x96\x31\xd2\x33\
+\xb4\xf4\x8b\xa7\x72\x04\x59\x1c\xa0\x9b\xf0\x20\xea\x9f\xea\xa2\
+\xbe\x44\xd1\x04\xaf\x48\x3b\x8c\x31\x2d\xf5\x44\xf1\xf7\x79\x56\
+\x3c\xbc\x46\xe4\x93\xc9\x84\x1a\x54\x51\x03\xc4\xaa\x3d\x82\xc3\
+\x90\x2f\x2f\x2c\xe8\xb3\x58\xa6\x01\x1a\x71\x47\x03\xa9\xc8\x92\
+\x54\xfe\xbd\x76\x99\xe8\x67\xa5\xee\x02\x06\xaa\xa6\x0f\x82\x46\
+\x1e\x72\x11\x20\x51\x84\xbb\x5c\xe0\x5d\x18\x3d\x24\x75\xd9\x16\
+\xb1\x5f\x88\x1e\x5e\x30\x3f\x1a\x6f\x7e\x53\x85\x91\xa2\x57\xb5\
+\x68\x44\xdd\x09\xf3\xea\x44\x05\x6b\x88\xd6\xb4\x0a\x65\x0a\xea\
+\xd1\x5f\xb8\xc7\x6c\x3e\x72\x89\x1b\x31\xdb\x25\x1f\xb0\x6b\x7b\
+\x2a\xaa\xa3\x73\x8a\x47\x8c\x8c\x22\xac\x00\x9b\xe9\x22\x76\xf1\
+\x13\xdc\x0d\x10\x33\x98\xfb\xdc\xa0\x73\x6a\x00\xd3\xa2\x4b\xb6\
+\x51\xd4\x67\x6b\xe6\x3c\xea\x4f\x60\x59\xf4\x1f\x1f\xce\x78\x7c\
+\x16\x3e\xae\xb8\x77\x3a\x1f\x53\xfa\xff\x25\x39\x63\xfe\x26\xa6\
+\xcc\x9c\x23\x4b\x3a\x07\x1f\x7a\x49\x27\xf3\x71\x6c\x49\x57\x6c\
+\xf2\x26\xa6\xcc\x9c\x23\x4b\x3a\x07\x1f\x7a\x49\x27\xf3\x31\x2c\
+\xe9\x39\xaa\x7f\xb6\xca\x7f\x00\x99\x18\x96\x19\
+\x00\x00\x02\x20\
+\x00\
+\x00\x07\x7f\x78\x9c\xdd\x55\x3b\x6f\xdb\x30\x10\xde\xfb\x2b\xae\
+\xe8\xc0\x76\x20\x45\x52\x24\x45\x06\x51\x02\xd4\x40\xa7\x74\x4b\
+\x96\x6e\x6a\xcc\x48\x6c\x6c\xc9\x90\x54\xcb\xfd\xf7\x3d\xc5\xd6\
+\xc3\x56\xd0\x29\x43\x11\x69\xd0\x3d\x78\x77\xdf\x7d\xc7\x83\xae\
+\x6f\x0f\xdb\x0d\xec\x7d\xdd\x84\xaa\x4c\x89\x60\x9c\x80\x2f\x1f\
+\xab\x75\x28\xf3\x94\x3c\xdc\x7f\xa3\x96\xdc\xde\x7c\xb8\xfe\x48\
+\x29\xdc\x17\xa1\x81\xa7\xb0\xf1\xd0\x65\x0d\xe4\xbe\xf4\x75\xd6\
+\xfa\x35\xfc\xfc\x03\xeb\x7d\x68\xf6\xf9\x16\x24\x53\x40\x29\x9e\
+\x47\x0d\x0a\x1f\xf2\xa2\x4d\x89\x54\xbb\x96\xcc\x6b\x08\xd4\x82\
+\xef\xbe\x56\x87\x94\x68\xc3\x14\x77\x0a\x74\xcc\xac\xb6\x31\x08\
+\xcb\x54\x9c\x68\x90\x8a\x40\x17\xd6\x6d\x81\x01\x47\x53\x9f\x04\
+\xc1\x96\x4d\x4a\x8a\xb6\xdd\x5d\x45\x51\xd7\x75\xac\x8b\x59\x55\
+\xe7\x91\xe4\x9c\x47\x58\xf4\x74\xe4\xea\xb0\x09\xe5\xf3\x6b\x07\
+\x85\x73\x2e\x7a\xf1\x12\x84\x99\x43\x58\xa7\x64\x97\xe5\x5e\x1c\
+\xd5\xb6\xce\xca\xe6\xa9\xaa\xb7\x29\xd9\x66\x6d\x1d\x0e\x9f\x39\
+\x73\xce\x48\xa3\x80\xf7\xef\xa0\x18\xcd\x8c\xb4\x12\x12\xc5\x24\
+\x97\x5f\xfa\xe0\x5d\xd6\x16\x80\xd9\xbe\x03\xb5\x0c\xf1\x72\xa4\
+\x42\x33\x2e\x35\x97\x77\x33\x13\x9f\x2b\x02\x9b\x76\x26\xf6\x54\
+\xe8\xd5\x99\x59\xc6\x2e\xd1\xbd\x79\x66\x35\x4c\x38\x9b\x24\x68\
+\x35\xf3\x7c\xb3\x40\xc1\xb4\x12\x16\xa8\x42\x70\x28\xe1\x38\x12\
+\x27\x8c\x45\xe0\x27\x69\x05\x97\xae\x8b\xd0\x41\x45\x94\xaf\x88\
+\x53\x3f\x13\x54\xce\x38\x62\x9f\x74\x4c\xe4\x30\xd1\x50\x87\x0a\
+\xc9\xac\x12\x09\x62\x18\xc4\xd5\x04\x70\xf4\xd2\x45\x02\x7a\x5e\
+\xe2\x6e\xc9\xea\x0f\xd2\xdf\xc6\x4d\x4a\x3e\x59\xde\xbf\x24\xc2\
+\x29\x44\xf9\xdb\xcd\x71\x8e\x49\x18\x93\xcc\xdb\x44\xfe\xb8\xd5\
+\xb3\x36\x63\xe6\xb4\x55\x2f\x6d\x1e\xc5\xb3\x36\x4f\x5e\xba\x48\
+\x40\x97\x45\x26\x93\xc3\x78\xe5\xe4\x2c\xd1\x38\x94\x51\x9c\x46\
+\x3a\x3a\x17\xf1\x97\x35\x46\xe6\xca\xaa\xf4\x04\x9a\xb6\xae\x9e\
+\x3d\xf2\xc8\x5f\x9e\xc1\x40\x71\x4b\xfc\x63\xb6\x4b\x49\x5d\xfd\
+\x2e\xd7\x67\xe6\x5f\x55\x28\x2f\xed\xdb\xd0\xfa\x7a\x13\xf0\x83\
+\x3b\x8b\x33\xc3\x9a\xa3\x6f\x58\x65\x96\x68\xa3\xcd\x9b\x4f\x6a\
+\xc1\xe2\xbb\xd9\xb8\x53\x3f\xef\x6d\x60\xff\x5a\x2d\x8d\x44\x49\
+\x31\x5b\x2d\x77\x64\x8a\x8f\xe2\xd9\x6a\x9d\xbc\x74\x91\x60\x71\
+\x29\xfe\x13\x12\x8f\x44\xf6\x7f\xab\x9b\xbf\x3f\x45\xd8\x3d\
+\x00\x00\x01\x20\
+\x3c\
+\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\
+\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x3e\x3c\x70\x61\x74\x68\
+\x20\x64\x3d\x22\x4d\x34\x2e\x33\x34\x20\x31\x35\x2e\x36\x36\x41\
+\x37\x2e\x39\x37\x20\x37\x2e\x39\x37\x20\x30\x20\x30\x20\x30\x20\
+\x39\x20\x31\x37\x2e\x39\x34\x56\x31\x30\x48\x35\x56\x38\x68\x34\
+\x56\x35\x2e\x38\x33\x61\x33\x20\x33\x20\x30\x20\x31\x20\x31\x20\
+\x32\x20\x30\x56\x38\x68\x34\x76\x32\x68\x2d\x34\x76\x37\x2e\x39\
+\x34\x61\x37\x2e\x39\x37\x20\x37\x2e\x39\x37\x20\x30\x20\x30\x20\
+\x30\x20\x34\x2e\x36\x36\x2d\x32\x2e\x32\x38\x6c\x2d\x31\x2e\x34\
+\x32\x2d\x31\x2e\x34\x32\x68\x35\x2e\x36\x36\x6c\x2d\x32\x2e\x38\
+\x33\x20\x32\x2e\x38\x33\x61\x31\x30\x20\x31\x30\x20\x30\x20\x30\
+\x20\x31\x2d\x31\x34\x2e\x31\x34\x20\x30\x4c\x2e\x31\x20\x31\x34\
+\x2e\x32\x34\x68\x35\x2e\x36\x36\x6c\x2d\x31\x2e\x34\x32\x20\x31\
+\x2e\x34\x32\x7a\x4d\x31\x30\x20\x34\x61\x31\x20\x31\x20\x30\x20\
+\x31\x20\x30\x20\x30\x2d\x32\x20\x31\x20\x31\x20\x30\x20\x30\x20\
+\x30\x20\x30\x20\x32\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\x6c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x53\x61\x76\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\
+\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\
+\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\
+\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\x79\x3d\
+\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\
+\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\
+\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\
+\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\
+\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\
+\x31\x35\x2e\x31\x37\x33\x2c\x32\x48\x34\x43\x32\x2e\x38\x39\x39\
+\x2c\x32\x2c\x32\x2c\x32\x2e\x39\x2c\x32\x2c\x34\x76\x31\x32\x63\
+\x30\x2c\x31\x2e\x31\x2c\x30\x2e\x38\x39\x39\x2c\x32\x2c\x32\x2c\
+\x32\x68\x31\x32\x63\x31\x2e\x31\x30\x31\x2c\x30\x2c\x32\x2d\x30\
+\x2e\x39\x2c\x32\x2d\x32\x56\x35\x2e\x31\x32\x37\x4c\x31\x35\x2e\
+\x31\x37\x33\x2c\x32\x7a\x20\x4d\x31\x34\x2c\x38\x63\x30\x2c\x30\
+\x2e\x35\x34\x39\x2d\x30\x2e\x34\x35\x2c\x31\x2d\x31\x2c\x31\x48\
+\x37\x0d\x0a\x09\x43\x36\x2e\x34\x35\x2c\x39\x2c\x36\x2c\x38\x2e\
+\x35\x34\x39\x2c\x36\x2c\x38\x56\x33\x68\x38\x56\x38\x7a\x20\x4d\
+\x31\x33\x2c\x34\x68\x2d\x32\x76\x34\x68\x32\x56\x34\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xbd\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x69\x72\x63\x6c\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\
+\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\
+\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\
+\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\
+\x6f\x78\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\
+\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\
+\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\
+\x22\x4d\x31\x30\x2c\x30\x2e\x34\x43\x34\x2e\x36\x39\x38\x2c\x30\
+\x2e\x34\x2c\x30\x2e\x34\x2c\x34\x2e\x36\x39\x38\x2c\x30\x2e\x34\
+\x2c\x31\x30\x43\x30\x2e\x34\x2c\x31\x35\x2e\x33\x30\x32\x2c\x34\
+\x2e\x36\x39\x38\x2c\x31\x39\x2e\x36\x2c\x31\x30\x2c\x31\x39\x2e\
+\x36\x63\x35\x2e\x33\x30\x31\x2c\x30\x2c\x39\x2e\x36\x2d\x34\x2e\
+\x32\x39\x38\x2c\x39\x2e\x36\x2d\x39\x2e\x36\x30\x31\x0d\x0a\x09\
+\x43\x31\x39\x2e\x36\x2c\x34\x2e\x36\x39\x38\x2c\x31\x35\x2e\x33\
+\x30\x31\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\x34\x7a\x20\x4d\
+\x31\x30\x2c\x31\x37\x2e\x35\x39\x39\x63\x2d\x34\x2e\x31\x39\x37\
+\x2c\x30\x2d\x37\x2e\x36\x2d\x33\x2e\x34\x30\x32\x2d\x37\x2e\x36\
+\x2d\x37\x2e\x36\x53\x35\x2e\x38\x30\x32\x2c\x32\x2e\x34\x2c\x31\
+\x30\x2c\x32\x2e\x34\x63\x34\x2e\x31\x39\x37\x2c\x30\x2c\x37\x2e\
+\x36\x30\x31\x2c\x33\x2e\x34\x30\x32\x2c\x37\x2e\x36\x30\x31\x2c\
+\x37\x2e\x36\x0d\x0a\x09\x53\x31\x34\x2e\x31\x39\x37\x2c\x31\x37\
+\x2e\x35\x39\x39\x2c\x31\x30\x2c\x31\x37\x2e\x35\x39\x39\x7a\x22\
+\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x65\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\x76\x65\x72\x73\
+\x69\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\
+\x38\x33\x20\x31\x38\x2e\x37\x35\x20\x31\x38\x2e\x37\x35\x27\x20\
+\x77\x69\x64\x74\x68\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\
+\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x27\x3e\x0a\x3c\
+\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\
+\x20\x36\x33\x2e\x32\x33\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\
+\x68\x20\x64\x3d\x27\x4d\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x20\
+\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\x34\
+\x20\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\
+\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\x38\x2e\x36\
+\x35\x37\x33\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\
+\x38\x2e\x36\x35\x37\x33\x34\x20\x38\x2e\x36\x35\x37\x33\x34\x5a\
+\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\
+\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\
+\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\
+\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\
+\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x35\x30\x35\x36\x32\x27\
+\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\
+\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\
+\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\x20\x36\x33\x2e\x32\x33\
+\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\
+\x20\x34\x2e\x33\x32\x38\x36\x37\x20\x30\x43\x20\x34\x2e\x33\x32\
+\x38\x36\x37\x20\x2d\x32\x2e\x33\x39\x30\x36\x36\x20\x32\x2e\x33\
+\x39\x30\x36\x36\x20\x2d\x34\x2e\x33\x32\x38\x36\x37\x20\x30\x20\
+\x2d\x34\x2e\x33\x32\x38\x36\x37\x43\x20\x2d\x32\x2e\x33\x39\x30\
+\x36\x36\x20\x2d\x34\x2e\x33\x32\x38\x36\x37\x20\x2d\x34\x2e\x33\
+\x32\x38\x36\x37\x20\x2d\x32\x2e\x33\x39\x30\x36\x36\x20\x2d\x34\
+\x2e\x33\x32\x38\x36\x37\x20\x2d\x30\x43\x20\x2d\x34\x2e\x33\x32\
+\x38\x36\x37\x20\x32\x2e\x33\x39\x30\x36\x36\x20\x2d\x32\x2e\x33\
+\x39\x30\x36\x36\x20\x34\x2e\x33\x32\x38\x36\x37\x20\x30\x20\x34\
+\x2e\x33\x32\x38\x36\x37\x43\x20\x32\x2e\x33\x39\x30\x36\x36\x20\
+\x34\x2e\x33\x32\x38\x36\x37\x20\x34\x2e\x33\x32\x38\x36\x37\x20\
+\x32\x2e\x33\x39\x30\x36\x36\x20\x34\x2e\x33\x32\x38\x36\x37\x20\
+\x30\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\
+\x73\x76\x67\x3e\
+"
+
+qt_resource_name = b"\
+\x00\x05\
+\x00\x6f\xa6\x53\
+\x00\x69\
+\x00\x63\x00\x6f\x00\x6e\x00\x73\
+\x00\x10\
+\x08\x89\xfa\x47\
+\x00\x63\
+\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x6f\x00\x72\x00\x69\x00\x67\x00\x69\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0e\
+\x05\xed\x38\x67\
+\x00\x61\
+\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x6d\x00\x6f\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x14\
+\x0f\xa5\xe0\xc7\
+\x00\x6d\
+\x00\x61\x00\x67\x00\x6e\x00\x69\x00\x66\x00\x79\x00\x69\x00\x6e\x00\x67\x00\x2d\x00\x67\x00\x6c\x00\x61\x00\x73\x00\x73\x00\x2e\
+\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x09\x76\x60\xc7\
+\x00\x63\
+\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2d\x00\x72\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x0c\xf7\x55\x87\
+\x00\x74\
+\x00\x65\x00\x78\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x0c\x57\x65\x47\
+\x00\x61\
+\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x72\x00\x65\x00\x73\x00\x69\x00\x7a\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x07\x0e\xc4\x87\
+\x00\x6f\
+\x00\x70\x00\x65\x00\x6e\x00\x70\x00\x6f\x00\x6c\x00\x79\x00\x67\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1d\
+\x06\xec\xf4\xc7\
+\x00\x63\
+\x00\x68\x00\x65\x00\x76\x00\x72\x00\x6f\x00\x6e\x00\x2d\x00\x77\x00\x69\x00\x74\x00\x68\x00\x2d\x00\x63\x00\x69\x00\x72\x00\x63\
+\x00\x6c\x00\x65\x00\x2d\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x08\xe4\xaf\x47\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x64\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x05\xa8\x57\x87\
+\x00\x63\
+\x00\x6f\x00\x64\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x11\
+\x0c\xa7\xc7\x47\
+\x00\x63\
+\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x70\x00\x6f\x00\x6c\x00\x79\x00\x67\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+\x00\x11\
+\x01\x60\xbc\x47\
+\x00\x73\
+\x00\x6f\x00\x63\x00\x69\x00\x61\x00\x6c\x00\x2d\x00\x70\x00\x79\x00\x74\x00\x68\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+\x00\x19\
+\x0f\xef\x7b\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x63\x00\x6f\x00\x6c\x00\x6f\x00\x72\x00\x2d\x00\x70\x00\x61\x00\x6c\
+\x00\x65\x00\x74\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x12\
+\x08\x55\xef\xc7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x64\x00\x65\x00\x6c\x00\x65\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x12\
+\x08\x79\x97\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x63\x00\x61\x00\x6d\x00\x65\x00\x72\x00\x61\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x19\
+\x0a\x43\x45\xc7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x66\x00\x6f\x00\x72\
+\x00\x77\x00\x61\x00\x72\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x01\xca\x6d\x87\
+\x00\x62\
+\x00\x75\x00\x63\x00\x6b\x00\x65\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x13\
+\x03\x24\x75\x47\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x72\x00\x65\x00\x66\x00\x72\x00\x65\x00\x73\x00\x68\x00\x2e\x00\x73\
+\x00\x76\x00\x67\
+\x00\x09\
+\x0b\x9e\x89\x07\
+\x00\x63\
+\x00\x68\x00\x65\x00\x63\x00\x6b\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1c\
+\x08\x8a\x79\x07\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x72\x00\x61\x00\x64\x00\x69\x00\x6f\x00\x2d\x00\x62\x00\x75\x00\x74\
+\x00\x74\x00\x6f\x00\x6e\x00\x2d\x00\x6f\x00\x66\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1b\
+\x0e\xb5\x68\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x72\x00\x61\x00\x64\x00\x69\x00\x6f\x00\x2d\x00\x62\x00\x75\x00\x74\
+\x00\x74\x00\x6f\x00\x6e\x00\x2d\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x12\
+\x0c\x5e\xd4\xa7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x6c\x00\x6f\x00\x63\x00\x61\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x12\
+\x04\xb2\x21\x47\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x65\x00\x78\x00\x70\x00\x61\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x0e\
+\x0f\xcb\xd5\xc7\
+\x00\x70\
+\x00\x6c\x00\x75\x00\x73\x00\x2d\x00\x72\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x17\
+\x07\x87\x48\x27\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x66\x00\x6f\x00\x6c\x00\x64\x00\x65\x00\x72\x00\x2d\x00\x6f\x00\x70\
+\x00\x65\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x06\xe3\xaf\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x68\x00\x61\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x04\xf2\xa7\x87\
+\x00\x63\
+\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x63\x00\x75\x00\x72\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x17\
+\x06\xc6\x02\xa7\
+\x00\x74\
+\x00\x72\x00\x69\x00\x61\x00\x6e\x00\x67\x00\x6c\x00\x65\x00\x2d\x00\x73\x00\x74\x00\x72\x00\x6f\x00\x6b\x00\x65\x00\x64\x00\x2d\
+\x00\x31\x00\x35\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0d\
+\x05\x20\xce\x87\
+\x00\x6f\
+\x00\x70\x00\x65\x00\x6e\x00\x63\x00\x75\x00\x72\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x07\
+\x0c\xf8\x5a\x07\
+\x00\x65\
+\x00\x79\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x0b\x07\x57\xa7\
+\x00\x65\
+\x00\x64\x00\x69\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x16\
+\x01\xfb\x76\x27\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x62\x00\x61\x00\x63\
+\x00\x6b\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1c\
+\x04\x66\xe1\x67\
+\x00\x63\
+\x00\x68\x00\x65\x00\x76\x00\x72\x00\x6f\x00\x6e\x00\x2d\x00\x77\x00\x69\x00\x74\x00\x68\x00\x2d\x00\x63\x00\x69\x00\x72\x00\x63\
+\x00\x6c\x00\x65\x00\x2d\x00\x6c\x00\x65\x00\x66\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x15\
+\x0f\xc4\x59\xe7\
+\x00\x73\
+\x00\x75\x00\x62\x00\x64\x00\x69\x00\x72\x00\x65\x00\x63\x00\x74\x00\x6f\x00\x72\x00\x79\x00\x2d\x00\x6c\x00\x65\x00\x66\x00\x74\
+\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x11\
+\x0c\xdb\x38\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+\x00\x08\
+\x08\xf7\x57\x07\
+\x00\x67\
+\x00\x72\x00\x69\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x04\xa9\x22\xc7\
+\x00\x66\
+\x00\x69\x00\x6c\x00\x6c\x00\x65\x00\x64\x00\x62\x00\x75\x00\x63\x00\x6b\x00\x65\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0f\x68\x53\xe7\
+\x00\x61\
+\x00\x6e\x00\x63\x00\x68\x00\x6f\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x08\xc8\x55\xe7\
+\x00\x73\
+\x00\x61\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0a\x2d\x1b\xc7\
+\x00\x63\
+\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0a\xc8\x62\x67\
+\x00\x63\
+\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\
+"
+
+qt_resource_struct_v1 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x29\x00\x00\x00\x02\
+\x00\x00\x01\xae\x00\x00\x00\x00\x00\x01\x00\x00\x24\x33\
+\x00\x00\x02\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x39\x2f\
+\x00\x00\x04\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x74\xb4\
+\x00\x00\x02\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x3e\xea\
+\x00\x00\x05\x16\x00\x00\x00\x00\x00\x01\x00\x00\x77\x35\
+\x00\x00\x05\xc2\x00\x01\x00\x00\x00\x01\x00\x00\x80\x09\
+\x00\x00\x03\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x4f\xdc\
+\x00\x00\x04\x42\x00\x00\x00\x00\x00\x01\x00\x00\x5f\x35\
+\x00\x00\x04\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x68\xc4\
+\x00\x00\x01\x70\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x82\
+\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x04\x14\
+\x00\x00\x04\x66\x00\x00\x00\x00\x00\x01\x00\x00\x63\xf6\
+\x00\x00\x04\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x59\x67\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x15\x4c\
+\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x11\x26\
+\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x56\x11\
+\x00\x00\x02\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x30\xe2\
+\x00\x00\x02\x38\x00\x00\x00\x00\x00\x01\x00\x00\x33\x88\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x02\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x45\x24\
+\x00\x00\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x83\x51\
+\x00\x00\x01\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x19\x05\
+\x00\x00\x05\xac\x00\x01\x00\x00\x00\x01\x00\x00\x7e\x28\
+\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x78\
+\x00\x00\x06\x18\x00\x00\x00\x00\x00\x01\x00\x00\x85\xc1\
+\x00\x00\x02\x62\x00\x00\x00\x00\x00\x01\x00\x00\x36\xae\
+\x00\x00\x06\x32\x00\x00\x00\x00\x00\x01\x00\x00\x88\x82\
+\x00\x00\x04\xce\x00\x00\x00\x00\x00\x01\x00\x00\x71\x44\
+\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x42\x14\
+\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xa3\
+\x00\x00\x03\x72\x00\x00\x00\x00\x00\x01\x00\x00\x4b\x74\
+\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xff\
+\x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x00\x7b\x6d\
+\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xc2\
+\x00\x00\x04\xba\x00\x00\x00\x00\x00\x01\x00\x00\x6d\x55\
+\x00\x00\x03\x36\x00\x00\x00\x00\x00\x01\x00\x00\x48\x24\
+\x00\x00\x05\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x82\x2d\
+\x00\x00\x00\x58\x00\x00\x00\x00\x00\x01\x00\x00\x06\xe1\
+\x00\x00\x05\x54\x00\x00\x00\x00\x00\x01\x00\x00\x7a\xfd\
+\x00\x00\x03\xc6\x00\x00\x00\x00\x00\x01\x00\x00\x53\x16\
+\x00\x00\x01\xd6\x00\x00\x00\x00\x00\x01\x00\x00\x2b\xb7\
+"
+
+qt_resource_struct_v2 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x29\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x01\xae\x00\x00\x00\x00\x00\x01\x00\x00\x24\x33\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x39\x2f\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x74\xb4\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x02\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x3e\xea\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x05\x16\x00\x00\x00\x00\x00\x01\x00\x00\x77\x35\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x05\xc2\x00\x01\x00\x00\x00\x01\x00\x00\x80\x09\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x4f\xdc\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\x42\x00\x00\x00\x00\x00\x01\x00\x00\x5f\x35\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x04\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x68\xc4\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x01\x70\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x82\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x04\x14\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\x66\x00\x00\x00\x00\x00\x01\x00\x00\x63\xf6\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x04\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x59\x67\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x15\x4c\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x11\x26\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x56\x11\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x02\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x30\xe2\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x02\x38\x00\x00\x00\x00\x00\x01\x00\x00\x33\x88\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x45\x24\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x83\x51\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x01\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x19\x05\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x05\xac\x00\x01\x00\x00\x00\x01\x00\x00\x7e\x28\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x78\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x06\x18\x00\x00\x00\x00\x00\x01\x00\x00\x85\xc1\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\x62\x00\x00\x00\x00\x00\x01\x00\x00\x36\xae\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x06\x32\x00\x00\x00\x00\x00\x01\x00\x00\x88\x82\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\xce\x00\x00\x00\x00\x00\x01\x00\x00\x71\x44\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x42\x14\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xa3\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x03\x72\x00\x00\x00\x00\x00\x01\x00\x00\x4b\x74\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xff\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x00\x7b\x6d\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xc2\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x04\xba\x00\x00\x00\x00\x00\x01\x00\x00\x6d\x55\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\x36\x00\x00\x00\x00\x00\x01\x00\x00\x48\x24\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x05\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x82\x2d\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x00\x58\x00\x00\x00\x00\x00\x01\x00\x00\x06\xe1\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x05\x54\x00\x00\x00\x00\x00\x01\x00\x00\x7a\xfd\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\xc6\x00\x00\x00\x00\x00\x01\x00\x00\x53\x16\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x01\xd6\x00\x00\x00\x00\x00\x01\x00\x00\x2b\xb7\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+"
+
+qt_version = QtCore.qVersion().split('.')
+if qt_version < ['5', '8', '0']:
+ rcc_version = 1
+ qt_resource_struct = qt_resource_struct_v1
+else:
+ rcc_version = 2
+ qt_resource_struct = qt_resource_struct_v2
+
+def qInitResources():
+ QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
Property changes on: trunk/Build/source/utils/asymptote/GUI/icons_rc.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/labelEditor.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/labelEditor.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/labelEditor.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+
+from pyUIClass.labelTextEditor import Ui_Dialog
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtSvg as Qs
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import xasyArgs as xa
+import xasy2asy as x2a
+import subprocess
+import xasyOptions as xo
+import xasyUtils as xu
+import tempfile
+import uuid
+import os
+import io
+
+
+class labelEditor(Qw.QDialog):
+ def __init__(self, text=''):
+ super().__init__()
+ self.ui = Ui_Dialog()
+ self.ui.setupUi(self)
+
+ self.ui.btnAccept.clicked.connect(self.accept)
+ self.ui.btnCancel.clicked.connect(self.reject)
+ self.ui.chkMathMode.stateChanged.connect(self.chkMathModeChecked)
+ self.ui.btnPreview.clicked.connect(self.btnPreviewOnClick)
+ self.ui.btnGetText.clicked.connect(self.btnGetTextOnClick)
+
+ self.svgPreview = None
+ self.initializeText(text)
+
+ def initializeText(self, text: str):
+ if text[0] == '$' and text[-1] == '$':
+ self.ui.chkMathMode.setChecked(True)
+ text = text.strip('$')
+
+ if text.startswith('\\displaystyle{'):
+ self.ui.cmbMathStyle.setCurrentText('Display Style')
+ text = text.rstrip('}')
+ text = text.replace('\\displaystyle{', '', 1)
+ elif text.startswith('\\scriptstyle{'):
+ self.ui.cmbMathStyle.setCurrentText('Script Style')
+ text = text.rstrip('}')
+ text = text.replace('\\scriptstyle{', '', 1)
+
+ self.ui.txtLabelEdit.setPlainText(text)
+
+ def chkMathModeChecked(self, checked):
+ self.ui.cmbMathStyle.setEnabled(checked)
+
+ def getText(self):
+ rawText = self.ui.txtLabelEdit.toPlainText()
+ rawText.replace('\n', ' ')
+ if self.ui.chkMathMode.isChecked():
+ prefix = ''
+ suffix = ''
+ if self.ui.cmbMathStyle.currentText() == 'Display Style':
+ prefix = '\\displaystyle{'
+ suffix = '}'
+ elif self.ui.cmbMathStyle.currentText() == 'Script Style':
+ prefix = '\\scriptstyle{'
+ suffix = '}'
+ return '${0}{1}{2}$'.format(prefix, rawText, suffix)
+ else:
+ return rawText
+
+ def btnPreviewOnClick(self):
+ path = xa.getArgs().asypath
+ if path is None:
+ opt = xo.xasyOptions().load()
+ path = opt['asyPath']
+
+ asyInput = """
+ frame f;
+ label(f, "{0}");
+ write(min(f), newl);
+ write(max(f), newl);
+ shipout(f);
+ """
+
+ self.svgPreview = Qs.QSvgRenderer()
+ with tempfile.TemporaryDirectory(prefix='xasylbl_') as tmpdir:
+ id = str(uuid.uuid4())
+ tmpFile = os.path.join(tmpdir, 'lbl-{0}.svg'.format(id))
+
+ with subprocess.Popen(args=[path, '-fsvg', '-o', tmpFile, '-'], encoding='utf-8', stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE) as asy:
+ asy.stdin.write(asyInput.format(self.getText()))
+ asy.stdin.close()
+ out = asy.stdout.read()
+
+ raw_array = out.splitlines()
+
+ bounds_1, bounds_2 = [val.strip() for val in raw_array]
+
+ min_bounds = xu.listize(bounds_1, (float, float))
+ max_bounds = xu.listize(bounds_2, (float, float))
+
+ new_rect = self.processBounds(min_bounds, max_bounds)
+ self.svgPreview.load(tmpFile)
+
+
+
+ self.drawPreview(new_rect)
+
+ def drawPreview(self, naturalBounds):
+ img = Qg.QPixmap(self.ui.lblLabelPreview.size())
+ img.fill(Qg.QColor.fromRgbF(1, 1, 1, 1))
+ if self.svgPreview is None:
+ pass
+ else:
+ with Qg.QPainter(img) as pnt:
+ scale_ratio = self.getIdealScaleRatio(naturalBounds, self.ui.lblLabelPreview.rect())
+
+ pnt.translate(self.ui.lblLabelPreview.rect().center())
+ pnt.scale(scale_ratio, scale_ratio)
+ self.svgPreview.render(pnt, naturalBounds)
+ self.ui.lblLabelPreview.setPixmap(img)
+
+
+ def getIdealScaleRatio(self, rect, boundsRect):
+ assert isinstance(rect, (Qc.QRect, Qc.QRectF))
+ assert isinstance(rect, (Qc.QRect, Qc.QRectF))
+
+ magic_ratio = 0.50
+ idealRatioHeight = (magic_ratio * boundsRect.height()) / rect.height()
+ magicRatioWidth = 0.50
+
+ if idealRatioHeight * rect.width() > magicRatioWidth * boundsRect.width():
+ idealRatioWidth = (magicRatioWidth * boundsRect.width()) / rect.width()
+ idealRatio = min(idealRatioHeight, idealRatioWidth)
+ else:
+ idealRatio = idealRatioHeight
+ return idealRatio
+
+ def processBounds(self, minPt, maxPt):
+ p1x, p1y = minPt
+ p2x, p2y = maxPt
+
+ minPt = Qc.QPointF(p1x, p1y)
+ maxPt = Qc.QPointF(p2x, p2y)
+
+ newRect = Qc.QRectF(minPt, maxPt)
+ return newRect
+
+
+ def btnGetTextOnClick(self):
+ msgbox = Qw.QMessageBox()
+ msgbox.setText('Text Preview:\n' + self.getText())
+ msgbox.setWindowTitle('Text preview')
+ msgbox.show()
+ return msgbox.exec_()
Property changes on: trunk/Build/source/utils/asymptote/GUI/labelEditor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,24 @@
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Supakorn Rassameemasmuang, 2018.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-05-16 17:07-0600\n"
+"PO-Revision-Date: 2018-05-16 17:20-0700\n"
+"Last-Translator: Supakorn Rassameemasmuang <rassamee at ualberta.ca>\n"
+"Language-Team: English <kde-i18n-doc at kde.org>\n"
+"Language: th\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 2.0\n"
+
+#: xasyStrings.py:10
+msgid "Rotate"
+msgstr "หมุน"
+
+
Property changes on: trunk/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/custMatTransform.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Dialog(object):
+ def setupUi(self, Dialog):
+ Dialog.setObjectName("Dialog")
+ Dialog.resize(500, 320)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
+ Dialog.setSizePolicy(sizePolicy)
+ Dialog.setMinimumSize(QtCore.QSize(500, 320))
+ Dialog.setMaximumSize(QtCore.QSize(500, 320))
+ Dialog.setMouseTracking(False)
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(":/icons/android-expand.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ Dialog.setWindowIcon(icon)
+ Dialog.setSizeGripEnabled(True)
+ Dialog.setModal(False)
+ self.centralFrame = QtWidgets.QFrame(Dialog)
+ self.centralFrame.setGeometry(QtCore.QRect(20, 20, 461, 271))
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.centralFrame.sizePolicy().hasHeightForWidth())
+ self.centralFrame.setSizePolicy(sizePolicy)
+ self.centralFrame.setBaseSize(QtCore.QSize(0, 0))
+ self.centralFrame.setObjectName("centralFrame")
+ self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralFrame)
+ self.verticalLayout_3.setSpacing(4)
+ self.verticalLayout_3.setObjectName("verticalLayout_3")
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+ self.verticalLayout = QtWidgets.QVBoxLayout()
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.label = QtWidgets.QLabel(self.centralFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
+ self.label.setSizePolicy(sizePolicy)
+ self.label.setObjectName("label")
+ self.verticalLayout.addWidget(self.label)
+ self.gridFrame = QtWidgets.QFrame(self.centralFrame)
+ self.gridFrame.setFrameShape(QtWidgets.QFrame.Box)
+ self.gridFrame.setObjectName("gridFrame")
+ self.gridLayout = QtWidgets.QGridLayout(self.gridFrame)
+ self.gridLayout.setObjectName("gridLayout")
+ self.lineMat00 = QtWidgets.QLineEdit(self.gridFrame)
+ self.lineMat00.setMaximumSize(QtCore.QSize(70, 16777215))
+ self.lineMat00.setObjectName("lineMat00")
+ self.gridLayout.addWidget(self.lineMat00, 1, 0, 1, 1)
+ self.lineMat11 = QtWidgets.QLineEdit(self.gridFrame)
+ self.lineMat11.setMaximumSize(QtCore.QSize(70, 16777215))
+ self.lineMat11.setObjectName("lineMat11")
+ self.gridLayout.addWidget(self.lineMat11, 2, 1, 1, 1)
+ self.lineMat10 = QtWidgets.QLineEdit(self.gridFrame)
+ self.lineMat10.setMaximumSize(QtCore.QSize(70, 16777215))
+ self.lineMat10.setObjectName("lineMat10")
+ self.gridLayout.addWidget(self.lineMat10, 2, 0, 1, 1)
+ self.lineMat01 = QtWidgets.QLineEdit(self.gridFrame)
+ self.lineMat01.setMaximumSize(QtCore.QSize(70, 16777215))
+ self.lineMat01.setObjectName("lineMat01")
+ self.gridLayout.addWidget(self.lineMat01, 1, 1, 1, 1)
+ self.verticalLayout.addWidget(self.gridFrame)
+ self.horizontalLayout_3.addLayout(self.verticalLayout)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_3.addItem(spacerItem)
+ self.verticalLayout_4 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_4.setObjectName("verticalLayout_4")
+ self.label_3 = QtWidgets.QLabel(self.centralFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth())
+ self.label_3.setSizePolicy(sizePolicy)
+ self.label_3.setObjectName("label_3")
+ self.verticalLayout_4.addWidget(self.label_3)
+ self.gridFrame_2 = QtWidgets.QFrame(self.centralFrame)
+ self.gridFrame_2.setFrameShape(QtWidgets.QFrame.Box)
+ self.gridFrame_2.setObjectName("gridFrame_2")
+ self.gridLayout_2 = QtWidgets.QGridLayout(self.gridFrame_2)
+ self.gridLayout_2.setObjectName("gridLayout_2")
+ self.lineMatTy = QtWidgets.QLineEdit(self.gridFrame_2)
+ self.lineMatTy.setMaximumSize(QtCore.QSize(70, 16777215))
+ self.lineMatTy.setObjectName("lineMatTy")
+ self.gridLayout_2.addWidget(self.lineMatTy, 2, 1, 1, 1)
+ self.lineMatTx = QtWidgets.QLineEdit(self.gridFrame_2)
+ self.lineMatTx.setMaximumSize(QtCore.QSize(70, 16777215))
+ self.lineMatTx.setObjectName("lineMatTx")
+ self.gridLayout_2.addWidget(self.lineMatTx, 1, 1, 1, 1)
+ self.verticalLayout_4.addWidget(self.gridFrame_2)
+ self.horizontalLayout_3.addLayout(self.verticalLayout_4)
+ self.horizontalLayout.addLayout(self.horizontalLayout_3)
+ spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem1)
+ self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_2.setObjectName("verticalLayout_2")
+ self.label_2 = QtWidgets.QLabel(self.centralFrame)
+ self.label_2.setObjectName("label_2")
+ self.verticalLayout_2.addWidget(self.label_2)
+ self.imgPreview = QtWidgets.QLabel(self.centralFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.imgPreview.sizePolicy().hasHeightForWidth())
+ self.imgPreview.setSizePolicy(sizePolicy)
+ self.imgPreview.setMinimumSize(QtCore.QSize(150, 150))
+ self.imgPreview.setBaseSize(QtCore.QSize(300, 300))
+ self.imgPreview.setFrameShape(QtWidgets.QFrame.Box)
+ self.imgPreview.setText("")
+ self.imgPreview.setObjectName("imgPreview")
+ self.verticalLayout_2.addWidget(self.imgPreview)
+ self.horizontalLayout.addLayout(self.verticalLayout_2)
+ self.verticalLayout_3.addLayout(self.horizontalLayout)
+ self.lblAnchor = QtWidgets.QLabel(self.centralFrame)
+ self.lblAnchor.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
+ self.lblAnchor.setObjectName("lblAnchor")
+ self.verticalLayout_3.addWidget(self.lblAnchor)
+ self.lblCoordsMode = QtWidgets.QLabel(self.centralFrame)
+ self.lblCoordsMode.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
+ self.lblCoordsMode.setObjectName("lblCoordsMode")
+ self.verticalLayout_3.addWidget(self.lblCoordsMode)
+ spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_3.addItem(spacerItem2)
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout_2.addItem(spacerItem3)
+ self.btnReset = QtWidgets.QPushButton(self.centralFrame)
+ self.btnReset.setObjectName("btnReset")
+ self.horizontalLayout_2.addWidget(self.btnReset)
+ self.btnCancel = QtWidgets.QPushButton(self.centralFrame)
+ self.btnCancel.setObjectName("btnCancel")
+ self.horizontalLayout_2.addWidget(self.btnCancel)
+ self.btnAccept = QtWidgets.QPushButton(self.centralFrame)
+ self.btnAccept.setObjectName("btnAccept")
+ self.horizontalLayout_2.addWidget(self.btnAccept)
+ self.verticalLayout_3.addLayout(self.horizontalLayout_2)
+
+ self.retranslateUi(Dialog)
+ QtCore.QMetaObject.connectSlotsByName(Dialog)
+
+ def retranslateUi(self, Dialog):
+ _translate = QtCore.QCoreApplication.translate
+ Dialog.setWindowTitle(_translate("Dialog", "Set Custom Transformation"))
+ self.label.setText(_translate("Dialog", "Transformation Matrix"))
+ self.lineMat00.setText(_translate("Dialog", "1"))
+ self.lineMat11.setText(_translate("Dialog", "1"))
+ self.lineMat10.setText(_translate("Dialog", "0"))
+ self.lineMat01.setText(_translate("Dialog", "0"))
+ self.label_3.setText(_translate("Dialog", "Translation"))
+ self.lineMatTy.setText(_translate("Dialog", "0"))
+ self.lineMatTx.setText(_translate("Dialog", "0"))
+ self.label_2.setText(_translate("Dialog", "Preview:"))
+ self.imgPreview.setToolTip(_translate("Dialog", "Shows a red square if transformation determinant is negative."))
+ self.lblAnchor.setText(_translate("Dialog", "Anchor: Top Left"))
+ self.lblCoordsMode.setText(_translate("Dialog", "Coordinates: Global"))
+ self.btnReset.setText(_translate("Dialog", "Reset"))
+ self.btnCancel.setText(_translate("Dialog", "Cancel"))
+ self.btnAccept.setText(_translate("Dialog", "Accept"))
+
+import icons_rc
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/labelTextEditor.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Dialog(object):
+ def setupUi(self, Dialog):
+ Dialog.setObjectName("Dialog")
+ Dialog.resize(473, 424)
+ self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.frame = QtWidgets.QFrame(Dialog)
+ self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
+ self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
+ self.frame.setObjectName("frame")
+ self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.frame)
+ self.verticalLayout_3.setObjectName("verticalLayout_3")
+ self.gridLayout = QtWidgets.QGridLayout()
+ self.gridLayout.setContentsMargins(-1, 0, -1, -1)
+ self.gridLayout.setObjectName("gridLayout")
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.gridLayout.addItem(spacerItem, 0, 2, 1, 1)
+ self.chkMathMode = QtWidgets.QCheckBox(self.frame)
+ self.chkMathMode.setObjectName("chkMathMode")
+ self.gridLayout.addWidget(self.chkMathMode, 0, 0, 1, 1)
+ self.cmbMathStyle = QtWidgets.QComboBox(self.frame)
+ self.cmbMathStyle.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.cmbMathStyle.sizePolicy().hasHeightForWidth())
+ self.cmbMathStyle.setSizePolicy(sizePolicy)
+ self.cmbMathStyle.setMinimumSize(QtCore.QSize(100, 0))
+ self.cmbMathStyle.setObjectName("cmbMathStyle")
+ self.cmbMathStyle.addItem("")
+ self.cmbMathStyle.addItem("")
+ self.cmbMathStyle.addItem("")
+ self.gridLayout.addWidget(self.cmbMathStyle, 0, 1, 1, 1)
+ self.verticalLayout_3.addLayout(self.gridLayout)
+ self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_2.setObjectName("verticalLayout_2")
+ self.txtLabelEdit = QtWidgets.QPlainTextEdit(self.frame)
+ self.txtLabelEdit.setObjectName("txtLabelEdit")
+ self.verticalLayout_2.addWidget(self.txtLabelEdit)
+ self.verticalLayout_3.addLayout(self.verticalLayout_2)
+ self.verticalLayout_4 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_4.setContentsMargins(-1, 0, -1, -1)
+ self.verticalLayout_4.setObjectName("verticalLayout_4")
+ self.label = QtWidgets.QLabel(self.frame)
+ self.label.setObjectName("label")
+ self.verticalLayout_4.addWidget(self.label)
+ self.lblLabelPreview = QtWidgets.QLabel(self.frame)
+ self.lblLabelPreview.setMinimumSize(QtCore.QSize(0, 100))
+ self.lblLabelPreview.setFrameShape(QtWidgets.QFrame.Box)
+ self.lblLabelPreview.setText("")
+ self.lblLabelPreview.setObjectName("lblLabelPreview")
+ self.verticalLayout_4.addWidget(self.lblLabelPreview)
+ self.verticalLayout_3.addLayout(self.verticalLayout_4)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem1)
+ self.btnGetText = QtWidgets.QPushButton(self.frame)
+ self.btnGetText.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnGetText.setText("")
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(":/icons/text.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnGetText.setIcon(icon)
+ self.btnGetText.setFlat(True)
+ self.btnGetText.setObjectName("btnGetText")
+ self.horizontalLayout.addWidget(self.btnGetText)
+ self.btnPreview = QtWidgets.QPushButton(self.frame)
+ self.btnPreview.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnPreview.setText("")
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(":/icons/eye.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnPreview.setIcon(icon1)
+ self.btnPreview.setFlat(True)
+ self.btnPreview.setObjectName("btnPreview")
+ self.horizontalLayout.addWidget(self.btnPreview)
+ self.btnCancel = QtWidgets.QPushButton(self.frame)
+ self.btnCancel.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnCancel.setText("")
+ icon2 = QtGui.QIcon()
+ icon2.addPixmap(QtGui.QPixmap(":/icons/android-close.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnCancel.setIcon(icon2)
+ self.btnCancel.setFlat(True)
+ self.btnCancel.setObjectName("btnCancel")
+ self.horizontalLayout.addWidget(self.btnCancel)
+ self.btnAccept = QtWidgets.QPushButton(self.frame)
+ self.btnAccept.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnAccept.setText("")
+ icon3 = QtGui.QIcon()
+ icon3.addPixmap(QtGui.QPixmap(":/icons/android-done.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnAccept.setIcon(icon3)
+ self.btnAccept.setFlat(True)
+ self.btnAccept.setObjectName("btnAccept")
+ self.horizontalLayout.addWidget(self.btnAccept)
+ self.verticalLayout_3.addLayout(self.horizontalLayout)
+ self.verticalLayout.addWidget(self.frame)
+
+ self.retranslateUi(Dialog)
+ QtCore.QMetaObject.connectSlotsByName(Dialog)
+
+ def retranslateUi(self, Dialog):
+ _translate = QtCore.QCoreApplication.translate
+ Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
+ self.chkMathMode.setText(_translate("Dialog", "Math Mode"))
+ self.cmbMathStyle.setItemText(0, _translate("Dialog", "Inline Style"))
+ self.cmbMathStyle.setItemText(1, _translate("Dialog", "Display Style"))
+ self.cmbMathStyle.setItemText(2, _translate("Dialog", "Script Style"))
+ self.label.setText(_translate("Dialog", "Preview"))
+
+import icons_rc
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/setCustomAnchor.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Dialog(object):
+ def setupUi(self, Dialog):
+ Dialog.setObjectName("Dialog")
+ Dialog.resize(245, 161)
+ self.verticalLayoutWidget = QtWidgets.QWidget(Dialog)
+ self.verticalLayoutWidget.setGeometry(QtCore.QRect(20, 20, 201, 121))
+ self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
+ self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.formLayout = QtWidgets.QFormLayout()
+ self.formLayout.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
+ self.formLayout.setObjectName("formLayout")
+ self.label = QtWidgets.QLabel(self.verticalLayoutWidget)
+ self.label.setObjectName("label")
+ self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
+ self.lineEditX = QtWidgets.QLineEdit(self.verticalLayoutWidget)
+ self.lineEditX.setObjectName("lineEditX")
+ self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEditX)
+ self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget)
+ self.label_2.setObjectName("label_2")
+ self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2)
+ self.lineEditY = QtWidgets.QLineEdit(self.verticalLayoutWidget)
+ self.lineEditY.setObjectName("lineEditY")
+ self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.lineEditY)
+ self.verticalLayout.addLayout(self.formLayout)
+ self.buttonBox = QtWidgets.QDialogButtonBox(self.verticalLayoutWidget)
+ self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
+ self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Reset)
+ self.buttonBox.setObjectName("buttonBox")
+ self.verticalLayout.addWidget(self.buttonBox)
+
+ self.retranslateUi(Dialog)
+ self.buttonBox.accepted.connect(Dialog.accept)
+ self.buttonBox.rejected.connect(Dialog.reject)
+ QtCore.QMetaObject.connectSlotsByName(Dialog)
+
+ def retranslateUi(self, Dialog):
+ _translate = QtCore.QCoreApplication.translate
+ Dialog.setWindowTitle(_translate("Dialog", "Set Custom Anchor"))
+ self.label.setText(_translate("Dialog", "X:"))
+ self.lineEditX.setText(_translate("Dialog", "0"))
+ self.label_2.setText(_translate("Dialog", "Y:"))
+ self.lineEditY.setText(_translate("Dialog", "0"))
+
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_addLabel.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.setWindowModality(QtCore.Qt.NonModal)
+ Form.resize(599, 35)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+ Form.setSizePolicy(sizePolicy)
+ Form.setMinimumSize(QtCore.QSize(0, 35))
+ Form.setMaximumSize(QtCore.QSize(16777215, 35))
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
+ self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout_2.setSpacing(0)
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.txtLabelText = QtWidgets.QLineEdit(Form)
+ self.txtLabelText.setObjectName("txtLabelText")
+ self.horizontalLayout.addWidget(self.txtLabelText)
+ self.btnAdvancedEdit = QtWidgets.QPushButton(Form)
+ self.btnAdvancedEdit.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnAdvancedEdit.setText("")
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnAdvancedEdit.setIcon(icon)
+ self.btnAdvancedEdit.setFlat(True)
+ self.btnAdvancedEdit.setObjectName("btnAdvancedEdit")
+ self.horizontalLayout.addWidget(self.btnAdvancedEdit)
+ self.label = QtWidgets.QLabel(Form)
+ self.label.setObjectName("label")
+ self.horizontalLayout.addWidget(self.label)
+ self.cmbAlign = QtWidgets.QComboBox(Form)
+ self.cmbAlign.setObjectName("cmbAlign")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.cmbAlign.addItem("")
+ self.horizontalLayout.addWidget(self.cmbAlign)
+ self.label_3 = QtWidgets.QLabel(Form)
+ self.label_3.setObjectName("label_3")
+ self.horizontalLayout.addWidget(self.label_3)
+ self.cmbFontSize = QtWidgets.QComboBox(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.cmbFontSize.sizePolicy().hasHeightForWidth())
+ self.cmbFontSize.setSizePolicy(sizePolicy)
+ self.cmbFontSize.setEditable(True)
+ self.cmbFontSize.setObjectName("cmbFontSize")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.cmbFontSize.addItem("")
+ self.horizontalLayout.addWidget(self.cmbFontSize)
+ self.label_2 = QtWidgets.QLabel(Form)
+ self.label_2.setObjectName("label_2")
+ self.horizontalLayout.addWidget(self.label_2)
+ self.txtShiftX = QtWidgets.QLineEdit(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.txtShiftX.sizePolicy().hasHeightForWidth())
+ self.txtShiftX.setSizePolicy(sizePolicy)
+ self.txtShiftX.setMaximumSize(QtCore.QSize(50, 16777215))
+ self.txtShiftX.setObjectName("txtShiftX")
+ self.horizontalLayout.addWidget(self.txtShiftX)
+ self.txtShiftY = QtWidgets.QLineEdit(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.txtShiftY.sizePolicy().hasHeightForWidth())
+ self.txtShiftY.setSizePolicy(sizePolicy)
+ self.txtShiftY.setMaximumSize(QtCore.QSize(50, 16777215))
+ self.txtShiftY.setObjectName("txtShiftY")
+ self.horizontalLayout.addWidget(self.txtShiftY)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.horizontalLayout_2.addLayout(self.horizontalLayout)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "Form"))
+ self.txtLabelText.setToolTip(_translate("Form", "Number of Sides"))
+ self.txtLabelText.setPlaceholderText(_translate("Form", "Text"))
+ self.label.setText(_translate("Form", "Align"))
+ self.cmbAlign.setItemText(0, _translate("Form", "Center"))
+ self.cmbAlign.setItemText(1, _translate("Form", "N"))
+ self.cmbAlign.setItemText(2, _translate("Form", "E"))
+ self.cmbAlign.setItemText(3, _translate("Form", "W"))
+ self.cmbAlign.setItemText(4, _translate("Form", "S"))
+ self.cmbAlign.setItemText(5, _translate("Form", "NW"))
+ self.cmbAlign.setItemText(6, _translate("Form", "NE"))
+ self.cmbAlign.setItemText(7, _translate("Form", "SW"))
+ self.cmbAlign.setItemText(8, _translate("Form", "SE"))
+ self.cmbAlign.setItemText(9, _translate("Form", "Custom"))
+ self.label_3.setText(_translate("Form", "Font Size"))
+ self.cmbFontSize.setItemText(0, _translate("Form", "-"))
+ self.cmbFontSize.setItemText(1, _translate("Form", "8"))
+ self.cmbFontSize.setItemText(2, _translate("Form", "9"))
+ self.cmbFontSize.setItemText(3, _translate("Form", "10"))
+ self.cmbFontSize.setItemText(4, _translate("Form", "11"))
+ self.cmbFontSize.setItemText(5, _translate("Form", "12"))
+ self.cmbFontSize.setItemText(6, _translate("Form", "14"))
+ self.cmbFontSize.setItemText(7, _translate("Form", "18"))
+ self.cmbFontSize.setItemText(8, _translate("Form", "24"))
+ self.cmbFontSize.setItemText(9, _translate("Form", "48"))
+ self.cmbFontSize.setItemText(10, _translate("Form", "72"))
+ self.label_2.setText(_translate("Form", "Custom Align"))
+ self.txtShiftX.setPlaceholderText(_translate("Form", "Shift X"))
+ self.txtShiftY.setPlaceholderText(_translate("Form", "Shift Y"))
+
+import icons_rc
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_addPolyOpt.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.setWindowModality(QtCore.Qt.NonModal)
+ Form.resize(326, 35)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+ Form.setSizePolicy(sizePolicy)
+ Form.setMinimumSize(QtCore.QSize(0, 35))
+ Form.setMaximumSize(QtCore.QSize(16777215, 35))
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
+ self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout_2.setSpacing(0)
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.chkInscribed = QtWidgets.QCheckBox(Form)
+ self.chkInscribed.setObjectName("chkInscribed")
+ self.horizontalLayout.addWidget(self.chkInscribed)
+ self.txtSides = QtWidgets.QLineEdit(Form)
+ self.txtSides.setObjectName("txtSides")
+ self.horizontalLayout.addWidget(self.txtSides)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.horizontalLayout_2.addLayout(self.horizontalLayout)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "Form"))
+ self.chkInscribed.setText(_translate("Form", "Start at Vertex"))
+ self.txtSides.setToolTip(_translate("Form", "Number of Sides"))
+ self.txtSides.setPlaceholderText(_translate("Form", "Sides"))
+
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_editBezier.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.setWindowModality(QtCore.Qt.NonModal)
+ Form.resize(692, 35)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+ Form.setSizePolicy(sizePolicy)
+ Form.setMinimumSize(QtCore.QSize(0, 35))
+ Form.setMaximumSize(QtCore.QSize(16777215, 35))
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
+ self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout_2.setSpacing(0)
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.cmbLockMode = QtWidgets.QComboBox(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.cmbLockMode.sizePolicy().hasHeightForWidth())
+ self.cmbLockMode.setSizePolicy(sizePolicy)
+ self.cmbLockMode.setObjectName("cmbLockMode")
+ self.cmbLockMode.addItem("")
+ self.cmbLockMode.addItem("")
+ self.cmbLockMode.addItem("")
+ self.horizontalLayout.addWidget(self.cmbLockMode)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.chkRecompute = QtWidgets.QCheckBox(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.chkRecompute.sizePolicy().hasHeightForWidth())
+ self.chkRecompute.setSizePolicy(sizePolicy)
+ self.chkRecompute.setObjectName("chkRecompute")
+ self.horizontalLayout.addWidget(self.chkRecompute)
+ self.btnForceRecompute = QtWidgets.QPushButton(Form)
+ self.btnForceRecompute.setObjectName("btnForceRecompute")
+ self.horizontalLayout.addWidget(self.btnForceRecompute)
+ self.btnOk = QtWidgets.QPushButton(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnOk.sizePolicy().hasHeightForWidth())
+ self.btnOk.setSizePolicy(sizePolicy)
+ self.btnOk.setMaximumSize(QtCore.QSize(25, 25))
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(":/icons/check.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnOk.setIcon(icon)
+ self.btnOk.setFlat(True)
+ self.btnOk.setObjectName("btnOk")
+ self.horizontalLayout.addWidget(self.btnOk)
+ self.btnCancel = QtWidgets.QPushButton(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnCancel.sizePolicy().hasHeightForWidth())
+ self.btnCancel.setSizePolicy(sizePolicy)
+ self.btnCancel.setMaximumSize(QtCore.QSize(25, 25))
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(":/icons/close-round.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnCancel.setIcon(icon1)
+ self.btnCancel.setFlat(True)
+ self.btnCancel.setObjectName("btnCancel")
+ self.horizontalLayout.addWidget(self.btnCancel)
+ self.horizontalLayout_2.addLayout(self.horizontalLayout)
+
+ self.retranslateUi(Form)
+ self.cmbLockMode.setCurrentIndex(1)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "Form"))
+ self.cmbLockMode.setItemText(0, _translate("Form", "No Lock"))
+ self.cmbLockMode.setItemText(1, _translate("Form", "Lock Angle"))
+ self.cmbLockMode.setItemText(2, _translate("Form", "Lock Angle & Scale"))
+ self.chkRecompute.setText(_translate("Form", "Recompute Path"))
+ self.btnForceRecompute.setText(_translate("Form", "Recompute Once"))
+
+import icons_rc
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widgetPointEditor.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+ def setupUi(self, Form):
+ Form.setObjectName("Form")
+ Form.resize(324, 67)
+ self.verticalLayout = QtWidgets.QVBoxLayout(Form)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.nameLabel = QtWidgets.QLabel(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.nameLabel.sizePolicy().hasHeightForWidth())
+ self.nameLabel.setSizePolicy(sizePolicy)
+ self.nameLabel.setObjectName("nameLabel")
+ self.verticalLayout.addWidget(self.nameLabel)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.lineXorA = QtWidgets.QLineEdit(Form)
+ self.lineXorA.setEnabled(False)
+ self.lineXorA.setReadOnly(False)
+ self.lineXorA.setObjectName("lineXorA")
+ self.horizontalLayout.addWidget(self.lineXorA)
+ self.lineYorM = QtWidgets.QLineEdit(Form)
+ self.lineYorM.setEnabled(False)
+ self.lineYorM.setAutoFillBackground(False)
+ self.lineYorM.setReadOnly(False)
+ self.lineYorM.setObjectName("lineYorM")
+ self.horizontalLayout.addWidget(self.lineYorM)
+ self.btnRelative = QtWidgets.QPushButton(Form)
+ self.btnRelative.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnRelative.sizePolicy().hasHeightForWidth())
+ self.btnRelative.setSizePolicy(sizePolicy)
+ self.btnRelative.setText("")
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(":/icons/android-locate.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnRelative.setIcon(icon)
+ self.btnRelative.setCheckable(True)
+ self.btnRelative.setFlat(False)
+ self.btnRelative.setObjectName("btnRelative")
+ self.horizontalLayout.addWidget(self.btnRelative)
+ self.btnPolar = QtWidgets.QPushButton(Form)
+ self.btnPolar.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnPolar.sizePolicy().hasHeightForWidth())
+ self.btnPolar.setSizePolicy(sizePolicy)
+ self.btnPolar.setText("")
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(":/icons/android-radio-button-off.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnPolar.setIcon(icon1)
+ self.btnPolar.setCheckable(True)
+ self.btnPolar.setFlat(False)
+ self.btnPolar.setObjectName("btnPolar")
+ self.horizontalLayout.addWidget(self.btnPolar)
+ self.btnManualAdj = QtWidgets.QPushButton(Form)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnManualAdj.sizePolicy().hasHeightForWidth())
+ self.btnManualAdj.setSizePolicy(sizePolicy)
+ self.btnManualAdj.setText("")
+ icon2 = QtGui.QIcon()
+ icon2.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnManualAdj.setIcon(icon2)
+ self.btnManualAdj.setCheckable(True)
+ self.btnManualAdj.setFlat(False)
+ self.btnManualAdj.setObjectName("btnManualAdj")
+ self.horizontalLayout.addWidget(self.btnManualAdj)
+ self.verticalLayout.addLayout(self.horizontalLayout)
+
+ self.retranslateUi(Form)
+ QtCore.QMetaObject.connectSlotsByName(Form)
+
+ def retranslateUi(self, Form):
+ _translate = QtCore.QCoreApplication.translate
+ Form.setWindowTitle(_translate("Form", "Form"))
+ self.nameLabel.setText(_translate("Form", "Left Control Point"))
+ self.lineXorA.setToolTip(_translate("Form", "X"))
+ self.lineXorA.setPlaceholderText(_translate("Form", "X"))
+ self.lineYorM.setToolTip(_translate("Form", "X"))
+ self.lineYorM.setPlaceholderText(_translate("Form", "Y"))
+
+import icons_rc
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/pyUIClass/window1.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/pyUIClass/window1.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/pyUIClass/window1.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,930 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/window1.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_MainWindow(object):
+ def setupUi(self, MainWindow):
+ MainWindow.setObjectName("MainWindow")
+ MainWindow.resize(1030, 768)
+ self.centralwidget = QtWidgets.QWidget(MainWindow)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
+ self.centralwidget.setSizePolicy(sizePolicy)
+ self.centralwidget.setMouseTracking(True)
+ self.centralwidget.setObjectName("centralwidget")
+ self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.centralwidget)
+ self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout_4.setSpacing(0)
+ self.horizontalLayout_4.setObjectName("horizontalLayout_4")
+ self.mainWidget = QtWidgets.QWidget(self.centralwidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.mainWidget.sizePolicy().hasHeightForWidth())
+ self.mainWidget.setSizePolicy(sizePolicy)
+ self.mainWidget.setMouseTracking(True)
+ self.mainWidget.setObjectName("mainWidget")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.mainWidget)
+ self.verticalLayout.setContentsMargins(2, 2, 2, 2)
+ self.verticalLayout.setSpacing(4)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.menuFrame = QtWidgets.QFrame(self.mainWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.menuFrame.sizePolicy().hasHeightForWidth())
+ self.menuFrame.setSizePolicy(sizePolicy)
+ self.menuFrame.setFrameShape(QtWidgets.QFrame.NoFrame)
+ self.menuFrame.setObjectName("menuFrame")
+ self.horizontalLayout = QtWidgets.QHBoxLayout(self.menuFrame)
+ self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
+ self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout.setSpacing(4)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.btnUndo = QtWidgets.QPushButton(self.menuFrame)
+ self.btnUndo.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnUndo.sizePolicy().hasHeightForWidth())
+ self.btnUndo.setSizePolicy(sizePolicy)
+ self.btnUndo.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnUndo.setBaseSize(QtCore.QSize(32, 32))
+ self.btnUndo.setText("")
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap(":/icons/android-arrow-back.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnUndo.setIcon(icon)
+ self.btnUndo.setIconSize(QtCore.QSize(16, 16))
+ self.btnUndo.setFlat(True)
+ self.btnUndo.setObjectName("btnUndo")
+ self.horizontalLayout.addWidget(self.btnUndo)
+ self.btnRedo = QtWidgets.QPushButton(self.menuFrame)
+ self.btnRedo.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnRedo.sizePolicy().hasHeightForWidth())
+ self.btnRedo.setSizePolicy(sizePolicy)
+ self.btnRedo.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnRedo.setBaseSize(QtCore.QSize(32, 32))
+ self.btnRedo.setText("")
+ icon1 = QtGui.QIcon()
+ icon1.addPixmap(QtGui.QPixmap(":/icons/android-arrow-forward.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnRedo.setIcon(icon1)
+ self.btnRedo.setFlat(True)
+ self.btnRedo.setObjectName("btnRedo")
+ self.horizontalLayout.addWidget(self.btnRedo)
+ self.btnLoadFile = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnLoadFile.sizePolicy().hasHeightForWidth())
+ self.btnLoadFile.setSizePolicy(sizePolicy)
+ self.btnLoadFile.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnLoadFile.setBaseSize(QtCore.QSize(32, 32))
+ self.btnLoadFile.setText("")
+ icon2 = QtGui.QIcon()
+ icon2.addPixmap(QtGui.QPixmap(":/icons/android-folder-open.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnLoadFile.setIcon(icon2)
+ self.btnLoadFile.setFlat(True)
+ self.btnLoadFile.setObjectName("btnLoadFile")
+ self.horizontalLayout.addWidget(self.btnLoadFile)
+ self.btnSave = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnSave.sizePolicy().hasHeightForWidth())
+ self.btnSave.setSizePolicy(sizePolicy)
+ self.btnSave.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnSave.setBaseSize(QtCore.QSize(32, 32))
+ self.btnSave.setText("")
+ icon3 = QtGui.QIcon()
+ icon3.addPixmap(QtGui.QPixmap(":/icons/save.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnSave.setIcon(icon3)
+ self.btnSave.setFlat(True)
+ self.btnSave.setObjectName("btnSave")
+ self.horizontalLayout.addWidget(self.btnSave)
+ self.btnViewCode = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnViewCode.sizePolicy().hasHeightForWidth())
+ self.btnViewCode.setSizePolicy(sizePolicy)
+ self.btnViewCode.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnViewCode.setBaseSize(QtCore.QSize(32, 32))
+ self.btnViewCode.setText("")
+ icon4 = QtGui.QIcon()
+ icon4.addPixmap(QtGui.QPixmap(":/icons/code.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnViewCode.setIcon(icon4)
+ self.btnViewCode.setFlat(True)
+ self.btnViewCode.setObjectName("btnViewCode")
+ self.horizontalLayout.addWidget(self.btnViewCode)
+ self.btnQuickScreenshot = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnQuickScreenshot.sizePolicy().hasHeightForWidth())
+ self.btnQuickScreenshot.setSizePolicy(sizePolicy)
+ self.btnQuickScreenshot.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnQuickScreenshot.setBaseSize(QtCore.QSize(32, 32))
+ self.btnQuickScreenshot.setText("")
+ icon5 = QtGui.QIcon()
+ icon5.addPixmap(QtGui.QPixmap(":/icons/android-camera.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnQuickScreenshot.setIcon(icon5)
+ self.btnQuickScreenshot.setFlat(True)
+ self.btnQuickScreenshot.setObjectName("btnQuickScreenshot")
+ self.horizontalLayout.addWidget(self.btnQuickScreenshot)
+ spacerItem = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem)
+ self.btnDrawAxes = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnDrawAxes.sizePolicy().hasHeightForWidth())
+ self.btnDrawAxes.setSizePolicy(sizePolicy)
+ self.btnDrawAxes.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnDrawAxes.setBaseSize(QtCore.QSize(32, 32))
+ font = QtGui.QFont()
+ font.setFamily("Roboto")
+ font.setBold(True)
+ font.setWeight(75)
+ self.btnDrawAxes.setFont(font)
+ self.btnDrawAxes.setText("")
+ icon6 = QtGui.QIcon()
+ icon6.addPixmap(QtGui.QPixmap(":/icons/plus-round.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnDrawAxes.setIcon(icon6)
+ self.btnDrawAxes.setCheckable(True)
+ self.btnDrawAxes.setChecked(True)
+ self.btnDrawAxes.setFlat(True)
+ self.btnDrawAxes.setObjectName("btnDrawAxes")
+ self.horizontalLayout.addWidget(self.btnDrawAxes)
+ self.btnDrawGrid = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnDrawGrid.sizePolicy().hasHeightForWidth())
+ self.btnDrawGrid.setSizePolicy(sizePolicy)
+ self.btnDrawGrid.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnDrawGrid.setBaseSize(QtCore.QSize(32, 32))
+ font = QtGui.QFont()
+ font.setFamily("Roboto")
+ font.setBold(True)
+ font.setWeight(75)
+ self.btnDrawGrid.setFont(font)
+ self.btnDrawGrid.setText("")
+ icon7 = QtGui.QIcon()
+ icon7.addPixmap(QtGui.QPixmap(":/icons/grid.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnDrawGrid.setIcon(icon7)
+ self.btnDrawGrid.setCheckable(True)
+ self.btnDrawGrid.setChecked(False)
+ self.btnDrawGrid.setFlat(True)
+ self.btnDrawGrid.setObjectName("btnDrawGrid")
+ self.horizontalLayout.addWidget(self.btnDrawGrid)
+ self.btnSetZoom = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnSetZoom.sizePolicy().hasHeightForWidth())
+ self.btnSetZoom.setSizePolicy(sizePolicy)
+ self.btnSetZoom.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnSetZoom.setBaseSize(QtCore.QSize(32, 32))
+ self.btnSetZoom.setText("")
+ icon8 = QtGui.QIcon()
+ icon8.addPixmap(QtGui.QPixmap(":/icons/magnifying-glass.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnSetZoom.setIcon(icon8)
+ self.btnSetZoom.setFlat(True)
+ self.btnSetZoom.setObjectName("btnSetZoom")
+ self.horizontalLayout.addWidget(self.btnSetZoom)
+ self.btnPanCenter = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnPanCenter.sizePolicy().hasHeightForWidth())
+ self.btnPanCenter.setSizePolicy(sizePolicy)
+ self.btnPanCenter.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnPanCenter.setBaseSize(QtCore.QSize(32, 32))
+ self.btnPanCenter.setText("")
+ icon9 = QtGui.QIcon()
+ icon9.addPixmap(QtGui.QPixmap(":/icons/center.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnPanCenter.setIcon(icon9)
+ self.btnPanCenter.setFlat(True)
+ self.btnPanCenter.setObjectName("btnPanCenter")
+ self.horizontalLayout.addWidget(self.btnPanCenter)
+ self.btnResetPan = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnResetPan.sizePolicy().hasHeightForWidth())
+ self.btnResetPan.setSizePolicy(sizePolicy)
+ self.btnResetPan.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnResetPan.setBaseSize(QtCore.QSize(32, 32))
+ self.btnResetPan.setText("")
+ icon10 = QtGui.QIcon()
+ icon10.addPixmap(QtGui.QPixmap(":/icons/centerorigin.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnResetPan.setIcon(icon10)
+ self.btnResetPan.setFlat(True)
+ self.btnResetPan.setObjectName("btnResetPan")
+ self.horizontalLayout.addWidget(self.btnResetPan)
+ self.btnAlignX = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnAlignX.sizePolicy().hasHeightForWidth())
+ self.btnAlignX.setSizePolicy(sizePolicy)
+ self.btnAlignX.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnAlignX.setBaseSize(QtCore.QSize(32, 32))
+ font = QtGui.QFont()
+ font.setFamily("Roboto")
+ font.setBold(True)
+ font.setWeight(75)
+ self.btnAlignX.setFont(font)
+ self.btnAlignX.setCheckable(True)
+ self.btnAlignX.setFlat(True)
+ self.btnAlignX.setObjectName("btnAlignX")
+ self.horizontalLayout.addWidget(self.btnAlignX)
+ self.btnAlignY = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnAlignY.sizePolicy().hasHeightForWidth())
+ self.btnAlignY.setSizePolicy(sizePolicy)
+ self.btnAlignY.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnAlignY.setBaseSize(QtCore.QSize(32, 32))
+ font = QtGui.QFont()
+ font.setBold(True)
+ font.setWeight(75)
+ self.btnAlignY.setFont(font)
+ self.btnAlignY.setCheckable(True)
+ self.btnAlignY.setFlat(True)
+ self.btnAlignY.setObjectName("btnAlignY")
+ self.horizontalLayout.addWidget(self.btnAlignY)
+ spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem1)
+ self.btnSelectEdit = QtWidgets.QPushButton(self.menuFrame)
+ self.btnSelectEdit.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnSelectEdit.sizePolicy().hasHeightForWidth())
+ self.btnSelectEdit.setSizePolicy(sizePolicy)
+ self.btnSelectEdit.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnSelectEdit.setText("")
+ icon11 = QtGui.QIcon()
+ icon11.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnSelectEdit.setIcon(icon11)
+ self.btnSelectEdit.setFlat(True)
+ self.btnSelectEdit.setObjectName("btnSelectEdit")
+ self.horizontalLayout.addWidget(self.btnSelectEdit)
+ self.btnDeleteMode = QtWidgets.QPushButton(self.menuFrame)
+ self.btnDeleteMode.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnDeleteMode.sizePolicy().hasHeightForWidth())
+ self.btnDeleteMode.setSizePolicy(sizePolicy)
+ self.btnDeleteMode.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnDeleteMode.setBaseSize(QtCore.QSize(32, 32))
+ self.btnDeleteMode.setText("")
+ icon12 = QtGui.QIcon()
+ icon12.addPixmap(QtGui.QPixmap(":/icons/android-delete.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnDeleteMode.setIcon(icon12)
+ self.btnDeleteMode.setCheckable(False)
+ self.btnDeleteMode.setFlat(True)
+ self.btnDeleteMode.setObjectName("btnDeleteMode")
+ self.horizontalLayout.addWidget(self.btnDeleteMode)
+ spacerItem2 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem2)
+ self.btnPan = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnPan.sizePolicy().hasHeightForWidth())
+ self.btnPan.setSizePolicy(sizePolicy)
+ self.btnPan.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnPan.setBaseSize(QtCore.QSize(32, 32))
+ self.btnPan.setText("")
+ icon13 = QtGui.QIcon()
+ icon13.addPixmap(QtGui.QPixmap(":/icons/android-hand.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnPan.setIcon(icon13)
+ self.btnPan.setCheckable(True)
+ self.btnPan.setFlat(True)
+ self.btnPan.setObjectName("btnPan")
+ self.horizontalLayout.addWidget(self.btnPan)
+ self.btnTranslate = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnTranslate.sizePolicy().hasHeightForWidth())
+ self.btnTranslate.setSizePolicy(sizePolicy)
+ self.btnTranslate.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnTranslate.setBaseSize(QtCore.QSize(32, 32))
+ self.btnTranslate.setText("")
+ icon14 = QtGui.QIcon()
+ icon14.addPixmap(QtGui.QPixmap(":/icons/arrow-move.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnTranslate.setIcon(icon14)
+ self.btnTranslate.setCheckable(True)
+ self.btnTranslate.setChecked(True)
+ self.btnTranslate.setFlat(True)
+ self.btnTranslate.setObjectName("btnTranslate")
+ self.horizontalLayout.addWidget(self.btnTranslate)
+ self.btnScale = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnScale.sizePolicy().hasHeightForWidth())
+ self.btnScale.setSizePolicy(sizePolicy)
+ self.btnScale.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnScale.setBaseSize(QtCore.QSize(32, 32))
+ self.btnScale.setText("")
+ icon15 = QtGui.QIcon()
+ icon15.addPixmap(QtGui.QPixmap(":/icons/arrow-resize.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnScale.setIcon(icon15)
+ self.btnScale.setCheckable(True)
+ self.btnScale.setFlat(True)
+ self.btnScale.setObjectName("btnScale")
+ self.horizontalLayout.addWidget(self.btnScale)
+ self.btnRotate = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnRotate.sizePolicy().hasHeightForWidth())
+ self.btnRotate.setSizePolicy(sizePolicy)
+ self.btnRotate.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnRotate.setBaseSize(QtCore.QSize(32, 32))
+ self.btnRotate.setText("")
+ icon16 = QtGui.QIcon()
+ icon16.addPixmap(QtGui.QPixmap(":/icons/android-refresh.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnRotate.setIcon(icon16)
+ self.btnRotate.setCheckable(True)
+ self.btnRotate.setFlat(True)
+ self.btnRotate.setObjectName("btnRotate")
+ self.horizontalLayout.addWidget(self.btnRotate)
+ spacerItem3 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem3)
+ self.btnAnchor = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnAnchor.sizePolicy().hasHeightForWidth())
+ self.btnAnchor.setSizePolicy(sizePolicy)
+ self.btnAnchor.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnAnchor.setBaseSize(QtCore.QSize(32, 32))
+ self.btnAnchor.setText("")
+ icon17 = QtGui.QIcon()
+ icon17.addPixmap(QtGui.QPixmap(":/icons/anchor.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnAnchor.setIcon(icon17)
+ self.btnAnchor.setCheckable(True)
+ self.btnAnchor.setChecked(False)
+ self.btnAnchor.setFlat(True)
+ self.btnAnchor.setObjectName("btnAnchor")
+ self.horizontalLayout.addWidget(self.btnAnchor)
+ self.comboAnchor = QtWidgets.QComboBox(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.comboAnchor.sizePolicy().hasHeightForWidth())
+ self.comboAnchor.setSizePolicy(sizePolicy)
+ self.comboAnchor.setMinimumSize(QtCore.QSize(127, 0))
+ self.comboAnchor.setMaximumSize(QtCore.QSize(127, 25))
+ self.comboAnchor.setLayoutDirection(QtCore.Qt.LeftToRight)
+ self.comboAnchor.setEditable(False)
+ self.comboAnchor.setInsertPolicy(QtWidgets.QComboBox.InsertAtCurrent)
+ self.comboAnchor.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContentsOnFirstShow)
+ self.comboAnchor.setIconSize(QtCore.QSize(0, 0))
+ self.comboAnchor.setDuplicatesEnabled(False)
+ self.comboAnchor.setFrame(False)
+ self.comboAnchor.setModelColumn(0)
+ self.comboAnchor.setObjectName("comboAnchor")
+ self.comboAnchor.addItem("")
+ self.comboAnchor.addItem("")
+ self.comboAnchor.addItem("")
+ self.comboAnchor.addItem("")
+ self.comboAnchor.addItem("")
+ self.comboAnchor.addItem("")
+ self.comboAnchor.addItem("")
+ self.horizontalLayout.addWidget(self.comboAnchor)
+ self.btnToggleVisible = QtWidgets.QPushButton(self.menuFrame)
+ self.btnToggleVisible.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnToggleVisible.sizePolicy().hasHeightForWidth())
+ self.btnToggleVisible.setSizePolicy(sizePolicy)
+ self.btnToggleVisible.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnToggleVisible.setBaseSize(QtCore.QSize(32, 32))
+ self.btnToggleVisible.setText("")
+ icon18 = QtGui.QIcon()
+ icon18.addPixmap(QtGui.QPixmap(":/icons/eye.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnToggleVisible.setIcon(icon18)
+ self.btnToggleVisible.setCheckable(False)
+ self.btnToggleVisible.setFlat(True)
+ self.btnToggleVisible.setObjectName("btnToggleVisible")
+ self.horizontalLayout.addWidget(self.btnToggleVisible)
+ self.btnCustTransform = QtWidgets.QPushButton(self.menuFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnCustTransform.sizePolicy().hasHeightForWidth())
+ self.btnCustTransform.setSizePolicy(sizePolicy)
+ self.btnCustTransform.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnCustTransform.setBaseSize(QtCore.QSize(32, 32))
+ self.btnCustTransform.setText("")
+ icon19 = QtGui.QIcon()
+ icon19.addPixmap(QtGui.QPixmap(":/icons/android-expand.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnCustTransform.setIcon(icon19)
+ self.btnCustTransform.setFlat(True)
+ self.btnCustTransform.setObjectName("btnCustTransform")
+ self.horizontalLayout.addWidget(self.btnCustTransform)
+ self.btnSendBackwards = QtWidgets.QPushButton(self.menuFrame)
+ self.btnSendBackwards.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnSendBackwards.sizePolicy().hasHeightForWidth())
+ self.btnSendBackwards.setSizePolicy(sizePolicy)
+ self.btnSendBackwards.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnSendBackwards.setBaseSize(QtCore.QSize(32, 32))
+ self.btnSendBackwards.setText("")
+ icon20 = QtGui.QIcon()
+ icon20.addPixmap(QtGui.QPixmap(":/icons/chevron-with-circle-left.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnSendBackwards.setIcon(icon20)
+ self.btnSendBackwards.setFlat(True)
+ self.btnSendBackwards.setObjectName("btnSendBackwards")
+ self.horizontalLayout.addWidget(self.btnSendBackwards)
+ self.btnSendForwards = QtWidgets.QPushButton(self.menuFrame)
+ self.btnSendForwards.setEnabled(False)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnSendForwards.sizePolicy().hasHeightForWidth())
+ self.btnSendForwards.setSizePolicy(sizePolicy)
+ self.btnSendForwards.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnSendForwards.setBaseSize(QtCore.QSize(32, 32))
+ self.btnSendForwards.setText("")
+ icon21 = QtGui.QIcon()
+ icon21.addPixmap(QtGui.QPixmap(":/icons/chevron-with-circle-right.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnSendForwards.setIcon(icon21)
+ self.btnSendForwards.setFlat(True)
+ self.btnSendForwards.setObjectName("btnSendForwards")
+ self.horizontalLayout.addWidget(self.btnSendForwards)
+ spacerItem4 = QtWidgets.QSpacerItem(40, 25, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
+ self.horizontalLayout.addItem(spacerItem4)
+ self.btnUndo.raise_()
+ self.btnRedo.raise_()
+ self.btnLoadFile.raise_()
+ self.btnSave.raise_()
+ self.btnViewCode.raise_()
+ self.btnQuickScreenshot.raise_()
+ self.btnDrawAxes.raise_()
+ self.btnDrawGrid.raise_()
+ self.btnSetZoom.raise_()
+ self.btnPanCenter.raise_()
+ self.btnResetPan.raise_()
+ self.btnAlignX.raise_()
+ self.btnAlignY.raise_()
+ self.btnPan.raise_()
+ self.btnTranslate.raise_()
+ self.btnScale.raise_()
+ self.btnCustTransform.raise_()
+ self.btnSendBackwards.raise_()
+ self.btnSendForwards.raise_()
+ self.comboAnchor.raise_()
+ self.btnToggleVisible.raise_()
+ self.btnAnchor.raise_()
+ self.btnRotate.raise_()
+ self.btnSelectEdit.raise_()
+ self.btnDeleteMode.raise_()
+ self.verticalLayout.addWidget(self.menuFrame)
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setSpacing(4)
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_2.setSpacing(3)
+ self.verticalLayout_2.setObjectName("verticalLayout_2")
+ self.addOption = QtWidgets.QHBoxLayout()
+ self.addOption.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
+ self.addOption.setContentsMargins(6, -1, -1, 0)
+ self.addOption.setSpacing(6)
+ self.addOption.setObjectName("addOption")
+ self.btnFill = QtWidgets.QPushButton(self.mainWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnFill.sizePolicy().hasHeightForWidth())
+ self.btnFill.setSizePolicy(sizePolicy)
+ self.btnFill.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnFill.setBaseSize(QtCore.QSize(32, 32))
+ self.btnFill.setAutoFillBackground(False)
+ self.btnFill.setStyleSheet("")
+ self.btnFill.setText("")
+ icon22 = QtGui.QIcon()
+ icon22.addPixmap(QtGui.QPixmap(":/icons/bucket.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ icon22.addPixmap(QtGui.QPixmap(":/icons/filledbucket.svg"), QtGui.QIcon.Normal, QtGui.QIcon.On)
+ self.btnFill.setIcon(icon22)
+ self.btnFill.setCheckable(True)
+ self.btnFill.setDefault(False)
+ self.btnFill.setFlat(True)
+ self.btnFill.setObjectName("btnFill")
+ self.addOption.addWidget(self.btnFill)
+ self.addOptionLayout = QtWidgets.QGridLayout()
+ self.addOptionLayout.setSpacing(6)
+ self.addOptionLayout.setObjectName("addOptionLayout")
+ self.addOption.addLayout(self.addOptionLayout)
+ spacerItem5 = QtWidgets.QSpacerItem(40, 35, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum)
+ self.addOption.addItem(spacerItem5)
+ self.label = QtWidgets.QLabel(self.mainWidget)
+ self.label.setObjectName("label")
+ self.addOption.addWidget(self.label)
+ self.txtLineWidth = QtWidgets.QLineEdit(self.mainWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.txtLineWidth.sizePolicy().hasHeightForWidth())
+ self.txtLineWidth.setSizePolicy(sizePolicy)
+ self.txtLineWidth.setMaximumSize(QtCore.QSize(75, 16777215))
+ self.txtLineWidth.setObjectName("txtLineWidth")
+ self.addOption.addWidget(self.txtLineWidth)
+ self.frameCurrColor = QtWidgets.QFrame(self.mainWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.frameCurrColor.sizePolicy().hasHeightForWidth())
+ self.frameCurrColor.setSizePolicy(sizePolicy)
+ self.frameCurrColor.setMinimumSize(QtCore.QSize(15, 15))
+ self.frameCurrColor.setAutoFillBackground(False)
+ self.frameCurrColor.setStyleSheet("QFrame{ \n"
+"padding: 4.0;\n"
+"border-radius: 3.0; \n"
+"background: rgb(0, 0, 0)\n"
+"}")
+ self.frameCurrColor.setFrameShape(QtWidgets.QFrame.StyledPanel)
+ self.frameCurrColor.setFrameShadow(QtWidgets.QFrame.Sunken)
+ self.frameCurrColor.setObjectName("frameCurrColor")
+ self.addOption.addWidget(self.frameCurrColor)
+ self.btnSelectColor = QtWidgets.QPushButton(self.mainWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnSelectColor.sizePolicy().hasHeightForWidth())
+ self.btnSelectColor.setSizePolicy(sizePolicy)
+ self.btnSelectColor.setMaximumSize(QtCore.QSize(25, 25))
+ self.btnSelectColor.setBaseSize(QtCore.QSize(32, 32))
+ self.btnSelectColor.setAutoFillBackground(False)
+ self.btnSelectColor.setStyleSheet("")
+ self.btnSelectColor.setText("")
+ icon23 = QtGui.QIcon()
+ icon23.addPixmap(QtGui.QPixmap(":/icons/android-color-palette.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnSelectColor.setIcon(icon23)
+ self.btnSelectColor.setDefault(False)
+ self.btnSelectColor.setFlat(True)
+ self.btnSelectColor.setObjectName("btnSelectColor")
+ self.addOption.addWidget(self.btnSelectColor)
+ self.verticalLayout_2.addLayout(self.addOption)
+ self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_7.setContentsMargins(-1, 6, -1, -1)
+ self.horizontalLayout_7.setSpacing(6)
+ self.horizontalLayout_7.setObjectName("horizontalLayout_7")
+ self.formFrame = QtWidgets.QFrame(self.mainWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.formFrame.sizePolicy().hasHeightForWidth())
+ self.formFrame.setSizePolicy(sizePolicy)
+ self.formFrame.setFrameShape(QtWidgets.QFrame.NoFrame)
+ self.formFrame.setFrameShadow(QtWidgets.QFrame.Plain)
+ self.formFrame.setLineWidth(0)
+ self.formFrame.setObjectName("formFrame")
+ self.formLayout = QtWidgets.QFormLayout(self.formFrame)
+ self.formLayout.setContentsMargins(0, 0, 0, 0)
+ self.formLayout.setSpacing(0)
+ self.formLayout.setObjectName("formLayout")
+ self.btnOpenPoly = QtWidgets.QPushButton(self.formFrame)
+ self.btnOpenPoly.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnOpenPoly.sizePolicy().hasHeightForWidth())
+ self.btnOpenPoly.setSizePolicy(sizePolicy)
+ self.btnOpenPoly.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnOpenPoly.setText("")
+ icon24 = QtGui.QIcon()
+ icon24.addPixmap(QtGui.QPixmap(":/icons/openpolygon.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnOpenPoly.setIcon(icon24)
+ self.btnOpenPoly.setFlat(True)
+ self.btnOpenPoly.setObjectName("btnOpenPoly")
+ self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.btnOpenPoly)
+ self.btnClosedPoly = QtWidgets.QPushButton(self.formFrame)
+ self.btnClosedPoly.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnClosedPoly.sizePolicy().hasHeightForWidth())
+ self.btnClosedPoly.setSizePolicy(sizePolicy)
+ self.btnClosedPoly.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnClosedPoly.setText("")
+ icon25 = QtGui.QIcon()
+ icon25.addPixmap(QtGui.QPixmap(":/icons/closedpolygon.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnClosedPoly.setIcon(icon25)
+ self.btnClosedPoly.setFlat(True)
+ self.btnClosedPoly.setObjectName("btnClosedPoly")
+ self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.btnClosedPoly)
+ self.btnOpenCurve = QtWidgets.QPushButton(self.formFrame)
+ self.btnOpenCurve.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnOpenCurve.sizePolicy().hasHeightForWidth())
+ self.btnOpenCurve.setSizePolicy(sizePolicy)
+ self.btnOpenCurve.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnOpenCurve.setText("")
+ icon26 = QtGui.QIcon()
+ icon26.addPixmap(QtGui.QPixmap(":/icons/opencurve.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnOpenCurve.setIcon(icon26)
+ self.btnOpenCurve.setFlat(True)
+ self.btnOpenCurve.setObjectName("btnOpenCurve")
+ self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.btnOpenCurve)
+ self.btnClosedCurve = QtWidgets.QPushButton(self.formFrame)
+ self.btnClosedCurve.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnClosedCurve.sizePolicy().hasHeightForWidth())
+ self.btnClosedCurve.setSizePolicy(sizePolicy)
+ self.btnClosedCurve.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnClosedCurve.setText("")
+ icon27 = QtGui.QIcon()
+ icon27.addPixmap(QtGui.QPixmap(":/icons/closedcurve.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnClosedCurve.setIcon(icon27)
+ self.btnClosedCurve.setFlat(True)
+ self.btnClosedCurve.setObjectName("btnClosedCurve")
+ self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.btnClosedCurve)
+ self.btnAddPoly = QtWidgets.QPushButton(self.formFrame)
+ self.btnAddPoly.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnAddPoly.sizePolicy().hasHeightForWidth())
+ self.btnAddPoly.setSizePolicy(sizePolicy)
+ self.btnAddPoly.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnAddPoly.setText("")
+ icon28 = QtGui.QIcon()
+ icon28.addPixmap(QtGui.QPixmap(":/icons/triangle-stroked-15.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnAddPoly.setIcon(icon28)
+ self.btnAddPoly.setFlat(True)
+ self.btnAddPoly.setObjectName("btnAddPoly")
+ self.formLayout.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.btnAddPoly)
+ self.btnAddCircle = QtWidgets.QPushButton(self.formFrame)
+ self.btnAddCircle.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnAddCircle.sizePolicy().hasHeightForWidth())
+ self.btnAddCircle.setSizePolicy(sizePolicy)
+ self.btnAddCircle.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnAddCircle.setText("")
+ icon29 = QtGui.QIcon()
+ icon29.addPixmap(QtGui.QPixmap(":/icons/circle.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnAddCircle.setIcon(icon29)
+ self.btnAddCircle.setFlat(True)
+ self.btnAddCircle.setObjectName("btnAddCircle")
+ self.formLayout.setWidget(10, QtWidgets.QFormLayout.LabelRole, self.btnAddCircle)
+ self.btnAddLabel = QtWidgets.QPushButton(self.formFrame)
+ self.btnAddLabel.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnAddLabel.sizePolicy().hasHeightForWidth())
+ self.btnAddLabel.setSizePolicy(sizePolicy)
+ self.btnAddLabel.setMaximumSize(QtCore.QSize(32, 32))
+ self.btnAddLabel.setText("")
+ icon30 = QtGui.QIcon()
+ icon30.addPixmap(QtGui.QPixmap(":/icons/text.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnAddLabel.setIcon(icon30)
+ self.btnAddLabel.setFlat(True)
+ self.btnAddLabel.setObjectName("btnAddLabel")
+ self.formLayout.setWidget(11, QtWidgets.QFormLayout.LabelRole, self.btnAddLabel)
+ self.horizontalLayout_7.addWidget(self.formFrame)
+ self.imgFrame = QtWidgets.QFrame(self.mainWidget)
+ self.imgFrame.setMinimumSize(QtCore.QSize(0, 6))
+ self.imgFrame.setMouseTracking(True)
+ self.imgFrame.setFrameShape(QtWidgets.QFrame.NoFrame)
+ self.imgFrame.setFrameShadow(QtWidgets.QFrame.Raised)
+ self.imgFrame.setObjectName("imgFrame")
+ self.gridLayout = QtWidgets.QGridLayout(self.imgFrame)
+ self.gridLayout.setContentsMargins(0, 0, 0, 0)
+ self.gridLayout.setSpacing(0)
+ self.gridLayout.setObjectName("gridLayout")
+ self.imgLabel = QtWidgets.QLabel(self.imgFrame)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.imgLabel.sizePolicy().hasHeightForWidth())
+ self.imgLabel.setSizePolicy(sizePolicy)
+ self.imgLabel.setMouseTracking(True)
+ self.imgLabel.setFrameShape(QtWidgets.QFrame.Panel)
+ self.imgLabel.setText("")
+ self.imgLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
+ self.imgLabel.setObjectName("imgLabel")
+ self.gridLayout.addWidget(self.imgLabel, 0, 1, 1, 1)
+ self.horizontalLayout_7.addWidget(self.imgFrame)
+ self.verticalLayout_2.addLayout(self.horizontalLayout_7)
+ self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_3.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
+ self.horizontalLayout_3.setContentsMargins(-1, 0, -1, -1)
+ self.horizontalLayout_3.setSpacing(0)
+ self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+ self.btnTogglePython = QtWidgets.QPushButton(self.mainWidget)
+ self.btnTogglePython.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnTogglePython.sizePolicy().hasHeightForWidth())
+ self.btnTogglePython.setSizePolicy(sizePolicy)
+ self.btnTogglePython.setText("")
+ icon31 = QtGui.QIcon()
+ icon31.addPixmap(QtGui.QPixmap(":/icons/social-python.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnTogglePython.setIcon(icon31)
+ self.btnTogglePython.setIconSize(QtCore.QSize(16, 16))
+ self.btnTogglePython.setCheckable(True)
+ self.btnTogglePython.setFlat(True)
+ self.btnTogglePython.setObjectName("btnTogglePython")
+ self.horizontalLayout_3.addWidget(self.btnTogglePython)
+ self.txtTerminalPrompt = QtWidgets.QLineEdit(self.mainWidget)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.txtTerminalPrompt.sizePolicy().hasHeightForWidth())
+ self.txtTerminalPrompt.setSizePolicy(sizePolicy)
+ self.txtTerminalPrompt.setObjectName("txtTerminalPrompt")
+ self.horizontalLayout_3.addWidget(self.txtTerminalPrompt)
+ self.btnEnterCommand = QtWidgets.QPushButton(self.mainWidget)
+ self.btnEnterCommand.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.btnEnterCommand.sizePolicy().hasHeightForWidth())
+ self.btnEnterCommand.setSizePolicy(sizePolicy)
+ self.btnEnterCommand.setText("")
+ icon32 = QtGui.QIcon()
+ icon32.addPixmap(QtGui.QPixmap(":/icons/subdirectory-left.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ self.btnEnterCommand.setIcon(icon32)
+ self.btnEnterCommand.setFlat(True)
+ self.btnEnterCommand.setObjectName("btnEnterCommand")
+ self.horizontalLayout_3.addWidget(self.btnEnterCommand)
+ self.verticalLayout_2.addLayout(self.horizontalLayout_3)
+ self.horizontalLayout_2.addLayout(self.verticalLayout_2)
+ self.verticalLayout.addLayout(self.horizontalLayout_2)
+ self.horizontalLayout_4.addWidget(self.mainWidget)
+ MainWindow.setCentralWidget(self.centralwidget)
+ self.menubar = QtWidgets.QMenuBar(MainWindow)
+ self.menubar.setGeometry(QtCore.QRect(0, 0, 1030, 28))
+ self.menubar.setObjectName("menubar")
+ self.menuFIle = QtWidgets.QMenu(self.menubar)
+ self.menuFIle.setObjectName("menuFIle")
+ self.menuEdit = QtWidgets.QMenu(self.menubar)
+ self.menuEdit.setObjectName("menuEdit")
+ self.menuOptions = QtWidgets.QMenu(self.menubar)
+ self.menuOptions.setObjectName("menuOptions")
+ self.menuHelp = QtWidgets.QMenu(self.menubar)
+ self.menuHelp.setObjectName("menuHelp")
+ self.menuTools = QtWidgets.QMenu(self.menubar)
+ self.menuTools.setObjectName("menuTools")
+ MainWindow.setMenuBar(self.menubar)
+ self.statusbar = QtWidgets.QStatusBar(MainWindow)
+ self.statusbar.setSizeGripEnabled(False)
+ self.statusbar.setObjectName("statusbar")
+ MainWindow.setStatusBar(self.statusbar)
+ self.actionAbout = QtWidgets.QAction(MainWindow)
+ self.actionAbout.setObjectName("actionAbout")
+ self.actionManual = QtWidgets.QAction(MainWindow)
+ self.actionManual.setObjectName("actionManual")
+ self.actionSettings = QtWidgets.QAction(MainWindow)
+ self.actionSettings.setObjectName("actionSettings")
+ self.actionPause = QtWidgets.QAction(MainWindow)
+ self.actionPause.setObjectName("actionPause")
+ self.actionSaveAs = QtWidgets.QAction(MainWindow)
+ self.actionSaveAs.setObjectName("actionSaveAs")
+ self.actionEnterCommand = QtWidgets.QAction(MainWindow)
+ self.actionEnterCommand.setObjectName("actionEnterCommand")
+ self.actionQuit = QtWidgets.QAction(MainWindow)
+ self.actionQuit.setObjectName("actionQuit")
+ self.actionUndo = QtWidgets.QAction(MainWindow)
+ self.actionUndo.setEnabled(False)
+ self.actionUndo.setObjectName("actionUndo")
+ self.actionRedo = QtWidgets.QAction(MainWindow)
+ self.actionRedo.setEnabled(False)
+ self.actionRedo.setObjectName("actionRedo")
+ self.actionShow_Grid = QtWidgets.QAction(MainWindow)
+ self.actionShow_Grid.setObjectName("actionShow_Grid")
+ self.actionShow_Local_Grid = QtWidgets.QAction(MainWindow)
+ self.actionShow_Local_Grid.setObjectName("actionShow_Local_Grid")
+ self.actionTransform = QtWidgets.QAction(MainWindow)
+ self.actionTransform.setObjectName("actionTransform")
+ self.actionExportAsymptote = QtWidgets.QAction(MainWindow)
+ self.actionExportAsymptote.setObjectName("actionExportAsymptote")
+ self.actionSave = QtWidgets.QAction(MainWindow)
+ self.actionSave.setObjectName("actionSave")
+ self.actionOpen = QtWidgets.QAction(MainWindow)
+ self.actionOpen.setObjectName("actionOpen")
+ self.menuFIle.addAction(self.actionOpen)
+ self.menuFIle.addAction(self.actionSave)
+ self.menuFIle.addAction(self.actionSaveAs)
+ self.menuFIle.addAction(self.actionExportAsymptote)
+ self.menuFIle.addSeparator()
+ self.menuFIle.addAction(self.actionQuit)
+ self.menuEdit.addAction(self.actionUndo)
+ self.menuEdit.addAction(self.actionRedo)
+ self.menuEdit.addSeparator()
+ self.menuOptions.addAction(self.actionSettings)
+ self.menuHelp.addAction(self.actionManual)
+ self.menuHelp.addAction(self.actionAbout)
+ self.menuTools.addAction(self.actionEnterCommand)
+ self.menubar.addAction(self.menuFIle.menuAction())
+ self.menubar.addAction(self.menuEdit.menuAction())
+ self.menubar.addAction(self.menuOptions.menuAction())
+ self.menubar.addAction(self.menuTools.menuAction())
+ self.menubar.addAction(self.menuHelp.menuAction())
+
+ self.retranslateUi(MainWindow)
+ self.comboAnchor.setCurrentIndex(0)
+ QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+ def retranslateUi(self, MainWindow):
+ _translate = QtCore.QCoreApplication.translate
+ MainWindow.setWindowTitle(_translate("MainWindow", "xasy"))
+ self.btnUndo.setToolTip(_translate("MainWindow", "Undo"))
+ self.btnRedo.setToolTip(_translate("MainWindow", "Redo"))
+ self.btnLoadFile.setToolTip(_translate("MainWindow", "<html><head/><body><p>Open file</p></body></html>"))
+ self.btnSave.setToolTip(_translate("MainWindow", "<html><head/><body><p>Save file</p></body></html>"))
+ self.btnViewCode.setToolTip(_translate("MainWindow", "<html><head/><body><p>Edit code</p></body></html>"))
+ self.btnQuickScreenshot.setToolTip(_translate("MainWindow", "<html><head/><body><p>Screenshot</p></body></html>"))
+ self.btnDrawAxes.setToolTip(_translate("MainWindow", "<html><head/><body><p>Toggle display axes</p></body></html>"))
+ self.btnDrawGrid.setToolTip(_translate("MainWindow", "<html><head/><body><p>Toggle grid</p></body></html>"))
+ self.btnSetZoom.setToolTip(_translate("MainWindow", "Synchronize with Asymptote"))
+ self.btnPanCenter.setToolTip(_translate("MainWindow", "<html><head/><body><p>Center</p></body></html>"))
+ self.btnResetPan.setToolTip(_translate("MainWindow", "<html><head/><body><p>Center about origin</p></body></html>"))
+ self.btnAlignX.setToolTip(_translate("MainWindow", "<html><head/><body><p>Lock transform to X axis</p></body></html>"))
+ self.btnAlignX.setText(_translate("MainWindow", "X"))
+ self.btnAlignY.setToolTip(_translate("MainWindow", "<html><head/><body><p>Lock transform to Y axis</p></body></html>"))
+ self.btnAlignY.setText(_translate("MainWindow", "Y"))
+ self.btnSelectEdit.setToolTip(_translate("MainWindow", "<html><head/><body><p>Bézier editor</p></body></html>"))
+ self.btnDeleteMode.setToolTip(_translate("MainWindow", "<html><head/><body><p>Delete</p></body></html>"))
+ self.btnPan.setToolTip(_translate("MainWindow", "Pan"))
+ self.btnTranslate.setToolTip(_translate("MainWindow", "Translate"))
+ self.btnScale.setToolTip(_translate("MainWindow", "Scale"))
+ self.btnRotate.setToolTip(_translate("MainWindow", "Rotate"))
+ self.btnAnchor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Set custom anchor</p></body></html>"))
+ self.comboAnchor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Anchor</p></body></html>"))
+ self.comboAnchor.setCurrentText(_translate("MainWindow", "Origin"))
+ self.comboAnchor.setItemText(0, _translate("MainWindow", "Origin"))
+ self.comboAnchor.setItemText(1, _translate("MainWindow", "Center"))
+ self.comboAnchor.setItemText(2, _translate("MainWindow", "Top Left"))
+ self.comboAnchor.setItemText(3, _translate("MainWindow", "Top Right"))
+ self.comboAnchor.setItemText(4, _translate("MainWindow", "Bottom Right"))
+ self.comboAnchor.setItemText(5, _translate("MainWindow", "Bottom Left"))
+ self.comboAnchor.setItemText(6, _translate("MainWindow", "Custom"))
+ self.btnCustTransform.setToolTip(_translate("MainWindow", "<html><head/><body><p><br/></p></body></html>"))
+ self.btnSendBackwards.setToolTip(_translate("MainWindow", "<html><head/><body><p><br/></p></body></html>"))
+ self.btnSendForwards.setToolTip(_translate("MainWindow", "Translate"))
+ self.btnFill.setToolTip(_translate("MainWindow", "<html><head/><body><p>Toggle fill/outline</p></body></html>"))
+ self.label.setText(_translate("MainWindow", "Line Width:"))
+ self.txtLineWidth.setToolTip(_translate("MainWindow", "<html><head/><body><p>Current pen width</p></body></html>"))
+ self.frameCurrColor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Current pen color</p></body></html>"))
+ self.btnSelectColor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Set color</p></body></html>"))
+ self.btnOpenPoly.setToolTip(_translate("MainWindow", "<html><head/><body><p>Open polygon</p></body></html>"))
+ self.btnClosedPoly.setToolTip(_translate("MainWindow", "<html><head/><body><p>Closed polygon</p></body></html>"))
+ self.btnOpenCurve.setToolTip(_translate("MainWindow", "<html><head/><body><p>Open Bézier curve</p></body></html>"))
+ self.btnClosedCurve.setToolTip(_translate("MainWindow", "<html><head/><body><p>Closed Bézier curve</p></body></html>"))
+ self.btnAddPoly.setToolTip(_translate("MainWindow", "<html><head/><body><p>Regular polygon</p></body></html>"))
+ self.btnAddCircle.setToolTip(_translate("MainWindow", "<html><head/><body><p>Circle</p></body></html>"))
+ self.btnAddLabel.setToolTip(_translate("MainWindow", "<html><head/><body><p>Text</p></body></html>"))
+ self.menuFIle.setTitle(_translate("MainWindow", "&File"))
+ self.menuEdit.setTitle(_translate("MainWindow", "&Edit"))
+ self.menuOptions.setTitle(_translate("MainWindow", "Optio&ns"))
+ self.menuHelp.setTitle(_translate("MainWindow", "&Help"))
+ self.menuTools.setTitle(_translate("MainWindow", "&Tools"))
+ self.actionAbout.setText(_translate("MainWindow", "&About"))
+ self.actionManual.setText(_translate("MainWindow", "&Manual"))
+ self.actionSettings.setText(_translate("MainWindow", "&Settings"))
+ self.actionPause.setText(_translate("MainWindow", "Pause "))
+ self.actionSaveAs.setText(_translate("MainWindow", "&Save As"))
+ self.actionEnterCommand.setText(_translate("MainWindow", "&Enter Command"))
+ self.actionQuit.setText(_translate("MainWindow", "&Quit"))
+ self.actionUndo.setText(_translate("MainWindow", "&Undo"))
+ self.actionRedo.setText(_translate("MainWindow", "&Redo"))
+ self.actionShow_Grid.setText(_translate("MainWindow", "&Show Grid"))
+ self.actionShow_Local_Grid.setText(_translate("MainWindow", "Show &Local Grid"))
+ self.actionTransform.setText(_translate("MainWindow", "&Transform"))
+ self.actionExportAsymptote.setText(_translate("MainWindow", "Export"))
+ self.actionSave.setText(_translate("MainWindow", "Save"))
+ self.actionOpen.setText(_translate("MainWindow", "Open"))
+
+import icons_rc
Property changes on: trunk/Build/source/utils/asymptote/GUI/pyUIClass/window1.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/requirements.txt
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/requirements.txt (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/requirements.txt 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,4 @@
+numpy==1.11.0
+cson==0.7
+PyQt5==5.11
+rsvg-convert==2.42.3
Property changes on: trunk/Build/source/utils/asymptote/GUI/requirements.txt
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/anchor.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/anchor.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/anchor.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M4.34 15.66A7.97 7.97 0 0 0 9 17.94V10H5V8h4V5.83a3 3 0 1 1 2 0V8h4v2h-4v7.94a7.97 7.97 0 0 0 4.66-2.28l-1.42-1.42h5.66l-2.83 2.83a10 10 0 0 1-14.14 0L.1 14.24h5.66l-1.42 1.42zM10 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_8_">
+ <g>
+ <path d="M427,234.625H167.296l119.702-119.702L256,85L85,256l171,171l29.922-29.924L167.296,277.375H427V234.625z"/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_8_">
+ <g>
+ <path d="M85,277.375h259.704L225.002,397.077L256,427l171-171L256,85l-29.922,29.924l118.626,119.701H85V277.375z"/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-camera.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-camera.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-camera.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+ <circle cx="256" cy="280" r="63"/>
+ <path d="M440,96h-88l-32-32H192l-32,32H72c-22.092,0-40,17.908-40,40v272c0,22.092,17.908,40,40,40h368c22.092,0,40-17.908,40-40
+ V136C480,113.908,462.092,96,440,96z M256,392c-61.855,0-112-50.145-112-112s50.145-112,112-112s112,50.145,112,112
+ S317.855,392,256,392z"/>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-close.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-close.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-close.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_5_">
+ <g>
+ <polygon points="405,136.798 375.202,107 256,226.202 136.798,107 107,136.798 226.202,256 107,375.202 136.798,405 256,285.798
+ 375.202,405 405,375.202 285.798,256 "/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_12_">
+ <g>
+ <path d="M256,64C150.401,64,64,150.401,64,256c0,105.604,86.401,192,192,192c18.136,0,32-13.864,32-32
+ c0-8.531-3.198-16-8.531-21.333c-5.333-5.334-8.531-12.803-8.531-21.334c0-18.135,13.864-32,32-32h38.396
+ c58.667,0,106.667-48,106.667-106.666C448,140.802,361.604,64,256,64z M138.667,256c-18.136,0-32-13.864-32-32s13.864-32,32-32
+ c18.135,0,32,13.864,32,32S156.802,256,138.667,256z M202.667,170.667c-18.136,0-32-13.865-32-32c0-18.136,13.864-32,32-32
+ c18.135,0,32,13.864,32,32C234.667,156.802,220.802,170.667,202.667,170.667z M309.333,170.667c-18.135,0-32-13.865-32-32
+ c0-18.136,13.865-32,32-32c18.136,0,32,13.864,32,32C341.333,156.802,327.469,170.667,309.333,170.667z M373.333,256
+ c-18.135,0-32-13.864-32-32s13.865-32,32-32c18.136,0,32,13.864,32,32S391.469,256,373.333,256z"/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-delete.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-delete.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-delete.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+ <path d="M128,405.429C128,428.846,147.198,448,170.667,448h170.667C364.802,448,384,428.846,384,405.429V160H128V405.429z M416,96
+ h-80l-26.785-32H202.786L176,96H96v32h320V96z"/>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-done.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-done.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-done.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_1_">
+ <g>
+ <g>
+ <polygon points="186.301,339.893 96,249.461 64,279.968 186.301,402 448,140.506 416,110 "/>
+ </g>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-expand.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-expand.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-expand.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+ <polygon points="396.795,396.8 320,396.8 320,448 448,448 448,320 396.795,320 "/>
+ <polygon points="396.8,115.205 396.8,192 448,192 448,64 320,64 320,115.205 "/>
+ <polygon points="115.205,115.2 192,115.2 192,64 64,64 64,192 115.205,192 "/>
+ <polygon points="115.2,396.795 115.2,320 64,320 64,448 192,448 192,396.795 "/>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<path d="M437.334,144H256.006l-42.668-48H74.666C51.197,96,32,115.198,32,138.667v234.666C32,396.802,51.197,416,74.666,416h362.668
+ C460.803,416,480,396.802,480,373.333V186.667C480,163.198,460.803,144,437.334,144z M448,373.333
+ c0,5.782-4.885,10.667-10.666,10.667H74.666C68.884,384,64,379.115,64,373.333V176h373.334c5.781,0,10.666,4.885,10.666,10.667
+ V373.333z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-hand.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-hand.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-hand.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<path d="M450.679,273.5c-14.585-14.577-36.054-15.89-50.639-1.312l-41.687,41.664c-10.852,10.836-23.93,10.859-31.564,1.852
+ c-5.057-5.968-3.061-24.374-1.644-36.049l20.907-171.849c1.867-15.353-9.07-30.185-24.43-32.051
+ c-15.358-1.867-29.322,9.939-31.191,25.289L267.37,236.021c-1.205,3.358-3.79,3.938-4.081-0.582L255.44,60
+ c0-15.465-12.542-28-28.014-28c-15.473,0-28.015,12.535-28.015,28l-0.552,176.752c0.146,2.04-1.604,2.624-1.92,0.294L172.016,99.077
+ c-2.75-15.219-17.323-26.203-32.548-23.453c-15.227,2.748-25.339,18.187-22.591,33.403l22.193,161.455
+ c0.023,2.872-0.941,4.513-2.308,0.831l-33.109-88.517c-5.18-14.572-21.196-23.065-35.776-17.889
+ c-14.579,5.177-22.201,22.061-17.023,36.631l58.042,189.625c0.303,1.046,0.624,2.085,0.953,3.118l0.121,0.39
+ c0.011,0.031,0.025,0.058,0.035,0.088C126.079,444.233,172.57,480,227.427,480c35.116,0,71.591-12.378,99.357-33.672
+ c0.001,0,0.003-0.002,0.003-0.002c29.99-18.051,126.071-121.347,126.071-121.347C467.445,310.402,465.266,288.08,450.679,273.5z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-locate.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-locate.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-locate.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon">
+ <g>
+ <path d="M256,176c-44.004,0-80.001,36-80.001,80c0,44.004,35.997,80,80.001,80c44.005,0,79.999-35.996,79.999-80
+ C335.999,212,300.005,176,256,176z M446.938,234.667c-9.605-88.531-81.074-160-169.605-169.599V32h-42.666v33.067
+ c-88.531,9.599-160,81.068-169.604,169.599H32v42.667h33.062c9.604,88.531,81.072,160,169.604,169.604V480h42.666v-33.062
+ c88.531-9.604,160-81.073,169.605-169.604H480v-42.667H446.938z M256,405.333c-82.137,0-149.334-67.198-149.334-149.333
+ c0-82.136,67.197-149.333,149.334-149.333c82.135,0,149.332,67.198,149.332,149.333C405.332,338.135,338.135,405.333,256,405.333z
+ "/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_20_">
+ <g>
+ <path d="M256,48C141.601,48,48,141.601,48,256s93.601,208,208,208s208-93.601,208-208S370.399,48,256,48z M256,422.399
+ c-91.518,0-166.399-74.882-166.399-166.399S164.482,89.6,256,89.6S422.4,164.482,422.4,256S347.518,422.399,256,422.399z"/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_21_">
+ <g>
+ <path d="M256,152c-57.2,0-104,46.8-104,104s46.8,104,104,104s104-46.8,104-104S313.2,152,256,152z M256,48
+ C141.601,48,48,141.601,48,256s93.601,208,208,208s208-93.601,208-208S370.399,48,256,48z M256,422.4
+ c-91.518,0-166.4-74.883-166.4-166.4S164.482,89.6,256,89.6S422.4,164.482,422.4,256S347.518,422.4,256,422.4z"/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+ <path d="M256,388c-72.597,0-132-59.405-132-132c0-72.601,59.403-132,132-132c36.3,0,69.299,15.4,92.406,39.601L278,234h154V80
+ l-51.698,51.702C348.406,99.798,304.406,80,256,80c-96.797,0-176,79.203-176,176s78.094,176,176,176
+ c81.045,0,148.287-54.134,169.401-128H378.85C360.105,353.561,311.712,388,256,388z"/>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<polygon points="480,256 384,160 384,236 276,236 276,128 352,128 256,32 160,128 236,128 236,236 128,236 128,160 32,256 128,352
+ 128,276 236,276 236,384 160,384 256,480 352,384 275.8,384 275.4,275.5 384,275.8 384,352 "/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<polygon points="288,96 337.9,145.9 274,209.7 274,209.7 145.9,337.9 96,288 96,416 224,416 174.1,366.1 357.4,182.9 366.1,174.1
+ 416,224 416,96 "/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.asy (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,28 @@
+// Empty bucket: asy bucket -f svg
+// Filled bucket: asy bucket -f svg -u fill=true -o filledbucket
+
+real pixel=1inch/96;
+size(32*pixel);
+defaultpen(1.75bp);
+
+real h=4;
+real r=3;
+path left=(-r,h)--(-r,0);
+path right=(r,0)--(r,h);
+path bottom=xscale(r)*arc(0,1,180,360);
+
+real H=0.9h;
+path Left=(-r,H/2)--(-r,0);
+path Right=(r,0)--(r,H/2);
+
+bool fill=false; // Set to true for filled bucket.
+usersetting();
+
+if(fill)
+ fill(Left--bottom--Right--shift(0,H)*xscale(r)*arc(0,1,0,180)--cycle,gray);
+
+
+draw(shift(0,h)*xscale(r)*unitcircle);
+draw(left--bottom--right);
+draw(shift(0,h)*scale(r)*arc(0,1,0,180));
+
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/bucket.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 18.4375 24' width='18.4375pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -12.7085 4.62541 -13.9584 0 -13.9584C -4.62541 -13.9584 -8.37504 -12.7085 -8.37504 -11.1667C -8.37504 -9.62492 -4.62541 -8.37504 0 -8.37504C 4.62541 -8.37504 8.37504 -9.62492 8.37504 -11.1667Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M -8.37504 -11.1667L -8.37504 -0L -8.37504 -1.85963e-15C -8.37504 -1.23975e-15 -8.37504 -6.19877e-16 -8.37504 -0C -8.37504 1.5418 -4.62541 2.79168 0 2.79168C 4.62541 2.79168 8.37504 1.5418 8.37504 0L 8.37504 0L 8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -15.7921 4.62541 -19.5418 0 -19.5418C -4.62541 -19.5418 -8.37504 -15.7921 -8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/center.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/center.asy (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/center.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,9 @@
+// Empty bucket: asy bucket -f svg
+// Filled bucket: asy bucket -f svg -u fill=true -o filledbucket
+
+real pixel=1inch/96;
+size(25*pixel);
+defaultpen(1.5bp);
+
+draw(scale(2)*shift(-0.5,-0.5)*unitsquare);
+fill(scale(0.5)*unitcircle);
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/center.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/center.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/center.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='18.75pt' version='1.1' viewBox='56.4094 53.8583 18.75 18.75' width='18.75pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M -8.65734 8.65734L 8.65734 8.65734L 8.65734 -8.65734L -8.65734 -8.65734L -8.65734 8.65734Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M 4.32867 0C 4.32867 -2.39066 2.39066 -4.32867 0 -4.32867C -2.39066 -4.32867 -4.32867 -2.39066 -4.32867 -0C -4.32867 2.39066 -2.39066 4.32867 0 4.32867C 2.39066 4.32867 4.32867 2.39066 4.32867 0Z' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,7 @@
+real pixel=1inch/96;
+size(25*pixel);
+defaultpen(1.5bp);
+
+draw(scale(2)*shift(-0.5,-0.5)*unitsquare);
+draw((-1,0)--(1,0));
+draw((0,-1)--(0,1));
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='18.75pt' version='1.1' viewBox='56.4094 53.8583 18.75 18.75' width='18.75pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M -8.65734 8.65734L 8.65734 8.65734L 8.65734 -8.65734L -8.65734 -8.65734L -8.65734 8.65734Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M -8.65734 -0L 8.65734 0' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M 0 8.65734L 0 -8.65734' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/check.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/check.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/check.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Check" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M8.294,16.998c-0.435,0-0.847-0.203-1.111-0.553L3.61,11.724c-0.465-0.613-0.344-1.486,0.27-1.951
+ c0.615-0.467,1.488-0.344,1.953,0.27l2.351,3.104l5.911-9.492c0.407-0.652,1.267-0.852,1.921-0.445
+ c0.653,0.406,0.854,1.266,0.446,1.92L9.478,16.34c-0.242,0.391-0.661,0.635-1.12,0.656C8.336,16.998,8.316,16.998,8.294,16.998z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Chevron_circled_left" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ x="0px" y="0px" viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M11.302,6.776c-0.196-0.197-0.515-0.197-0.71,0L7.785,9.641c-0.196,0.199-0.196,0.52,0,0.717l2.807,2.864
+ c0.195,0.199,0.514,0.198,0.71,0c0.196-0.197,0.196-0.518,0-0.717L9,10l2.302-2.506C11.498,7.296,11.498,6.976,11.302,6.776z
+ M10,0.4c-5.302,0-9.6,4.298-9.6,9.6c0,5.303,4.298,9.6,9.6,9.6s9.6-4.297,9.6-9.6C19.6,4.698,15.302,0.4,10,0.4z M10,18.354
+ c-4.615,0-8.354-3.74-8.354-8.354c0-4.614,3.739-8.354,8.354-8.354c4.613,0,8.354,3.74,8.354,8.354
+ C18.354,14.614,14.613,18.354,10,18.354z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Chevron_circled_right" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ x="0px" y="0px" viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M11,10L8.698,7.494c-0.196-0.198-0.196-0.519,0-0.718c0.196-0.197,0.515-0.197,0.71,0l2.807,2.864
+ c0.196,0.199,0.196,0.52,0,0.717l-2.807,2.864c-0.195,0.199-0.514,0.198-0.71,0c-0.196-0.197-0.196-0.518,0-0.717L11,10z M10,0.4
+ c5.302,0,9.6,4.298,9.6,9.6c0,5.303-4.298,9.6-9.6,9.6S0.4,15.303,0.4,10C0.4,4.698,4.698,0.4,10,0.4z M10,18.354
+ c4.613,0,8.354-3.74,8.354-8.354c0-4.614-3.741-8.354-8.354-8.354c-4.615,0-8.354,3.74-8.354,8.354
+ C1.645,14.614,5.385,18.354,10,18.354z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/circle.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/circle.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/circle.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Circle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M10,0.4C4.698,0.4,0.4,4.698,0.4,10C0.4,15.302,4.698,19.6,10,19.6c5.301,0,9.6-4.298,9.6-9.601
+ C19.6,4.698,15.301,0.4,10,0.4z M10,17.599c-4.197,0-7.6-3.402-7.6-7.6S5.802,2.4,10,2.4c4.197,0,7.601,3.402,7.601,7.6
+ S14.197,17.599,10,17.599z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/close-round.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/close-round.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/close-round.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<path d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5
+ c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9
+ c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,7 @@
+real pixel=1inch/96;
+size(32*pixel,IgnoreAspect);
+defaultpen(1.75bp);
+
+path p=W..NW..ENE..0.5*SE..cycle;
+draw(p);
+dot(p,linewidth(8pixel));
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<path d='M -9.39118 -0C -9.96861 -3.83004 -8.55706 -7.51944 -6.64057 -10.2171C -0.491089 -18.8733 8.35676 -15.1906 8.67632 -5.52948C 8.836 -0.702008 6.23968 2.94207 3.32028 5.10857C -1.96891 9.03371 -8.26895 7.4437 -9.39118 -0Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='-6.64057' cy='-10.2171' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='8.67632' cy='-5.52948' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='3.32028' cy='5.10857' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,7 @@
+real pixel=1inch/96;
+size(32*pixel,IgnoreAspect);
+defaultpen(1.75bp);
+
+path p=W--NW--ENE--0.5*SE--cycle;
+draw(p);
+dot(p,linewidth(8pixel));
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<path d='M -9.39118 -0L -6.64057 -12.045L 8.67632 -6.51871L 3.32028 6.0225L -9.39118 -0Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-6.64057' cy='-12.045' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='8.67632' cy='-6.51871' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='3.32028' cy='6.0225' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/code.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/code.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/code.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Code" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M5.719,14.75c-0.236,0-0.474-0.083-0.664-0.252L-0.005,10l5.341-4.748C5.748,4.887,6.38,4.922,6.747,5.335
+ c0.367,0.413,0.33,1.045-0.083,1.412L3.005,10l3.378,3.002c0.413,0.367,0.45,0.999,0.083,1.412
+ C6.269,14.637,5.994,14.75,5.719,14.75z M14.664,14.748L20.005,10l-5.06-4.498c-0.413-0.367-1.045-0.33-1.411,0.083
+ c-0.367,0.413-0.33,1.045,0.083,1.412L16.995,10l-3.659,3.252c-0.413,0.367-0.45,0.999-0.083,1.412C13.45,14.887,13.725,15,14,15
+ C14.236,15,14.474,14.917,14.664,14.748z M9.986,16.165l2-12c0.091-0.545-0.277-1.06-0.822-1.151
+ c-0.547-0.092-1.061,0.277-1.15,0.822l-2,12c-0.091,0.545,0.277,1.06,0.822,1.151C8.892,16.996,8.946,17,9.001,17
+ C9.481,17,9.905,16.653,9.986,16.165z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/edit.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/edit.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/edit.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+
+ <rect x="178.846" y="92.087" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 224.3476 631.1498)" width="128.085" height="354.049"/>
+ <path d="M471.723,88.393l-48.115-48.114c-11.723-11.724-31.558-10.896-44.304,1.85l-45.202,45.203l90.569,90.568l45.202-45.202
+ C482.616,119.952,483.445,100.116,471.723,88.393z"/>
+ <polygon points="64.021,363.252 32,480 148.737,447.979 "/>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/eye.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/eye.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/eye.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+ <path d="M256,128c-81.9,0-145.7,48.8-224,128c67.4,67.7,124,128,224,128c99.9,0,173.4-76.4,224-126.6
+ C428.2,198.6,354.8,128,256,128z M256,347.3c-49.4,0-89.6-41-89.6-91.3c0-50.4,40.2-91.3,89.6-91.3s89.6,41,89.6,91.3
+ C345.6,306.4,305.4,347.3,256,347.3z"/>
+ <g>
+ <path d="M256,224c0-7.9,2.9-15.1,7.6-20.7c-2.5-0.4-5-0.6-7.6-0.6c-28.8,0-52.3,23.9-52.3,53.3c0,29.4,23.5,53.3,52.3,53.3
+ s52.3-23.9,52.3-53.3c0-2.3-0.2-4.6-0.4-6.9c-5.5,4.3-12.3,6.9-19.8,6.9C270.3,256,256,241.7,256,224z"/>
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,17 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 18.4375 24' width='18.4375pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M -8.37504 -5.02502L -8.37504 -0L -8.37504 -1.85963e-15C -8.37504 -1.23975e-15 -8.37504 -6.19877e-16 -8.37504 -0C -8.37504 1.5418 -4.62541 2.79168 0 2.79168C 4.62541 2.79168 8.37504 1.5418 8.37504 0L 8.37504 0L 8.37504 -5.02502L 8.37504 -10.05C 8.37504 -11.5918 4.62541 -12.8417 0 -12.8417C -4.62541 -12.8417 -8.37504 -11.5918 -8.37504 -10.05L -8.37504 -5.02502Z' fill='#808080'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -12.7085 4.62541 -13.9584 0 -13.9584C -4.62541 -13.9584 -8.37504 -12.7085 -8.37504 -11.1667C -8.37504 -9.62492 -4.62541 -8.37504 0 -8.37504C 4.62541 -8.37504 8.37504 -9.62492 8.37504 -11.1667Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M -8.37504 -11.1667L -8.37504 -0L -8.37504 -1.85963e-15C -8.37504 -1.23975e-15 -8.37504 -6.19877e-16 -8.37504 -0C -8.37504 1.5418 -4.62541 2.79168 0 2.79168C 4.62541 2.79168 8.37504 1.5418 8.37504 0L 8.37504 0L 8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -15.7921 4.62541 -19.5418 0 -19.5418C -4.62541 -19.5418 -8.37504 -15.7921 -8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/grid.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/grid.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/grid.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+ <g>
+ <path d="M160,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
+ />
+ <path d="M288,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
+ />
+ <path d="M416,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
+ />
+ </g>
+ <g>
+ <path d="M160,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
+ />
+ <path d="M288,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
+ />
+ <path d="M416,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
+ />
+ </g>
+ <g>
+ <path d="M160,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
+ />
+ <path d="M288,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
+ />
+ <path d="M416,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
+ />
+ </g>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Magnifying_glass" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
+ y="0px" viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M17.545,15.467l-3.779-3.779c0.57-0.935,0.898-2.035,0.898-3.21c0-3.417-2.961-6.377-6.378-6.377
+ C4.869,2.1,2.1,4.87,2.1,8.287c0,3.416,2.961,6.377,6.377,6.377c1.137,0,2.2-0.309,3.115-0.844l3.799,3.801
+ c0.372,0.371,0.975,0.371,1.346,0l0.943-0.943C18.051,16.307,17.916,15.838,17.545,15.467z M4.004,8.287
+ c0-2.366,1.917-4.283,4.282-4.283c2.366,0,4.474,2.107,4.474,4.474c0,2.365-1.918,4.283-4.283,4.283
+ C6.111,12.76,4.004,10.652,4.004,8.287z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,7 @@
+real pixel=1inch/96;
+size(32*pixel,IgnoreAspect);
+defaultpen(1.75bp);
+
+path p=W..NW..ENE..0.5*SE;
+draw(p);
+dot(p,linewidth(8pixel));
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<path d='M -9.39118 -0C -9.32257 -3.77783 -8.34324 -7.38444 -6.64057 -10.1298C -1.26219 -18.8017 7.68971 -15.5351 8.67632 -5.4822C 9.18679 -0.280877 6.74937 4.51887 3.32028 5.06489' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='-6.64057' cy='-10.1298' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='8.67632' cy='-5.4822' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='3.32028' cy='5.06489' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,7 @@
+real pixel=1inch/96;
+size(32*pixel,IgnoreAspect);
+defaultpen(1.75bp);
+
+path p=W--NW--ENE--0.5*SE;
+draw(p);
+dot(p,linewidth(8pixel));
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<path d='M -9.39118 -0L -6.64057 -12.045L 8.67632 -6.51871L 3.32028 6.0225' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-6.64057' cy='-12.045' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='8.67632' cy='-6.51871' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='3.32028' cy='6.0225' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/plus-round.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/plus-round.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/plus-round.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<path d="M417.4,224H288V94.6c0-16.9-14.3-30.6-32-30.6c-17.7,0-32,13.7-32,30.6V224H94.6C77.7,224,64,238.3,64,256
+ c0,17.7,13.7,32,30.6,32H224v129.4c0,16.9,14.3,30.6,32,30.6c17.7,0,32-13.7,32-30.6V288h129.4c16.9,0,30.6-14.3,30.6-32
+ C448,238.3,434.3,224,417.4,224z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/save.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/save.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/save.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Save" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M15.173,2H4C2.899,2,2,2.9,2,4v12c0,1.1,0.899,2,2,2h12c1.101,0,2-0.9,2-2V5.127L15.173,2z M14,8c0,0.549-0.45,1-1,1H7
+ C6.45,9,6,8.549,6,8V3h8V8z M13,4h-2v4h2V4z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/social-python.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/social-python.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/social-python.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+ <path d="M193.46,249.056c3.723-0.67,7.589-1.041,11.586-1.041L201.924,248h103.823c4.503,0,8.806-0.617,12.908-1.754
+ c19.37-5.363,33.345-22.537,33.345-43.663v-30.822v-56.402c0-24.832-21.15-43.484-46.289-47.606
+ c-15.931-2.624-39.258-3.827-55.089-3.749c-15.829,0.086-30.981,1.404-44.277,3.749C167.143,74.576,160,88.928,160,115.359V144h96
+ v16H128.82c-35.628,0-64.538,42.571-64.813,95.242C64.005,255.495,64,255.747,64,256c0,9.523,0.94,18.72,2.685,27.404
+ C74.648,323.07,99.451,352,128.82,352H144v-2.662v-43.273C144,279.238,164.146,254.332,193.46,249.056z M203.656,127.002
+ c-9.592,0-17.384-7.785-17.384-17.403c0-9.664,7.774-17.52,17.384-17.52c9.574,0,17.399,7.855,17.399,17.52
+ C221.056,119.217,213.246,127.002,203.656,127.002z"/>
+ <path d="M443.951,222.543C434.78,186.021,411.033,160,383.18,160H368v2.626v38.046c0,33.915-22.286,58.474-49.489,62.681
+ c-2.737,0.424-5.483,0.646-8.301,0.646H206.351c-4.518,0-8.904,0.584-13.049,1.672C174.18,270.689,160,286.6,160,307.236v32.922
+ v54.305c0,24.832,24.977,39.426,49.481,46.551c29.327,8.531,61.267,10.068,96.366,0C329.15,434.354,352,420.893,352,394.463V368
+ h-96v-16h127.18c25.24,0,47.107-21.365,57.814-52.549C445.474,286.404,448,271.641,448,256
+ C448,244.232,446.567,232.962,443.951,222.543z M307.867,382.82c9.59,0,17.381,7.785,17.381,17.4
+ c0,9.65-7.791,17.521-17.381,17.521c-9.577,0-17.399-7.871-17.399-17.521C290.468,390.59,298.274,382.82,307.867,382.82z"/>
+</g>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M18 12v1H8v5l-6-6 6-6v5h8V2h2z"/></svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/text.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/text.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/text.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
+ <path d="M0 0v2h.5c0-.55.45-1 1-1h1.5v5.5c0 .28-.22.5-.5.5h-.5v1h4v-1h-.5c-.28 0-.5-.22-.5-.5v-5.5h1.5c.55 0 1 .45 1 1h.5v-2h-8z" />
+</svg>
\ No newline at end of file
Added: trunk/Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1"
+ id="svg4619" inkscape:version="0.91+devel+osxmenu r12911" sodipodi:docname="triangle-stroked-15.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="15px" height="15px"
+ viewBox="0 0 15 15" style="enable-background:new 0 0 15 15;" xml:space="preserve">
+<path id="rect3338" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccc" d="M7.5243,1.5004
+ C7.2429,1.4913,6.9787,1.6423,6.8336,1.8952l-5.5,9.8692C1.0218,12.3078,1.395,12.9999,2,13h11
+ c0.605-0.0001,0.9782-0.6922,0.6664-1.2355l-5.5-9.8692C8.0302,1.6579,7.7884,1.5092,7.5243,1.5004z M7.5,3.8993l4.1267,7.4704
+ H3.3733L7.5,3.8993z"/>
+</svg>
Added: trunk/Build/source/utils/asymptote/GUI/res/icons.qrc
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/res/icons.qrc (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/res/icons.qrc 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,45 @@
+<RCC>
+ <qresource prefix="">
+ <file>icons/android-arrow-back.svg</file>
+ <file>icons/android-arrow-forward.svg</file>
+ <file>icons/android-folder-open.svg</file>
+ <file>icons/save.svg</file>
+ <file>icons/code.svg</file>
+ <file>icons/android-camera.svg</file>
+ <file>icons/plus-round.svg</file>
+ <file>icons/grid.svg</file>
+ <file>icons/magnifying-glass.svg</file>
+ <file>icons/center.svg</file>
+ <file>icons/centerorigin.svg</file>
+ <file>icons/edit.svg</file>
+ <file>icons/android-delete.svg</file>
+ <file>icons/android-hand.svg</file>
+ <file>icons/arrow-move.svg</file>
+ <file>icons/arrow-resize.svg</file>
+ <file>icons/android-refresh.svg</file>
+ <file>icons/anchor.svg</file>
+ <file>icons/eye.svg</file>
+ <file>icons/android-expand.svg</file>
+ <file>icons/chevron-with-circle-left.svg</file>
+ <file>icons/chevron-with-circle-right.svg</file>
+ <file>icons/bucket.svg</file>
+ <file>icons/filledbucket.svg</file>
+ <file>icons/android-color-palette.svg</file>
+ <file>icons/openpolygon.svg</file>
+ <file>icons/closedpolygon.svg</file>
+ <file>icons/opencurve.svg</file>
+ <file>icons/closedcurve.svg</file>
+ <file>icons/triangle-stroked-15.svg</file>
+ <file>icons/circle.svg</file>
+ <file>icons/text.svg</file>
+ <file>icons/social-python.svg</file>
+ <file>icons/subdirectory-left.svg</file>
+ <file>icons/android-done.svg</file>
+ <file>icons/android-close.svg</file>
+ <file>icons/check.svg</file>
+ <file>icons/android-radio-button-on.svg</file>
+ <file>icons/android-radio-button-off.svg</file>
+ <file>icons/android-locate.svg</file>
+ <file>icons/close-round.svg</file>
+ </qresource>
+</RCC>
Added: trunk/Build/source/utils/asymptote/GUI/setup.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/setup.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/setup.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+
+import xasyVersion
+from setuptools import setup
+
+setup(
+ name="xasy",
+ version=xasyVersion.xasyVersion,
+ author="Supakorn Rassameemasmuang, Orest Shardt, and John C. Bowman",
+ description="User interface for Asymptote, a vector graphics language",
+ url="http://asymptote.sourceforge.net",
+ download_url="https://sourceforge.net/projects/asymptote/"
+)
Property changes on: trunk/Build/source/utils/asymptote/GUI/setup.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>500</width>
+ <height>320</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>500</width>
+ <height>320</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>500</width>
+ <height>320</height>
+ </size>
+ </property>
+ <property name="mouseTracking">
+ <bool>false</bool>
+ </property>
+ <property name="windowTitle">
+ <string>Set Custom Transformation</string>
+ </property>
+ <property name="windowIcon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-expand.svg</normaloff>:/icons/android-expand.svg</iconset>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="modal">
+ <bool>false</bool>
+ </property>
+ <widget class="QFrame" name="centralFrame">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>20</y>
+ <width>461</width>
+ <height>271</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Transformation Matrix</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="gridFrame">
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="0">
+ <widget class="QLineEdit" name="lineMat00">
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="lineMat11">
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLineEdit" name="lineMat10">
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="lineMat01">
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Translation</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="gridFrame_2">
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="lineMatTy">
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="lineMatTx">
+ <property name="maximumSize">
+ <size>
+ <width>70</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Preview:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="imgPreview">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>150</width>
+ <height>150</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>300</width>
+ <height>300</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Shows a red square if transformation determinant is negative.</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblAnchor">
+ <property name="text">
+ <string>Anchor: Top Left</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblCoordsMode">
+ <property name="text">
+ <string>Coordinates: Global</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnReset">
+ <property name="text">
+ <string>Reset</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCancel">
+ <property name="text">
+ <string>Cancel</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAccept">
+ <property name="text">
+ <string>Accept</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources>
+ <include location="../res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>473</width>
+ <height>424</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="chkMathMode">
+ <property name="text">
+ <string>Math Mode</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="cmbMathStyle">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>0</height>
+ </size>
+ </property>
+ <item>
+ <property name="text">
+ <string>Inline Style</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Display Style</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Script Style</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <widget class="QPlainTextEdit" name="txtLabelEdit"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Preview</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblLabelPreview">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>100</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Box</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnGetText">
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/text.svg</normaloff>:/icons/text.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnPreview">
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/eye.svg</normaloff>:/icons/eye.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCancel">
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-close.svg</normaloff>:/icons/android-close.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAccept">
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-done.svg</normaloff>:/icons/android-done.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Dialog</class>
+ <widget class="QDialog" name="Dialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>245</width>
+ <height>161</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Set Custom Anchor</string>
+ </property>
+ <widget class="QWidget" name="verticalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>20</x>
+ <y>20</y>
+ <width>201</width>
+ <height>121</height>
+ </rect>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>X:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="lineEditX">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Y:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="lineEditY">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Reset</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>Dialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>Dialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>599</width>
+ <height>35</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>35</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>35</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="txtLabelText">
+ <property name="toolTip">
+ <string>Number of Sides</string>
+ </property>
+ <property name="placeholderText">
+ <string>Text</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAdvancedEdit">
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/edit.svg</normaloff>:/icons/edit.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Align</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="cmbAlign">
+ <item>
+ <property name="text">
+ <string>Center</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>N</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>E</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>W</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>S</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>NW</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>NE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>SW</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>SE</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Custom</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Font Size</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="cmbFontSize">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ <item>
+ <property name="text">
+ <string>-</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>8</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>9</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>10</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>11</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>12</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>14</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>18</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>24</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>48</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>72</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Custom Align</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="txtShiftX">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="placeholderText">
+ <string>Shift X</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="txtShiftY">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>50</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="placeholderText">
+ <string>Shift Y</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>326</width>
+ <height>35</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>35</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>35</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QCheckBox" name="chkInscribed">
+ <property name="text">
+ <string>Start at Vertex</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="txtSides">
+ <property name="toolTip">
+ <string>Number of Sides</string>
+ </property>
+ <property name="placeholderText">
+ <string>Sides</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="windowModality">
+ <enum>Qt::NonModal</enum>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>692</width>
+ <height>35</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>35</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>16777215</width>
+ <height>35</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QComboBox" name="cmbLockMode">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>No Lock</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Lock Angle</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Lock Angle & Scale</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="chkRecompute">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Recompute Path</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnForceRecompute">
+ <property name="text">
+ <string>Recompute Once</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnOk">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/check.svg</normaloff>:/icons/check.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCancel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/close-round.svg</normaloff>:/icons/close-round.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Form</class>
+ <widget class="QWidget" name="Form">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>324</width>
+ <height>67</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="nameLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Left Control Point</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="lineXorA">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>X</string>
+ </property>
+ <property name="readOnly">
+ <bool>false</bool>
+ </property>
+ <property name="placeholderText">
+ <string>X</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="lineYorM">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>X</string>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="readOnly">
+ <bool>false</bool>
+ </property>
+ <property name="placeholderText">
+ <string>Y</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnRelative">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-locate.svg</normaloff>:/icons/android-locate.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnPolar">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-radio-button-off.svg</normaloff>:/icons/android-radio-button-off.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnManualAdj">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/edit.svg</normaloff>:/icons/edit.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources>
+ <include location="../res/icons.qrc"/>
+ </resources>
+ <connections/>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/windows/window1.ui
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/windows/window1.ui (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/windows/window1.ui 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,2000 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1030</width>
+ <height>768</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>xasy</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="mouseTracking">
+ <bool>true</bool>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QWidget" name="mainWidget" native="true">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="mouseTracking">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
+ <number>2</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="menuFrame">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinimumSize</enum>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="btnUndo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Undo</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-arrow-back.svg</normaloff>:/icons/android-arrow-back.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnRedo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Redo</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-arrow-forward.svg</normaloff>:/icons/android-arrow-forward.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnLoadFile">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Open file</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-folder-open.svg</normaloff>:/icons/android-folder-open.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSave">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Save file</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/save.svg</normaloff>:/icons/save.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnViewCode">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Edit code</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/code.svg</normaloff>:/icons/code.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnQuickScreenshot">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Screenshot</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-camera.svg</normaloff>:/icons/android-camera.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnDrawAxes">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>Roboto</family>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Toggle display axes</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/plus-round.svg</normaloff>:/icons/plus-round.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnDrawGrid">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>Roboto</family>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Toggle grid</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/grid.svg</normaloff>:/icons/grid.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSetZoom">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Synchronize with Asymptote</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/magnifying-glass.svg</normaloff>:/icons/magnifying-glass.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnPanCenter">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Center</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/center.svg</normaloff>:/icons/center.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnResetPan">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Center about origin</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/centerorigin.svg</normaloff>:/icons/centerorigin.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAlignX">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <family>Roboto</family>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Lock transform to X axis</p></body></html></string>
+ </property>
+ <property name="text">
+ <string>X</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAlignY">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Lock transform to Y axis</p></body></html></string>
+ </property>
+ <property name="text">
+ <string>Y</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_6">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSelectEdit">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Bézier editor</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/edit.svg</normaloff>:/icons/edit.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnDeleteMode">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Delete</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-delete.svg</normaloff>:/icons/android-delete.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnPan">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Pan</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-hand.svg</normaloff>:/icons/android-hand.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnTranslate">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Translate</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/arrow-move.svg</normaloff>:/icons/arrow-move.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnScale">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Scale</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/arrow-resize.svg</normaloff>:/icons/arrow-resize.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnRotate">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Rotate</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-refresh.svg</normaloff>:/icons/android-refresh.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Minimum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnAnchor">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Set custom anchor</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/anchor.svg</normaloff>:/icons/anchor.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="comboAnchor">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>127</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>127</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Anchor</p></body></html></string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="currentText">
+ <string>Origin</string>
+ </property>
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::InsertAtCurrent</enum>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="duplicatesEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="frame">
+ <bool>false</bool>
+ </property>
+ <property name="modelColumn">
+ <number>0</number>
+ </property>
+ <item>
+ <property name="text">
+ <string>Origin</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Center</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Top Left</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Top Right</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Bottom Right</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Bottom Left</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Custom</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnToggleVisible">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/eye.svg</normaloff>:/icons/eye.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnCustTransform">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p><br/></p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-expand.svg</normaloff>:/icons/android-expand.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSendBackwards">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p><br/></p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/chevron-with-circle-left.svg</normaloff>:/icons/chevron-with-circle-left.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSendForwards">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>Translate</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/chevron-with-circle-right.svg</normaloff>:/icons/chevron-with-circle-right.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>25</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ <zorder>btnUndo</zorder>
+ <zorder>btnRedo</zorder>
+ <zorder>btnLoadFile</zorder>
+ <zorder>btnSave</zorder>
+ <zorder>btnViewCode</zorder>
+ <zorder>btnQuickScreenshot</zorder>
+ <zorder>btnDrawAxes</zorder>
+ <zorder>btnDrawGrid</zorder>
+ <zorder>btnSetZoom</zorder>
+ <zorder>btnPanCenter</zorder>
+ <zorder>btnResetPan</zorder>
+ <zorder>btnAlignX</zorder>
+ <zorder>btnAlignY</zorder>
+ <zorder>btnPan</zorder>
+ <zorder>btnTranslate</zorder>
+ <zorder>btnScale</zorder>
+ <zorder>btnCustTransform</zorder>
+ <zorder>btnSendBackwards</zorder>
+ <zorder>btnSendForwards</zorder>
+ <zorder>comboAnchor</zorder>
+ <zorder>btnToggleVisible</zorder>
+ <zorder>btnAnchor</zorder>
+ <zorder>btnRotate</zorder>
+ <zorder>btnSelectEdit</zorder>
+ <zorder>btnDeleteMode</zorder>
+ <zorder>horizontalSpacer_4</zorder>
+ <zorder>horizontalSpacer_5</zorder>
+ <zorder>horizontalSpacer_6</zorder>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>4</number>
+ </property>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="addOption">
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="leftMargin">
+ <number>6</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="btnFill">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Toggle fill/outline</p></body></html></string>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/bucket.svg</normaloff>
+ <normalon>:/icons/filledbucket.svg</normalon>:/icons/bucket.svg</iconset>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QGridLayout" name="addOptionLayout"/>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_7">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>35</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Line Width:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="txtLineWidth">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>75</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Current pen width</p></body></html></string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="frameCurrColor">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>15</width>
+ <height>15</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Current pen color</p></body></html></string>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">QFrame{
+padding: 4.0;
+border-radius: 3.0;
+background: rgb(0, 0, 0)
+}</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnSelectColor">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>25</width>
+ <height>25</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Set color</p></body></html></string>
+ </property>
+ <property name="autoFillBackground">
+ <bool>false</bool>
+ </property>
+ <property name="styleSheet">
+ <string notr="true"/>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/android-color-palette.svg</normaloff>:/icons/android-color-palette.svg</iconset>
+ </property>
+ <property name="default">
+ <bool>false</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <item>
+ <widget class="QFrame" name="formFrame">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="horizontalSpacing">
+ <number>0</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item row="4" column="0">
+ <widget class="QPushButton" name="btnOpenPoly">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Open polygon</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/openpolygon.svg</normaloff>:/icons/openpolygon.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QPushButton" name="btnClosedPoly">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Closed polygon</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/closedpolygon.svg</normaloff>:/icons/closedpolygon.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QPushButton" name="btnOpenCurve">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Open Bézier curve</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/opencurve.svg</normaloff>:/icons/opencurve.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="7" column="0">
+ <widget class="QPushButton" name="btnClosedCurve">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Closed Bézier curve</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/closedcurve.svg</normaloff>:/icons/closedcurve.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="8" column="0">
+ <widget class="QPushButton" name="btnAddPoly">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Regular polygon</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/triangle-stroked-15.svg</normaloff>:/icons/triangle-stroked-15.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="10" column="0">
+ <widget class="QPushButton" name="btnAddCircle">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Circle</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/circle.svg</normaloff>:/icons/circle.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="0">
+ <widget class="QPushButton" name="btnAddLabel">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32</width>
+ <height>32</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string><html><head/><body><p>Text</p></body></html></string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/text.svg</normaloff>:/icons/text.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QFrame" name="imgFrame">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>6</height>
+ </size>
+ </property>
+ <property name="mouseTracking">
+ <bool>true</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Raised</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QLabel" name="imgLabel">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="mouseTracking">
+ <bool>true</bool>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::Panel</enum>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="btnTogglePython">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/social-python.svg</normaloff>:/icons/social-python.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="txtTerminalPrompt">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="btnEnterCommand">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset>
+ <normaloff>:/icons/subdirectory-left.svg</normaloff>:/icons/subdirectory-left.svg</iconset>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QMenuBar" name="menubar">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1030</width>
+ <height>28</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFIle">
+ <property name="title">
+ <string>&File</string>
+ </property>
+ <addaction name="actionOpen"/>
+ <addaction name="actionSave"/>
+ <addaction name="actionSaveAs"/>
+ <addaction name="actionExportAsymptote"/>
+ <addaction name="separator"/>
+ <addaction name="actionQuit"/>
+ </widget>
+ <widget class="QMenu" name="menuEdit">
+ <property name="title">
+ <string>&Edit</string>
+ </property>
+ <addaction name="actionUndo"/>
+ <addaction name="actionRedo"/>
+ <addaction name="separator"/>
+ </widget>
+ <widget class="QMenu" name="menuOptions">
+ <property name="title">
+ <string>Optio&ns</string>
+ </property>
+ <addaction name="actionSettings"/>
+ </widget>
+ <widget class="QMenu" name="menuHelp">
+ <property name="title">
+ <string>&Help</string>
+ </property>
+ <addaction name="actionManual"/>
+ <addaction name="actionAbout"/>
+ </widget>
+ <widget class="QMenu" name="menuTools">
+ <property name="title">
+ <string>&Tools</string>
+ </property>
+ <addaction name="actionEnterCommand"/>
+ </widget>
+ <addaction name="menuFIle"/>
+ <addaction name="menuEdit"/>
+ <addaction name="menuOptions"/>
+ <addaction name="menuTools"/>
+ <addaction name="menuHelp"/>
+ </widget>
+ <widget class="QStatusBar" name="statusbar">
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <action name="actionAbout">
+ <property name="text">
+ <string>&About</string>
+ </property>
+ </action>
+ <action name="actionManual">
+ <property name="text">
+ <string>&Manual</string>
+ </property>
+ </action>
+ <action name="actionSettings">
+ <property name="text">
+ <string>&Settings</string>
+ </property>
+ </action>
+ <action name="actionPause">
+ <property name="text">
+ <string>Pause </string>
+ </property>
+ </action>
+ <action name="actionSaveAs">
+ <property name="text">
+ <string>&Save As</string>
+ </property>
+ </action>
+ <action name="actionEnterCommand">
+ <property name="text">
+ <string>&Enter Command</string>
+ </property>
+ </action>
+ <action name="actionQuit">
+ <property name="text">
+ <string>&Quit</string>
+ </property>
+ </action>
+ <action name="actionUndo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&Undo</string>
+ </property>
+ </action>
+ <action name="actionRedo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&Redo</string>
+ </property>
+ </action>
+ <action name="actionShow_Grid">
+ <property name="text">
+ <string>&Show Grid</string>
+ </property>
+ </action>
+ <action name="actionShow_Local_Grid">
+ <property name="text">
+ <string>Show &Local Grid</string>
+ </property>
+ </action>
+ <action name="actionTransform">
+ <property name="text">
+ <string>&Transform</string>
+ </property>
+ </action>
+ <action name="actionExportAsymptote">
+ <property name="text">
+ <string>Export</string>
+ </property>
+ </action>
+ <action name="actionSave">
+ <property name="text">
+ <string>Save</string>
+ </property>
+ </action>
+ <action name="actionOpen">
+ <property name="text">
+ <string>Open</string>
+ </property>
+ </action>
+ </widget>
+ <layoutdefault spacing="6" margin="9"/>
+ <resources>
+ <include location="../res/icons.qrc"/>
+ </resources>
+ <connections/>
+ <designerdata>
+ <property name="gridDeltaX">
+ <number>10</number>
+ </property>
+ <property name="gridDeltaY">
+ <number>10</number>
+ </property>
+ <property name="gridSnapX">
+ <bool>true</bool>
+ </property>
+ <property name="gridSnapY">
+ <bool>true</bool>
+ </property>
+ <property name="gridVisible">
+ <bool>true</bool>
+ </property>
+ </designerdata>
+</ui>
Property changes on: trunk/Build/source/utils/asymptote/GUI/windows/window1.ui
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Build/source/utils/asymptote/GUI/xasy.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasy.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasy.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,38 +1,16 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasy implements a graphical interface for Asymptote.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-############################################################################
+#!/usr/bin/env python3
-import getopt,sys,signal
-import xasyMainWin
-if sys.version_info >= (3, 0):
- from tkinter import *
-else:
- from Tkinter import *
+import sys
+import PyQt5.QtWidgets as Qw
+from Window1 import MainWindow1
-signal.signal(signal.SIGINT,signal.SIG_IGN)
-root = Tk()
-mag = 1.0
-try:
- opts,args = getopt.getopt(sys.argv[1:],"x:")
- if(len(opts)>=1):
- mag = float(opts[0][1])
-except:
- print ("Invalid arguments.")
- print ("Usage: xasy.py [-x magnification] [filename]")
- sys.exit(1)
-if(mag <= 0.0):
- print ("Magnification must be positive.")
- sys.exit(1)
-if(len(args)>=1):
- app = xasyMainWin.xasyMainWin(root,args[0],mag)
-else:
- app = xasyMainWin.xasyMainWin(root,magnification=mag)
-root.mainloop()
+def main(args):
+ qtApp = Qw.QApplication(args)
+ mainWin1 = MainWindow1()
+ mainWin1.show()
+ return qtApp.exec_()
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv) or 0)
Modified: trunk/Build/source/utils/asymptote/GUI/xasy2asy.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasy2asy.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasy2asy.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,766 +1,1407 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
+
###########################################################################
#
# xasy2asy provides a Python interface to Asymptote
#
#
-# Author: Orest Shardt
-# Created: June 29, 2007
+# Authors: Orest Shardt, Supakorn Rassameemasmuang, and John C. Bowman
#
###########################################################################
-import sys,os,signal,threading
-from subprocess import *
-from string import *
-import xasyOptions
-from tempfile import mkdtemp
-if sys.version_info >= (3, 0):
- from tkinter import *
- import queue
-else:
- from Tkinter import *
- import Queue as queue
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import PyQt5.QtSvg as Qs
-# PIL support is now mandatory due to rotations
-try:
- from PIL import ImageTk
- from PIL import Image
-except:
- pass
+import numpy as np
-import CubicBezier
+import sys
+import os
+import signal
+import threading
+import string
+import subprocess
+import tempfile
+import re
+import shutil
+import copy
+import queue
+import io
+import atexit
+import DebugFlags
-quickAsyFailed = True
-global AsyTempDir
+import xasyUtils as xu
+import xasyArgs as xa
+import xasyOptions as xo
+import xasySvg as xs
-console=None
+class AsymptoteEngine:
+ xasy=chr(4)+"\n"
-def startQuickAsy():
- global quickAsy
- global quickAsyFailed
- global AsyTempDir
- global fout,fin
- if quickAsyRunning():
- return
- try:
- fout.close()
- quickAsy.wait()
- except:
- pass
- try:
- quickAsyFailed = False
- if os.name == "nt":
- AsyTempDir=mkdtemp(prefix="asy_", dir="./")
- else:
- AsyTempDir=mkdtemp(prefix="asy_")+os.sep
- if sys.platform[:3] == 'win':
- quickAsy=Popen([xasyOptions.options['asyPath'],"-noV","-multiline","-q",
- "-o"+AsyTempDir,"-inpipe=0","-outpipe=2"],stdin=PIPE,
- stderr=PIPE,universal_newlines=True)
- fout=quickAsy.stdin
- fin=quickAsy.stderr
- else:
- (rx,wx) = os.pipe()
- (ra,wa) = os.pipe()
- if sys.version_info >= (3, 4):
- os.set_inheritable(rx, True)
- os.set_inheritable(wx, True)
- os.set_inheritable(ra, True)
- os.set_inheritable(wa, True)
- quickAsy=Popen([xasyOptions.options['asyPath'],"-noV","-multiline","-q",
- "-o"+AsyTempDir,"-inpipe="+str(rx),"-outpipe="+str(wa)],
- close_fds=False)
- fout=os.fdopen(wx,'w')
- fin=os.fdopen(ra,'r')
- if quickAsy.returncode != None:
- quickAsyFailed = True
- except:
- quickAsyFailed = True
-
-def stopQuickAsy():
- if quickAsyRunning():
- fout.write("exit;\n");
+ def __init__(self, path=None, keepFiles=DebugFlags.keepFiles, keepDefaultArgs=True):
+ if path is None:
+ path = xa.getArgs().asypath
+ if path is None:
+ opt = xo.BasicConfigs.defaultOpt
+ opt.load()
+ path = opt['asyPath']
-def getAsyTempDir():
- return AsyTempDir
+ if sys.platform[:3] == 'win':
+ rx = 0 # stdin
+ wa = 2 # stderr
+ else:
+ rx, wx = os.pipe()
+ ra, wa = os.pipe()
+ os.set_inheritable(rx, True)
+ os.set_inheritable(wx, True)
+ os.set_inheritable(ra, True)
+ os.set_inheritable(wa, True)
+ self.ostream = os.fdopen(wx, 'w')
+ self.istream = os.fdopen(ra, 'r')
+
+ self.keepFiles = keepFiles
+ if sys.platform[:3] == 'win':
+ self.tmpdir = tempfile.mkdtemp(prefix='xasyData_',dir='./')+'/'
+ else:
+ self.tmpdir = tempfile.mkdtemp(prefix='xasyData_')+os.sep
-def quickAsyRunning():
- if quickAsyFailed or quickAsy.returncode != None:
- return False
- else:
- return True
+ self.args=['-xasy', '-noV', '-q', '-inpipe=' + str(rx), '-outpipe=' + str(wa), '-o', self.tmpdir]
-def asyExecute(command):
- if not quickAsyRunning():
- startQuickAsy()
- fout.write(command)
+ self.asyPath = path
+ self.asyProcess = None
-def closeConsole(event):
- global console
- console = None
+ def start(self):
+ try:
+ if sys.platform[:3] == 'win':
+ self.asyProcess = subprocess.Popen([self.asyPath] + self.args,
+ stdin=subprocess.PIPE, stderr=subprocess.PIPE,
+ universal_newlines=True)
+ self.ostream = self.asyProcess.stdin
+ self.istream = self.asyProcess.stderr
+ else:
+ self.asyProcess = subprocess.Popen([self.asyPath] + self.args,close_fds=False)
+ finally:
+ atexit.register(self.cleanup)
-def consoleOutput(line):
- global console
- global ctl
- if console == None:
- ctl=Toplevel()
- ctl.title("Asymptote Console")
- ctl.bind("<Destroy>",closeConsole)
- yscrollbar=Scrollbar(ctl)
- yscrollbar.pack(side=RIGHT,fill=Y)
- console=Text(ctl,yscrollcommand=yscrollbar.set)
- console.pack()
- yscrollbar.config(command=console.yview)
- console.insert(END,line)
- ctl.lift()
+ def wait(self):
+ if self.asyProcess.returncode is not None:
+ return
+ else:
+ return self.asyProcess.wait()
-class asyTransform:
- """A python implementation of an asy transform"""
- def __init__(self,initTuple,delete=False):
- """Initialize the transform with a 6 entry tuple"""
- if type(initTuple) == type((0,)) and len(initTuple) == 6:
- self.t = initTuple
- self.x,self.y,self.xx,self.xy,self.yx,self.yy = initTuple
- self.deleted = delete
- else:
- raise Exception("Illegal initializer for asyTransform")
+ def __enter__(self):
+ self.start()
+ return self
- def getCode(self):
- """Obtain the asy code that represents this transform"""
- if self.deleted:
- return str(self.t) + ", false"
- else:
- return str(self.t)
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.stop()
+ self.wait()
- def scale(self,s):
- return asyTransform((0,0,s,0,0,s))*self
+ @property
+ def tempDirName(self):
+ return self.tmpdir
- def __str__(self):
- """Equivalent functionality to getCode(). It allows the expression str(asyTransform) to be meaningful."""
- return self.getCode()
+ def startThenStop(self):
+ self.start()
+ self.stop()
+ self.wait()
- def __mul__(self,other):
- """Define multiplication of transforms as composition."""
- if type(other)==type((0,)):
- if len(other) == 6:
- return self*asyTransform(other)
- elif len(other) == 2:
- return ((self.t[0]+self.t[2]*other[0]+self.t[3]*other[1]),(self.t[1]+self.t[4]*other[0]+self.t[5]*other[1]))
- else:
- raise Exception("Illegal multiplier of {:s}".format(str(type(other))))
- elif isinstance(other,asyTransform):
- result = asyTransform((0,0,0,0,0,0))
- result.x = self.x+self.xx*other.x+self.xy*other.y
- result.y = self.y+self.yx*other.x+self.yy*other.y
- result.xx = self.xx*other.xx+self.xy*other.yx
- result.xy = self.xx*other.xy+self.xy*other.yy
- result.yx = self.yx*other.xx+self.yy*other.yx
- result.yy = self.yx*other.xy+self.yy*other.yy
- result.t = (result.x,result.y,result.xx,result.xy,result.yx,result.yy)
- return result
- else:
- raise Exception("Illegal multiplier of {:s}".format(str(type(other))))
+ @property
+ def active(self):
+ if self.asyProcess is None:
+ return False
+ return self.asyProcess.returncode is None
+ def stop(self):
+ if self.active:
+ self.asyProcess.kill()
+
+ def cleanup(self):
+ self.stop()
+ if self.asyProcess is not None:
+ self.asyProcess.wait()
+ if not self.keepFiles:
+ if os.path.isdir(self.tempDirName + os.sep):
+ shutil.rmtree(self.tempDirName, ignore_errors=True)
+
+class asyTransform(Qc.QObject):
+ """A python implementation of an asy transform"""
+
+ def __init__(self, initTuple, delete=False):
+ """Initialize the transform with a 6 entry tuple"""
+ super().__init__()
+ if isinstance(initTuple, (tuple, list)) and len(initTuple) == 6:
+ self.t = initTuple
+ self.x, self.y, self.xx, self.xy, self.yx, self.yy = initTuple
+ self._deleted = delete
+ else:
+ raise TypeError("Illegal initializer for asyTransform")
+
+ @property
+ def deleted(self):
+ return self._deleted
+
+ @deleted.setter
+ def deleted(self, value):
+ self._deleted = value
+
+ @classmethod
+ def zero(cls):
+ return asyTransform((0, 0, 0, 0, 0, 0))
+
+ @classmethod
+ def fromQTransform(cls, transform: Qg.QTransform):
+ tx, ty = transform.dx(), transform.dy()
+ xx, xy, yx, yy = transform.m11(), transform.m21(), transform.m12(), transform.m22()
+
+ return asyTransform((tx, ty, xx, xy, yx, yy))
+
+ @classmethod
+ def fromNumpyMatrix(cls, transform: np.ndarray):
+ assert transform.shape == (3, 3)
+
+ tx = transform[0, 2]
+ ty = transform[1, 2]
+
+ xx, xy, yx, yy = transform[0:2, 0:2].ravel().tolist()[0]
+
+ return asyTransform((tx, ty, xx, xy, yx, yy))
+
+ def getRawCode(self):
+ return xu.tuple2StrWOspaces(self.t)
+
+ def getCode(self, asy2psmap=None):
+ """Obtain the asy code that represents this transform"""
+ if asy2psmap is None:
+ asy2psmap = asyTransform((0, 0, 1, 0, 0, 1))
+ if self.deleted:
+ return 'zeroTransform'
+ else:
+ return (asy2psmap.inverted() * self * asy2psmap).getRawCode()
+
+ def scale(self, s):
+ return asyTransform((0, 0, s, 0, 0, s)) * self
+
+ def toQTransform(self):
+ return Qg.QTransform(self.xx, self.yx, self.xy, self.yy, self.x, self.y)
+
+ def __str__(self):
+ """Equivalent functionality to getCode(). It allows the expression str(asyTransform) to be meaningful."""
+ return self.getCode()
+
+ def isIdentity(self):
+ return self == identity()
+
+ def inverted(self):
+ return asyTransform.fromQTransform(self.toQTransform().inverted()[0])
+
+ def __eq__(self, other):
+ return list(self.t) == list(other.t)
+
+ def __mul__(self, other):
+ """Define multiplication of transforms as composition."""
+ if isinstance(other, tuple):
+ if len(other) == 6:
+ return self * asyTransform(other)
+ elif len(other) == 2:
+ return ((self.t[0] + self.t[2] * other[0] + self.t[3] * other[1]),
+ (self.t[1] + self.t[4] * other[0] + self.t[5] * other[1]))
+ else:
+ raise Exception("Illegal multiplier of {:s}".format(str(type(other))))
+ elif isinstance(other, asyTransform):
+ result = asyTransform((0, 0, 0, 0, 0, 0))
+ result.x = self.x + self.xx * other.x + self.xy * other.y
+ result.y = self.y + self.yx * other.x + self.yy * other.y
+ result.xx = self.xx * other.xx + self.xy * other.yx
+ result.xy = self.xx * other.xy + self.xy * other.yy
+ result.yx = self.yx * other.xx + self.yy * other.yx
+ result.yy = self.yx * other.xy + self.yy * other.yy
+ result.t = (result.x, result.y, result.xx, result.xy, result.yx, result.yy)
+ return result
+ elif isinstance(other, str):
+ if other != 'cycle':
+ raise TypeError
+ else:
+ return 'cycle'
+ else:
+ raise TypeError("Illegal multiplier of {:s}".format(str(type(other))))
+
+
def identity():
- return asyTransform((0,0,1,0,0,1))
+ return asyTransform((0, 0, 1, 0, 0, 1))
-class asyObj:
- """A base class for asy objects: an item represented by asymptote code."""
- def __init__(self):
- """Initialize the object"""
- self.asyCode = ""
+def yflip():
+ return asyTransform((0, 0, 1, 0, 0, -1))
- def updateCode(self,mag=1.0):
- """Update the object's code: should be overriden."""
- pass
+class asyObj(Qc.QObject):
+ """A base class for asy objects: an item represented by asymptote code."""
+ def __init__(self):
+ """Initialize the object"""
+ super().__init__()
+ self.asyCode = ''
- def getCode(self):
- """Return the code describing the object"""
- self.updateCode()
- return self.asyCode
+ def updateCode(self, ps2asymap=identity()):
+ """Update the object's code: should be overriden."""
+ raise NotImplementedError
+ def getCode(self, ps2asymap=identity()):
+ """Return the code describing the object"""
+ self.updateCode(ps2asymap)
+ return self.asyCode
+
+
class asyPen(asyObj):
- """A python wrapper for an asymptote pen"""
- def __init__(self,color=(0,0,0),width=0.5,options=""):
- """Initialize the pen"""
- asyObj.__init__(self)
- self.options=options
- self.width=width
- self.setColor(color)
- self.updateCode()
- if options != "":
- self.computeColor()
+ """A python wrapper for an asymptote pen"""
+ @staticmethod
+ def getColorFromQColor(color):
+ return color.redF(), color.greenF(), color.blueF()
- def updateCode(self,mag=1.0):
- """Generate the pen's code"""
- self.asyCode = "rgb({:g},{:g},{:g})+{:s}".format(self.color[0], self.color[1], self.color[2],str(self.width))
- if len(self.options) > 0:
- self.asyCode += "+"+self.options
+ @staticmethod
+ def convertToQColor(color):
+ r, g, b = color
+ return Qg.QColor.fromRgbF(r, g, b)
- def setWidth(self,newWidth):
- """Set the pen's width"""
- self.width=newWidth
- self.updateCode()
+ @classmethod
+ def fromAsyPen(cls, pen):
+ assert isinstance(pen, cls)
+ return cls(asyengine=pen._asyengine, color=pen.color, width=pen.width, pen_options=pen.options)
- def setColor(self,color):
- """Set the pen's color"""
- if type(color) == type((1,)) and len(color) == 3:
- self.color = color
- else:
- self.color = "(0,0,0)"
- self.updateCode()
+ def __init__(self, asyengine=None, color=(0, 0, 0), width=0.5, pen_options=""):
+ """Initialize the pen"""
+ asyObj.__init__(self)
+ self.color = (0, 0, 0)
+ self.options = pen_options
+ self.width = width
+ self._asyengine = asyengine
+ self._deferAsyfy = False
+ if pen_options:
+ self._deferAsyfy = True
+ self.updateCode()
+ self.setColor(color)
- def computeColor(self):
- """Find out the color of an arbitrary asymptote pen."""
- fout.write("pen p="+self.getCode()+';\n')
- fout.write("file fout=output(mode='pipe');\n")
- fout.write("write(fout,colorspace(p),newl);\n")
- fout.write("write(fout,colors(p));\n")
- fout.write("flush(fout);\n")
- fout.flush()
- colorspace = fin.readline()
- if colorspace.find("cmyk") != -1:
- lines = fin.readline()+fin.readline()+fin.readline()+fin.readline()
- parts = lines.split()
- c,m,y,k = eval(parts[0]),eval(parts[1]),eval(parts[2]),eval(parts[3])
- k = 1-k
- r,g,b = ((1-c)*k,(1-m)*k,(1-y)*k)
- elif colorspace.find("rgb") != -1:
- lines = fin.readline()+fin.readline()+fin.readline()
- parts = lines.split()
- r,g,b = eval(parts[0]),eval(parts[1]),eval(parts[2])
- elif colorspace.find("gray") != -1:
- lines = fin.readline()
- parts = lines.split()
- r = g = b = eval(parts[0])
- self.color = (r,g,b)
+ @property
+ def asyEngine(self):
+ return self._asyengine
- def tkColor(self):
- """Return the tk version of the pen's color"""
- self.computeColor()
- return '#{}'.format("".join(["{:02x}".format(min(int(256*a),255)) for a in self.color]))
+ @asyEngine.setter
+ def asyEngine(self, value):
+ self._asyengine = value
+ def updateCode(self, asy2psmap=identity()):
+ """Generate the pen's code"""
+ if self._deferAsyfy:
+ self.computeColor()
+ self.asyCode = 'rgb({:g},{:g},{:g})+{:s}'.format(self.color[0], self.color[1], self.color[2], str(self.width))
+ if len(self.options) > 0:
+ self.asyCode = self.asyCode + '+' + self.options
+
+ def setWidth(self, newWidth):
+ """Set the pen's width"""
+ self.width = newWidth
+ self.updateCode()
+
+ def setColor(self, color):
+ """Set the pen's color"""
+ if isinstance(color, tuple) and len(color) == 3:
+ self.color = color
+ else:
+ self.color = (0, 0, 0)
+ self.updateCode()
+
+ def setColorFromQColor(self, color):
+ self.setColor(asyPen.getColorFromQColor(color))
+
+ def computeColor(self):
+ """Find out the color of an arbitrary asymptote pen."""
+ assert isinstance(self.asyEngine, AsymptoteEngine)
+ assert self.asyEngine.active
+
+ fout = self.asyEngine.ostream
+ fin = self.asyEngine.istream
+
+ fout.write("pen p=" + self.getCode() + ';\n')
+ fout.write("write(_outpipe,colorspace(p),newl);\n")
+ fout.write("write(_outpipe,colors(p));\n")
+ fout.write("flush(_outpipe);\n")
+ fout.write(self.asyEngine.xasy)
+ fout.flush()
+
+ colorspace = fin.readline()
+ if colorspace.find("cmyk") != -1:
+ lines = fin.readline() + fin.readline() + fin.readline() + fin.readline()
+ parts = lines.split()
+ c, m, y, k = eval(parts[0]), eval(parts[1]), eval(parts[2]), eval(parts[3])
+ k = 1 - k
+ r, g, b = ((1 - c) * k, (1 - m) * k, (1 - y) * k)
+ elif colorspace.find("rgb") != -1:
+ lines = fin.readline() + fin.readline() + fin.readline()
+ parts = lines.split()
+ r, g, b = eval(parts[0]), eval(parts[1]), eval(parts[2])
+ elif colorspace.find("gray") != -1:
+ lines = fin.readline()
+ parts = lines.split()
+ r = g = b = eval(parts[0])
+ else:
+ raise ChildProcessError('Asymptote error.')
+ self.color = (r, g, b)
+ self._deferAsyfy = False
+
+ def tkColor(self):
+ """Return the tk version of the pen's color"""
+ self.computeColor()
+ return '#{}'.format("".join(["{:02x}".format(min(int(256 * a), 255)) for a in self.color]))
+
+ def toQPen(self):
+ if self._deferAsyfy:
+ self.computeColor()
+ newPen = Qg.QPen()
+ newPen.setColor(asyPen.convertToQColor(self.color))
+ newPen.setWidthF(self.width)
+
+ return newPen
+
+
class asyPath(asyObj):
- """A python wrapper for an asymptote path"""
- def __init__(self):
- """Initialize the path to be an empty path: a path with no nodes, control points, or links."""
- asyObj.__init__(self)
- self.nodeSet = []
- self.linkSet = []
- self.controlSet = []
- self.computed = False
+ """A python wrapper for an asymptote path"""
- def initFromNodeList(self,nodeSet,linkSet):
- """Initialize the path from a set of nodes and link types, "--", "..", or "::" """
- if len(nodeSet)>0:
- self.nodeSet = nodeSet[:]
- self.linkSet = linkSet[:]
- self.computed = False
+ def __init__(self, asyengine: AsymptoteEngine=None, forceCurve=False):
+ """Initialize the path to be an empty path: a path with no nodes, control points, or links."""
+ super().__init__()
+ self.nodeSet = []
+ self.linkSet = []
+ self.forceCurve = forceCurve
+ self.controlSet = []
+ self.computed = False
+ self.asyengine = asyengine
- def initFromControls(self,nodeSet,controlSet):
- """Initialize the path from nodes and control points"""
- self.controlSet = controlSet[:]
- self.nodeSet = nodeSet[:]
- self.computed = True
+ @classmethod
+ def fromPath(cls, oldPath):
+ newObj = asyPath(None)
+ newObj.nodeSet = copy.copy(oldPath.nodeSet)
+ newObj.linkSet = copy.copy(oldPath.linkSet)
+ newObj.controlSet = copy.deepcopy(oldPath.controlSet)
+ newObj.computed = oldPath.computed
+ newObj.asyengine = oldPath.asyengine
- def makeNodeStr(self,node):
- """Represent a node as a string"""
- if node == 'cycle':
- return node
- else:
- return "("+str(node[0])+","+str(node[1])+")"
+ return newObj
- def updateCode(self,mag=1.0):
- """Generate the code describing the path"""
- if not self.computed:
- count = 0
- #this string concatenation could be optimised
- self.asyCode = self.makeNodeStr(self.nodeSet[0])
- for node in self.nodeSet[1:]:
- self.asyCode += self.linkSet[count]+self.makeNodeStr(node)
- count += 1
- else:
- count = 0
- #this string concatenation could be optimised
- self.asyCode = self.makeNodeStr(self.nodeSet[0])
- for node in self.nodeSet[1:]:
- self.asyCode += "..controls"
- self.asyCode += self.makeNodeStr(self.controlSet[count][0])
- self.asyCode += "and"
- self.asyCode += self.makeNodeStr(self.controlSet[count][1])
- self.asyCode += ".." + self.makeNodeStr(node) + "\n"
- count += 1
+ @classmethod
+ def fromBezierPoints(cls, pointList: list, engine=None):
+ if not pointList:
+ return None
+ assert isinstance(pointList[0], BezierCurveEditor.BezierPoint)
+ nodeList = []
+ controlList = []
+ for point in pointList:
+ nodeList.append(BezierCurveEditor.QPoint2Tuple(point.point))
+ if point.rCtrlPoint is not None: # first
+ controlList.append([BezierCurveEditor.QPoint2Tuple(point.rCtrlPoint)])
+ if point.lCtrlPoint is not None: # last
+ controlList[-1].append(BezierCurveEditor.QPoint2Tuple(point.lCtrlPoint))
+ newPath = asyPath(asyengine=engine)
+ newPath.initFromControls(nodeList, controlList)
+ return newPath
- def getNode(self,index):
- """Return the requested node"""
- return self.nodeSet[index]
+ def setInfo(self, path):
+ self.nodeSet = copy.copy(path.nodeSet)
+ self.linkSet = copy.copy(path.linkSet)
+ self.controlSet = copy.deepcopy(path.controlSet)
+ self.computed = path.computed
- def getLink(self,index):
- """Return the requested link"""
- return self.linkSet[index]
+ @property
+ def isEmpty(self):
+ return len(self.nodeSet) == 0
- def setNode(self,index,newNode):
- """Set a node to a new position"""
- self.nodeSet[index] = newNode
+ @property
+ def isDrawable(self):
+ return len(self.nodeSet) >= 2
- def moveNode(self,index,offset):
- """Translate a node"""
- if self.nodeSet[index] != "cycle":
- self.nodeSet[index] = (self.nodeSet[index][0]+offset[0],self.nodeSet[1]+offset[1])
+ def toQPainterPath(self) -> Qg.QPainterPath:
+ return self.toQPainterPathCurve() if self.containsCurve else self.toQPainterPathLine()
- def setLink(self,index,ltype):
- """Change the specified link"""
- self.linkSet[index] = ltype
+ def toQPainterPathLine(self):
+ baseX, baseY = self.nodeSet[0]
+ painterPath = Qg.QPainterPath(Qc.QPointF(baseX, baseY))
- def addNode(self,point,ltype):
- """Add a node to the end of a path"""
- self.nodeSet.append(point)
- if len(self.nodeSet) != 1:
- self.linkSet.append(ltype)
- if self.computed:
- self.computeControls()
+ for pointIndex in range(1, len(self.nodeSet)):
+ node = self.nodeSet[pointIndex]
+ if self.nodeSet[pointIndex] == 'cycle':
+ node = self.nodeSet[0]
- def insertNode(self,index,point,ltype=".."):
- """Insert a node, and its corresponding link, at the given index"""
- self.nodeSet.insert(index,point)
- self.linkSet.insert(index,ltype)
- if self.computed:
- self.computeControls()
+ painterPath.lineTo(*node)
- def setControl(self,index,position):
- """Set a control point to a new position"""
- self.controlSet[index] = position
+ return painterPath
- def moveControl(self,index,offset):
- """Translate a control point"""
- self.controlSet[index] = (self.controlSet[index][0]+offset[0],self.controlSet[index][1]+offset[1])
- def computeControls(self):
- """Evaluate the code of the path to obtain its control points"""
- fout.write("file fout=output(mode='pipe');\n")
- fout.write("path p="+self.getCode()+';\n')
- fout.write("write(fout,length(p),newl);\n")
- fout.write("write(fout,unstraighten(p),endl);\n")
- fout.flush()
- lengthStr = fin.readline()
- pathSegments = eval(lengthStr.split()[-1])
- pathStrLines = []
- for i in range(pathSegments+1):
- line=fin.readline()
- line=line.replace("\n","")
- pathStrLines.append(line)
- oneLiner = "".join(pathStrLines).replace(" ", "")
- splitList = oneLiner.split("..")
- nodes = [a for a in splitList if a.find("controls")==-1]
- self.nodeSet = []
- for a in nodes:
- if a == 'cycle':
- self.nodeSet.append(a)
- else:
- self.nodeSet.append(eval(a))
- controls = [a.replace("controls","").split("and") for a in splitList if a.find("controls") != -1]
- self.controlSet = [[eval(a[0]),eval(a[1])] for a in controls]
- self.computed = True
+ def toQPainterPathCurve(self):
+ if not self.computed:
+ self.computeControls()
+ baseX, baseY = self.nodeSet[0]
+ painterPath = Qg.QPainterPath(Qc.QPointF(baseX, baseY))
+
+ for pointIndex in range(1, len(self.nodeSet)):
+ node = self.nodeSet[pointIndex]
+ if self.nodeSet[pointIndex] == 'cycle':
+ node = self.nodeSet[0]
+ endPoint = Qc.QPointF(node[0], node[1])
+ ctrlPoint1 = Qc.QPointF(self.controlSet[pointIndex-1][0][0], self.controlSet[pointIndex-1][0][1])
+ ctrlPoint2 = Qc.QPointF(self.controlSet[pointIndex-1][1][0], self.controlSet[pointIndex-1][1][1])
+
+ painterPath.cubicTo(ctrlPoint1, ctrlPoint2, endPoint)
+ return painterPath
+
+ def initFromNodeList(self, nodeSet, linkSet):
+ """Initialize the path from a set of nodes and link types, "--", "..", or "::" """
+ if len(nodeSet) > 0:
+ self.nodeSet = nodeSet[:]
+ self.linkSet = linkSet[:]
+ self.computed = False
+
+ def initFromControls(self, nodeSet, controlSet):
+ """Initialize the path from nodes and control points"""
+ self.controlSet = controlSet[:]
+ self.nodeSet = nodeSet[:]
+ self.computed = True
+
+ def makeNodeStr(self, node):
+ """Represent a node as a string"""
+ if node == 'cycle':
+ return node
+ else:
+ # if really want to, disable this rounding
+ # shouldn't be to much of a problem since 10e-6 is quite small...
+ return '({:.6g},{:.6g})'.format(node[0], node[1])
+
+ def updateCode(self, ps2asymap=identity()):
+ """Generate the code describing the path"""
+ # currently at postscript. Convert to asy
+ asy2psmap = ps2asymap.inverted()
+ with io.StringIO() as rawAsyCode:
+ count = 0
+ rawAsyCode.write(self.makeNodeStr(asy2psmap * self.nodeSet[0]))
+ for node in self.nodeSet[1:]:
+ if not self.computed or count >= len(self.controlSet):
+ rawAsyCode.write(self.linkSet[count])
+ rawAsyCode.write(self.makeNodeStr(asy2psmap * node))
+ else:
+ rawAsyCode.write('..controls ')
+ rawAsyCode.write(self.makeNodeStr(asy2psmap * self.controlSet[count][0]))
+ rawAsyCode.write(' and ')
+ rawAsyCode.write(self.makeNodeStr(asy2psmap * self.controlSet[count][1]))
+ rawAsyCode.write(".." + self.makeNodeStr(asy2psmap * node))
+ count = count + 1
+ self.asyCode = rawAsyCode.getvalue()
+
+ @property
+ def containsCurve(self):
+ return '..' in self.linkSet or self.forceCurve
+
+ def getNode(self, index):
+ """Return the requested node"""
+ return self.nodeSet[index]
+
+ def getLink(self, index):
+ """Return the requested link"""
+ return self.linkSet[index]
+
+ def setNode(self, index, newNode):
+ """Set a node to a new position"""
+ self.nodeSet[index] = newNode
+
+ def moveNode(self, index, offset):
+ """Translate a node"""
+ if self.nodeSet[index] != "cycle":
+ self.nodeSet[index] = (self.nodeSet[index][0] + offset[0], self.nodeSet[index][1] + offset[1])
+
+ def setLink(self, index, ltype):
+ """Change the specified link"""
+ self.linkSet[index] = ltype
+
+ def addNode(self, point, ltype):
+ """Add a node to the end of a path"""
+ self.nodeSet.append(point)
+ if len(self.nodeSet) != 1:
+ self.linkSet.append(ltype)
+ if self.computed:
+ self.computeControls()
+
+ def insertNode(self, index, point, ltype=".."):
+ """Insert a node, and its corresponding link, at the given index"""
+ self.nodeSet.insert(index, point)
+ self.linkSet.insert(index, ltype)
+ if self.computed:
+ self.computeControls()
+
+ def setControl(self, index, position):
+ """Set a control point to a new position"""
+ self.controlSet[index] = position
+
+ def popNode(self):
+ if len(self.controlSet) == len(self.nodeSet):
+ self.controlSet.pop()
+ self.nodeSet.pop()
+ self.linkSet.pop()
+
+ def moveControl(self, index, offset):
+ """Translate a control point"""
+ self.controlSet[index] = (self.controlSet[index][0] + offset[0], self.controlSet[index][1] + offset[1])
+
+ def computeControls(self):
+ """Evaluate the code of the path to obtain its control points"""
+ # For now, if no asymptote process is given spawns a new one.
+ # Only happens if asyengine is None.
+ if self.asyengine is not None:
+ assert isinstance(self.asyengine, AsymptoteEngine)
+ assert self.asyengine.active
+ asy = self.asyengine
+ startUp = False
+ else:
+ startUp = True
+ asy = AsymptoteEngine()
+ asy.start()
+
+ fout = asy.ostream
+ fin = asy.istream
+
+ fout.write("path p=" + self.getCode() + ';\n')
+ fout.write("write(_outpipe,length(p),newl);\n")
+ fout.write("write(_outpipe,unstraighten(p),endl);\n")
+ fout.write(asy.xasy)
+ fout.flush()
+
+ lengthStr = fin.readline()
+ pathSegments = eval(lengthStr.split()[-1])
+ pathStrLines = []
+ for i in range(pathSegments + 1):
+ line = fin.readline()
+ line = line.replace("\n", "")
+ pathStrLines.append(line)
+ oneLiner = "".join(pathStrLines).replace(" ", "")
+ splitList = oneLiner.split("..")
+ nodes = [a for a in splitList if a.find("controls") == -1]
+ self.nodeSet = []
+ for a in nodes:
+ if a == 'cycle':
+ self.nodeSet.append(a)
+ else:
+ self.nodeSet.append(eval(a))
+ controls = [a.replace("controls", "").split("and") for a in splitList if a.find("controls") != -1]
+ self.controlSet = [[eval(a[0]), eval(a[1])] for a in controls]
+ self.computed = True
+
+ if startUp:
+ asy.stop()
+
class asyLabel(asyObj):
- """A python wrapper for an asy label"""
- def __init__(self,text="",location=(0,0),pen=asyPen()):
- """Initialize the label with the given test, location, and pen"""
- asyObj.__init__(self)
- self.text = text
- self.location = location
- self.pen = pen
+ """A python wrapper for an asy label"""
- def updateCode(self,mag=1.0):
- """Generate the code describing the label"""
- self.asyCode = "Label(\""+self.text+"\","+str((self.location[0],self.location[1]))+","+self.pen.getCode()+",align=SE)"
+ def __init__(self, text="", location=(0, 0), pen=None, align=None, fontSize:int=None):
+ """Initialize the label with the given test, location, and pen"""
+ asyObj.__init__(self)
+ self.align = align
+ self.pen = pen
+ self.fontSize = fontSize
+ if align is None:
+ self.align = 'SE'
+ if pen is None:
+ self.pen = asyPen()
+ self.text = text
+ self.location = location
- def setText(self,text):
- """Set the label's text"""
- self.text = text
- self.updateCode()
+ def updateCode(self, asy2psmap=identity()):
+ """Generate the code describing the label"""
+ newLoc = asy2psmap.inverted() * self.location
+ locStr = xu.tuple2StrWOspaces(newLoc)
+ self.asyCode = 'Label("{0}",{1},p={2}{4},align={3})'.format(self.text, locStr, self.pen.getCode(), self.align,
+ self.getFontSizeText())
- def setPen(self,pen):
- """Set the label's pen"""
- self.pen = pen
- self.updateCode()
+ def getFontSizeText(self):
+ if self.fontSize is not None:
+ return '+fontsize({:.6g})'.format(self.fontSize)
+ else:
+ return ''
- def moveTo(self,newl):
- """Translate the label's location"""
- self.location = newl
+ def setText(self, text):
+ """Set the label's text"""
+ self.text = text
+ self.updateCode()
+ def setPen(self, pen):
+ """Set the label's pen"""
+ self.pen = pen
+ self.updateCode()
+
+ def moveTo(self, newl):
+ """Translate the label's location"""
+ self.location = newl
+
+
class asyImage:
- """A structure containing an image and its format, bbox, and IDTag"""
- def __init__(self,image,format,bbox):
- self.image = image
- self.format = format
- self.bbox = bbox
- self.IDTag = None
+ """A structure containing an image and its format, bbox, and IDTag"""
+ def __init__(self, image, format, bbox, transfKey=None, keyIndex=0):
+ self.image = image
+ self.format = format
+ self.bbox = bbox
+ self.IDTag = None
+ self.key = transfKey
+ self.keyIndex = keyIndex
-class xasyItem:
- """A base class for items in the xasy GUI"""
- def __init__(self,canvas=None):
- """Initialize the item to an empty item"""
- self.transform = [identity()]
- self.asyCode = ""
- self.imageList = []
- self.IDTag = None
- self.asyfied = False
- self.onCanvas = canvas
+class xasyItem(Qc.QObject):
+ """A base class for items in the xasy GUI"""
+ mapString = 'xmap'
+ setKeyFormatStr = string.Template('$map("{:s}",{:s});').substitute(map=mapString)
+ setKeyAloneFormatStr = string.Template('$map("{:s}");').substitute(map=mapString)
+ resizeComment="// Resize to initial xasy transform"
+ asySize=""
+ def __init__(self, canvas=None, asyengine=None):
+ """Initialize the item to an empty item"""
+ super().__init__()
+ self.transfKeymap = {} # the new keymap.
+ # should be a dictionary to a list...
+ self.asyCode = ''
+ self.imageList = []
+ self.IDTag = None
+ self.asyfied = False
+ self.onCanvas = canvas
+ self.keyBuffer = None
+ self._asyengine = asyengine
+ self.drawObjects = []
+ self.drawObjectsMap = {}
+ self.setKeyed = True
+ self.unsetKeys = set()
+ self.userKeys = set()
+ self.lineOffset = 0
+ self.imageHandleQueue = queue.Queue()
- def updateCode(self,mag=1.0):
- """Update the item's code: to be overriden"""
- pass
+ def updateCode(self, ps2asymap=identity()):
+ """Update the item's code: to be overriden"""
+ with io.StringIO() as rawCode:
+ transfCode = self.getTransformCode()
+ objCode = self.getObjectCode()
- def getCode(self):
- """Return the code describing the item"""
- self.updateCode()
- return self.asyCode
+ rawCode.write(transfCode)
+ rawCode.write(objCode)
+ self.asyCode = rawCode.getvalue()
- def handleImageReception(self,file,format,bbox,count):
- """Receive an image from an asy deconstruction. It replaces the default in asyProcess."""
- image = Image.open(file)
- self.imageList.append(asyImage(image,format,bbox))
- if self.onCanvas != None:
- self.imageList[-1].itk = ImageTk.PhotoImage(image)
- self.imageList[-1].originalImage = image.copy()
- self.imageList[-1].originalImage.theta = 0.0
- self.imageList[-1].originalImage.bbox = bbox
- if count >= len(self.transform) or self.transform[count].deleted == False:
- self.imageList[-1].IDTag = self.onCanvas.create_image(bbox[0],-bbox[3],anchor=NW,tags=("image"),image=self.imageList[-1].itk)
- self.onCanvas.update()
+ return len(transfCode.splitlines()), len(objCode.splitlines())
- def asyfy(self,mag=1.0):
- self.removeFromCanvas()
- self.imageList = []
- self.imageHandleQueue = queue.Queue()
- worker = threading.Thread(target=self.asyfyThread,args=(mag,))
- worker.start()
- item = self.imageHandleQueue.get()
- if console != None:
- console.delete(1.0,END)
- while item != (None,) and item[0] != "ERROR":
- if(item[0] == "OUTPUT"):
- consoleOutput(item[1])
- else:
- self.handleImageReception(*item)
- try:
- os.remove(item[0])
- except:
- pass
- item = self.imageHandleQueue.get()
- #self.imageHandleQueue.task_done()
- worker.join()
+ @property
+ def asyengine(self):
+ return self._asyengine
- def asyfyThread(self,mag=1.0):
- """Convert the item to a list of images by deconstructing this item's code"""
- fout.write("reset;\n")
- fout.write("initXasyMode();\n")
- fout.write("atexit(null);\n")
- for line in self.getCode().splitlines():
- fout.write(line+"\n");
- fout.write("deconstruct({:f});\n".format(mag))
- fout.flush()
- maxargs = int(fin.readline().split()[0])
- boxes=[]
- batch=0
- n=0
- text = fin.readline()
- # template=AsyTempDir+"%d_%d.%s"
- fileformat = "png"
- def render():
- for i in range(len(boxes)):
- l,b,r,t = [float(a) for a in boxes[i].split()]
- name="{:s}{:d}_{:d}.{:s}".format(AsyTempDir,batch,i+1,fileformat)
- self.imageHandleQueue.put((name,fileformat,(l,b,r,t),i))
- while text != "Done\n" and text != "Error\n":
- boxes.append(text)
- text = fin.readline()
- n += 1
- if n >= maxargs:
- render()
- boxes=[]
- batch += 1
- n=0
- if text == "Error\n":
- self.imageHandleQueue.put(("ERROR",fin.readline()))
- else:
- render()
- self.imageHandleQueue.put((None,))
- self.asyfied = True
+ @asyengine.setter
+ def asyengine(self, value):
+ self._asyengine = value
- def drawOnCanvas(self,canvas,mag,forceAddition=False):
- pass
- def removeFromCanvas(self):
- pass
+ def getCode(self, ps2asymap=identity()):
+ """Return the code describing the item"""
+ self.updateCode(ps2asymap)
+ return self.asyCode
+ def getTransformCode(self, asy2psmap=identity()):
+ raise NotImplementedError
+
+ def getObjectCode(self, asy2psmap=identity()):
+ raise NotImplementedError
+
+ def generateDrawObjects(self):
+ raise NotImplementedError
+
+ def handleImageReception(self, file, fileformat, bbox, count, key=None, localCount=0, containsClip=False):
+ """Receive an image from an asy deconstruction. It replaces the default n asyProcess."""
+ # image = Image.open(file).transpose(Image.FLIP_TOP_BOTTOM)
+ if fileformat == 'png':
+ image = Qg.QImage(file)
+ elif fileformat == 'svg':
+ if containsClip:
+ image = xs.SvgObject(file)
+ else:
+ image = Qs.QSvgRenderer(file)
+ assert image.isValid()
+ else:
+ raise Exception('Format not supported!')
+ self.imageList.append(asyImage(image, fileformat, bbox, transfKey=key, keyIndex=localCount))
+ if self.onCanvas is not None:
+ # self.imageList[-1].iqt = ImageTk.PhotoImage(image)
+ currImage = self.imageList[-1]
+ currImage.iqt = image
+ currImage.originalImage = image
+ currImage.originalImage.theta = 0.0
+ currImage.originalImage.bbox = list(bbox)
+ currImage.performCanvasTransform = False
+
+ # handle this case if transform is not in the map yet.
+ # if deleted - set transform to 0, 0, 0, 0, 0
+ transfExists = key in self.transfKeymap.keys()
+ if transfExists:
+ transfExists = localCount <= len(self.transfKeymap[key]) - 1
+ if transfExists:
+ validKey = not self.transfKeymap[key][localCount].deleted
+ else:
+ validKey = False
+
+ if (not transfExists) or validKey:
+ currImage.IDTag = str(file)
+ newDrawObj = DrawObject(currImage.iqt, self.onCanvas['canvas'], transform=identity(),
+ btmRightanchor=Qc.QPointF(bbox[0], bbox[2]), drawOrder=-1, key=key,
+ parentObj=self, keyIndex=localCount)
+ newDrawObj.setBoundingBoxPs(bbox)
+ newDrawObj.setParent(self)
+
+ self.drawObjects.append(newDrawObj)
+
+ if key not in self.drawObjectsMap.keys():
+ self.drawObjectsMap[key] = [newDrawObj]
+ else:
+ self.drawObjectsMap[key].append(newDrawObj)
+ return containsClip
+ def asyfy(self, force=False):
+ if self.asyengine is None:
+ return 1
+ if self.asyfied and not force:
+ return
+
+ self.drawObjects = []
+ self.drawObjectsMap.clear()
+ assert isinstance(self.asyengine, AsymptoteEngine)
+ self.imageList = []
+
+ self.unsetKeys.clear()
+ self.userKeys.clear()
+
+ self.imageHandleQueue = queue.Queue()
+ worker = threading.Thread(target=self.asyfyThread, args=[])
+ worker.start()
+ item = self.imageHandleQueue.get()
+ while item != (None,) and item[0] != "ERROR":
+ if item[0] == "OUTPUT":
+ print(item[1])
+ else:
+ keepFile = self.handleImageReception(*item)
+ if not DebugFlags.keepFiles and not keepFile:
+ try:
+ os.remove(item[0])
+ pass
+ except OSError:
+ pass
+ finally:
+ pass
+ item = self.imageHandleQueue.get()
+ # self.imageHandleQueue.task_done()
+ worker.join()
+
+ def asyfyThread(self):
+ """Convert the item to a list of images by deconstructing this item's code"""
+ assert self.asyengine.active
+
+ fout = self.asyengine.ostream
+ fin = self.asyengine.istream
+
+ self.lineOffset = len(self.getTransformCode().splitlines())
+
+ fout.write("reset\n")
+ fout.flush();
+ for line in self.getCode().splitlines():
+ if DebugFlags.printDeconstTranscript:
+ print('fout:', line)
+ fout.write(line+"\n")
+ fout.write(self.asySize)
+ fout.write("deconstruct();\n")
+ fout.write('write(_outpipe,yscale(-1)*currentpicture.calculateTransform(),endl);\n')
+ fout.write(self.asyengine.xasy)
+ fout.flush()
+
+ imageInfos = [] # of (box, key)
+ n = 0
+
+ keyCounts = {}
+
+ def render():
+ for i in range(len(imageInfos)):
+ box, key, localCount, useClip = imageInfos[i]
+ l, b, r, t = [float(a) for a in box.split()]
+ name = "{:s}_{:d}.{:s}".format(self.asyengine.tempDirName, i, fileformat)
+
+ self.imageHandleQueue.put((name, fileformat, (l, -t, r, -b), i, key, localCount, useClip))
+
+ # key first, box second.
+ # if key is "Done"
+ raw_text = fin.readline()
+ text = ""
+ if DebugFlags.printDeconstTranscript:
+ print(raw_text.strip())
+
+ # template=AsyTempDir+"%d_%d.%s"
+ fileformat = 'svg'
+
+ while raw_text != "Done\n" and raw_text != "Error\n":
+# print(raw_text)
+ text = fin.readline() # the actual bounding box.
+ # print('TESTING:', text)
+ keydata = raw_text.strip().replace('KEY=', '', 1) # key
+
+ clipflag = keydata[-1] == '1'
+ userkey = keydata[-2] == '1'
+ keydata = keydata[:-3]
+
+ if not userkey:
+ self.unsetKeys.add(keydata) # the line and column to replace.
+ else:
+ self.userKeys.add(keydata)
+
+# print(line, col)
+
+ if keydata not in keyCounts.keys():
+ keyCounts[keydata] = 0
+
+ imageInfos.append((text, keydata, keyCounts[keydata], clipflag)) # key-data pair
+
+ # for the next item
+ keyCounts[keydata] += 1
+
+ raw_text = fin.readline()
+
+ if DebugFlags.printDeconstTranscript:
+ print(text.rstrip())
+ print(raw_text.rstrip())
+
+ n += 1
+
+ if text == "Error\n":
+ self.imageHandleQueue.put(("ERROR", fin.readline()))
+ else:
+ render()
+
+ self.asy2psmap = asyTransform(xu.listize(fin.readline().rstrip(),float))
+ self.imageHandleQueue.put((None,))
+ self.asyfied = True
+
class xasyDrawnItem(xasyItem):
- """A base class for GUI items was drawn by the user. It combines a path, a pen, and a transform."""
- def __init__(self,path,pen = asyPen(),transform = identity()):
- """Initialize the item with a path, pen, and transform"""
- xasyItem.__init__(self)
- self.path = path
- self.pen = pen
- self.transform = [transform]
+ """A base class for GUI items was drawn by the user. It combines a path, a pen, and a transform."""
- def appendPoint(self,point,link=None):
- """Append a point to the path. If the path is cyclic, add this point before the 'cycle' node."""
- if self.path.nodeSet[-1] == 'cycle':
- self.path.nodeSet[-1] = point
- self.path.nodeSet.append('cycle')
- else:
- self.path.nodeSet.append(point)
- self.path.computed = False
- if len(self.path.nodeSet) > 1 and link != None:
- self.path.linkSet.append(link)
+ def __init__(self, path, engine, pen=None, transform=identity(), key=None):
+ """Initialize the item with a path, pen, and transform"""
+ super().__init__(canvas=None, asyengine=engine)
+ if pen is None:
+ pen = asyPen()
+ self.path = path
+ self.path.asyengine = engine
+ self.asyfied = True
+ self.pen = pen
+ self._asyengine = engine
+ self.rawIdentifier = ''
+ self.transfKey = key
+ self.transfKeymap = {self.transfKey: [transform]}
- def clearTransform(self):
- """Reset the item's transform"""
- self.transform = [identity()]
+ @property
+ def asyengine(self):
+ return self._asyengine
- def removeLastPoint(self):
- """Remove the last point in the path. If the path is cyclic, remove the node before the 'cycle' node."""
- if self.path.nodeSet[-1] == 'cycle':
- del self.path.nodeSet[-2]
- else:
- del self.path.nodeSet[-1]
- del self.path.linkSet[-1]
- self.path.computed = False
+ @asyengine.setter
+ def asyengine(self, value: AsymptoteEngine):
+ self._asyengine = value
+ self.path.asyengine = value
- def setLastPoint(self,point):
- """Modify the last point in the path. If the path is cyclic, modify the node before the 'cycle' node."""
- if self.path.nodeSet[-1] == 'cycle':
- self.path.nodeSet[-2] = point
- else:
- self.path.nodeSet[-1] = point
- self.path.computed = False
+ def setKey(self, newKey=None):
+ transform = self.transfKeymap[self.transfKey][0]
-class xasyShape(xasyDrawnItem):
- """An outlined shape drawn on the GUI"""
- def __init__(self,path,pen=asyPen(),transform=identity()):
- """Initialize the shape with a path, pen, and transform"""
- xasyDrawnItem.__init__(self,path,pen,transform)
+ self.transfKey = newKey
+ self.transfKeymap = {self.transfKey: [transform]}
- def updateCode(self,mag=1.0):
- """Generate the code to describe this shape"""
- self.asyCode = "xformStack.push("+self.transform[0].getCode()+");\n"
- self.asyCode += "draw("+self.path.getCode()+","+self.pen.getCode()+");"
+ def generateDrawObjects(self, forceUpdate=False):
+ raise NotImplementedError
- def removeFromCanvas(self,canvas):
- """Remove the shape's depiction from a tk canvas"""
- if self.IDTag != None:
- canvas.delete(self.IDTag)
+ def appendPoint(self, point, link=None):
+ """Append a point to the path. If the path is cyclic, add this point before the 'cycle' node."""
+ if self.path.nodeSet[-1] == 'cycle':
+ self.path.nodeSet[-1] = point
+ self.path.nodeSet.append('cycle')
+ else:
+ self.path.nodeSet.append(point)
+ self.path.computed = False
+ self.asyfied = False
+ if len(self.path.nodeSet) > 1 and link is not None:
+ self.path.linkSet.append(link)
- def drawOnCanvas(self,canvas,mag,asyFy=False,forceAddition=False):
- """Add this shape to a tk canvas"""
- if not asyFy:
- if self.IDTag == None or forceAddition:
- #add ourselves to the canvas
- self.path.computeControls()
- self.IDTag = canvas.create_line(0,0,0,0,tags=("drawn","xasyShape"),fill=self.pen.tkColor(),width=self.pen.width*mag)
- self.drawOnCanvas(canvas,mag)
- else:
- self.path.computeControls()
- pointSet = []
- previousNode = self.path.nodeSet[0]
- nodeCount = 0
- if len(self.path.nodeSet) == 0:
- pointSet = [0,0,0,0]
- elif len(self.path.nodeSet) == 1:
- if self.path.nodeSet[-1] != 'cycle':
- p = self.transform[0]*(self.path.nodeSet[0][0],self.path.nodeSet[0][1])
- pointSet = [p[0],-p[1],p[0],-p[1],p[0],-p[1]]
- else:
- pointSet = [0,0,0,0]
+ def clearTransform(self):
+ """Reset the item's transform"""
+ self.transform = [identity()]
+ self.asyfied = False
+
+ def removeLastPoint(self):
+ """Remove the last point in the path. If the path is cyclic, remove the node before the 'cycle' node."""
+ if self.path.nodeSet[-1] == 'cycle':
+ del self.path.nodeSet[-2]
else:
- for node in self.path.nodeSet[1:]:
- if node == 'cycle':
- node = self.path.nodeSet[0]
- transform = self.transform[0].scale(mag)
- points = CubicBezier.makeBezier(transform*previousNode,transform*self.path.controlSet[nodeCount][0],transform*self.path.controlSet[nodeCount][1],transform*node)
- for point in points:
- pointSet += [point[0],-point[1]]
- nodeCount += 1
- previousNode = node
- canvas.coords(self.IDTag,*pointSet)
- canvas.itemconfigure(self.IDTag,fill=self.pen.tkColor(),width=self.pen.width*mag)
- else:
- #first asyfy then add an image list
- pass
+ del self.path.nodeSet[-1]
+ del self.path.linkSet[-1]
+ self.path.computed = False
+ self.asyfied = False
- def __str__(self):
- """Create a string describing this shape"""
- return "xasyShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+ def setLastPoint(self, point):
+ """Modify the last point in the path. If the path is cyclic, modify the node before the 'cycle' node."""
+ if self.path.nodeSet[-1] == 'cycle':
+ self.path.nodeSet[-2] = point
+ else:
+ self.path.nodeSet[-1] = point
+ self.path.computed = False
+ self.asyfied = False
-class xasyFilledShape(xasyShape):
- """A filled shape drawn on the GUI"""
- def __init__(self,path,pen=asyPen(),transform=identity()):
- """Initialize this shape with a path, pen, and transform"""
- if path.nodeSet[-1] != 'cycle':
- raise Exception("Filled paths must be cyclic")
- xasyShape.__init__(self,path,pen,transform)
- def updateCode(self,mag=1.0):
- """Generate the code describing this shape"""
- self.asyCode = "xformStack.push("+self.transform[0].getCode()+");\n"
- self.asyCode += "fill("+self.path.getCode()+","+self.pen.getCode()+");"
+class xasyShape(xasyDrawnItem):
+ """An outlined shape drawn on the GUI"""
+ def __init__(self, path, asyengine, pen=None, transform=identity()):
+ """Initialize the shape with a path, pen, and transform"""
+ super().__init__(path=path, engine=asyengine, pen=pen, transform=transform)
- def removeFromCanvas(self,canvas):
- """Remove this shape's depiction from a tk canvas"""
- if self.IDTag != None:
- canvas.delete(self.IDTag)
+ def getObjectCode(self, asy2psmap=identity()):
+ return 'draw(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n'
- def drawOnCanvas(self,canvas,mag,asyFy=False,forceAddition=False):
- """Add this shape to a tk canvas"""
- if not asyFy:
- if self.IDTag == None or forceAddition:
- #add ourselves to the canvas
- self.path.computeControls()
- self.IDTag = canvas.create_polygon(0,0,0,0,0,0,tags=("drawn","xasyFilledShape"),fill=self.pen.tkColor(),outline=self.pen.tkColor(),width=1*mag)
- self.drawOnCanvas(canvas,mag)
- else:
- self.path.computeControls()
- pointSet = []
- previousNode = self.path.nodeSet[0]
- nodeCount = 0
- if len(self.path.nodeSet) == 0:
- pointSet = [0,0,0,0,0,0]
- elif len(self.path.nodeSet) == 1:
- if self.path.nodeSet[-1] != 'cycle':
- p = self.transform[0]*(self.path.nodeSet[0][0],self.path.nodeSet[0][1])
- pointSet = [p[0],-p[1],p[0],-p[1],p[0],-p[1]]
- else:
- pointSet = [0,0,0,0,0,0]
- elif len(self.path.nodeSet) == 2:
- if self.path.nodeSet[-1] != 'cycle':
- p = self.transform[0].scale(mag)*(self.path.nodeSet[0][0],self.path.nodeSet[0][1])
- p2 = self.transform[0].scale(mag)*(self.path.nodeSet[1][0],self.path.nodeSet[1][1])
- pointSet = [p[0],-p[1],p2[0],-p2[1],p[0],-p[1]]
- else:
- pointSet = [0,0,0,0,0,0]
+ def getTransformCode(self, asy2psmap=identity()):
+ transf = self.transfKeymap[self.transfKey][0]
+ if transf == identity():
+ return ''
else:
- for node in self.path.nodeSet[1:]:
- if node == 'cycle':
- node = self.path.nodeSet[0]
- transform = self.transform[0].scale(mag)
- points = CubicBezier.makeBezier(transform*previousNode,transform*self.path.controlSet[nodeCount][0],transform*self.path.controlSet[nodeCount][1],transform*node)
- for point in points:
- pointSet += [point[0],-point[1]]
- nodeCount += 1
- previousNode = node
- canvas.coords(self.IDTag,*pointSet)
- canvas.itemconfigure(self.IDTag,fill=self.pen.tkColor(),outline=self.pen.tkColor(),width=1*mag)
- else:
- #first asyfy then add an image list
- pass
+ return xasyItem.setKeyFormatStr.format(self.transfKey, transf.getCode(asy2psmap))+'\n'
- def __str__(self):
- """Return a string describing this shape"""
- return "xasyFilledShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+ def generateDrawObjects(self, forceUpdate=False):
+ if self.path.containsCurve:
+ self.path.computeControls()
+ transf = self.transfKeymap[self.transfKey][0]
+ newObj = DrawObject(self.path.toQPainterPath(), None, drawOrder=0, transform=transf, pen=self.pen,
+ key=self.transfKey)
+ newObj.originalObj = self
+ newObj.setParent(self)
+ return [newObj]
+
+ def __str__(self):
+ """Create a string describing this shape"""
+ return "xasyShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+
+
+class xasyFilledShape(xasyShape):
+ """A filled shape drawn on the GUI"""
+
+ def __init__(self, path, asyengine, pen=None, transform=identity()):
+ """Initialize this shape with a path, pen, and transform"""
+ if path.nodeSet[-1] != 'cycle':
+ raise Exception("Filled paths must be cyclic")
+ super().__init__(path, asyengine, pen, transform)
+
+ def getObjectCode(self, asy2psmap=identity()):
+ return 'fill(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n'
+
+ def generateDrawObjects(self, forceUpdate=False):
+ if self.path.containsCurve:
+ self.path.computeControls()
+ newObj = DrawObject(self.path.toQPainterPath(), None, drawOrder=0, transform=self.transfKeymap[self.transfKey][0],
+ pen=self.pen, key=self.transfKey, fill=True)
+ newObj.originalObj = self
+ newObj.setParent(self)
+ return [newObj]
+
+ def __str__(self):
+ """Return a string describing this shape"""
+ return "xasyFilledShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+
+
class xasyText(xasyItem):
- """Text created by the GUI"""
- def __init__(self,text,location,pen=asyPen(),transform=identity()):
- """Initialize this item with text, a location, pen, and transform"""
- xasyItem.__init__(self)
- self.label=asyLabel(text,location,pen)
- self.transform = [transform]
- self.onCanvas = None
+ """Text created by the GUI"""
- def updateCode(self,mag=1.0):
- """Generate the code describing this object"""
- self.asyCode = "xformStack.push("+self.transform[0].getCode()+");\n"
- self.asyCode += "label("+self.label.getCode()+");"
+ def __init__(self, text, location, asyengine, pen=None, transform=yflip(), key=None, align=None, fontsize:int=None):
+ """Initialize this item with text, a location, pen, and transform"""
+ super().__init__(asyengine=asyengine)
+ if pen is None:
+ pen = asyPen(asyengine=asyengine)
+ if pen.asyEngine is None:
+ pen.asyEngine = asyengine
+ self.label = asyLabel(text, location, pen, align, fontSize=fontsize)
+ # self.transform = [transform]
+ self.transfKey = key
+ self.transfKeymap = {self.transfKey: [transform]}
+ self.asyfied = False
+ self.onCanvas = None
+
+ def setKey(self, newKey=None):
+ transform = self.transfKeymap[self.transfKey][0]
- def removeFromCanvas(self):
- """Removes the label's images from a tk canvas"""
- if self.onCanvas == None:
- return
- for image in self.imageList:
- if image.IDTag != None:
- self.onCanvas.delete(image.IDTag)
+ self.transfKey = newKey
+ self.transfKeymap = {self.transfKey: [transform]}
- def drawOnCanvas(self,canvas,mag,asyFy=True,forceAddition=False):
- """Adds the label's images to a tk canvas"""
- if self.onCanvas == None:
- self.onCanvas = canvas
- elif self.onCanvas != canvas:
- raise Exception("Error: item cannot be added to more than one canvas")
- self.asyfy(mag)
+ def getTransformCode(self, asy2psmap=yflip()):
+ transf = self.transfKeymap[self.transfKey][0]
+ if transf == yflip():
+ # return xasyItem.setKeyAloneFormatStr.format(self.transfKey)
+ return ''
+ else:
+ return xasyItem.setKeyFormatStr.format(self.transfKey, transf.getCode(asy2psmap))+"\n"
- def __str__(self):
- return "xasyText code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+ def getObjectCode(self, asy2psmap=yflip()):
+ return 'label(KEY="{0}",{1});'.format(self.transfKey, self.label.getCode(asy2psmap))+'\n'
+ def generateDrawObjects(self, forceUpdate=False):
+ self.asyfy(forceUpdate)
+ return self.drawObjects
+
+ def getBoundingBox(self):
+ self.asyfy()
+ return self.imageList[0].bbox
+
+ def __str__(self):
+ return "xasyText code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+
+
class xasyScript(xasyItem):
- """A set of images create from asymptote code. It is always deconstructed."""
- def __init__(self,canvas,script="",transforms=[]):
- """Initialize this script item"""
- xasyItem.__init__(self,canvas)
- self.transform = transforms[:]
- self.script = script
+ """A set of images create from asymptote code. It is always deconstructed."""
- def clearTransform(self):
- """Reset the transforms for each of the deconstructed images"""
- self.transform = [identity() for im in self.imageList]
+ def __init__(self, canvas, engine, script="", transforms=None, transfKeyMap=None):
+ """Initialize this script item"""
+ super().__init__(canvas, asyengine=engine)
+ if transfKeyMap is not None:
+ self.transfKeymap = transfKeyMap
+ else:
+ self.transfKeymap = {}
- def updateCode(self,mag=1.0):
- """Generate the code describing this script"""
- self.asyCode = "";
- if len(self.transform) > 0:
- self.asyCode = "xformStack.add("
- isFirst = True
- count = 0
- for xform in self.transform:
- if not isFirst:
- self.asyCode+=",\n"
- self.asyCode += "indexedTransform({:d},{:s})".format(count,str(xform))
- isFirst = False
- count += 1
- self.asyCode += ");\n"
- self.asyCode += "startScript(); {\n"
- self.asyCode += self.script.replace("\t"," ")
- self.asyCode = self.asyCode.rstrip()
- self.asyCode += "\n} endScript();\n"
+ self.script = script
+ self.key2imagemap = {}
+ self.namedUnsetKeys = {}
+ self.keyPrefix = ''
+ self.scriptAsyfied = False
+ self.updatedPrefix = True
- def setScript(self,script):
- """Sets the content of the script item."""
- self.script = script
- self.updateCode()
+ def clearTransform(self):
+ """Reset the transforms for each of the deconstructed images"""
+ # self.transform = [identity()] * len(self.imageList)
+ keyCount = {}
- def removeFromCanvas(self):
- """Removes the script's images from a tk canvas"""
- if self.onCanvas == None:
- return
- for image in self.imageList:
- if image.IDTag != None:
- self.onCanvas.delete(image.IDTag)
+ for im in self.imageList:
+ if im.key not in keyCount.keys():
+ keyCount[im.key] = 1
+ else:
+ keyCount[im.key] += 1
- def asyfy(self,mag):
- """Generate the list of images described by this object and adjust the length of the transform list."""
- xasyItem.asyfy(self,mag)
- while len(self.imageList) > len(self.transform):
- self.transform.append(identity())
- while len(self.imageList) < len(self.transform):
- self.transform.pop()
- self.updateCode()
+ for key in keyCount:
+ self.transfKeymap[key] = [identity()] * keyCount[key]
- def drawOnCanvas(self,canvas,mag,asyFy=True,forceAddition=False):
- """Adds the script's images to a tk canvas"""
- if self.onCanvas == None:
- self.onCanvas = canvas
- elif self.onCanvas != canvas:
- raise Exception("Error: item cannot be added to more than one canvas")
- self.asyfy(mag)
+ def getMaxKeyCounter(self):
+ maxCounter = -1
+ for key in self.transfKeymap:
+ testNum = re.match(r'^x(\d+)$', key)
+ if testNum is not None:
+ maxCounter = max(maxCounter, int(testNum.group(1)))
+ return maxCounter + 1
- def __str__(self):
- """Return a string describing this script"""
- retVal = "xasyScript\n\tTransforms:\n"
- for xform in self.transform:
- retVal += "\t"+str(xform)+"\n"
- retVal += "\tCode Ommitted"
- return retVal
+ def getTransformCode(self, asy2psmap=identity()):
+ with io.StringIO() as rawAsyCode:
+ if self.transfKeymap:
+ for key in self.transfKeymap.keys():
+ val = self.transfKeymap[key]
-if __name__=='__main__':
- root = Tk()
- t=xasyText("test",(0,0))
- t.asyfy()
+ writeval = list(reversed(val))
+ # need to map all transforms in a list if there is any non-identity
+ # unfortunately, have to check all transformations in the list.
+ while not all(checktransf == identity() for checktransf in writeval) and writeval:
+ transf = writeval.pop()
+ if transf.deleted:
+ rawAsyCode.write(xasyItem.setKeyFormatStr.format(key, transf.getCode(asy2psmap)) + '\n//')
+ if transf == identity() and not transf.deleted:
+ rawAsyCode.write(xasyItem.setKeyAloneFormatStr.format(key))
+ else:
+ rawAsyCode.write(xasyItem.setKeyFormatStr.format(key, transf.getCode(asy2psmap)))
+ rawAsyCode.write('\n')
+ result = rawAsyCode.getvalue()
+ return result
+
+ def findNonIdKeys(self):
+ return {key for key in self.transfKeymap if not all(transf == identity() for transf in self.transfKeymap[key]) }
+
+ def getObjectCode(self, asy2psmap=identity()):
+ numeric=r'([-+]?(?:(?:\d*\.\d+)|(?:\d+\.?)))'
+ rSize=re.compile("size\(\("+numeric+","+numeric+","+numeric+","
+ +numeric+","+numeric+","+numeric+"\)\); "+
+ self.resizeComment)
+
+ newScript = self.getReplacedKeysCode(self.findNonIdKeys())
+ with io.StringIO() as rawAsyCode:
+ for line in newScript.splitlines():
+ if(rSize.match(line)):
+ self.asySize=line.rstrip()+'\n'
+ else:
+ raw_line = line.rstrip().replace('\t', ' ' * 4)
+ rawAsyCode.write(raw_line + '\n')
+
+ self.updatedCode = rawAsyCode.getvalue()
+ return self.updatedCode
+
+ def setScript(self, script):
+ """Sets the content of the script item."""
+ self.script = script
+ self.updateCode()
+
+ def setKeyPrefix(self, newPrefix=''):
+ self.keyPrefix = newPrefix
+ self.updatedPrefix = False
+
+ def getReplacedKeysCode(self, key2replace: set=None) -> str:
+ keylist = {}
+ prefix = ''
+
+ key2replaceSet = self.unsetKeys if key2replace is None else \
+ self.unsetKeys & key2replace
+
+ linenum2key = {}
+
+ if not self.updatedPrefix:
+ prefix = self.keyPrefix
+
+ for key in key2replaceSet:
+ actualkey = key
+
+ key = key.split(':')[0]
+ raw_parsed = xu.tryParseKey(key)
+ assert raw_parsed is not None
+ line, col = [int(val) for val in raw_parsed.groups()]
+ if line not in keylist:
+ keylist[line] = set()
+ keylist[line].add(col)
+ linenum2key[(line, col)] = actualkey
+ self.unsetKeys.discard(key)
+
+
+ raw_code_lines = self.script.splitlines()
+ with io.StringIO() as raw_str:
+ for i_0 in range(len(raw_code_lines)):
+ i = i_0 + self.lineOffset
+ curr_str = raw_code_lines[i_0]
+ if i + 1 in keylist.keys():
+ # this case, we have a key.
+ with io.StringIO() as raw_line:
+ for j in range(len(curr_str)):
+ raw_line.write(curr_str[j])
+ if j + 1 in keylist[i + 1]:
+ # at this point, replace keys with xkey
+ raw_line.write('KEY="{0:s}",'.format(linenum2key[(i + 1, j + 1)]))
+ self.userKeys.add(linenum2key[(i + 1, j + 1)])
+ curr_str = raw_line.getvalue()
+ # else, skip and just write the line.
+ raw_str.write(curr_str + '\n')
+ return raw_str.getvalue()
+
+ def getUnusedKey(self, oldkey) -> str:
+ baseCounter = 0
+ newKey = oldkey
+ while newKey in self.userKeys:
+ newKey = oldkey + ':' + str(baseCounter)
+ baseCounter += 1
+ return newKey
+
+ def asyfy(self, keyOnly=False):
+ """Generate the list of images described by this object and adjust the length of the transform list."""
+ super().asyfy()
+
+ # Id --> Transf --> asy-fied --> Transf
+ # Transf should keep the original, raw transformation
+ # but for all new drawn objects - assign Id as transform.
+
+ if self.scriptAsyfied:
+ return
+
+ keyCount = {}
+ settedKey = {}
+
+ for im in self.imageList:
+ if im.key in self.unsetKeys and im.key not in settedKey.keys():
+ oldkey = im.key
+ self.unsetKeys.remove(im.key)
+ im.key = self.getUnusedKey(im.key)
+ self.unsetKeys.add(im.key)
+
+ for drawobj in self.drawObjectsMap[oldkey]:
+ drawobj.key = im.key
+
+ self.drawObjectsMap[im.key] = self.drawObjectsMap[oldkey]
+ self.drawObjectsMap.pop(oldkey)
+
+ settedKey[oldkey] = im.key
+ elif im.key in settedKey.keys():
+ im.key = settedKey[im.key]
+
+ if im.key not in keyCount.keys():
+ keyCount[im.key] = 1
+ else:
+ keyCount[im.key] += 1
+
+ if im.key not in self.key2imagemap.keys():
+ self.key2imagemap[im.key] = [im]
+ else:
+ self.key2imagemap[im.key].append(im)
+
+
+
+ for key in keyCount:
+ if key not in self.transfKeymap.keys():
+ self.transfKeymap[key] = [identity()] * keyCount[key]
+ else:
+ while len(self.transfKeymap[key]) < keyCount[key]:
+ self.transfKeymap[key].append(identity())
+
+ # while len(self.transfKeymap[key]) > keyCount[key]:
+ # self.transfKeymap[key].pop()
+
+ # change of basis
+ for keylist in self.transfKeymap.values():
+ for i in range(len(keylist)):
+ if keylist[i] != identity():
+ keylist[i] = self.asy2psmap * keylist[i] * self.asy2psmap.inverted()
+
+ self.updateCode()
+ self.scriptAsyfied = True
+
+ def generateDrawObjects(self, forceUpdate=False):
+ self.asyfy(forceUpdate)
+ return self.drawObjects
+
+ def __str__(self):
+ """Return a string describing this script"""
+ retVal = "xasyScript\n\tTransforms:\n"
+ for xform in self.transform:
+ retVal += "\t" + str(xform) + "\n"
+ retVal += "\tCode Ommitted"
+ return retVal
+
+
+class DrawObject(Qc.QObject):
+ def __init__(self, drawObject, mainCanvas=None, transform=identity(), btmRightanchor=Qc.QPointF(0, 0),
+ drawOrder=(-1, -1), pen=None, key=None, parentObj=None, fill=False, keyIndex=0):
+ super().__init__()
+ self.drawObject = drawObject
+ self.mainCanvas = mainCanvas
+ self.pTransform = transform
+ self.baseTransform = transform
+ self.drawOrder = drawOrder
+ self.btmRightAnchor = btmRightanchor
+ self.originalObj = parentObj
+ self.explicitBoundingBox = None
+ self.useCanvasTransformation = False
+ self.key = key
+ self.cachedSvgImg = None
+ self.cachedDPI = None
+ self.maxDPI=0
+ self.keyIndex = keyIndex
+ self.pen = pen
+ self.fill = fill
+
+ def getInteriorScrTransform(self, transform):
+ """Generates the transform with Interior transform applied beforehand."""
+ if isinstance(transform, Qg.QTransform):
+ transform = asyTransform.fromQTransform(transform)
+ return self.transform * transform * self.baseTransform.inverted()
+
+ @property
+ def transform(self):
+ return self.pTransform
+
+ @transform.setter
+ def transform(self, value):
+ self.pTransform = value
+
+ def setBoundingBoxPs(self, bbox):
+ l, b, r, t = bbox
+ self.explicitBoundingBox = Qc.QRectF(Qc.QPointF(l, b), Qc.QPointF(r, t))
+ # self.explicitBoundingBox = Qc.QRectF(0, 0, 100, 100)
+
+ @property
+ def boundingBox(self):
+ if self.explicitBoundingBox is not None:
+ testBbox = self.explicitBoundingBox
+ else:
+ if isinstance(self.drawObject, Qg.QImage):
+ testBbox = self.drawObject.rect()
+ testBbox.moveTo(self.btmRightAnchor.toPoint())
+ elif isinstance(self.drawObject, Qg.QPainterPath):
+ testBbox = self.baseTransform.toQTransform().mapRect(self.drawObject.boundingRect())
+ else:
+ raise TypeError('drawObject is not a valid type!')
+ pointList = [self.getScreenTransform().toQTransform().map(point) for point in [
+ testBbox.topLeft(), testBbox.topRight(), testBbox.bottomLeft(), testBbox.bottomRight()
+ ]]
+ return Qg.QPolygonF(pointList).boundingRect()
+
+ @property
+ def localBoundingBox(self):
+ testBbox = self.drawObject.rect()
+ testBbox.moveTo(self.btmRightAnchor.toPoint())
+ return testBbox
+
+ def getScreenTransform(self):
+ scrTransf = self.baseTransform.toQTransform().inverted()[0] * self.pTransform.toQTransform()
+ return asyTransform.fromQTransform(scrTransf)
+
+ def draw(self, additionalTransformation=None, applyReverse=False, canvas: Qg.QPainter=None, dpi=300):
+ if canvas is None:
+ canvas = self.mainCanvas
+ if additionalTransformation is None:
+ additionalTransformation = Qg.QTransform()
+
+ assert canvas.isActive()
+
+ canvas.save()
+ if self.pen:
+ oldPen = Qg.QPen(canvas.pen())
+ canvas.setPen(self.pen.toQPen())
+ else:
+ oldPen = Qg.QPen()
+
+ if not applyReverse:
+ canvas.setTransform(additionalTransformation, True)
+ canvas.setTransform(self.transform.toQTransform(), True)
+ else:
+ canvas.setTransform(self.transform.toQTransform(), True)
+ canvas.setTransform(additionalTransformation, True)
+
+ canvas.setTransform(self.baseTransform.toQTransform().inverted()[0], True)
+
+ if isinstance(self.drawObject, Qg.QImage):
+ canvas.drawImage(self.explicitBoundingBox, self.drawObject)
+ elif isinstance(self.drawObject, xs.SvgObject):
+ threshold = 1.44
+
+ if self.cachedDPI is None or self.cachedSvgImg is None \
+ or dpi > self.maxDPI*threshold:
+ self.cachedDPI = dpi
+ self.maxDPI=max(self.maxDPI,dpi)
+ self.cachedSvgImg = self.drawObject.render(dpi)
+
+ canvas.drawImage(self.explicitBoundingBox, self.cachedSvgImg)
+ elif isinstance(self.drawObject, Qs.QSvgRenderer):
+ self.drawObject.render(canvas, self.explicitBoundingBox)
+ elif isinstance(self.drawObject, Qg.QPainterPath):
+ path = self.baseTransform.toQTransform().map(self.drawObject)
+ if self.fill:
+ if self.pen:
+ brush = self.pen.toQPen().brush()
+ else:
+ brush = Qg.QBrush()
+ canvas.fillPath(path, brush)
+ else:
+ canvas.drawPath(path)
+
+ if self.pen:
+ canvas.setPen(oldPen)
+ canvas.restore()
+
+ def collide(self, coords, canvasCoordinates=True):
+ # modify these values to grow/shrink the fuzz.
+ fuzzTolerance = 1
+ marginGrowth = 1
+ leftMargin = marginGrowth if self.boundingBox.width() < fuzzTolerance else 0
+ topMargin = marginGrowth if self.boundingBox.height() < fuzzTolerance else 0
+
+ newMargin = Qc.QMarginsF(leftMargin, topMargin, leftMargin, topMargin)
+ return self.boundingBox.marginsAdded(newMargin).contains(coords)
+
+ def getID(self):
+ return self.originalObj
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyActions.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyActions.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyActions.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,391 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyActions implements the possible actions and their inverses
-# for the undo/redo stack in xasy
-#
-# Author: Orest Shardt
-# Created: July 23, 2007
-#
-###########################################################################
-import math
-import sys
-import UndoRedoStack
-import xasy2asy
-if sys.version_info >= (3, 0):
- from tkinter import *
-else:
- from Tkinter import *
-
-class translationAction(UndoRedoStack.action):
- def __init__(self,owner,itemList,indexList,translation):
- self.translation = translation
- self.owner = owner
- self.itemList = itemList
- self.indexList = indexList
- UndoRedoStack.action.__init__(self,self.transF,self.unTransF)
-
- def transF(self):
- mag = self.owner.magnification
- for i in range(len(self.itemList)):
- for index in self.indexList[i]:
- self.owner.translateSomething(-1,(self.translation[0]/mag,self.translation[1]/mag),self.itemList[i],index)
- if index==None:
- index = 0
- try:
- self.owner.mainCanvas.move(self.itemList[i].imageList[index].IDTag,self.translation[0]*mag,-self.translation[1]*mag)
- except:
- self.owner.mainCanvas.move(self.itemList[i].IDTag,self.translation[0]*mag,-self.translation[1]*mag)
- self.owner.updateSelection()
- self.owner.updateCanvasSize()
-
- def unTransF(self):
- mag = self.owner.magnification
- for i in range(len(self.itemList)):
- for index in self.indexList[i]:
- self.owner.translateSomething(-1,(-self.translation[0]/mag,-self.translation[1]/mag),self.itemList[i],index)
- try:
- self.owner.mainCanvas.move(self.itemList[i].imageList[index].IDTag,-self.translation[0]*mag,self.translation[1]*mag)
- except:
- self.owner.mainCanvas.move(self.itemList[i].IDTag,-self.translation[0]*mag,self.translation[1]*mag)
- self.owner.updateSelection()
- self.owner.updateCanvasSize()
-
- def __str__(self):
- return "Translation of "+str(self.itemList)+str(self.indexList)+" by "+str(self.translation)
-
-class rotationAction(UndoRedoStack.action):
- def __init__(self,owner,itemList,indexList,angle,origin):
- self.owner = owner
- self.itemList = itemList
- self.indexList = indexList
- self.angle = angle
- self.origin = origin
- UndoRedoStack.action.__init__(self,self.rotF,self.unRotF)
-
- def rotF(self):
- for i in range(len(self.itemList)):
- for index in self.indexList[i]:
- self.owner.rotateSomething(-1,self.angle,self.origin,self.itemList[i],index)
- for item in self.itemList:
- item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(item)
- self.owner.updateSelection()
- self.owner.updateCanvasSize()
-
- def unRotF(self):
- for i in range(len(self.itemList)):
- for index in self.indexList[i]:
- self.owner.rotateSomething(-1,-self.angle,self.origin,self.itemList[i],index)
- for item in self.itemList:
- item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(item)
- self.owner.updateSelection()
- self.owner.updateCanvasSize()
-
- def __str__(self):
- return "Rotation of "+str(self.itemList)+str(self.indexList)+" by "+"%.3f"%(self.angle*180.0/math.pi)+" about "+str(self.origin)
-
-class addLabelAction(UndoRedoStack.action):
- def __init__(self,owner,label):
- self.owner = owner
- self.label = label
- UndoRedoStack.action.__init__(self,self.addF,self.unAddF)
-
- def addF(self):
- self.owner.addItemToFile(self.label)
- self.label.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.label)
-
- def unAddF(self):
- self.label.removeFromCanvas()
- del self.owner.fileItems[-1]
- self.owner.propList.delete(0)
- self.owner.clearSelection()
-
- def __str__(self):
- return "Addition of a label"
-
-class deleteLabelAction(UndoRedoStack.action):
- def __init__(self,owner,label,index):
- self.owner = owner
- self.label = label
- self.index = index
- UndoRedoStack.action.__init__(self,self.delF,self.unDelF)
-
- def delF(self):
- self.owner.fileItems[self.index].removeFromCanvas()
- self.owner.propList.delete(len(self.owner.fileItems)-self.index-1)
- del self.owner.fileItems[self.index]
-
- def unDelF(self):
- self.owner.fileItems.insert(self.index,self.label)
- self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.propList.insert(len(self.owner.fileItems)-self.index-1,self.owner.describeItem(self.label))
- self.owner.bindItemEvents(self.label)
-
- def __str__(self):
- return "Deletion of a label"
-
-class editLabelTextAction(UndoRedoStack.action):
- def __init__(self,owner,label,newText,oldText):
- self.owner = owner
- self.label = label
- self.newText = newText
- self.oldText = oldText
- UndoRedoStack.action.__init__(self,self.modT,self.unModT)
-
- def modT(self):
- self.label.label.setText(self.newText)
- self.label.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.label)
-
- def unModT(self):
- self.label.label.setText(self.oldText)
- self.label.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.label)
-
- def __str__(self):
- return "Editing a label's text"
-
-class editLabelPenAction(UndoRedoStack.action):
- def __init__(self,owner,oldPen,newPen,index):
- self.owner = owner
- self.newPen = newPen
- self.oldPen = oldPen
- self.index = index
- UndoRedoStack.action.__init__(self,self.editF,self.unEditF)
-
- def editF(self):
- self.owner.fileItems[self.index].removeFromCanvas()
- self.owner.fileItems[self.index].label.pen = self.newPen
- self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
- def unEditF(self):
- self.owner.fileItems[self.index].removeFromCanvas()
- self.owner.fileItems[self.index].label.pen = self.oldPen
- self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
- def __str__(self):
- return "Changing a label's pen"
-
-class addScriptAction(UndoRedoStack.action):
- def __init__(self,owner,script):
- self.owner = owner
- self.script = script
- UndoRedoStack.action.__init__(self,self.addF,self.unAddF)
-
- def addF(self):
- self.owner.addItemToFile(self.script)
- self.script.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.script)
-
- def unAddF(self):
- self.script.removeFromCanvas()
- del self.owner.fileItems[-1]
- self.owner.propList.delete(0)
- self.owner.clearSelection()
-
- def __str__(self):
- return "Addition of a script"
-
-class deleteScriptAction(UndoRedoStack.action):
- def __init__(self,owner,script,index):
- self.owner = owner
- self.script = script
- self.index = index
- UndoRedoStack.action.__init__(self,self.delF,self.unDelF)
-
- def delF(self):
- self.owner.fileItems[self.index].removeFromCanvas()
- self.owner.propList.delete(len(self.owner.fileItems)-self.index-1)
- del self.owner.fileItems[self.index]
-
- def unDelF(self):
- self.owner.fileItems.insert(self.index,self.script)
- self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.propList.insert(len(self.owner.fileItems)-self.index-1,self.owner.describeItem(self.script))
- self.owner.bindItemEvents(self.script)
-
- def __str__(self):
- return "Deletion of a script"
-
-class deleteScriptItemAction(UndoRedoStack.action):
- def __init__(self,owner,script,indices,oldTransforms):
- self.owner = owner
- self.script = script
- self.indices = indices[:]
- UndoRedoStack.action.__init__(self,self.delI,self.unDelI)
- def delI(self):
- for index in self.indices:
- self.script.transform[index].deleted = True
- self.owner.mainCanvas.delete(self.script.imageList[index].IDTag)
-
- def unDelI(self):
- for i in range(len(self.indices)):
- index = self.indices[i]
- self.script.transform[index].deleted = False
- bbox = self.script.imageList[index].originalImage.bbox
- self.script.imageList[index].IDTag = self.owner.mainCanvas.create_image(bbox[0],-bbox[3],anchor=NW,tags=("image"),image=self.script.imageList[index].itk)
- self.owner.bindEvents(self.script.imageList[index].IDTag)
- self.owner.resetStacking()
-
- def __str__(self):
- return "Deletion of item "+str(self.indices)+" in "+str(self.script)
-
-class editScriptAction(UndoRedoStack.action):
- def __init__(self,owner,script,newText,oldText):
- self.owner = owner
- self.script = script
- self.newText = newText
- self.oldText = oldText
- UndoRedoStack.action.__init__(self,self.modS,self.unModS)
-
- def modS(self):
- self.script.setScript(self.newText)
- self.script.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.script)
-
- def unModS(self):
- self.script.setScript(self.oldText)
- self.script.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
- self.owner.bindItemEvents(self.script)
-
- def __str__(self):
- return "Modification of a script"
-
-class clearItemTransformsAction(UndoRedoStack.action):
- def __init__(self,owner,item,oldTransforms):
- self.owner = owner
- self.item = item
- self.oldTransforms = oldTransforms
- UndoRedoStack.action.__init__(self,self.clearF,self.unClearF)
-
- def clearF(self):
- for i in range(len(self.oldTransforms)):
- self.item.transform[i] = xasy2asy.identity()
- self.item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-
- def unClearF(self):
- for i in range(len(self.oldTransforms)):
- self.item.transform[i] = self.oldTransforms[i]
- self.item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-
- def __str__(self):
- return "Clear the transforms of "+str(self.item)+" from "+str(self.oldTransforms)
-
-class itemRaiseAction(UndoRedoStack.action):
- def __init__(self,owner,items,oldPositions):
- self.owner = owner
- self.items = items[:]
- self.oldPositions = oldPositions[:]
- UndoRedoStack.action.__init__(self,self.raiseI,self.unRaiseI)
-
- def raiseI(self):
- for item in self.items:
- self.owner.raiseSomething(item)
-
- def unRaiseI(self):
- length = len(self.owner.fileItems)
- indices = self.oldPositions[:]
- indices = [length-i-1 for i in indices]
- indices.reverse()
- for index in indices:
- for i in range(index):
- self.owner.raiseSomething(self.owner.fileItems[length-index-1])
-
- def __str__(self):
- return "Raise items "+str(self.items)+" from positions "+str(self.oldPositions)
-
-class itemLowerAction(UndoRedoStack.action):
- def __init__(self,owner,items,oldPositions):
- self.owner = owner
- self.items = items[:]
- self.oldPositions = oldPositions[:]
- UndoRedoStack.action.__init__(self,self.lowerI,self.unLowerI)
-
- def lowerI(self):
- for item in self.items:
- self.owner.lowerSomething(item)
-
- def unLowerI(self):
- indices = self.oldPositions[:]
- indices.reverse()
- for index in indices:
- for i in range(index):
- self.owner.lowerSomething(self.owner.fileItems[index])
-
- def __str__(self):
- return "Lower items "+str(self.items)+" from positions "+str(self.oldPositions)
-
-class addDrawnItemAction(UndoRedoStack.action):
- def __init__(self,owner,item):
- self.owner = owner
- self.item = item
- UndoRedoStack.action.__init__(self,self.drawF,self.unDrawF)
-
- def drawF(self):
- self.owner.addItemToFile(self.item)
- self.item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
- self.owner.bindItemEvents(self.item)
-
- def unDrawF(self):
- self.item.removeFromCanvas(self.owner.mainCanvas)
- del self.owner.fileItems[-1]
- self.owner.propList.delete(0)
- self.owner.clearSelection()
-
- def __str__(self):
- return "Drawing of an item"
-
-class deleteDrawnItemAction(UndoRedoStack.action):
- def __init__(self,owner,item,index):
- self.owner = owner
- self.item = item
- self.index = index
- UndoRedoStack.action.__init__(self,self.delF,self.unDelF)
-
- def delF(self):
- self.owner.fileItems[self.index].removeFromCanvas(self.owner.mainCanvas)
- self.owner.propList.delete(len(self.owner.fileItems)-self.index-1)
- del self.owner.fileItems[self.index]
-
- def unDelF(self):
- self.owner.fileItems.insert(self.index,self.item)
- self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
- self.owner.propList.insert(len(self.owner.fileItems)-self.index-1,self.owner.describeItem(self.item))
- self.owner.bindItemEvents(self.item)
-
- def __str__(self):
- return "Deletion of a drawn item"
-
-class editDrawnItemAction(UndoRedoStack.action):
- def __init__(self,owner,oldItem,newItem,index):
- self.owner = owner
- self.oldItem = oldItem
- self.newItem = newItem
- self.index = index
- UndoRedoStack.action.__init__(self,self.editF,self.unEditF)
-
- def editF(self):
- self.owner.fileItems[self.index].removeFromCanvas(self.owner.mainCanvas)
- self.owner.fileItems[self.index].path = self.newItem.path
- self.owner.fileItems[self.index].pen = self.newItem.pen
- self.owner.fileItems[self.index].transform = self.newItem.transform
- self.owner.fileItems[self.index].IDTag = self.newItem.IDTag
- self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
- self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
- def unEditF(self):
- self.owner.fileItems[self.index].removeFromCanvas(self.owner.mainCanvas)
- self.owner.fileItems[self.index].path = self.oldItem.path
- self.owner.fileItems[self.index].pen = self.oldItem.pen
- self.owner.fileItems[self.index].transform = self.oldItem.transform
- self.owner.fileItems[self.index].IDTag = self.oldItem.IDTag
- self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
- self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
- def __str__(self):
- return "Modification of a drawn item"
Added: trunk/Build/source/utils/asymptote/GUI/xasyArgs.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyArgs.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/xasyArgs.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+import argparse
+import xasyVersion
+import PyQt5.QtCore as Qc
+# Add arguments here.
+
+
+def parseArgs(args):
+ parser = argparse.ArgumentParser(args)
+ parser.add_argument('-p', '--asypath', help='Custom Asymptote asy executable')
+ parser.add_argument('-v', '--version', help='Version number', action='version',
+ version='xasy v{0}'.format(xasyVersion.xasyVersion))
+ parser.add_argument('-l', '--language', help='language')
+ parser.add_argument('-x', '--mag', help='Magnification. Defaults to 1', default=1, type=float)
+
+ parser.add_argument(
+ 'filename', help='Filename to load. If empty, initializes empty xasy canvas.', nargs='?', default=None)
+
+ return parser.parse_args()
+
+
+def getArgs():
+ return parseArgs(Qc.QCoreApplication.arguments())
Property changes on: trunk/Build/source/utils/asymptote/GUI/xasyArgs.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyBezierEditor.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyBezierEditor.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyBezierEditor.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,213 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyBezierEditor implements the ability to graphically edit the location
-# of the nodes and control points of a bezier curve.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-
-import math
-import sys
-from CubicBezier import *
-import xasy2asy
-
-if sys.version_info >= (3, 0):
- from tkinter import *
-else:
- from Tkinter import *
-
-class node:
- def __init__(self,precontrol,node,postcontrol,uid,isTied = True):
- self.node = node
- self.precontrol = precontrol
- self.postcontrol = postcontrol
- self.isTied = isTied
- self.uid = uid
- self.nodeID = self.precontrolID = self.prelineID = self.postcontrolID = self.postlineID = None
-
- def shiftNode(self,delta):
- self.node = (self.node[0]+delta[0],self.node[1]+delta[1])
- if self.precontrol != None:
- self.precontrol = (self.precontrol[0]+delta[0],self.precontrol[1]+delta[1])
- if self.postcontrol != None:
- self.postcontrol = (self.postcontrol[0]+delta[0],self.postcontrol[1]+delta[1])
-
- def shiftPrecontrol(self,delta):
- self.precontrol = (self.precontrol[0]+delta[0],self.precontrol[1]+delta[1])
- if self.isTied and self.postcontrol != None:
- self.rotatePostControl(self.precontrol)
-
- def shiftPostcontrol(self,delta):
- self.postcontrol = (self.postcontrol[0]+delta[0],self.postcontrol[1]+delta[1])
- if self.isTied and self.precontrol != None:
- self.rotatePrecontrol(self.postcontrol)
-
- def rotatePrecontrol(self,after):
- vx,vy = after[0]-self.node[0],after[1]-self.node[1]
- l = norm((vx,vy))
- if l == 0:
- return
- m = norm((self.precontrol[0]-self.node[0],self.precontrol[1]-self.node[1]))
- vx = -m*vx/l
- vy = -m*vy/l
- self.precontrol = self.node[0]+vx,self.node[1]+vy
-
- def rotatePostControl(self,after):
- vx,vy = after[0]-self.node[0],after[1]-self.node[1]
- l = norm((vx,vy))
- if l == 0:
- return
- m = norm((self.postcontrol[0]-self.node[0],self.postcontrol[1]-self.node[1]))
- vx = -m*vx/l
- vy = -m*vy/l
- self.postcontrol = self.node[0]+vx,self.node[1]+vy
-
- def draw(self,canvas):
- width = 3
- if self.precontrol != None:
- if self.prelineID == None:
- self.prelineID = canvas.create_line(self.precontrol[0],-self.precontrol[1],self.node[0],-self.node[1],tags=("preline",self.uid))
- else:
- canvas.coords(self.prelineID,self.precontrol[0],-self.precontrol[1],self.node[0],-self.node[1])
- if self.precontrolID == None:
- self.precontrolID = canvas.create_oval(self.precontrol[0]-width,-self.precontrol[1]-width,self.precontrol[0]+width,-self.precontrol[1]+width,
- fill="red",outline="black",tags=("precontrol",self.uid))
- else:
- canvas.coords(self.precontrolID,self.precontrol[0]-width,-self.precontrol[1]-width,self.precontrol[0]+width,-self.precontrol[1]+width)
- if self.postcontrol != None:
- if self.postlineID == None:
- self.postlineID = canvas.create_line(self.postcontrol[0],-self.postcontrol[1],self.node[0],-self.node[1],tags=("postline",self.uid))
- else:
- canvas.coords(self.postlineID,self.postcontrol[0],-self.postcontrol[1],self.node[0],-self.node[1])
- if self.postcontrolID == None:
- self.postcontrolID = canvas.create_oval(self.postcontrol[0]-width,-self.postcontrol[1]-width,self.postcontrol[0]+width,-self.postcontrol[1]+width,
- fill="red",outline="black",tags=("postcontrol",self.uid))
- else:
- canvas.coords(self.postcontrolID,self.postcontrol[0]-width,-self.postcontrol[1]-width,self.postcontrol[0]+width,-self.postcontrol[1]+width)
- if self.isTied:
- color = "blue"
- else:
- color = "green"
- if self.nodeID == None:
- self.nodeID = canvas.create_oval(self.node[0]-width,-self.node[1]-width,self.node[0]+width,-self.node[1]+width,
- fill=color,outline="black",tags=("node",self.uid))
- else:
- canvas.coords(self.nodeID,self.node[0]-width,-self.node[1]-width,self.node[0]+width,-self.node[1]+width)
- canvas.itemconfigure(self.nodeID,fill=color)
-
-class xasyBezierEditor:
- def __init__(self,parent,shape,canvas):
- self.parent = parent
- self.shape = shape
- self.transform = self.shape.transform[0]
- self.path = self.shape.path
- self.canvas = canvas
- self.modified = False
- self.path.computeControls()
- isCyclic = self.path.nodeSet[-1] == 'cycle'
- segments = len(self.path.controlSet)
- self.nodeList = []
- for i in range(segments):
- if i == 0:
- node0 = self.transform*self.path.nodeSet[i]
- control = self.transform*self.path.controlSet[i][0]
- self.nodeList.append(node(None,node0,control,len(self.nodeList)))
- else:
- node0 = self.transform*self.path.nodeSet[i]
- precontrol = self.transform*self.path.controlSet[i-1][1]
- postcontrol = self.transform*self.path.controlSet[i][0]
- self.nodeList.append(node(precontrol,node0,postcontrol,len(self.nodeList)))
- if not isCyclic:
- node0 = self.transform*self.path.nodeSet[-1]
- precontrol = self.transform*self.path.controlSet[-1][1]
- self.nodeList.append(node(precontrol,node0,None,len(self.nodeList)))
- else:
- self.nodeList[0].precontrol = self.transform*self.path.controlSet[-1][1]
- self.showControls()
- self.bindNodeEvents()
- self.bindControlEvents()
-
- def showControls(self):
- for n in self.nodeList:
- n.draw(self.canvas)
- self.bindNodeEvents()
- self.bindControlEvents()
- self.parent.updateCanvasSize()
-
- def bindNodeEvents(self):
- self.canvas.tag_bind("node","<B1-Motion>",self.nodeDrag)
- self.canvas.tag_bind("node","<Button-1>",self.buttonDown)
- self.canvas.tag_bind("node","<Double-Button-1>",self.toggleNode)
-
- def unbindNodeEvents(self):
- self.canvas.tag_unbind("node","<B1-Motion>")
- self.canvas.tag_unbind("node","<Button-1>")
- self.canvas.tag_unbind("node","<Double-Button-1>")
-
- def bindControlEvents(self):
- self.canvas.tag_bind("precontrol || postcontrol","<B1-Motion>",self.controlDrag)
- self.canvas.tag_bind("precontrol || postcontrol","<Button-1>",self.buttonDown)
-
- def unbindControlEvents(self):
- self.canvas.tag_unbind("precontrol || postcontrol","<B1-Motion>")
- self.canvas.tag_unbind("precontrol || postcontrol","<Button-1>")
-
- def buttonDown(self,event):
- self.parent.freeMouseDown = False
- self.startx,self.starty = event.x,event.y
-
- def toggleNode(self,event):
- self.parent.freeMouseDown = False
- tags = self.canvas.gettags(CURRENT)
- obj = tags[0]
- uid = int(tags[1])
- self.nodeList[uid].isTied = not self.nodeList[uid].isTied
- self.showControls()
-
- def nodeDrag(self,event):
- self.parent.freeMouseDown = False
- deltax = event.x-self.startx
- deltay = event.y-self.starty
- tags = self.canvas.gettags(CURRENT)
- obj = tags[0]
- uid = int(tags[1])
- self.nodeList[uid].shiftNode((deltax,-deltay))
- self.startx,self.starty = event.x,event.y
- self.applyChanges()
- self.showControls()
- self.shape.drawOnCanvas(self.canvas,self.parent.magnification)
-
- def controlDrag(self,event):
- self.parent.freeMouseDown = False
- deltax = event.x-self.startx
- deltay = event.y-self.starty
- tags = self.canvas.gettags(CURRENT)
- obj = tags[0]
- uid = int(tags[1])
- if obj == "precontrol":
- self.nodeList[uid].shiftPrecontrol((deltax,-deltay))
- elif obj == "postcontrol":
- self.nodeList[uid].shiftPostcontrol((deltax,-deltay))
- self.startx,self.starty = event.x,event.y
- self.applyChanges()
- self.showControls()
- self.shape.drawOnCanvas(self.canvas,self.parent.magnification)
-
- def applyChanges(self):
- self.modified = True
- self.shape.transform[0] = xasy2asy.asyTransform((0,0,1,0,0,1))
- for i in range(len(self.nodeList)):
- self.path.nodeSet[i] = self.nodeList[i].node
- if self.nodeList[i].postcontrol != None:
- self.path.controlSet[i][0] = self.nodeList[i].postcontrol
- if self.nodeList[i].precontrol != None:
- self.path.controlSet[i-1][1] = self.nodeList[i].precontrol
-
- def endEdit(self):
- self.unbindNodeEvents()
- self.unbindControlEvents()
- self.canvas.delete("node || precontrol || postcontrol || preline || postline")
Added: trunk/Build/source/utils/asymptote/GUI/xasyBezierInterface.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyBezierInterface.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/xasyBezierInterface.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,375 @@
+#!/usr/bin/env python3
+
+import xasy2asy as x2a
+import xasyUtils as xu
+
+import PyQt5.QtCore as Qc
+import PyQt5.QtGui as Qg
+import PyQt5.QtWidgets as Qw
+
+import Widg_editBezier as Web
+
+import InplaceAddObj
+
+import math
+
+class CurrentlySelctedType:
+ none = -1
+ node = 0
+ ctrlPoint = 1
+
+class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess):
+ editAccepted = Qc.pyqtSignal()
+ editRejected = Qc.pyqtSignal()
+
+ def __init__(self, parent: Qc.QObject, obj: x2a.xasyDrawnItem, info: dict={}):
+ super().__init__(parent)
+ self.info = info
+ self.asyPathBackup = x2a.asyPath.fromPath(obj.path)
+ self.asyPath = obj.path
+ self.curveMode = self.asyPath.containsCurve
+ assert isinstance(self.asyPath, x2a.asyPath)
+ self.transf = obj.transfKeymap[obj.transfKey][0]
+ self._active = True
+
+ self.currentSelMode = None
+ # (Node index, Node subindex for )
+ self.currentSelIndex = (None, 0)
+
+ self.nodeSelRects = []
+ self.ctrlSelRects = []
+
+ self.setSelectionBoundaries()
+
+ self.lastSelPoint = None
+ self.preCtrlOffset = None
+ self.postCtrlOffset = None
+ self.inTransformMode = False
+
+ self.opt = None
+
+ self.prosectiveNodes = []
+ self.prospectiveCtrlPts = []
+
+ def setSelectionBoundaries(self):
+ self.nodeSelRects = self.handleNodeSelectionBounds()
+
+ if self.curveMode:
+ self.ctrlSelRects = self.handleCtrlSelectionBoundaries()
+
+ def handleNodeSelectionBounds(self):
+ nodeSelectionBoundaries = []
+
+ for node in self.asyPath.nodeSet:
+ if node == 'cycle':
+ nodeSelectionBoundaries.append(None)
+ continue
+
+ selEpsilon = 6/self.info['magnification']
+ newRect = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon)
+ x, y = self.transf * node
+ x = int(round(x))
+ y = int(round(y))
+ newRect.moveCenter(Qc.QPoint(x, y))
+
+ nodeSelectionBoundaries.append(newRect)
+
+ return nodeSelectionBoundaries
+
+ def handleCtrlSelectionBoundaries(self):
+ ctrlPointSelBoundaries = []
+
+ for nodes in self.asyPath.controlSet:
+ nodea, nodeb = nodes
+
+ selEpsilon = 6/self.info['magnification']
+
+ newRect = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon)
+ newRectb = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon)
+
+ x, y = self.transf * nodea
+ x2, y2 = self.transf * nodeb
+
+ x = int(round(x))
+ y = int(round(y))
+
+ x2 = int(round(x2))
+ y2 = int(round(y2))
+
+ newRect.moveCenter(Qc.QPoint(x, y))
+ newRectb.moveCenter(Qc.QPoint(x2, y2))
+
+ ctrlPointSelBoundaries.append((newRect, newRectb))
+
+ return ctrlPointSelBoundaries
+
+ def postDrawPreview(self, canvas: Qg.QPainter):
+ assert canvas.isActive()
+
+ dashedPen = Qg.QPen(Qc.Qt.DashLine)
+ dashedPen.setWidthF(1/self.info['magnification'])
+ # draw the base points
+ canvas.save()
+ canvas.setWorldTransform(self.transf.toQTransform(), True)
+
+ epsilonSize = 6/self.info['magnification']
+
+ if self.info['autoRecompute'] or not self.curveMode:
+ ctrlPtsColor = 'gray'
+ else:
+ ctrlPtsColor = 'red'
+
+ canvas.setPen(dashedPen)
+
+ canvas.drawPath(self.asyPath.toQPainterPath())
+
+ nodePen = Qg.QPen(Qg.QColor('blue'))
+ nodePen.setWidthF(1/self.info['magnification'])
+
+ ctlPtsPen = Qg.QPen(Qg.QColor(ctrlPtsColor))
+ ctlPtsPen.setWidthF(1/self.info['magnification'])
+
+ for index in range(len(self.asyPath.nodeSet)):
+ point = self.asyPath.nodeSet[index]
+
+ if point != 'cycle':
+ basePoint = Qc.QPointF(point[0], point[1])
+ canvas.setPen(nodePen)
+ canvas.drawEllipse(basePoint, epsilonSize, epsilonSize)
+ else:
+ point = self.asyPath.nodeSet[0]
+ basePoint = Qc.QPointF(point[0], point[1])
+ if self.curveMode:
+ if index != 0:
+ canvas.setPen(ctlPtsPen)
+ postCtrolSet = self.asyPath.controlSet[index - 1][1]
+ postCtrlPoint = Qc.QPointF(postCtrolSet[0], postCtrolSet[1])
+ canvas.drawEllipse(postCtrlPoint, epsilonSize, epsilonSize)
+
+ canvas.setPen(dashedPen)
+ canvas.drawLine(basePoint, postCtrlPoint)
+
+ if index != len(self.asyPath.nodeSet) - 1:
+ canvas.setPen(ctlPtsPen)
+ preCtrlSet = self.asyPath.controlSet[index][0]
+ preCtrlPoint = Qc.QPointF(preCtrlSet[0], preCtrlSet[1])
+ canvas.drawEllipse(preCtrlPoint, epsilonSize, epsilonSize)
+
+ canvas.setPen(dashedPen)
+ canvas.drawLine(basePoint, preCtrlPoint)
+
+ canvas.restore()
+
+ def getPreAndPostCtrlPts(self, index):
+ isCycle = self.asyPath.nodeSet[-1] == 'cycle'
+
+ if index == 0 and not isCycle:
+ preCtrl = None
+ else:
+ preCtrl = self.asyPath.controlSet[index - 1][1]
+
+ if index == len(self.asyPath.nodeSet) - 1 and not isCycle:
+ postCtrl = None
+ else:
+ postCtrl = self.asyPath.controlSet[index % (len(self.asyPath.nodeSet) - 1)][0]
+
+ return preCtrl, postCtrl
+
+ def findLinkingNode(self, index, subindex):
+ """index and subindex are of the control points list."""
+ if subindex == 0:
+ return index
+ else:
+ if self.asyPath.nodeSet[index + 1] == 'cycle':
+ return 0
+ else:
+ return index + 1
+
+ def resetObj(self):
+ self.asyPath.setInfo(self.asyPathBackup)
+ self.setSelectionBoundaries()
+
+ def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+ self.lastSelPoint = pos
+ if self.inTransformMode:
+ return
+
+ if self.prosectiveNodes and not self.inTransformMode:
+ self.currentSelMode = CurrentlySelctedType.node
+ self.currentSelIndex = (self.prosectiveNodes[0], 0)
+ self.inTransformMode = True
+ self.parentNodeIndex = self.currentSelIndex[0]
+ elif self.prospectiveCtrlPts and not self.inTransformMode:
+ self.currentSelMode = CurrentlySelctedType.ctrlPoint
+ self.currentSelIndex = self.prospectiveCtrlPts[0]
+ self.inTransformMode = True
+ self.parentNodeIndex = self.findLinkingNode(*self.currentSelIndex)
+
+ if self.inTransformMode:
+ parentNode = self.asyPath.nodeSet[self.parentNodeIndex]
+
+ # find the offset of each control point to the node
+ if not self.curveMode:
+ return
+
+ preCtrl, postCtrl = self.getPreAndPostCtrlPts(self.parentNodeIndex)
+
+ if parentNode == 'cycle':
+ parentNode = self.asyPath.nodeSet[0]
+ self.parentNodeIndex = 0
+
+ if preCtrl is not None:
+ self.preCtrlOffset = xu.funcOnList(
+ preCtrl, parentNode, lambda a, b: a - b)
+ else:
+ self.preCtrlOffset = None
+
+ if postCtrl is not None:
+ self.postCtrlOffset = xu.funcOnList(
+ postCtrl, parentNode, lambda a, b: a - b)
+ else:
+ self.postCtrlOffset = None
+
+ def mouseMove(self, pos, event: Qg.QMouseEvent):
+ if self.currentSelMode is None and not self.inTransformMode:
+ # in this case, search for prosective nodes.
+ prospectiveNodes = []
+ prospectiveCtrlpts = []
+
+ for i in range(len(self.nodeSelRects)):
+ rect = self.nodeSelRects[i]
+ if rect is None:
+ continue
+ if rect.contains(pos):
+ prospectiveNodes.append(i)
+
+ self.prosectiveNodes = prospectiveNodes
+
+ if not self.info['autoRecompute'] and self.curveMode:
+ for i in range(len(self.ctrlSelRects)):
+ recta, rectb = self.ctrlSelRects[i]
+
+ if recta.contains(pos):
+ prospectiveCtrlpts.append((i, 0))
+
+ if rectb.contains(pos):
+ prospectiveCtrlpts.append((i, 1))
+
+ self.prospectiveCtrlPts = prospectiveCtrlpts
+ else:
+ self.prospectiveCtrlPts = []
+
+
+ if self.inTransformMode:
+ index, subindex = self.currentSelIndex
+ deltaPos = pos - self.lastSelPoint
+ newNode = (pos.x(), pos.y())
+ if self.currentSelMode == CurrentlySelctedType.node:
+ # static throughout the moving
+ if self.asyPath.nodeSet[index] == 'cycle':
+ return
+
+ self.asyPath.setNode(index, newNode)
+ # if also move node:
+
+ if self.curveMode:
+ checkPre, checkPost = self.getPreAndPostCtrlPts(index)
+
+ if 1 == 1: # TODO: Replace this with an option to also move control pts.
+ if checkPre is not None:
+ self.asyPath.controlSet[index - 1][1] = xu.funcOnList(
+ newNode, self.preCtrlOffset, lambda a, b: a + b
+ )
+ if checkPost is not None:
+ self.asyPath.controlSet[index][0] = xu.funcOnList(
+ newNode, self.postCtrlOffset, lambda a, b: a + b
+ )
+
+ if self.info['autoRecompute']:
+ self.quickRecalculateCtrls()
+
+
+ elif self.currentSelMode == CurrentlySelctedType.ctrlPoint and self.curveMode:
+ self.asyPath.controlSet[index][subindex] = newNode
+ parentNode = self.asyPath.nodeSet[self.parentNodeIndex]
+
+ if parentNode == 'cycle':
+ parentNode = self.asyPath.nodeSet[0]
+ isCycle = True
+ else:
+ isCycle = False
+
+ if self.parentNodeIndex == 0 and self.asyPath.nodeSet[-1] == 'cycle':
+ isCycle = True
+
+ rawNewNode = xu.funcOnList(newNode, parentNode, lambda a, b: a - b)
+ rawAngle = math.atan2(rawNewNode[1], rawNewNode[0])
+ newNorm = xu.twonorm(rawNewNode)
+
+
+ if self.info['editBezierlockMode'] >= Web.LockMode.angleLock:
+ otherIndex = 1 - subindex # 1 if 0, 0 otherwise.
+ if otherIndex == 0:
+ if index < (len(self.asyPath.controlSet) - 1) or isCycle:
+ newIndex = 0 if isCycle else index + 1
+
+ oldOtherCtrlPnt = xu.funcOnList(
+ self.asyPath.controlSet[newIndex][0], parentNode, lambda a, b: a - b)
+
+ if self.info['editBezierlockMode'] >= Web.LockMode.angleAndScaleLock:
+ rawNorm = newNorm
+ else:
+ rawNorm = xu.twonorm(oldOtherCtrlPnt)
+
+ newPnt = (rawNorm * math.cos(rawAngle + math.pi),
+ rawNorm * math.sin(rawAngle + math.pi))
+
+ self.asyPath.controlSet[newIndex][0] = xu.funcOnList(
+ newPnt, parentNode, lambda a, b: a + b)
+ else:
+ if index > 0 or isCycle:
+ newIndex = -1 if isCycle else index - 1
+ oldOtherCtrlPnt = xu.funcOnList(
+ self.asyPath.controlSet[newIndex][1], parentNode, lambda a, b: a - b)
+
+ if self.info['editBezierlockMode'] >= Web.LockMode.angleAndScaleLock:
+ rawNorm = newNorm
+ else:
+ rawNorm = xu.twonorm(oldOtherCtrlPnt)
+
+ newPnt = (rawNorm * math.cos(rawAngle + math.pi),
+ rawNorm * math.sin(rawAngle + math.pi))
+ self.asyPath.controlSet[newIndex][1] = xu.funcOnList(
+ newPnt, parentNode, lambda a, b: a + b)
+
+ def recalculateCtrls(self):
+ self.quickRecalculateCtrls()
+ self.setSelectionBoundaries()
+
+ def quickRecalculateCtrls(self):
+ self.asyPath.controlSet.clear()
+ self.asyPath.computeControls()
+
+ def mouseRelease(self):
+ if self.inTransformMode:
+ self.inTransformMode = False
+ self.currentSelMode = None
+
+ self.setSelectionBoundaries()
+
+ def forceFinalize(self):
+ self.objectUpdated.emit()
+
+ def createOptWidget(self, info):
+ self.opt = Web.Widg_editBezier(self.info, self.curveMode)
+ self.opt.ui.btnOk.clicked.connect(self.editAccepted)
+ self.opt.ui.btnCancel.clicked.connect(self.editRejected)
+ self.opt.ui.btnForceRecompute.clicked.connect(self.recalculateCtrls)
+
+ return self.opt
+
+ def getObject(self):
+ pass
+
+ def getXasyObject(self):
+ pass
Property changes on: trunk/Build/source/utils/asymptote/GUI/xasyBezierInterface.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyCodeEditor.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyCodeEditor.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyCodeEditor.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyCodeEditor implements a simple text editor for Asymptote scripts in
-# xasy.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-############################################################################
-
-from subprocess import call
-from tempfile import mkstemp
-from os import remove
-from os import fdopen
-from os import path
-import xasyOptions
-
-def getText(text=""):
- """Launch the external editor"""
- temp = mkstemp()
- tempf = fdopen(temp[0],"w")
- tempf.write(text)
- tempf.close()
- try:
- cmdpath,cmd = path.split(path.expandvars(xasyOptions.options['externalEditor']))
- split_cmd = cmd.split()
- cmdpart = [path.join(cmdpath,split_cmd[0])]
- argpart = split_cmd[1:]+[temp[1]]
- arglist = cmdpart+argpart
- call(arglist)
- except Exception as e:
- raise Exception('Error launching external editor.')
-
- try:
- tempf = open(temp[1],"r")
- text = tempf.read()
- tempf.close()
- remove(temp[1])
- except Exception as e:
- raise Exception('Error reading from external editor.')
- return text
-
-if __name__ == '__main__':
- #run a test
- print (getText("Here is some text to edit"))
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyColorPicker.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyColorPicker.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyColorPicker.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,240 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyColorPicker implements a dialog that allows a user to choose a color
-# from those already defined in Asymptote or a custom RGB color.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-############################################################################
-
-import sys
-
-if sys.version_info >= (3, 0):
- from tkinter import *
- from tkinter import colorchooser
-else:
- from Tkinter import *
- import tkColorChooser as colorchooser
-
-asyColors = { "black":(0,0,0),
- "white":(1,1,1),
- "gray":(0.5,0.5,0.5),
- "red":(1,0,0),
- "green":(0,1,0),
- "blue":(0,0,1),
- "cmyk":(1,1,1),
- "Cyan":(0,1,1),
- "Magenta":(1,0,1),
- "Yellow":(1,1,0),
- "Black":(0,0,0),
- "cyan":(0,1,1),
- "magenta":(1,0,1),
- "yellow":(1,1,0),
- "palered":(1,0.75,0.75),
- "palegreen":(0.75,1,0.75),
- "paleblue":(0.75,0.75,1),
- "palecyan":(0.75,1,1),
- "palemagenta":(1,0.75,1),
- "paleyellow":(1,1,0.75),
- "palegray":(0.95,0.95,0.95),
- "lightred":(1,0.5,0.5),
- "lightgreen":(0.5,1,0.5),
- "lightblue":(0.5,0.5,1),
- "lightcyan":(0.5,1,1),
- "lightmagenta":(1,0.5,1),
- "lightyellow":(1,1,0.5),
- "lightgray":(0.9,0.9,0.9),
- "mediumred":(1,0.25,0.25),
- "mediumgreen":(0.25,1,0.25),
- "mediumblue":(0.25,0.25,1),
- "mediumcyan":(0.25,1,1),
- "mediummagenta":(1,0.25,1),
- "mediumyellow":(1,1,0.25),
- "mediumgray":(0.75,0.75,0.75),
- "heavyred":(0.75,0,0),
- "heavygreen":(0,0.75,0),
- "heavyblue":(0,0,0.75),
- "heavycyan":(0,0.75,0.75),
- "heavymagenta":(0.75,0,0.75),
- "lightolive":(0.75,0.75,0),
- "heavygray":(0.25,0.25,0.25),
- "deepred":(0.5,0,0),
- "deepgreen":(0,0.5,0),
- "deepblue":(0,0,0.5),
- "deepcyan":(0,0.5,0.5),
- "deepmagenta":(0.5,0,0.5),
- "olive":(0.5,0.5,0),
- "deepgray":(0.1,0.1,0.1),
- "darkred":(0.25,0,0),
- "darkgreen":(0,0.25,0),
- "darkblue":(0,0,0.25),
- "darkcyan":(0,0.25,0.25),
- "darkmagenta":(0.25,0,0.25),
- "darkolive":(0.25,0.25,0),
- "darkgray":(0.05,0.05,0.05),
- "orange":(1,0.5,0),
- "fuchsia":(1,0,0.5),
- "chartreuse":(0.5,1,0),
- "springgreen":(0,1,0.5),
- "purple":(0.5,0,1),
- "royalblue":(0,0.5,1)
- }
-colorLayout = [['palered',
- 'lightred',
- 'mediumred',
- 'red',
- 'heavyred',
- 'deepred',
- 'darkred',
- 'palegreen',
- 'lightgreen',
- 'mediumgreen',
- 'green',
- 'heavygreen',
- 'deepgreen',
- 'darkgreen',
- 'paleblue',
- 'lightblue',
- 'mediumblue',
- 'blue',
- 'heavyblue',
- 'deepblue',
- 'darkblue'],
- ['palecyan',
- 'lightcyan',
- 'heavycyan',
- 'deepcyan',
- 'darkcyan',
- 'palemagenta',
- 'lightmagenta',
- 'mediummagenta',
- 'magenta',
- 'heavymagenta',
- 'deepmagenta',
- 'darkmagenta',
- 'yellow',
- 'lightyellow',
- 'mediumyellow',
- 'yellow',
- 'lightolive',
- 'olive',
- 'darkolive',
- 'palegray',
- 'lightgray',
- 'mediumgray',
- 'gray',
- 'heavygray',
- 'deepgray',
- 'darkgray'],
- ['black',
- 'white',
- 'orange',
- 'fuchsia',
- 'chartreuse',
- 'springgreen',
- 'purple',
- 'royalblue',
- 'Cyan',
- 'Magenta',
- 'Yellow',
- 'Black']]
-
-def makeRGBfromTkColor(tkColor):
- """Convert a Tk color of the form #rrggbb to an asy rgb color"""
- r = int('0x'+tkColor[1:3],16)
- g = int('0x'+tkColor[3:5],16)
- b = int('0x'+tkColor[5:7],16)
- r /= 255.0
- g /= 255.0
- b /= 255.0
- return (r,g,b)
-
-def RGBreal255(rgb):
- """Convert an RGB color from 0-1 to 0-255"""
- return [min(int(256*a),255) for a in rgb]
-
-def RGB255hex(rgb):
- """Make a color in the form #rrggbb in hex from r,g,b in 0-255"""
- return "#{}".format("".join(["{:02x}".format(a) for a in rgb]))
-
-class xasyColorDlg(Toplevel):
- """A dialog for choosing an asymptote color. It displays the usual asy presets and allows custom rgb colors"""
- def __init__(self,master=None,color=(0,0,0)):
- Toplevel.__init__(self,master,width=500,height=500)
- self.resizable(False,False)
- self.parent = master
- self.title("Color Picker")
- self.transient(master)
- self.focus_set()
- self.wait_visibility()
- self.grab_set()
- self.color = self.oldColor = color
- cwidth = 120
- rheight = 20
- self.pframe=Frame(self,bd=0)
- self.pframe.rowconfigure(0,weight=1)
- self.pframe.columnconfigure(0,weight=1)
- Label(self.pframe,text="Color Presets").grid(row=0,column=0)
- self.colScroll = Scrollbar(self.pframe,orient=VERTICAL)
- self.colorList = Canvas(self.pframe, width=cwidth*len(colorLayout), scrollregion=(0,0,20+cwidth*len(colorLayout),20+rheight*max([len(i) for i in colorLayout])),yscrollcommand=self.colScroll.set,relief=FLAT)
- self.colScroll.config(command=self.colorList.yview)
- self.colScroll.grid(row=1,column=1,sticky=N+S)
- self.colorList.grid(row=1,column=0,sticky=W)
- ccount = 0
- for column in colorLayout:
- rcount = 0
- for name in column:
- self.colorList.create_rectangle(10+cwidth*ccount,10+rheight*rcount,cwidth*ccount+25,rheight*rcount+25,tags=(name,"preset"),fill=RGB255hex(RGBreal255(asyColors[name])))
- self.colorList.create_text(cwidth*ccount+30,10+rheight*rcount,text=name,anchor=NW,tags=(name,"preset"),fill="black",activefill=RGB255hex(RGBreal255(asyColors[name])))
- rcount += 1
- ccount += 1
- self.colorList.tag_bind("preset","<Button-1>",self.setColorEvt)
- Button(self,text="Custom color...",command=self.getCustom).grid(row=2,column=0,sticky=W,padx=5,pady=5)
- self.colDisp = Canvas(self,width=200,height=20,background=RGB255hex(RGBreal255(self.color)),relief=SUNKEN, bd=3)
- self.colDisp.grid(row=2,column=1,columnspan=2)
- self.rowconfigure(3,minsize=10)
- self.columnconfigure(0,weight=1)
- self.columnconfigure(1,weight=1)
- self.columnconfigure(2,weight=1)
- Button(self,text="OK",default=ACTIVE,command=self.destroy).grid(row=4,column=1,sticky=E+W,padx=5,pady=5)
- Button(self,text="Cancel",command=self.cancel).grid(row=4,column=2,sticky=E+W,padx=5,pady=5)
- self.pframe.grid(row=1,column=0,columnspan=3,padx=10,pady=10)
- self.bind("<Return>",self.closeUp)
- self.setColor(color)
- def closeUp(self,event):
- """Close the dialog forcibly"""
- self.destroy()
- def getCustom(self):
- """Request a custom RGB color using a colorchooser"""
- result=colorchooser.askcolor(initialcolor=RGB255hex(RGBreal255(self.color)),title="Custom Color",parent=self)
- if result != (None,None):
- self.setColor((result[0][0]/255.0,result[0][1]/255.0,result[0][2]/255.0))
- def cancel(self):
- """Respond to the user pressing cancel"""
- self.color = self.oldColor
- self.destroy()
- def setColor(self,color):
- """Save the color and update the color display"""
- self.color = color
- self.colDisp.configure(background=RGB255hex(RGBreal255(self.color)))
- def setColorEvt(self,event):
- """Respond to the user clicking a color from the palette"""
- self.setColor(asyColors[self.colorList.gettags(CURRENT)[0]])
- def getColor(self,initialColor=(0,0,0)):
- """Use this method to prompt for a color. It returns the new color or the old color if the user cancelled the operation.
-
- e.g:
- print (xasyColorDlg(Tk()).getColor((1,1,0)))
- """
- self.setColor(initialColor)
- self.oldColor = initialColor
- self.wait_window(self)
- return self.color
-
-if __name__ == '__main__':
- root = Tk()
- Button(root,text="Pick Color",command=lambda:xasyColorDlg(root).getColor()).pack()
- root.mainloop()
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyExample.asy
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyExample.asy 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyExample.asy 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,63 +0,0 @@
-initXasyMode();
-// This file was generated by xasy. It may be edited manually, however, a strict
-// syntax must be followed. It is advised that manually scripted items be added
-// in the form of a script either by using xasy or by mimicking the format of an
-// xasy-generated script item.
-// Please consult the documentation or the examples provided for details.
-xformStack.add(indexedTransform(0,(0, 0, 1, 0, 0, 1)),
-indexedTransform(1,(0, 0, 1, 0, 0, 1)),
-indexedTransform(2,(0, 0, 1, 0, 0, 1)),
-indexedTransform(3,(0, 0, 1, 0, 0, 1)),
-indexedTransform(4,(0, 0, 1, 0, 0, 1)),
-indexedTransform(5,(0, 0, 1, 0, 0, 1)),
-indexedTransform(6,(0, 0, 1, 0, 0, 1)),
-indexedTransform(7,(0, 0, 1, 0, 0, 1)),
-indexedTransform(8,(0, 0, 1, 0, 0, 1)),
-indexedTransform(9,(0, 0, 1, 0, 0, 1)),
-indexedTransform(10,(0, 0, 1, 0, 0, 1)),
-indexedTransform(11,(0, 0, 1, 0, 0, 1)),
-indexedTransform(12,(0, 0, 1, 0, 0, 1)));
-startScript(); {
-size(0,150);
-
-pen colour1=red;
-pen colour2=green;
-
-pair z0=(0,0);
-pair z1=(-1,0);
-pair z2=(1,0);
-real r=1.5;
-guide c1=circle(z1,r);
-guide c2=circle(z2,r);
-fill(c1,colour1);
-fill(c2,colour2);
-
-picture intersection;
-fill(intersection,c1,colour1+colour2);
-clip(intersection,c2);
-
-add(intersection);
-
-draw(c1);
-draw(c2);
-
-label("$A$",z1);
-label("$B$",z2);
-
-pair z=(0,-2);
-real m=3;
-margin BigMargin=Margin(0,m*dot(unit(z1-z),unit(z0-z)));
-
-draw(Label("$A\cap B$",0),conj(z)--z0,Arrow,BigMargin);
-draw(Label("$A\cup B$",0),z--z0,Arrow,BigMargin);
-draw(z--z1,Arrow,Margin(0,m));
-draw(z--z2,Arrow,Margin(0,m));
-} endScript();
-
-
-xformStack.push((-28.0, 7.0, 1, 0, 0, 1));
-label(Label("A Venn Diagram",(-79.0, 91.0),rgb(0,0,0)+0.5,align=SE));
-
-// This is the end of the file
-exitXasyMode();
-
Modified: trunk/Build/source/utils/asymptote/GUI/xasyFile.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyFile.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyFile.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
###########################################################################
#
# xasyFile implements the loading, parsing, and saving of an xasy file.
@@ -10,306 +10,74 @@
############################################################################
from string import *
-from xasy2asy import *
+import xasy2asy as x2a
+import io
import re
+
class xasyParseError(Exception):
- """A parsing error"""
- pass
+ """A parsing error"""
+ pass
+
class xasyFileError(Exception):
- """An i/o error or other error not related to parsing"""
- pass
+ """An i/o error or other error not related to parsing"""
+ pass
-def parseFile(inFile):
- """Parse a file returning a list of xasyItems"""
- lines = inFile.read()
- lines = lines.splitlines()
- #lines = [line for line in lines.splitlines() if not line.startswith("//")]
- result = []
- if lines[0] != "initXasyMode();":
- raise xasyFileError("Invalid file format: First line must be \"initXasyMode();\"")
- lines.pop(0)
- lineCount = 2
- lineNum = len(lines)
- while lineNum > 0:
- line = lines[0]
- lines.pop(0)
- if not line.isspace() and len(line)>0:
- try:
- #print ("Line {:d}: {:s}".format(lineCount,line))
- lineResult = parseLine(line.strip(),lines)
- except:
- raise xasyParseError("Parsing error: line {:d} in {:s}\n{:s}".format(lineCount,inFile.name,line))
- if lineResult != None:
- result.append(lineResult)
- #print ("\tproduced: {:s}".format(str(lineResult)))
- lineCount += lineNum-len(lines)
- lineNum = len(lines)
- return result
-
-transformPrefix = "xformStack"
-scriptPrefix = "startScript(); {"
-scriptSuffix = "} endScript();"
-def extractScript(lines):
- """Find the code belonging to a script item"""
- theScript = ""
- line = lines.pop(0)
- level = 1
- while level > 0:
- check = line.lstrip()
- while check.endswith(scriptSuffix):
- level -= 1
- line = line[:len(line)-len(scriptSuffix)]
- check = line.lstrip()
- if check.startswith(scriptPrefix):
- level += 1
- theScript += line + "\n"
- if level > 0:
- line = lines.pop(0)
-
- global pendingTransformsD
- ts = pendingTransformsD[:]
- pendingTransformsD = []
- return xasyScript(None,script=theScript,transforms=ts[:])
-
-pendingTransforms = []
-pendingTransformsD = []
-def addTransform(index,t,active=1):
- """Place a transform in the list of transforms, expanding the list as needed"""
- while len(pendingTransformsD) < index+1:
- pendingTransformsD.append(identity())
- deleted = int(active==0)
- pendingTransformsD[index]=asyTransform(t,deleted)
-
-def parseIndexedTransforms(args):
- """Parse a list of indexedTransforms, adding them to the current list of transforms"""
- global pendingTransformsD
- pendingTransformsD = []
- args = args.replace("indexedTransform","")
- false = 0
- tList = [eval(a) for a in ")?(".join(args.split("),(")).split("?")]
- for a in tList:
- addTransform(*a)
-
-def parseTransformExpression(line):
- """Parse statements related to the xformStack
-
- Syntax:
- xformStack.push(transform)
- e.g.: xformStack.push((0,0,1,0,0,1)); //the identity
- xformStack.add(indexedTransform(index,transform)[,...])
- e.g.: xformStack.add(indexedTransform(1,(0,0,1,0,0,1));
- """
- global pendingTransforms
- stackCmd = line[len(transformPrefix)+1:line.find("(")]
- if line[-2:] != ");":
- raise xasyParseError("Invalid syntax")
- args = line[line.find("(")+1:-2]
- if stackCmd == "push":
- t = asyTransform(eval(args))
- pendingTransforms.append(t)
- elif stackCmd == "add":
- parseIndexedTransforms(args)
- else:
- raise xasyParseError("Invalid transform stack command.")
- return None
-
-def parseLabel(line):
- """Parse an asy Label statement, returning an xasyText item"""
- if not (line.startswith("Label(") and line.endswith(",align=SE)")):
- raise xasyParseError("Invalid syntax")
- args = line[6:-1]
- loc2 = args.rfind(",align=SE")
- loc1 = args.rfind(",",0,loc2-1)
- loc = args.rfind(",(",0,loc1-1)
- if loc < 2:
- raise xasyParseError("Invalid syntax")
- text = args[1:loc-1]
- location = eval(args[loc+1:args.find("),",loc)+1])
- pen = args[loc:loc2]
- pen = pen[pen.find(",")+1:]
- pen = pen[pen.find(",")+1:]
- pen = pen[pen.find(",")+1:]
- global pendingTransforms
- return xasyText(text,location,parsePen(pen),pendingTransforms.pop())
-
-def parseLabelCommand(line):
- """Parse a label command returning an xasyText object
-
- Syntax:
- label(Label(text,location,pen,align=SE));
- e.g.: label(Label("Hello world!",(0,0),rgb(0,0,0)+0.5,align=SE));
- """
- if line[-2:] != ");":
- raise xasyParseError("Invalid syntax")
- arguments = line[6:-2]
- return parseLabel(arguments)
-
-def parseDrawCommand(line):
- """Parse a draw command returning an xasyShape object
-
- Syntax:
- draw(path,pen);
- e.g.: draw((0,0)..controls(0.33,0.33)and(0.66,0.66)..(1,1),rgb(1,0,1)+1.5);
- """
- if line[-2:] != ");":
- raise xasyParseError("Invalid syntax")
- args = line[5:-2]
- loc = args.rfind(",rgb")
- path = args[:loc]
- pen = args[loc+1:]
- global pendingTransforms
- return xasyShape(parsePathExpression(path),parsePen(pen),pendingTransforms.pop())
-
-def parseFillCommand(line):
- """Parse a fill command returning an xasyFilledShape object
-
- Syntax:
- fill(cyclic path,pen);
- e.g.: fill((0,0)..controls(0.33,0.33)and(0.66,0.66)..(1,1)..controls(0.66,0)and(0.33,0)..cycle,rgb(1,0,1)+1.5);
- """
- if line[-2:] != ");":
- raise xasyParseError("Invalid syntax")
- args = line[5:-2]
- loc = args.rfind(",rgb")
- path = args[:loc]
- pen = args[loc+1:]
- global pendingTransforms
- return xasyFilledShape(parsePathExpression(path),parsePen(pen),pendingTransforms.pop())
-
-def parsePen(pen):
- """Parse a pen expression returning an asyPen
-
- Syntax:
- color+width[+options]
- e.g.: rgb(0,0,0)+1.5+evenodd
- e.g.: rgb(0,1,0)+1.23
- """
- try:
- tokens = pen.split("+")
- color = eval(tokens[0][3:])
- width = float(tokens[1])
- if len(tokens)>2:
- options = "+".join(tokens[2:])
+def extractTransform(line):
+ """Returns key and the new transform."""
+ # see https://regex101.com/r/6DqkRJ/4 for info
+ mapString = x2a.xasyItem.mapString
+ testMatch = re.match(
+ r'^{0:s}\s*\(\s*\"([^\"]+)\"\s*,\s*\(([-\d, .]+)\)\s*\)'.format(mapString), line.strip())
+ if testMatch is None:
+ mapOnlyMatch = re.match(r'^{0:s}\s*\(\s *\"([^\"]+)\"\s*\)'.format(mapString), line.strip())
+ if mapOnlyMatch is None:
+ return None
+ else:
+ key = mapOnlyMatch.group(1)
+ return key, x2a.identity()
else:
- options = ""
- return asyPen(color,width,options)
- except:
- raise xasyParseError("Invalid pen")
+ key = testMatch.group(1)
+ rawStr = testMatch.group(2)
+ rawStrArray = rawStr.split(',')
-def parsePathExpression(expr):
- """Parse an asy path returning an asyPath()"""
- result = asyPath()
- expr = "".join(expr.split())
- #print (expr)
- if expr.find("controls") != -1:
- #parse a path with control points
- tokens = expr.split("..")
- nodes = [a for a in tokens if not a.startswith("controls")]
- for a in range(len(nodes)):
- if nodes[a] != "cycle":
- nodes[a] = eval(nodes[a])
- controls = [[eval(b) for b in a.replace("controls", "").split("and")] for a in tokens if a.startswith("controls")]
- result.initFromControls(nodes, controls)
- else:
- #parse a path without control points
- tokens = re.split(r"(::|--|\.\.)",expr)
- linkSet = re.findall("::|--|\.\.",expr)
- nodeSet = [a for a in tokens if not re.match(r"::|--|\.\.",a)]
- #print (nodeSet)
- for a in range(len(nodeSet)):
- if nodeSet[a] != "cycle":
- nodeSet[a] = eval(nodeSet[a])
- #print (nodeSet)
- result.initFromNodeList(nodeSet, linkSet)
- return result
+ if len(rawStrArray) != 6:
+ return None
+ transf = [float(val.strip()) for val in rawStrArray]
+ return key, x2a.asyTransform(transf)
-def takeUntilSemicolon(line,lines):
- """Read and concatenate lines until the collected lines end with a semicolon"""
- data = line
- while not data.endswith(";"):
- newline = lines.pop(0)
- data += newline
- return data
-def parseLine(line,lines):
- """Parse a line of the file"""
- if len(line)==0 or line.isspace() or line.startswith("//"):
- return None
- elif line.startswith(scriptPrefix):
- return extractScript(lines)
- elif line.startswith(transformPrefix):
- return parseTransformExpression(takeUntilSemicolon(line,lines))
- elif line.startswith("label("):
- return parseLabelCommand(takeUntilSemicolon(line,lines))
- elif line.startswith("draw("):
- return parseDrawCommand(takeUntilSemicolon(line,lines))
- elif line.startswith("fill("):
- return parseFillCommand(takeUntilSemicolon(line,lines))
- elif line.startswith("exitXasyMode();"):
- return None
- raise Exception("Could not parse the line")
+def extractTransformsFromFile(fileStr):
+ transfDict = {}
+ maxItemCount = 0
+ with io.StringIO() as rawCode:
+ for line in fileStr.splitlines():
+ test_transf = extractTransform(line.rstrip())
+ if test_transf is None:
+ rawCode.write(line + '\n')
+ else:
+ key, transf = test_transf
+ if key not in transfDict.keys():
+ transfDict[key] = []
+ transfDict[key].append(transf)
-fileHeader = """initXasyMode();
-// This file was generated by xasy. It may be edited manually, however, a strict
-// syntax must be followed. It is advised that manually scripted items be added
-// in the form of a script either by using xasy or by mimicking the format of an
-// xasy-generated script item.
-// Please consult the documentation or the examples provided for details.
-"""
+ # see https://regex101.com/r/RgeBVc/2 for regex
-fileFooter = """// This is the end of the file
-exitXasyMode();
+ testNum = re.match(r'^x(\d+)($|:.*$)', key)
+ if testNum is not None:
+ maxItemCount = max(maxItemCount, int(testNum.group(1)))
+ final_str = rawCode.getvalue()
+ return final_str, transfDict, maxItemCount
-"""
-def saveFile(file,xasyItems):
- """Write a list of xasyItems to a file"""
- file.write(fileHeader)
- for item in xasyItems:
- file.write(item.getCode()+"\n\n")
- file.write(fileFooter)
+def saveFile(file, xasyItems, asy2psmap):
+ """Write a list of xasyItems to a file"""
+ for item in xasyItems:
+ file.write(item.getTransformCode(asy2psmap))
-if __name__ == '__main__':
- root = Tk()
- try:
- name = raw_input("enter file name (\"../../xasyTest.asy\"):")
- if name == '':
- name = "../../xasyTest.asy"
- f = open(name,"rt")
- except:
- print ("Could not open file.")
- asy.quit()
- sys.exit(1)
+ for item in xasyItems:
+ file.write(item.getObjectCode(asy2psmap))
- fileItems = []
- try:
- fileItems = parseFile(f)
- res = [str(a) for a in fileItems]
- print ("----------------------------------")
- print ("Objects in {:s}".format(f.name))
- print ("----------------------------------")
- for a in res:
- print (a)
- print ("----------------------------------")
- print ("successful parse")
- f.close()
- except:
- f.close()
- print ("parse failed")
- raise
-
- print ("making a file")
- f = open("testfile.asy","wt")
- saveFile(f,fileItems)
- f.close()
- root.configure(width=500,height=500)
- root.title("Results")
- canv = Canvas(root,width=500,height=500)
- canv.pack()
- for i in fileItems[1].imageList:
- canv.create_image(250+i.bbox[0],250-i.bbox[3],anchor = NW, image=i.image)
- Button(root,image=i.image).pack(side=LEFT)
- root.mainloop()
+ file.write('size('+str(asy2psmap*x2a.yflip())+'); '+ x2a.xasyItem.resizeComment+'\n')
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyGUIIcons.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyGUIIcons.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyGUIIcons.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,92 +0,0 @@
-#!/usr/bin/env python
-##################################################################
-# This file stores the icons used by the xasy GUI
-#
-# About images and base64
-#
-# Suppose you have image.gif and want to create a base64
-# string. This can be accomplished using:
-#
-# import base64
-# base64.encodestring(open("image.gif","rb").read())
-#
-# The resulting output, including the enclosing single quotes,
-# is the base64 encoding of the image and can be used in the
-# dictionary below.
-#
-#
-# Suppose you have a base64 string, b64str, and want to create
-# an image. This can be accomplished using:
-#
-# import base64
-# open("image.gif","w").write(base64.decodestring(b64str))
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-##################################################################
-import base64
-import os
-#toolbar icon image data in base64 eliminates need to worry about files
-#these are the base64 encodings of the content of the directory xasy3Imgs
-iconB64 = {
-'lower': 'R0lGODlhGAAYAPEBAAAAAP///8zMzAAAACH5BAEAAAIALAAAAAAYABgAAAItlI+py+0Po5yUgosz\nrrybK2giqADed6LHKCZm+p7xx2Zuqsqr95KcJpv9cJUCADs=\n',
-'rotate': 'R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAI7jI8JkO231mux1mkistL1zX0Q\ng2Fi6aGmurKp+8KKrJB0Zt+nzOQw6XPZgqjczuQ7eohKEDKoUYWIgQIAOw==\n',
-'raise': 'R0lGODlhGAAYAPEBAAAAAP///8zMzAAAACH5BAEAAAIALAAAAAAYABgAAAIwlI+pywgND3ixzVvZ\nNDSn3nlKKH7fhaZmObKtk8Yh6dKlLcfC5vZ1jvIJh8SikVUAADs=\n',
-'fillPoly': 'R0lGODlhGAAYAPEAAAAAAIOBgwAAAAAAACH5BAEAAAIALAAAAAAYABgAAAJGlI+py+0PEYgNBDCp\nDPxqY3UcRoViRzrmKWbLyqIMHI9vHbsbfuoHjfOBcrlbT0ATIo+gldKpMD1lL8vUo5oqS9vS5wsp\nAAA7\n',
-'move': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAI4jI+py+0I3gNUNhqtwlVD7m3h\nkoVdUJ4MaKTYysVymbDoYcM4Tmv9eAO2cp6YEKUavY5BpvMZKgAAOw==\n',
-'drawBezi': 'R0lGODlhGAAYAPEBAAAAAP///6usrQAAACH5BAEAAAIALAAAAAAYABgAAAI6lI+py+0AnYRUKhox\nsFvUFDXdM4LWUaKnEaorhqSX1noPmMquWJukzpr0YitRcfE5oobFpPIJjUoZBQA7\n',
-'vertiMove': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAIsjI+py+0I3gNUNhqtwlVD7m3h\nko2QmZRooKKt+Y5xOFtc7dwrtrLd3gsKTQUAOw==\n',
-'horizMove': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAIljI+py+0Po5y02oshAGu/7Skg\n143mSYpgGTYt8mbyTNf2jedWAQA7\n',
-'fillEllip': 'R0lGODlhGAAYAPECAAAAAIOBg////6usrSH5BAEAAAMALAAAAAAYABgAAAJAnI+py+0PowS0gkmD\n3qE6wIXctYDi2SkmepLGyrYHHIcuXW93Lr+86BrgakHfrzjjIRGVFgVjWUqm1Kr1ijUUAAA7\n',
-'text': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAI+jI+py+0Po5x0AgSu1SZvHnhS\nBnpio5Ukt2Idm3bysYrnddLwy+czH0rhFDkbTigj6UzKl68CjUqn1Ko1UAAAOw==\n',
-'drawPoly': 'R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAI4jI+py+0PEYhtgkmlzgFL/4DJ\nFULiVi4ns66smrUxrMj1fdqHR+60kfPdgCwLzbWTIU1LE+cJKQAAOw==\n',
-'drawLines': 'R0lGODlhGAAYAPEBAAAAAP///6usrQAAACH5BAEAAAIALAAAAAAYABgAAAI3lI+py+0AnYRAPmoZ\njvlwX3Vh8j2XUIIWNXoZS3ZoO8soSK+4fRuYnQPyFEHhcHecFV+ppDNRAAA7\n',
-'drawShape': 'R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAI5jI+pywffIjQzIrCwdXnTplmh\nMoKmKIHVeZXp5cFcPH+0HbjbqKN17OoxgrTeKiOkPHjH3fIGjS4KADs=\n',
-'drawEllip': 'R0lGODlhGAAYAPEBAAAAAP///6usrQAAACH5BAEAAAIALAAAAAAYABgAAAIylI+py+0PowS0gklX\ndRd29XmgdIQh+Z1TSSJpyxpqZMLqzOB4sgsbmKFZgrCi8YhMNgoAOw==\n',
-'select': 'R0lGODlhGAAYAPIDAAAAAICAgMDAwP///6usrQAAAAAAAAAAACH5BAEAAAQALAAAAAAYABgAAANH\nSLrc/mvA6YCkGIiLIQhb54Gh2HwkZxKo4KoiSpam7L6rfdNZ4M+C3I+0Ush8wSLKCFIyPsnisyld\nAD7VabR6DWSt37BYmgAAOw==\n',
-'fillShape': 'R0lGODlhGAAYAPEAAAAAAIOBgwAAAAAAACH5BAEAAAIALAAAAAAYABgAAAJHlI+pywff4gsUxgSo\nrhflzXXCB4YXWQIiCqpnubnLw8KyU8Omket77wvcgD4ZUTcMIj3KlOLYejY1N8/R0qChaCIrtgsO\nRwoAOw==\n',
-'asy': 'R0lGODlhGAAYAIABAP8AAAAAACH5BAEKAAEALAIAAwAUABIAAAImjI+py+0AHINy0ZouNjBurmGd\nt40fFT4j2aydGqaBq8jvxH46UwAAOw==\n'
-}
-
-def createGIF(key):
- """Create a gif file from the data in the iconB64 list of icons"""
- if key not in iconB64.keys():
- print ("Error: {:s} not found in icon list.".format(key))
- print ("Available icons:",iconB64.keys())
- else:
- print ("Generating {:s}.gif".format(key))
- open("{:s}.gif".format(key),"w").write(base64.decodestring(iconB64[key]))
-
-def createGIFs():
- """Create the files for all the icons in iconB64"""
- for name in iconB64.keys():
- createGIF(name)
-
-def createStrFromGif(gifFile):
- """Create the base64 representation of a file"""
- return base64.encodestring(gifFile.read())
-
-if __name__=='__main__':
- print ("Testing the xasyGUIIcons module.")
- print ("Generating all the GIFs:")
- createGIFs()
- print ("Checking consistency of all icons in iconB64")
- allpassed = True
- for icon in iconB64.keys():
- print ("Checking {:s}".format(icon))
- if createStrFromGif(open("{:s}.gif".format(icon),"rb")) == iconB64[icon]:
- print ("\tPassed.")
- else:
- print ("\tFailed.")
- allpassed= False
- if allpassed:
- print ("All files succeeded.")
- s = raw_input("Delete generated files? (y/n)")
- if s == "y":
- for name in iconB64.keys():
- print ("Deleting {:s}.gif".format(name))
- os.unlink(name+".gif")
- print ("\tdone")
- print ("Done")
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyMainWin.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyMainWin.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyMainWin.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,1748 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyMainWin implements the functionality of the GUI. It depends on
-# xasy2asy for its interaction with Asymptote.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-
-import os
-import sys
-from string import *
-import subprocess
-import math
-import copy
-
-if sys.version_info >= (3, 0):
- # python3
- from tkinter import *
- from tkinter import filedialog, messagebox, simpledialog
-else:
- # python2
- # from Tkinter import *
- import tkFileDialog as filedialog
- import tkMessageBox as messagebox
- import tkSimpleDialog as simpledialog
-
-import threading
-import time
-
-from xasyVersion import xasyVersion
-import xasyCodeEditor
-from xasy2asy import *
-import xasyFile
-import xasyOptions
-import xasyOptionsDialog
-import CubicBezier
-from xasyBezierEditor import xasyBezierEditor
-from xasyGUIIcons import iconB64
-from xasyColorPicker import *
-
-from UndoRedoStack import *
-from xasyActions import *
-
-import string
-
-try:
- from PIL import ImageTk
- from PIL import Image
- PILAvailable = True
-except:
- PILAvailable = False
-
-class xasyMainWin:
- def __init__(self,master,file=None,magnification=1.0):
- self.opLock = threading.Lock()
- self.parent = master
- self.magnification = magnification
- self.previousZoom = self.magnification
- self.magList = [0.1,0.25,1.0/3,0.5,1,2,3,4,5,10]
- self.bindGlobalEvents()
- self.createWidgets()
- self.resetGUI()
- site=""
- if not PILAvailable:
- messagebox.showerror("Failed Dependencies","An error occurred loading the required PIL library. Please install Pillow from http://pypi.python.org/pypi/Pillow")
- self.parent.destroy()
- sys.exit(1)
- if file != None:
- self.loadFile(file)
- self.parent.after(100,self.tickHandler)
-
- def testOrAcquireLock(self):
- val = self.opLock.acquire(False)
- if val:
- self.closeDisplayLock()
- return val
-
- def acquireLock(self):
- self.closeDisplayLock()
- self.opLock.acquire()
-
- def releaseLock(self):
- self.opLock.release()
- self.openDisplayLock()
-
- def tickHandler(self):
- self.tickCount += 1
- self.mainCanvas.itemconfigure("outlineBox",dashoffset=self.tickCount%9)
- self.parent.after(100,self.tickHandler)
-
- def closeDisplayLock(self):
- self.status.config(text="Busy")
- self.parent.update_idletasks()
-
- def openDisplayLock(self):
- self.status.config(text="Ready")
-
- def bindGlobalEvents(self):
- #global bindings
- self.parent.bind_all("<Control-z>",lambda q:self.editUndoCmd())# z -> no shift
- self.parent.bind_all("<Control-Z>",lambda q:self.editRedoCmd())# Z -> with shift
- self.parent.bind_all("<Control-o>",lambda q:self.fileOpenCmd())
- self.parent.bind_all("<Control-n>",lambda q:self.fileNewCmd())
- self.parent.bind_all("<Control-s>",lambda q:self.fileSaveCmd())
- self.parent.bind_all("<Control-q>",lambda q:self.fileExitCmd())
- self.parent.bind_all("<F1>",lambda q:self.helpHelpCmd())
-
- def unbindGlobalEvents(self):
- #global bindings
- self.parent.unbind("<Control-z>")
- self.parent.unbind("<Control-Z>")
- self.parent.unbind("<Control-o>")
- self.parent.unbind("<Control-n>")
- self.parent.unbind("<Control-s>")
- self.parent.unbind("<Control-q>")
- self.parent.unbind("<F1>")
-
- def createWidgets(self):
- #first some configuration
- self.parent.geometry("800x600")
- self.parent.title("Xasy")
- self.parent.resizable(True,True)
-
- #try to capture the closing of the window
- #find a better way to do this since the widgets may
- #already be destroyed when this is called
- self.parent.protocol("WM_DELETE_WINDOW",self.canQuit)
-
- #the main menu
- self.mainMenu = Menu(self.parent)
- self.parent.config(menu=self.mainMenu)
-
- #the file menu
- self.fileMenu = Menu(self.mainMenu,tearoff=0)
- self.fileMenu.add_command(label="New",command=self.fileNewCmd,accelerator="Ctrl+N",underline=0)
- self.fileMenu.add_command(label="Open",command=self.fileOpenCmd,accelerator="Ctrl+O",underline=0)
- self.fileMenu.add_separator()
- self.fileMenu.add_command(label="Save",command=self.fileSaveCmd,accelerator="Ctrl+S",underline=0)
- self.fileMenu.add_command(label="Save As",command=self.fileSaveAsCmd,underline=5)
- self.fileMenu.add_separator()
-
- #an export menu
- self.exportMenu = Menu(self.fileMenu,tearoff=0)
- self.exportMenu.add_command(label="EPS...",command=self.exportEPS,underline=0)
- self.exportMenu.add_command(label="PDF...",command=self.exportPDF,underline=0)
- self.exportMenu.add_command(label="GIF...",command=self.exportGIF,underline=0)
- self.exportMenu.add_command(label="PNG...",command=self.exportPNG,underline=1)
- self.exportMenu.add_command(label="SVG...",command=self.exportSVG,underline=0)
- self.fileMenu.add_cascade(label="Export",menu=self.exportMenu,underline=1)
- self.fileMenu.add_separator()
-
- self.fileMenu.add_command(label="Quit",command=self.fileExitCmd,accelerator="Ctrl+Q",underline=0)
-
- self.mainMenu.add_cascade(label="File",menu=self.fileMenu,underline=0)
-
- #the edit menu
- self.editMenu = Menu(self.mainMenu,tearoff=0)
- self.editMenu.add_command(label="Undo",command=self.editUndoCmd,accelerator="Ctrl+Z",underline=0)
- self.editMenu.add_command(label="Redo",command=self.editRedoCmd,accelerator="Shift+Ctrl+Z",underline=0)
- self.mainMenu.add_cascade(label="Edit",menu=self.editMenu,underline=0)
-
- #the tools menu
- self.toolsMenu = Menu(self.mainMenu,tearoff=0)
- self.mainMenu.add_cascade(label="Tools",menu=self.toolsMenu,underline=0)
-
- #the options menu
- self.optionsMenu = Menu(self.toolsMenu,tearoff=0)
- self.toolsMenu.add_cascade(label="Options",menu=self.optionsMenu,underline=0)
- self.optionsMenu.add_command(label="Edit...",command=self.editOptions,underline=0)
- self.optionsMenu.add_command(label="Reset defaults",command=self.resetOptions,underline=6)
-
- #the help menu
- self.helpMenu = Menu(self.mainMenu,tearoff=0)
- self.helpMenu.add_command(label="Help",command=self.helpHelpCmd,state=DISABLED,accelerator="F1",underline=0)
- self.helpMenu.add_command(label="Asymptote Documentation",command=self.helpAsyDocCmd,underline=10)
- self.helpMenu.add_separator()
- self.helpMenu.add_command(label="About xasy",command=self.helpAboutCmd,underline=0)
- self.mainMenu.add_cascade(label="Help",menu=self.helpMenu,underline=0)
-
- #status bar
- self.statusBar = Frame(self.parent,relief=FLAT)
-
- self.magVal = DoubleVar()
- self.magVal.set(round(100*self.magnification,1))
- self.magVal.trace('w',self.zoomViewCmd)
- zoomList = self.magList
- if self.magnification not in zoomList:
- zoomList.append(self.magnification)
- zoomList.sort()
- zoomList = [round(100*i,1) for i in zoomList]
- self.zoomMenu = OptionMenu(self.statusBar,self.magVal,*zoomList)
- self.zoomMenu.pack(side=RIGHT)
- Label(self.statusBar,text="Zoom:",anchor=E,width=7).pack(side=RIGHT)
-
- self.coords = Label(self.statusBar,text="(0,0)",relief=SUNKEN,anchor=W)
- self.coords.pack(side=RIGHT,anchor=S)
- self.status = Label(self.statusBar,text="Ready",relief=SUNKEN,anchor=W)
- self.status.pack(side=RIGHT,fill=X,expand=1,anchor=SW)
- self.statusBar.pack(side=BOTTOM,fill=X)
-
- #toolbar for transformation, drawing, and adjustment commands
- self.toolBar = Frame(self.parent,relief=FLAT,borderwidth=3)
-
- #let's load some images
- self.toolIcons = {}
- for x in iconB64.keys():
- self.toolIcons[x] = PhotoImage(data=iconB64[x])
-
- self.transformLbl = Label(self.toolBar,text="",anchor=W)
- self.transformLbl.grid(row=0,column=0,columnspan=2,sticky=W)
- self.toolSelectButton = Button(self.toolBar,command=self.toolSelectCmd,image=self.toolIcons["select"])
- self.toolSelectButton.grid(row=1,column=0,sticky=N+S+E+W)
- self.toolMoveButton = Button(self.toolBar,command=self.toolMoveCmd,image=self.toolIcons["move"])
- self.toolMoveButton.grid(row=2,column=0,sticky=N+S+E+W)
- self.toolRotateButton = Button(self.toolBar,command=self.toolRotateCmd,image=self.toolIcons["rotate"])
- self.toolRotateButton.grid(row=2,column=1,sticky=N+S+E+W)
- self.toolVertiMoveButton = Button(self.toolBar,command=self.toolVertiMoveCmd,image=self.toolIcons["vertiMove"])
- self.toolVertiMoveButton.grid(row=3,column=0,sticky=N+S+E+W)
- self.toolHorizMoveButton = Button(self.toolBar,command=self.toolHorizMoveCmd,image=self.toolIcons["horizMove"])
- self.toolHorizMoveButton.grid(row=3,column=1,sticky=N+S+E+W)
-
- self.drawLbl = Label(self.toolBar,text="",anchor=W)
- self.drawLbl.grid(row=4,column=0,columnspan=2,sticky=W)
- self.toolDrawLinesButton = Button(self.toolBar,command=self.toolDrawLinesCmd,image=self.toolIcons["drawLines"])
- self.toolDrawLinesButton.grid(row=5,column=0,sticky=N+S+E+W)
- self.toolDrawBeziButton = Button(self.toolBar,command=self.toolDrawBeziCmd,image=self.toolIcons["drawBezi"])
- self.toolDrawBeziButton.grid(row=5,column=1,sticky=N+S+E+W)
- self.toolDrawPolyButton = Button(self.toolBar,command=self.toolDrawPolyCmd,image=self.toolIcons["drawPoly"])
- self.toolDrawPolyButton.grid(row=6,column=0,sticky=N+S+E+W)
- self.toolFillPolyButton = Button(self.toolBar,command=self.toolFillPolyCmd,image=self.toolIcons["fillPoly"])
- self.toolFillPolyButton.grid(row=6,column=1,sticky=N+S+E+W)
- self.toolDrawEllipButton = Button(self.toolBar,command=self.toolDrawEllipCmd,image=self.toolIcons["drawEllip"],state=DISABLED,relief=FLAT)
- #self.toolDrawEllipButton.grid(row=7,column=0,sticky=N+S+E+W)
- self.toolFillEllipButton = Button(self.toolBar,command=self.toolFillEllipCmd,image=self.toolIcons["fillEllip"],state=DISABLED,relief=FLAT)
- #self.toolFillEllipButton.grid(row=7,column=1,sticky=N+S+E+W)
- self.toolDrawShapeButton = Button(self.toolBar,command=self.toolDrawShapeCmd,image=self.toolIcons["drawShape"])
- self.toolDrawShapeButton.grid(row=8,column=0,sticky=N+S+E+W)
- self.toolFillShapeButton = Button(self.toolBar,command=self.toolFillShapeCmd,image=self.toolIcons["fillShape"])
- self.toolFillShapeButton.grid(row=8,column=1,sticky=N+S+E+W)
- self.toolTextButton = Button(self.toolBar,command=self.toolTextCmd,image=self.toolIcons["text"])
- self.toolTextButton.grid(row=9,column=0,sticky=N+S+E+W)
- self.toolAsyButton = Button(self.toolBar,command=self.toolAsyCmd,image=self.toolIcons["asy"])
- self.toolAsyButton.grid(row=9,column=1,sticky=N+S+E+W)
-
- self.adjLbl = Label(self.toolBar,text="",anchor=W)
- self.adjLbl.grid(row=10,column=0,columnspan=2,sticky=W)
- self.toolRaiseButton = Button(self.toolBar,command=self.toolRaiseCmd,image=self.toolIcons["raise"])
- self.toolRaiseButton.grid(row=11,column=0,sticky=N+S+E+W)
- self.toolLowerButton = Button(self.toolBar,command=self.toolLowerCmd,image=self.toolIcons["lower"])
- self.toolLowerButton.grid(row=11,column=1,sticky=N+S+E+W)
-
- self.toolBar.pack(side=LEFT,anchor=NW)
-
- #documentation for the tool bar buttons
- self.toolDocs = {
- self.toolSelectButton : "Click an item to select it. Control-Click will select/deselect additional items. Use mouse scroller (or Up/Down keys) to raise/lower highlighted items.",
- self.toolMoveButton : "Drag a selected item.",
- self.toolHorizMoveButton : "Drag a selected item. Only horizontal translation will be applied.",
- self.toolVertiMoveButton : "Drag a selected item. Only vertical translation will be applied.",
- self.toolRotateButton : "Drag a selected item to rotate it.",
- self.toolDrawLinesButton : "Click to draw line segments. Double click to place last point.",
- self.toolDrawBeziButton : "Click to place points. Double click to place last point.",
- self.toolDrawPolyButton : "Click to place vertices. Double click to place last point.",
- self.toolFillPolyButton : "Click to place vertices. Double click to place last point.",
- self.toolDrawEllipButton : "(UNIMPLEMENTED)Click to place center. Move mouse to achieve correct shape and double click.",
- self.toolFillEllipButton : "(UNIMPLEMENTED)Click to place center. Move mouse to achieve correct shape and double click.",
- self.toolDrawShapeButton : "Click to place points. Double click to place last point.",
- self.toolFillShapeButton : "Click to place points. Double click to place last point.",
- self.toolTextButton : "Click location of top left label position and enter text in dialog.",
- self.toolRaiseButton : "Raise selected items to top.",
- self.toolLowerButton : "Lower selected items to bottom.",
- self.toolAsyButton : "Insert/Edit Asymptote code."
- }
-
- #Current pen settings
- self.optionsBar = Frame(self.parent,height=100,relief=FLAT,borderwidth=3)
- self.penDisp = Canvas(self.optionsBar,width=100,height=25,bg="white",relief=SUNKEN,borderwidth=3)
- self.penDisp.grid(row=0,column=0,padx=3,pady=3)
- self.penDisp.create_line(10,25,30,10,60,20,80,10,smooth=True,tags="penDisp")
- self.penDisp.create_text(100,30,text="x1",tags="penMag",anchor=SE,font=("times","8"))
- self.penColButton = Button(self.optionsBar,text="Color...",width=5,command=self.setPenColCmd,relief=FLAT)
- self.penColButton.grid(row=0,column=1,padx=3,pady=3)
- Label(self.optionsBar,text="Width",anchor=E).grid(row=0,column=2)
- self.penWidthEntry = Entry(self.optionsBar,width=5)
- self.penWidthEntry.bind("<KeyRelease>",self.penWidthChanged)
- self.penWidthEntry.bind("<FocusOut>",self.applyPenWidthEvt)
- self.penWidthEntry.bind("<Return>",self.applyPenWidthEvt)
- self.penWidthEntry.grid(row=0,column=3)
- Label(self.optionsBar,text="Options",anchor=E).grid(row=0,column=4)
- self.penOptEntry = Entry(self.optionsBar)
- self.penOptEntry.bind("<FocusOut>",self.applyPenOptEvt)
- self.penOptEntry.bind("<Return>",self.applyPenOptEvt)
- self.penOptEntry.grid(row=0,column=5)
- self.optionsBar.pack(side=BOTTOM,anchor=NW)
-
- #a paned window for the canvas and propert explorer
- self.windowPane = PanedWindow(self.parent)
-
- #a property explorer
- self.propFrame = Frame(self.parent)
- self.propFrame.rowconfigure(1,weight=1)
- self.propFrame.columnconfigure(0,weight=1)
- Label(self.propFrame,text="Item List").grid(row=0,column=0,columnspan=2)
- self.itemScroll = Scrollbar(self.propFrame,orient=VERTICAL)
- self.propList = Listbox(self.propFrame, yscrollcommand=self.itemScroll.set)
- self.itemScroll.config(command=self.propList.yview)
- self.itemScroll.grid(row=1,column=1,sticky=N+S)
- self.propList.grid(row=1,column=0,sticky=N+S+E+W)
- self.propList.bind("<Double-Button-1>",self.propSelect)
- self.propList.bind("<Button-3>",self.itemPropMenuPopup)
-
- #the canvas's frame
- self.canvFrame = Frame(self.parent,relief=FLAT,borderwidth=0)
- self.canvFrame.rowconfigure(0,weight=1)
- self.canvFrame.columnconfigure(0,weight=1)
- self.canvVScroll = Scrollbar(self.canvFrame,orient=VERTICAL)
- self.canvHScroll = Scrollbar(self.canvFrame,orient=HORIZONTAL)
- self.canvHScroll.grid(row=1,column=0,sticky=E+W)
- self.canvVScroll.grid(row=0,column=1,sticky=N+S)
-
- #add the frames to the window pane
- self.windowPane.pack(side=RIGHT,fill=BOTH,expand=True)
- self.windowPane.add(self.canvFrame)
- self.windowPane.add(self.propFrame)
- self.windowPane.paneconfigure(self.propFrame,minsize=50,sticky=N+S+E+W)
- self.windowPane.bind("<Double-Button-1>",self.togglePaneEvt)
-
- #the highly important canvas!
- self.mainCanvas = Canvas(self.canvFrame,relief=SUNKEN,background="white",borderwidth=3,
- highlightthickness=0,closeenough=1.0,yscrollcommand=self.canvVScroll.set,
- xscrollcommand=self.canvHScroll.set)
- self.mainCanvas.grid(row=0,column=0,sticky=N+S+E+W)
-
- self.canvVScroll.config(command=self.mainCanvas.yview)
- self.canvHScroll.config(command=self.mainCanvas.xview)
-
- self.mainCanvas.bind("<Motion>",self.canvMotion)
- self.mainCanvas.bind("<Button-1>",self.canvLeftDown)
- self.mainCanvas.bind("<Double-Button-1>",self.endDraw)
- self.mainCanvas.bind("<ButtonRelease-1>",self.canvLeftUp)
- self.mainCanvas.bind("<B1-Motion>",self.canvDrag)
-
- self.mainCanvas.bind("<Enter>",self.canvEnter)
- self.mainCanvas.bind("<Leave>",self.canvLeave)
- self.mainCanvas.bind("<Delete>",self.itemDelete)
- #self.mainCanvas.bind("<Button-3>",self.canvRightDown)
- #self.mainCanvas.bind("<ButtonRelease-3>",self.canvRightUp)
- self.mainCanvas.bind("<Button-4>",self.itemRaise)
- self.mainCanvas.bind("<Button-5>",self.itemLower)
- self.mainCanvas.bind("<Up>",self.itemRaise)
- self.mainCanvas.bind("<Down>",self.itemLower)
- self.mainCanvas.bind("<Configure>",self.configEvt)
-
- def foregroundPenColor(self,hex):
- hex = hex[1:]
- rgb = max(hex[0:2], hex[2:4], hex[4:6])
- if(rgb >= "80"):
- return "black"
- else:
- return "white"
-
- def resetGUI(self):
- #set up the main window
- self.filename = None
- self.fileToOpen = None
- self.retitle()
-
- #set up the paned window
- self.paneVisible = True
-
- #setup the pen entries
- self.pendingPenWidthChange = None
- self.pendingPenOptChange = None
-
- #load one-time configs
- xasyOptions.load()
- self.tkPenColor = xasyOptions.options['defPenColor']
- self.penColor = makeRGBfromTkColor(self.tkPenColor)
- self.penColButton.config(activebackground=self.tkPenColor,
- activeforeground=self.foregroundPenColor(self.tkPenColor))
- self.penWidth = xasyOptions.options['defPenWidth']
- self.penWidthEntry.select_range(0,END)
- self.penWidthEntry.delete(0,END)
- self.penWidthEntry.insert(END,str(self.penWidth))
- self.penOptions = xasyOptions.options['defPenOptions']
- self.penOptEntry.select_range(0,END)
- self.penOptEntry.delete(0,END)
- self.penOptEntry.insert(END,str(self.penOptions))
- self.showCurrentPen()
-
- #load modifiable configs
- self.applyOptions()
-
- #set up editing
- self.editor = None
-
- #set up drawing
- self.pathInProgress = asyPath()
- self.currentIDTag = -1
- self.inDrawingMode = False
- self.freeMouseDown = True
- self.dragSelecting = False
- self.itemsBeingRotated = []
- self.inRotatingMode = False
-
- #set up the toolbar
- try:
- self.updateSelectedButton(self.toolSelectButton)
- except:
- self.selectedButton = self.toolSelectButton
- self.updateSelectedButton(self.toolSelectButton)
-
- #set up the canvas
- self.mainCanvas.delete(ALL)
- self.mainCanvas.create_rectangle(0,0,0,0,tags="outlineBox",width=0,outline="#801111",dash=(3,6))
- self.backColor = "white" #in future, load this from an options file. Or, should this really be an option?
- self.mainCanvas.configure(background=self.backColor)
-
- #set up the xasy item list
- self.fileItems = []
- self.propList.delete(0,END)
- self.updateCanvasSize()
-
- #setup timer
- self.tickCount = 0
-
- #setup undo/redo!
- self.undoRedoStack = actionStack()
- self.amDragging = False
-
- def retitle(self):
- if self.filename == None:
- self.parent.title("Xasy - New File")
- else:
- name = os.path.abspath(self.filename)
- name = os.path.basename(name)
- self.parent.title("Xasy - %s"%name)
-
- def applyOptions(self):
- self.gridcolor = xasyOptions.options['gridColor']
- self.tickcolor = xasyOptions.options['tickColor']
- self.axiscolor = xasyOptions.options['axesColor']
- self.gridVisible = xasyOptions.options['showGrid']
- self.gridxspace = xasyOptions.options['gridX']
- self.gridyspace = xasyOptions.options['gridY']
- self.axesVisible = xasyOptions.options['showAxes']
- self.axisxspace = xasyOptions.options['axisX']
- self.axisyspace = xasyOptions.options['axisY']
- self.updateCanvasSize()
- #test the asyProcess
- startQuickAsy()
- if not quickAsyRunning():
- if messagebox.askyesno("Xasy Error","Asymptote could not be executed.\r\nTry to find Asymptote automatically?"):
- xasyOptions.setAsyPathFromWindowsRegistry()
- xasyOptions.save()
- startQuickAsy()
- while not quickAsyRunning():
- if messagebox.askyesno("Xasy Error","Asymptote could not be executed.\r\nEdit settings?"):
- xasyOptionsDialog.xasyOptionsDlg(self.parent)
- xasyOptions.save()
- startQuickAsy()
- else:
- self.parent.destroy()
- sys.exit(1)
-
- def drawGrid(self):
- self.mainCanvas.delete("grid")
- if not self.gridVisible:
- return
- left,top,right,bottom = [int(float(a)) for a in self.mainCanvas.cget("scrollregion").split()]
- gridyspace = int(self.magnification*self.gridyspace)
- gridxspace = int(self.magnification*self.gridxspace)
- if gridxspace >= 3 and gridyspace >= 3:
- for i in range(0,right,gridxspace):
- self.mainCanvas.create_line(i,top,i,bottom,tags=("grid","vertical"),fill=self.gridcolor)
- for i in range(-gridxspace,left,-gridxspace):
- self.mainCanvas.create_line(i,top,i,bottom,tags=("grid","vertical"),fill=self.gridcolor)
- for i in range(-gridyspace,top,-gridyspace):
- self.mainCanvas.create_line(left,i,right,i,tags=("grid","horizontal"),fill=self.gridcolor)
- for i in range(0,bottom,gridyspace):
- self.mainCanvas.create_line(left,i,right,i,tags=("grid","horizontal"),fill=self.gridcolor)
- self.mainCanvas.tag_lower("grid")
-
- def drawAxes(self):
- self.mainCanvas.delete("axes")
- if not self.axesVisible:
- return
- left,top,right,bottom = [int(float(a)) for a in self.mainCanvas.cget("scrollregion").split()]
- self.mainCanvas.create_line(0,top,0,bottom,tags=("axes","yaxis"),fill=self.axiscolor)
- self.mainCanvas.create_line(left,0,right,0,tags=("axes","xaxis"),fill=self.axiscolor)
- axisxspace = int(self.magnification*self.axisxspace)
- axisyspace = int(self.magnification*self.axisyspace)
- if axisxspace >= 3 and axisyspace >= 3:
- for i in range(axisxspace,right,axisxspace):
- self.mainCanvas.create_line(i,-5,i,5,tags=("axes","xaxis-ticks"),fill=self.tickcolor)
- for i in range(-axisxspace,left,-axisxspace):
- self.mainCanvas.create_line(i,-5,i,5,tags=("axes","xaxis-ticks"),fill=self.tickcolor)
- for i in range(-axisyspace,top,-axisyspace):
- self.mainCanvas.create_line(-5,i,5,i,tags=("axes","yaxis-ticks"),fill=self.tickcolor)
- for i in range(axisyspace,bottom,axisyspace):
- self.mainCanvas.create_line(-5,i,5,i,tags=("axes","yaxis-ticks"),fill=self.tickcolor)
- self.mainCanvas.tag_lower("axes")
-
- def updateCanvasSize(self,left=-200,top=-200,right=200,bottom=200):
- self.parent.update_idletasks()
- bbox = self.mainCanvas.bbox("drawn || image || node || precontrol || postcontrol")
- if bbox == None:
- bbox = (0,0,0,0)
- #(topleft, bottomright)
- left = min(bbox[0],left)
- top = min(bbox[1],top)
- right = max(bbox[2],right)
- bottom = max(bbox[3],bottom)
- w,h = self.mainCanvas.winfo_width(),self.mainCanvas.winfo_height()
- if right-left < w:
- extraw = w-(right-left)
- right += extraw//2
- left -= extraw//2
- if bottom-top < h:
- extrah = h-(bottom-top)
- bottom += extrah//2
- top -= extrah//2
- self.mainCanvas.config(scrollregion=(left,top,right,bottom))
- #self.mainCanvas.xview(MOVETO,float(split(self.mainCanvas["scrollregion"])[0]))
- #self.mainCanvas.yview(MOVETO,float(split(self.mainCanvas["scrollregion"])[1]))
- #self.mainCanvas.xview(MOVETO,(left+right)/2)
- #self.mainCanvas.yview(MOVETO,(top+bottom)/2)
- self.drawAxes()
- self.drawGrid()
-
- def bindEvents(self,tagorID):
- if tagorID == None:
- return
- self.mainCanvas.tag_bind(tagorID,"<Control-Button-1>",self.itemToggleSelect)
- self.mainCanvas.tag_bind(tagorID,"<Button-1>",self.itemSelect)
- self.mainCanvas.tag_bind(tagorID,"<ButtonRelease-1>",self.itemMouseUp)
- self.mainCanvas.tag_bind(tagorID,"<Double-Button-1>",self.itemEditEvt)
- self.mainCanvas.tag_bind(tagorID,"<B1-Motion>",self.itemDrag)
- self.mainCanvas.tag_bind(tagorID,"<Delete>",self.itemDelete)
- self.mainCanvas.tag_bind(tagorID,"<Enter>",self.itemHighlight)
- self.mainCanvas.tag_bind(tagorID,"<Button-3>",self.itemCanvasMenuPopup)
-
- def bindItemEvents(self,item):
- if item == None:
- return
- if isinstance(item,xasyScript) or isinstance(item,xasyText):
- for image in item.imageList:
- self.bindEvents(image.IDTag)
- else:
- self.bindEvents(item.IDTag)
-
- def canQuit(self,force=False):
- #print ("Quitting")
- if not force and not self.testOrAcquireLock():
- return
- try:
- self.releaseLock()
- except:
- pass
- if self.undoRedoStack.changesMade():
- result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
- if str(result) == messagebox.CANCEL:
- return
- elif result == messagebox.YES:
- self.fileSaveCmd()
- try:
- os.rmdir(getAsyTempDir())
- except:
- pass
-
- stopQuickAsy()
- self.parent.destroy()
-
- def openFile(self,name):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock() #release the lock for loadFile
- self.resetGUI()
- self.loadFile(name)
-
- def loadFile(self,name):
- self.status.config(text="Loading "+name)
- self.filename = os.path.abspath(name)
- startQuickAsy()
- self.retitle()
- try:
- try:
- f = open(self.filename,'rt')
- except:
- if self.filename[-4:] == ".asy":
- raise
- else:
- f = open(self.filename+".asy",'rt')
- self.filename += ".asy"
- self.retitle()
- self.fileItems = xasyFile.parseFile(f)
- f.close()
- except IOError:
- messagebox.showerror("File Opening Failed.","File could not be opened.")
- self.fileItems = []
- except:
- self.fileItems = []
- self.autoMakeScript = True
- if self.autoMakeScript or messagebox.askyesno("Error Opening File", "File was not recognized as an xasy file.\nLoad as a script item?"):
- try:
- item = xasyScript(self.mainCanvas)
- f.seek(0)
- item.setScript(f.read())
- self.addItemToFile(item)
- except:
- messagebox.showerror("File Opening Failed.","Could not load as a script item.")
- self.fileItems = []
- self.populateCanvasWithItems()
- self.populatePropertyList()
- self.updateCanvasSize()
-
- def populateCanvasWithItems(self):
- if(not self.testOrAcquireLock()):
- return
- self.mainCanvas.delete("drawn || image")
- self.itemCount = 0
- for item in self.fileItems:
- item.drawOnCanvas(self.mainCanvas,self.magnification,forceAddition=True)
- self.bindItemEvents(item)
- self.releaseLock()
-
- def propListCountItem(self,item):
- plist = self.propList.get(0,END)
- count = 1
- for text in plist:
- if text.startswith(item):
- count += 1
- return count
-
- def describeItem(self,item):
- if isinstance(item,xasyScript):
- return "Code Module "+str(self.propListCountItem("Code Module"))
- elif isinstance(item,xasyText):
- return "Text Label "+str(self.propListCountItem("Text Label"))
- elif isinstance(item,xasyFilledShape):
- return "Filled Shape "+str(self.propListCountItem("Filled Shape"))
- elif isinstance(item,xasyShape):
- return "Outline "+str(self.propListCountItem("Outline"))
- else:
- return "If this happened, the program is corrupt!"
-
- def populatePropertyList(self):
- self.propList.delete(0,END)
- for item in self.fileItems:
- self.propList.insert(0,self.describeItem(item))
-
- def saveFile(self,name):
- if(not self.testOrAcquireLock()):
- return
- f = open(name,"wt")
- xasyFile.saveFile(f,self.fileItems)
- f.close()
- self.undoRedoStack.setCommitLevel()
- self.retitle()
- self.releaseLock()
-
- #menu commands
- def fileNewCmd(self):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- #print ("Create New File")
- if self.undoRedoStack.changesMade():
- result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
- if str(result) == messagebox.CANCEL:
- return
- elif result == messagebox.YES:
- self.fileSaveCmd()
- self.resetGUI()
-
- def fileOpenCmd(self):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- #print ("Open a file")
- if self.undoRedoStack.changesMade():
- result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
- if str(result) == messagebox.CANCEL:
- return
- elif result == messagebox.YES:
- self.fileSaveCmd()
- filename=filedialog.askopenfilename(filetypes=[("asy files","*.asy"),("All files","*")],title="Open File",parent=self.parent)
- if type(filename) != type((0,)) and filename != None and filename != '':
- self.filename = filename
- self.openFile(self.filename)
-
- def fileSaveCmd(self):
- #print ("Save current file")
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- if self.filename == None:
- filename=filedialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File")
- if type(filename) != type((0,)) and filename != None and filename != '':
- self.filename = filename
- if self.filename != None:
- self.saveFile(self.filename)
-
- def fileSaveAsCmd(self):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- #print ("Save current file as")
- filename=filedialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File")
- if type(filename) != type((0,)) and filename != None and filename != '':
- self.filename = filename
- self.saveFile(self.filename)
-
- #export the file
- def exportEPS(self):
- self.exportFile(self.filename,"eps")
-
- def exportPDF(self):
- self.exportFile(self.filename,"pdf")
-
- def exportGIF(self):
- self.exportFile(self.filename,"gif")
-
- def exportPNG(self):
- self.exportFile(self.filename,"png")
-
- def exportSVG(self):
- self.exportFile(self.filename,"svg")
-
- def exportFile(self,inFile, outFormat):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- if inFile == None:
- if messagebox.askyesno("xasy","File has not been saved.\nSave?"):
- self.fileSaveAsCmd()
- inFile = self.filename
- else:
- return
- elif self.undoRedoStack.changesMade():
- choice = messagebox._show("xasy","File has been modified.\nOnly saved changes can be exported.\nDo you want to save changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
- choice = str(choice)
- if choice != messagebox.YES:
- return
- else:
- self.fileSaveCmd()
- name = os.path.splitext(os.path.basename(self.filename))[0]+'.'+outFormat
- outfilename = filedialog.asksaveasfilename(defaultextension = '.'+outFormat,filetypes=[(outFormat+" files","*."+outFormat)],initialfile=name,parent=self.parent,title="Choose output file")
- if type(outfilename)==type((0,)) or not outfilename or outfilename == '':
- return
- fullname = os.path.abspath(outfilename)
- outName = os.path.basename(outfilename)
- command=[xasyOptions.options['asyPath'],"-f"+outFormat,"-o"+fullname,inFile]
- saver = subprocess.Popen(command,stdin=PIPE,stdout=PIPE,stderr=PIPE)
- saver.wait()
- if saver.returncode != 0:
- messagebox.showerror("Export Error","Export Error:\n"+saver.stdout.read()+saver.stderr.read())
- self.status.config(text="Error exporting file")
- else:
- self.status.config(text="File exported successfully")
-
- def fileExitCmd(self):
- #print ("Exit xasy")
- self.canQuit()
-
- def editUndoCmd(self):
- if not self.editor == None:
- return
- if(not self.testOrAcquireLock()):
- return
- self.undoOperation()
- self.releaseLock()
-
- def editRedoCmd(self):
- if not self.editor == None:
- return
- if(not self.testOrAcquireLock()):
- return
- self.redoOperation()
- self.releaseLock()
-
- def helpHelpCmd(self):
- print ("Get help on xasy")
-
- def helpAsyDocCmd(self):
- #print ("Open documentation about Asymptote")
- asyExecute("help;\n")
-
- def helpAboutCmd(self):
- messagebox.showinfo("About xasy","A graphical interface for Asymptote "+xasyVersion)
-
- def updateSelectedButton(self,newB):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- #disable switching modes during an incomplete drawing operation
- if self.inDrawingMode:
- return
- self.selectedButton.config(relief = RAISED)
- if newB == self.toolSelectButton or self.selectedButton == self.toolSelectButton:
- self.mainCanvas.delete("highlightBox")
- if self.editor != None:
- self.editor.endEdit()
- if self.editor.modified:
- self.undoRedoStack.add(editDrawnItemAction(self,self.itemBeingEdited,copy.deepcopy(self.editor.shape),self.fileItems.index(self.editor.shape)))
- if newB not in (self.toolSelectButton,self.toolMoveButton,self.toolHorizMoveButton,self.toolVertiMoveButton,self.toolRotateButton):
- self.clearSelection()
- self.selectedButton = newB
- self.selectedButton.config(relief = SUNKEN)
- self.status.config(text=self.toolDocs[newB])
-
- #toolbar commands
- def toolSelectCmd(self):
- self.updateSelectedButton(self.toolSelectButton)
- def toolMoveCmd(self):
- self.updateSelectedButton(self.toolMoveButton)
- def toolRotateCmd(self):
- self.updateSelectedButton(self.toolRotateButton)
- def toolVertiMoveCmd(self):
- self.updateSelectedButton(self.toolVertiMoveButton)
- def toolHorizMoveCmd(self):
- self.updateSelectedButton(self.toolHorizMoveButton)
- def toolDrawLinesCmd(self):
- self.updateSelectedButton(self.toolDrawLinesButton)
- def toolDrawBeziCmd(self):
- self.updateSelectedButton(self.toolDrawBeziButton)
- def toolDrawPolyCmd(self):
- self.updateSelectedButton(self.toolDrawPolyButton)
- def toolFillPolyCmd(self):
- self.updateSelectedButton(self.toolFillPolyButton)
- def toolDrawEllipCmd(self):
- self.updateSelectedButton(self.toolDrawEllipButton)
- def toolFillEllipCmd(self):
- self.updateSelectedButton(self.toolFillEllipButton)
- def toolDrawShapeCmd(self):
- self.updateSelectedButton(self.toolDrawShapeButton)
- def toolFillShapeCmd(self):
- self.updateSelectedButton(self.toolFillShapeButton)
- def toolTextCmd(self):
- self.updateSelectedButton(self.toolTextButton)
- def toolAsyCmd(self):
- # ignore the command if we are too busy to process it
- if not self.testOrAcquireLock():
- return
- self.updateSelectedButton(self.toolSelectButton)
- self.clearSelection()
- self.clearHighlight()
- self.unbindGlobalEvents()
- try:
- self.getNewText("// enter your code here")
- except Exception as e:
- messagebox.showerror('xasy Error',e.message)
- else:
- self.addItemToFile(xasyScript(self.mainCanvas))
- text = self.newText
- self.undoRedoStack.add(addScriptAction(self,self.fileItems[-1]))
- self.fileItems[-1].setScript(text)
- self.fileItems[-1].drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(self.fileItems[-1])
- self.bindGlobalEvents()
- self.releaseLock()
- def toolRaiseCmd(self):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- if not self.inDrawingMode and self.editor == None:
- itemList = []
- indexList = []
- for ID in self.mainCanvas.find_withtag("selectedItem"):
- item = self.findItem(ID)
- if item not in itemList:
- itemList.append(item)
- indexList.append(self.fileItems.index(item))
- self.raiseSomething(item)
- self.undoRedoStack.add(itemRaiseAction(self,itemList,indexList))
- def toolLowerCmd(self):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- if not self.inDrawingMode and self.editor == None:
- itemList = []
- indexList = []
- for ID in self.mainCanvas.find_withtag("selectedItem"):
- item = self.findItem(ID)
- if item not in itemList:
- itemList.append(item)
- indexList.append(self.fileItems.index(item))
- self.lowerSomething(item)
- self.undoRedoStack.add(itemLowerAction(self,itemList,indexList))
- def itemRaise(self,event):
- self.mainCanvas.tag_raise(CURRENT)
- def itemLower(self,event):
- self.mainCanvas.tag_lower(CURRENT)
-
- #options bar commands
- def setPenColCmd(self):
- if not self.testOrAcquireLock():
- return
- old = self.penColor
- self.penColor = xasyColorDlg(self.parent).getColor(self.penColor)
- if self.penColor != old:
- self.tkPenColor = RGB255hex(RGBreal255(self.penColor))
- self.penColButton.config(activebackground=self.tkPenColor,
- activeforeground=self.foregroundPenColor(self.tkPenColor))
- self.showCurrentPen()
- self.releaseLock()
-
- def clearSelection(self):
- self.hideSelectionBox()
- self.mainCanvas.dtag("selectedItem","selectedItem")
-
- def hideSelectionBox(self):
- self.mainCanvas.itemconfigure("outlineBox",width=1,outline=self.backColor)
- self.mainCanvas.tag_lower("outlineBox")
- self.mainCanvas.coords("outlineBox",self.mainCanvas.bbox(ALL))
-
- def showSelectionBox(self):
- self.mainCanvas.itemconfigure("outlineBox",width=2,outline="#801111")
- self.mainCanvas.tag_raise("outlineBox")
-
- def setSelection(self,what):
- self.mainCanvas.addtag_withtag("selectedItem",what)
- self.updateSelection()
- if self.selectedButton == self.toolSelectButton and len(self.mainCanvas.find_withtag("selectedItem")) > 0:
- self.updateSelectedButton(self.toolMoveButton)
-
- def unSelect(self,what):
- self.mainCanvas.dtag(what,"selectedItem")
- self.updateSelection()
-
- def updateSelection(self):
- self.clearHighlight()
- theBbox = self.mainCanvas.bbox("selectedItem")
- if theBbox != None:
- theBbox = (theBbox[0]-2,theBbox[1]-2,theBbox[2]+2,theBbox[3]+2)
- self.mainCanvas.coords("outlineBox",theBbox)
- self.showSelectionBox()
- else:
- self.clearSelection()
-
- #event handlers
- def updateZoom(self):
- self.zoomMenu.config(state=DISABLED)
- self.magnification = self.magVal.get()/100.0
- if self.magnification != self.previousZoom:
- self.populateCanvasWithItems()
- self.updateCanvasSize()
- self.updateSelection()
- self.drawAxes()
- self.drawGrid()
- self.previousZoom = self.magnification
- self.zoomMenu.config(state=NORMAL)
-
- def zoomViewCmd(self,*args):
- magnification = self.magVal.get()/100.0
- self.updateZoom();
-
- def selectItem(self,item):
- self.clearSelection()
- if isinstance(item,xasyScript) or isinstance(item,xasyText):
- for image in item.imageList:
- self.setSelection(image.IDTag)
- else:
- self.setSelection(item.IDTag)
-
- def propSelect(self,event):
- items = [int(a) for a in self.propList.curselection()]
- if len(items)>0:
- try:
- self.selectItem(self.fileItems[len(self.fileItems)-items[0]-1])
- except:
- raise
-
- def findItem(self,ID):
- for item in self.fileItems:
- if isinstance(item,xasyScript) or isinstance(item,xasyText):
- for image in item.imageList:
- if image.IDTag == ID:
- return item
- else:
- if item.IDTag == ID:
- return item
- raise Exception("Illegal operation: Item with matching ID could not be found.")
-
- def findItemImageIndex(self,item,ID):
- count = 0
- for image in item.imageList:
- if image.IDTag == ID:
- return count
- else:
- count += 1
- raise Exception("Illegal operation: Image with matching ID could not be found.")
- return None
-
- def raiseSomething(self,item,force=False):
- if self.fileItems[-1] != item or force:
- index = len(self.fileItems)-self.fileItems.index(item)-1
- text = self.propList.get(index)
- self.propList.delete(index)
- self.propList.insert(0,text)
- for i in range(self.fileItems.index(item),len(self.fileItems)-1):
- self.fileItems[i] = self.fileItems[i+1]
- self.fileItems[-1] = item
- if isinstance(item,xasyScript) or isinstance(item,xasyText):
- for im in item.imageList:
- if im.IDTag != None:
- self.mainCanvas.tag_raise(im.IDTag)
- else:
- if item.IDTag != None:
- self.mainCanvas.tag_raise(item.IDTag)
-
- def lowerSomething(self,item):
- if self.fileItems[0] != item:
- index = len(self.fileItems)-self.fileItems.index(item)-1
- text = self.propList.get(index)
- self.propList.delete(index)
- self.propList.insert(END,text)
- indices = range(self.fileItems.index(item))
- indices.reverse()
- for i in indices:
- self.fileItems[i+1] = self.fileItems[i]
- self.fileItems[0] = item
- if isinstance(item,xasyScript) or isinstance(item,xasyText):
- item.imageList.reverse()
- for im in item.imageList:
- if im.IDTag != None:
- self.mainCanvas.tag_lower(im.IDTag)
- item.imageList.reverse()
- else:
- if item.IDTag != None:
- self.mainCanvas.tag_lower(item.IDTag)
- self.mainCanvas.tag_lower("axes || grid")
-
- def translateSomething(self,ID,translation,specificItem=None,specificIndex=None):
- transform = asyTransform((translation[0],translation[1],1,0,0,1))
- if ID == -1:
- item = specificItem
- else:
- item = self.findItem(ID)
- if isinstance(item,xasyText) or isinstance(item,xasyScript):
- if ID == -1:
- index = specificIndex
- else:
- index = self.findItemImageIndex(item,ID)
- try:
- original = item.transform[index]
- except:
- original = identity()
- item.transform[index] = transform*original
- bbox = item.imageList[index].originalImage.bbox
- item.imageList[index].originalImage.bbox = bbox[0]+translation[0],bbox[1]+translation[1],bbox[2]+translation[0],bbox[3]+translation[1]
- else:
- item.transform = [transform*item.transform[0]]
-
- def makeRotationMatrix(self,theta,origin):
- rotMat = (math.cos(theta),-math.sin(theta),math.sin(theta),math.cos(theta))
- shift = asyTransform((0,0,1-rotMat[0],-rotMat[1],-rotMat[2],1-rotMat[3]))*origin
- return asyTransform((shift[0],shift[1],rotMat[0],rotMat[1],rotMat[2],rotMat[3]))
-
- def rotateSomething(self,ID,theta,origin,specificItem=None,specificIndex=None):
- #print ("Rotating by {} around {}".format(theta*180.0/math.pi,origin))
- rotMat = self.makeRotationMatrix(theta,(origin[0]/self.magnification,origin[1]/self.magnification))
- #print (rotMat)
- if ID == -1:
- item = specificItem
- else:
- item = self.findItem(ID)
- if isinstance(item,xasyText) or isinstance(item,xasyScript):
- #transform the image
- if ID == -1:
- index = specificIndex
- else:
- index = self.findItemImageIndex(item,ID)
- try:
- original = item.transform[index]
- except:
- original = identity()
- oldBbox = item.imageList[index].originalImage.bbox
- oldBbox = (oldBbox[0],-oldBbox[1],oldBbox[2],-oldBbox[3])
- item.transform[index] = rotMat*item.transform[index]
- item.transform[index] = rotMat*original
- item.imageList[index].originalImage.theta += theta
- item.imageList[index].image = item.imageList[index].originalImage.rotate(item.imageList[index].originalImage.theta*180.0/math.pi,expand=True,resample=Image.BICUBIC)
- item.imageList[index].itk = ImageTk.PhotoImage(item.imageList[index].image)
- self.mainCanvas.itemconfigure(ID,image=item.imageList[index].itk)
- #the image has been rotated in place
- #now, compensate for any resizing and shift to the correct location
- #
- # p0 --- p1 p1
- # | | ---> / \
- # p2 --- p3 p0 p3
- # \ /
- # p2
- #
- rotMat2 = self.makeRotationMatrix(item.imageList[index].originalImage.theta,origin)
- p0 = rotMat2*(oldBbox[0],-oldBbox[3])#switch to usual coordinates
- p1 = rotMat2*(oldBbox[2],-oldBbox[3])
- p2 = rotMat2*(oldBbox[0],-oldBbox[1])
- p3 = rotMat2*(oldBbox[2],-oldBbox[1])
- newTopLeft = (min(p0[0],p1[0],p2[0],p3[0]),-max(p0[1],p1[1],p2[1],p3[1]))#switch back to screen coords
- shift = (newTopLeft[0]-oldBbox[0],newTopLeft[1]-oldBbox[3])
- #print (theta*180.0/math.pi,origin,oldBbox,newTopLeft,shift)
- #print (item.imageList[index].originalImage.size)
- #print (item.imageList[index].image.size)
- #print
- self.mainCanvas.coords(ID,oldBbox[0]+shift[0],oldBbox[3]+shift[1])
- else:
- #transform each point of the object
- xform = rotMat*item.transform[0]
- item.transform = [identity()]
- for i in range(len(item.path.nodeSet)):
- if item.path.nodeSet[i] != 'cycle':
- item.path.nodeSet[i] = xform*item.path.nodeSet[i]
- for i in range(len(item.path.controlSet)):
- item.path.controlSet[i][0] = xform*item.path.controlSet[i][0]
- item.path.controlSet[i][1] = xform*item.path.controlSet[i][1]
- item.drawOnCanvas(self.mainCanvas,self.magnification)
-
- def deleteItem(self,item):
- if isinstance(item,xasyScript) or isinstance(item,xasyText):
- if isinstance(item,xasyScript):
- self.undoRedoStack.add(deleteScriptAction(self,item,self.fileItems.index(item)))
- else:
- self.undoRedoStack.add(deleteLabelAction(self,item,self.fileItems.index(item)))
- for image in item.imageList:
- self.mainCanvas.delete(image.IDTag)
- else:
- if isinstance(item,xasyDrawnItem):
- self.undoRedoStack.add(deleteDrawnItemAction(self,item,self.fileItems.index(item)))
- self.mainCanvas.delete(item.IDTag)
- self.fileItems.remove(item)
- self.populatePropertyList()
- self.clearSelection()
-
- def deleteSomething(self,ID):
- self.clearSelection()
- self.clearHighlight()
- if self.editor != None:
- self.editor.endEdit()
- if self.editor.modified:
- self.undoRedoStack.add(editDrawnItemAction(self,self.itemBeingEdited,copy.deepcopy(self.editor.shape),self.fileItems.index(self.editor.shape)))
- item = self.findItem(ID)
- #save an event on the undoredo stack
- if isinstance(item,xasyScript):
- index = self.findItemImageIndex(item,ID)
- item.transform[index].deleted = True
- else:
- if isinstance(item,xasyText):
- self.undoRedoStack.add(deleteLabelAction(self,item,self.fileItems.index(item)))
- elif isinstance(item,xasyDrawnItem):
- self.undoRedoStack.add(deleteDrawnItemAction(self,item,self.fileItems.index(item)))
- self.fileItems.remove(item)
- self.mainCanvas.delete(ID)
- self.populatePropertyList()
-
- def scriptEditThread(self,oldText):
- try:
- self.newText = xasyCodeEditor.getText(oldText)
- except:
- self.newText = -1
-
- def getNewText(self,oldText):
- editThread = threading.Thread(target=self.scriptEditThread,args=(oldText,))
- editThread.start()
- while editThread.isAlive():
- time.sleep(0.05)
- self.parent.update()
- editThread.join()
- if type(self.newText)==type(-1):
- self.newText = ''
- raise Exception('Error launching external editor. Please check xasy options.')
-
- def itemEdit(self,item):
- # are we too busy?
- if not self.testOrAcquireLock():
- return
- self.updateSelectedButton(self.toolSelectButton)
- if isinstance(item,xasyScript):
- self.unbindGlobalEvents()
- oldText = item.script
- try:
- self.getNewText(oldText)
- except Exception as e:
- messagebox.showerror('xasy Error',e.message)
- else:
- if self.newText != oldText:
- self.undoRedoStack.add(editScriptAction(self,item,self.newText,oldText))
- item.setScript(self.newText)
- item.drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(item)
- self.bindGlobalEvents()
- elif isinstance(item,xasyText):
- theText = simpledialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue=item.label.text,parent=self.parent)
- if theText != None and theText != "":
- self.undoRedoStack.add(editLabelTextAction(self,item,theText,item.label.text))
- item.label.text = theText
- item.drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(item)
- elif isinstance(item,xasyShape):
- self.clearSelection()
- self.clearHighlight()
- self.itemBeingEdited = copy.deepcopy(item)
- self.editor = xasyBezierEditor(self,item,self.mainCanvas)
- self.updateSelection()
- self.releaseLock()
-
- def itemEditEvt(self,event):
- if not self.inDrawingMode:
- ID = self.mainCanvas.find_withtag(CURRENT)[0]
- item = self.findItem(ID)
- self.itemEdit(item)
-
- def itemDrag(self,event):
- x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
- x = x0/self.magnification
- y = y0/self.magnification
- if self.selectedButton not in [self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton]:
- return
- if "selectedItem" in self.mainCanvas.gettags(CURRENT):
- self.amDragging = True
- for ID in self.mainCanvas.find_withtag("selectedItem"):
- transform = identity()
- if self.selectedButton == self.toolMoveButton:
- translation = (x0-self.dragStartx,-(y0-self.dragStarty))
- elif self.selectedButton == self.toolVertiMoveButton:
- translation = (0,-(y0-self.dragStarty))
- elif self.selectedButton == self.toolHorizMoveButton:
- translation = (x0-self.dragStartx,0)
- self.translateSomething(ID,(translation[0]/self.magnification,translation[1]/self.magnification))
- self.mainCanvas.move(ID,translation[0],-translation[1])
- self.updateSelection()
- self.updateCanvasSize()
- self.distanceDragged = (self.distanceDragged[0]+translation[0],self.distanceDragged[1]-translation[1])
- self.dragStartx,self.dragStarty = x0,y0
-
- def itemMouseUp(self,event):
- self.freeMouseDown = True
- if self.amDragging:
- IDList = self.mainCanvas.find_withtag("selectedItem")
- itemList = []
- indexList = []
- for ID in IDList:
- item = self.findItem(ID)
- if item not in itemList:
- itemList.append(item)
- try:
- indexList.append([self.findItemImageIndex(item,ID)])
- except:
- indexList.append([None])
- else:
- indexList[itemList.index(item)].append(self.findItemImageIndex(item,ID))
- self.undoRedoStack.add(translationAction(self,itemList,indexList,(self.distanceDragged[0],-self.distanceDragged[1])))
- self.amDragging = False
-
- def itemSelect(self,event):
- x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
- x = x0/self.magnification
- y = y0/self.magnification
- self.dragStartx,self.dragStarty = x0,y0
- self.distanceDragged = (0,0)
- if self.selectedButton in [self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton]:
- self.freeMouseDown = False
- if self.selectedButton == self.toolSelectButton or (len(self.mainCanvas.find_withtag("selectedItem"))<=1 and self.selectedButton in [self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton]):
- self.clearSelection()
- self.setSelection(CURRENT)
-
- def itemToggleSelect(self,event):
- #print ("control click")
- x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
- x = x0/self.magnification
- y = y0/self.magnification
- if self.selectedButton in [self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton]:
- self.freeMouseDown = False
- self.dragStartx,self.dragStarty = x0,y0
- if "selectedItem" in self.mainCanvas.gettags(CURRENT):
- self.unSelect(CURRENT)
- else:
- self.setSelection(CURRENT)
-
- def itemDelete(self,event):
- if(not self.testOrAcquireLock()):
- return
- itemList = []
- self.undoRedoStack.add(endActionGroup)
- for ID in self.mainCanvas.find_withtag("selectedItem"):
- item = self.findItem(ID)
- if isinstance(item,xasyScript):
- index = self.findItemImageIndex(item,ID)
- if item not in itemList:
- itemList.append([item,[index],[item.transform[index]]])
- else:
- x = None
- for i in itemList:
- if i[0] == item:
- x = i
- x[1].append(index)
- x[2].append(item.transform[index])
- self.deleteSomething(ID)
- for entry in itemList:
- self.undoRedoStack.add(deleteScriptItemAction(self,entry[0],entry[1],entry[2]))
- self.undoRedoStack.add(beginActionGroup)
- self.clearSelection()
- self.releaseLock()
-
- def itemMotion(self,event):
- pass
-
- def itemHighlight(self,event):
- if self.selectedButton in [self.toolSelectButton] and self.editor == None:
- box = self.mainCanvas.bbox(CURRENT)
- box = (box[0]-2,box[1]-2,box[2]+2,box[3]+2)
- if len(self.mainCanvas.find_withtag("highlightBox"))==0:
- self.mainCanvas.create_rectangle(box,tags="highlightBox",width=2,outline="red")
- else:
- self.mainCanvas.tag_raise("highlightBox")
- self.mainCanvas.coords("highlightBox",*box)
- self.mainCanvas.tag_bind("highlightBox","<Leave>",self.itemUnHighlight)
-
- def itemUnHighlight(self,event):
- self.clearHighlight()
-
- def clearHighlight(self):
- self.mainCanvas.delete("highlightBox")
-
- def itemLeftDown(self,event):
- pass
-
- def itemLeftUp(self,event):
- pass
-
- def itemRightDown(self,event):
- pass
-
- def itemRightUp(self,event):
- pass
-
- def canvMotion(self,event):
- self.coords.config(
- text="(%.3f,%.3f)"%(self.mainCanvas.canvasx(event.x)/self.magnification,-self.mainCanvas.canvasy(event.y)/self.magnification)
- )
-
- def addItemToFile(self,item):
- self.fileItems.append(item)
- self.propList.insert(0,self.describeItem(item))
- self.updateCanvasSize()
-
- def startDraw(self,event):
- # don't start if we can't finish
- if not self.testOrAcquireLock() and not self.inDrawingMode:
- return
- x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
- x = x0/self.magnification
- y = y0/self.magnification
- #self.mainCanvas.create_oval(x,y,x,y,width=5)
- if self.selectedButton == self.toolDrawEllipButton:
- pass
- elif self.selectedButton == self.toolFillEllipButton:
- pass
- elif self.selectedButton == self.toolTextButton:
- theText = simpledialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue="",parent=self.parent)
- if theText != None and theText != "":
- theItem = xasyText(theText,(x,-y),asyPen(self.penColor,self.penWidth,self.penOptions))
- theItem.drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(theItem)
- self.addItemToFile(theItem)
- self.undoRedoStack.add(addLabelAction(self,theItem))
- self.releaseLock()
- self.updateSelectedButton(self.toolSelectButton)
- elif self.selectedButton in [self.toolDrawLinesButton,self.toolDrawBeziButton,self.toolDrawPolyButton,self.toolDrawShapeButton,self.toolFillPolyButton,self.toolFillShapeButton]:
- self.inDrawingMode = True
- try:
- if len(self.itemBeingDrawn.path.nodeSet) == 0:
- raise Exception
- else:
- if self.selectedButton in [self.toolDrawLinesButton,self.toolDrawPolyButton,self.toolFillPolyButton]:
- self.itemBeingDrawn.appendPoint((x,-y),'--')
- else:#drawBezi,drawShape,fillShape
- self.itemBeingDrawn.appendPoint((x,-y),'..')
- except:
- path = asyPath()
- if self.selectedButton == self.toolDrawLinesButton:
- path.initFromNodeList([(x,-y),(x,-y)],['--'])
- elif self.selectedButton == self.toolDrawBeziButton:
- path.initFromNodeList([(x,-y),(x,-y)],['..'])
- elif self.selectedButton == self.toolDrawPolyButton or self.selectedButton == self.toolFillPolyButton:
- path.initFromNodeList([(x,-y),(x,-y),'cycle'],['--','--'])
- elif self.selectedButton == self.toolDrawShapeButton or self.selectedButton == self.toolFillShapeButton:
- path.initFromNodeList([(x,-y),(x,-y),'cycle'],['..','..'])
- if self.selectedButton in [self.toolDrawLinesButton,self.toolDrawBeziButton,self.toolDrawPolyButton,self.toolDrawShapeButton]:
- self.itemBeingDrawn = xasyShape(path,pen=asyPen(self.penColor,self.penWidth,self.penOptions))
- else:
- if self.penOptions.find("fillrule") != -1 or self.penOptions.find("evenodd") != -1 or self.penOptions.find("zerowinding") != -1:
- options = self.penOptions
- else:
- options = "evenodd"
- self.itemBeingDrawn = xasyFilledShape(path,pen=asyPen(self.penColor,self.penWidth,options))
- self.itemBeingDrawn.drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(self.itemBeingDrawn)
- self.mainCanvas.bind("<Motion>",self.extendDraw)
-
- def extendDraw(self,event):
- x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
- x = x0/self.magnification
- y = y0/self.magnification
- tags = self.mainCanvas.gettags("itemBeingDrawn")
- self.itemBeingDrawn.setLastPoint((x,-y))
- self.itemBeingDrawn.drawOnCanvas(self.mainCanvas,self.magnification)
- self.canvMotion(event)
-
- def endDraw(self,event):
- if not self.inDrawingMode or self.itemBeingDrawn == None:
- return
- x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
- x = x0/self.magnification
- y = y0/self.magnification
- #if self.selectedButton in [self.toolDrawLinesButton,self.toolDrawPolyButton,self.toolFillPolyButton]:
- #self.itemBeingDrawn.appendPoint((x,-y),'--')
- #else:
- #self.itemBeingDrawn.appendPoint((x,-y),'..')
-
- #only needed for certain key bindings when startDraw is triggered right before an endDraw
- #e.g.: single click: startDraw, double click: endDraw
- self.itemBeingDrawn.removeLastPoint()
- self.itemBeingDrawn.setLastPoint((x,-y))
- self.itemBeingDrawn.drawOnCanvas(self.mainCanvas,self.magnification)
- self.addItemToFile(self.itemBeingDrawn)
- self.undoRedoStack.add(addDrawnItemAction(self,self.itemBeingDrawn))
- self.itemBeingDrawn = None
- self.mainCanvas.dtag("itemBeingDrawn","itemBeingDrawn")
- self.mainCanvas.bind("<Motion>",self.canvMotion)
- self.inDrawingMode = False
- self.releaseLock()
-
- def canvLeftDown(self,event):
- #print ("Left Mouse Down")
- self.selectDragStart = (self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y))
- theBbox = self.mainCanvas.bbox("selectedItem")
- if theBbox != None:
- self.selectBboxMidpoint = (theBbox[0]+theBbox[2])/2.0,-(theBbox[1]+theBbox[3])/2.0
- if self.freeMouseDown and self.editor != None:
- self.editor.endEdit()
- if self.editor.modified:
- self.undoRedoStack.add(editDrawnItemAction(self,self.itemBeingEdited,copy.deepcopy(self.editor.shape),self.fileItems.index(self.editor.shape)))
- self.editor = None
- elif self.selectedButton in (self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton):
- if self.freeMouseDown:
- self.clearSelection()
- self.dragSelecting = False
- else:
- self.startDraw(event)
-
- def canvLeftUp(self,event):
- #print ("Left Mouse Up")
- # if we're busy, ignore it
- if not self.testOrAcquireLock():
- return
- self.freeMouseDown = True
- if self.inRotatingMode:
- for item in self.itemsBeingRotated:
- item.drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(item)
- self.updateSelection()
- self.itemsBeingRotated = []
- self.inRotatingMode = False
- if self.dragSelecting:
- self.hideSelectionBox()
- self.dragSelecting = False
- self.mainCanvas.addtag_enclosed("enclosed",self.selectDragStart[0],self.selectDragStart[1],self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y))
- for item in self.mainCanvas.find_withtag("enclosed"):
- tags = self.mainCanvas.gettags(item)
- if "drawn" not in tags and "image" not in tags:
- self.mainCanvas.dtag(item,"enclosed")
- self.mainCanvas.addtag_withtag("selectedItem","enclosed")
- self.mainCanvas.dtag("enclosed","enclosed")
- if self.selectedButton == self.toolSelectButton and len(self.mainCanvas.find_withtag("selectedItem")) > 0:
- self.updateSelectedButton(self.toolMoveButton)
- self.updateSelection()
- self.releaseLock()
-
- def canvDrag(self,event):
- x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
- x = x0/self.magnification
- y = y0/self.magnification
- if self.selectedButton == self.toolSelectButton and self.editor == None:
- self.mainCanvas.coords("outlineBox",self.selectDragStart[0],self.selectDragStart[1],x0,y0)
- self.showSelectionBox()
- self.dragSelecting = True
- elif self.selectedButton == self.toolRotateButton and self.editor == None:
- bbox = self.mainCanvas.bbox("selectedItem")
- if bbox != None:
- p1 = self.selectDragStart[0]-self.selectBboxMidpoint[0],-self.selectDragStart[1]-self.selectBboxMidpoint[1]
- mp1 = math.sqrt(p1[0]**2+p1[1]**2)
- p2 = x0-self.selectBboxMidpoint[0],-y0-self.selectBboxMidpoint[1]
- mp2 = math.sqrt(p2[0]**2+p2[1]**2)
- if mp1 != 0:
- t1 = math.acos(p1[0]/mp1)
- if p1[1] < 0:
- t1 *= -1
- else:
- t1 = 0
- if mp2 != 0:
- t2 = math.acos(p2[0]/mp2)
- if p2[1] < 0:
- t2 *= -1
- else:
- t2 = 0
- theta = t2-t1
- self.selectDragStart = x0,y0
- self.itemsBeingRotated = []
- for ID in self.mainCanvas.find_withtag("selectedItem"):
- self.rotateSomething(ID,theta,self.selectBboxMidpoint)
- item = self.findItem(ID)
- if not item in self.itemsBeingRotated:
- self.itemsBeingRotated.append(item)
- self.updateSelection()
- self.updateCanvasSize()
- if not self.inRotatingMode:
- self.currentRotationAngle = theta
- IDList = self.mainCanvas.find_withtag("selectedItem")
- itemList = []
- indexList = []
- for ID in IDList:
- item = self.findItem(ID)
- if item not in itemList:
- itemList.append(item)
- try:
- indexList.append([self.findItemImageIndex(item,ID)])
- except:
- indexList.append([None])
- else:
- indexList[itemList.index(item)].append(self.findItemImageIndex(item,ID))
- self.undoRedoStack.add(rotationAction(self,itemList,indexList,self.currentRotationAngle,self.selectBboxMidpoint))
- self.inRotatingMode = True
- else:
- self.currentRotationAngle += theta
- self.undoRedoStack.undoStack[-1].angle = self.currentRotationAngle
-
- def canvEnter(self,event):
- self.freeMouseDown = True
- event.widget.focus_set()
-
- def canvLeave(self,event):
- self.freeMouseDown = False
-
- def canvRightDown(self,event):
- pass
- #print ("Right Mouse Down")
-
- def canvRightUp(self,event):
- pass
- #print ("Right Mouse Up")
-
- def configEvt(self,event):
- self.updateCanvasSize()
- self.sizePane()
-
- def sizePane(self):
- width = self.windowPane.winfo_width()-10
- cwidth = min(int(0.87*self.windowPane.winfo_width()),width-75)
- if self.paneVisible:
- self.windowPane.paneconfigure(self.canvFrame,minsize=cwidth)
- else:
- self.windowPane.paneconfigure(self.canvFrame,minsize=width)
- self.windowPane.paneconfigure(self.propFrame,minsize=75)
-
- def togglePaneEvt(self,event):
- self.paneVisible = not self.paneVisible
- self.sizePane()
-
- def popupDelete(self):
- self.deleteItem(self.itemPopupMenu.item)
-
- def popupEdit(self):
- self.itemEdit(self.itemPopupMenu.item)
-
- def popupViewCode(self):
- messagebox.showinfo("Item Code",self.itemPopupMenu.item.getCode())
-
- def popupClearTransform(self):
- self.undoRedoStack.add(clearItemTransformsAction(self,self.itemPopupMenu.item,copy.deepcopy(self.itemPopupMenu.item.transform)))
- if isinstance(self.itemPopupMenu.item,xasyScript) or isinstance(self.itemPopupMenu.item,xasyText):
- for i in range(len(self.itemPopupMenu.item.transform)):
- self.itemPopupMenu.item.transform[i] = identity()
- else:
- self.itemPopupMenu.item.transform = [identity()]
- self.popupRedrawItem()
-
- def popupRedrawItem(self):
- if not self.testOrAcquireLock():
- return
- self.clearSelection()
- self.clearHighlight()
- self.itemPopupMenu.item.drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(self.itemPopupMenu.item)
- self.updateCanvasSize()
- self.releaseLock()
-
- def hidePopupMenu(self):
- try:
- self.itemPopupMenu.unpost()
- except:
- pass
-
- def itemMenuPopup(self,parent,item,x,y):
- self.hidePopupMenu()
- self.itemPopupMenu = Menu(parent,tearoff=False)
- self.itemPopupMenu.add_command(label="Edit",command=self.popupEdit)
- self.itemPopupMenu.add_command(label="Clear Transforms",command=self.popupClearTransform)
- self.itemPopupMenu.add_command(label="Redraw",command=self.popupRedrawItem)
- self.itemPopupMenu.add_command(label="View code",command=self.popupViewCode)
- self.itemPopupMenu.add_separator()
- self.itemPopupMenu.add_command(label="Delete",command=self.popupDelete)
- self.itemPopupMenu.item = item
- #self.itemPopupMenu.bind("<Leave>",lambda a:self.itemPopupMenu.unpost())
- #self.itemPopupMenu.bind("<FocusOut>",lambda a:self.itemPopupMenu.unpost())
- self.itemPopupMenu.post(x,y)
-
- def itemPropMenuPopup(self,event):
- try:
- item = self.fileItems[len(self.fileItems)-int(self.propList.curselection()[0])-1]
- self.itemMenuPopup(self.propList,item,event.x_root,event.y_root)
- except:
- pass
-
- def itemCanvasMenuPopup(self,event):
- if self.selectedButton in (self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton):
- try:
- item = self.findItem(self.mainCanvas.find_withtag(CURRENT)[0])
- except:
- item = None
- if item != None:
- self.itemMenuPopup(self.mainCanvas,item,event.x_root,event.y_root)
-
- def editOptions(self):
- if(not self.testOrAcquireLock()):
- return
- self.releaseLock()
- xasyOptionsDialog.xasyOptionsDlg(self.parent)
- self.applyOptions()
-
- def resetOptions(self):
- xasyOptions.setDefaults()
- self.applyOptions()
-
- def applyPenWidth(self):
- self.pendingPenWidthChange = None
- if self.validatePenWidth():
- old = self.penWidth
- self.penWidth = float(self.penWidthEntry.get())
- if old != self.penWidth:
- self.showCurrentPen()
-
- def validatePenWidth(self):
- text = self.penWidthEntry.get()
- try:
- width = float(text)
- if width <= 0:
- return False
- else:
- return True
- except:
- return False
-
- def showCurrentPen(self):
- mag = 1
- width = self.penWidth
- while width > 10:
- width /= 2
- mag *= 2
- self.penDisp.itemconfigure("penDisp",width=width,fill=self.tkPenColor)
- self.penDisp.itemconfigure("penMag",text="x%d"%mag)
- #apply the new pen to any selected items
- IDs = self.mainCanvas.find_withtag("selectedItem")
- madeAChange = False
- for ID in IDs:
- item = self.findItem(ID)
- if not isinstance(item,xasyScript):
- if not madeAChange:
- self.undoRedoStack.add(endActionGroup)
- madeAChange = True
- if isinstance(item,xasyText):
- temp = item.label.pen
- item.label.pen = asyPen(self.penColor,self.penWidth,self.penOptions)
- item.drawOnCanvas(self.mainCanvas,self.magnification)
- self.bindItemEvents(item)
- self.setSelection(item.imageList[0].IDTag)
- self.undoRedoStack.add(editLabelPenAction(self,temp,asyPen(self.penColor,self.penWidth,self.penOptions),self.fileItems.index(item)))
- else:
- temp = copy.deepcopy(item)
- item.pen = asyPen(self.penColor,self.penWidth,self.penOptions)
- item.drawOnCanvas(self.mainCanvas,self.magnification)
- self.undoRedoStack.add(editDrawnItemAction(self,temp,copy.deepcopy(item),self.fileItems.index(item)))
- if madeAChange:
- self.undoRedoStack.add(beginActionGroup)
-
- def applyPenWidthEvt(self,event):
- if not self.testOrAcquireLock():
- return
- self.applyPenWidth()
- self.releaseLock()
-
- def penWidthChanged(self,event):
- if self.pendingPenWidthChange is not None:
- self.penWidthEntry.after_cancel(self.pendingPenWidthChange)
- self.pendingPenWidthChange = self.penWidthEntry.after(1000,self.applyPenWidth)
-
- def applyPenOptEvt(self,event):
- if not self.testOrAcquireLock():
- return
- self.applyPenOpt()
- self.releaseLock()
-
- def validatePenOpt(self):
- try:
- penTest = asyPen(self.penColor,self.penWidth,self.penOptEntry.get())
- return True
- except:
- self.penOptEntry.select_range(0,END)
- self.penOptEntry.delete(0,END)
- self.penOptEntry.insert(END,"Invalid Pen Options")
- self.penOptEntry.after(5000,self.clearInvalidOptEntry)
- self.penOptions = ""
- return False
-
- def clearInvalidOptEntry(self):
- self.penOptEntry.select_range(0,END)
- self.penOptEntry.delete(0,END)
-
- def applyPenOpt(self):
- if self.validatePenOpt():
- old = self.penOptions
- self.penOptions = self.penOptEntry.get()
- if old != self.penOptions:
- self.showCurrentPen()
-
- def undoOperation(self):
- self.undoRedoStack.undo()
-
- def redoOperation(self):
- self.undoRedoStack.redo()
-
- def resetStacking(self):
- for item in self.fileItems:
- self.raiseSomething(item,force=True)
Modified: trunk/Build/source/utils/asymptote/GUI/xasyOptions.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyOptions.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyOptions.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
###########################################################################
#
# xasyOptions provides a mechanism for storing and restoring a user's
@@ -10,117 +10,149 @@
#
###########################################################################
-import pickle
-import sys,os
-import errno
+import json
+import sys
+import io
+import os
+import platform
+import shutil
-defaultOptions = {
- 'asyPath':'asy',
- 'showDebug':False,
- 'showGrid':False,
- 'gridX':10,
- 'gridY':10,
- 'gridColor':'#eeeeee',
- 'showAxes':True,
- 'axisX':10,
- 'axisY':10,
- 'axesColor':'#cccccc',
- 'tickColor':'#eeeeee',
- 'defPenOptions':'',
- 'defPenColor':'#000000',
- 'defPenWidth':1.0,
- 'externalEditor':''
- }
+import configs
-if sys.platform[:3] == "win":
- defaultOptions['externalEditor'] = "%PROGRAMFILES%\Windows NT\Accessories\wordpad.exe"
-else:
- defaultOptions['externalEditor'] = "emacs"
+try:
+ import cson
+except ModuleNotFoundError:
+ cson = None
+try:
+ pass
+# import yaml
+except ModuleNotFoundError:
+ yaml = None
-options = defaultOptions.copy()
+class xasyOptions:
+ def defaultOptions(self):
+ if self._defaultOptions is None:
+ f = io.open(self._defualtOptLocation)
+ try:
+ opt = cson.loads(f.read())
+ finally:
+ f.close()
+ self._defaultOptions = opt
+ return self._defaultOptions
-def settingsFileLocation():
- folder = ""
- try:
- folder = os.path.expanduser("~/.asy/")
- except:
- pass
- return os.path.normcase(os.path.join(folder,"xasy.conf"))
+ def overrideSettings(self):
+ settingsName = platform.system()
-def setAsyPathFromWindowsRegistry():
- try:
- import _winreg as registry
- #test both registry locations
- try:
- key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Asymptote")
- options['asyPath'] = registry.QueryValueEx(key,"Path")[0]+"\\asy.exe"
- registry.CloseKey(key)
- except:
- key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Asymptote")
- options['asyPath'] = registry.QueryValueEx(key,"InstallLocation")[0]+"\\asy.exe"
- registry.CloseKey(key)
- except:
- #looks like asy is not installed or this isn't Windows
- pass
+ if settingsName not in self.options:
+ return
-def setDefaults():
- global options
- options = defaultOptions.copy()
- if sys.platform[:3] == 'win': #for windows, wince, win32, etc
- setAsyPathFromWindowsRegistry()
- save()
+ for key in self.options[settingsName]:
+ self.options[key] = self.options[settingsName][key]
+
+
+ def settingsFileLocation(self):
+ folder = os.path.expanduser("~/.asy/")
-def load():
- global options
- fileName = settingsFileLocation()
- if not os.path.exists(fileName):
- #make folder
- thedir = os.path.dirname(fileName)
- if not os.path.exists(thedir):
- try:
- os.makedirs(thedir)
- except:
- raise Exception("Could not create configuration folder")
- if not os.path.isdir(thedir):
- raise Exception("Configuration folder path does not point to a folder")
- setDefaults()
- try:
- f = open(fileName,"rb")
- newOptions = pickle.load(f)
- for key in options.keys():
- if type(newOptions[key]) != type(options[key]):
- raise Exception("Bad type for entry in xasy settings")
- options = newOptions
- except:
- setDefaults()
+ searchOrder = ['.cson', '.yaml', '.json', '']
-def save():
- global options
- fileName = settingsFileLocation()
- try:
- f = open(fileName,"wb")
- pickle.dump(options,f)
- f.close()
- except:
- raise Exception("Error saving preferences")
+ searchIndex = 0
+ found = False
+ currentFile = ''
+ while searchIndex < len(searchOrder) and not found:
+ currentFile = os.path.join(folder, self.configName + searchOrder[searchIndex])
+ if os.path.isfile(currentFile):
+ found = True
+ searchIndex += 1
+
+ if found:
+ return os.path.normcase(currentFile)
+ else:
+ return os.path.normcase(os.path.join(folder, self.configName + '.cson'))
-load()
+ def __init__(self, configName, defaultConfigLocation):
+ self.configName = configName
+ self.defaultConfigName = defaultConfigLocation
-if __name__=='__main__':
- print (settingsFileLocation())
- print ("Current content")
- load()
- print ("Setting defaults")
- setDefaults()
- save()
- load()
- options['showAxes'] = options['showGrid'] = False
- save()
- print ("Set to False")
- load()
- options['showAxes'] = options['showGrid'] = True
- save()
- print ("Set to True")
- load()
- print (options)
+ self._defaultOptions = None
+ self._defualtOptLocation = os.path.join(defaultConfigLocation)
+
+ self.options = self.defaultOptions()
+ self.load()
+
+ def __getitem__(self, item):
+ return self.options[item]
+
+ def __setitem__(self, key, value):
+ self.options[key] = value
+
+ def load(self):
+ fileName = self.settingsFileLocation()
+ if not os.path.exists(fileName):
+ # make folder
+ thedir = os.path.dirname(fileName)
+ if not os.path.exists(thedir):
+ os.makedirs(thedir)
+ if not os.path.isdir(thedir):
+ raise Exception("Configuration folder path does not point to a folder")
+ self.setDefaults()
+ f = io.open(fileName, 'r')
+ try:
+ ext = os.path.splitext(fileName)[1]
+ if ext == '.cson':
+ if cson is None:
+ raise ModuleNotFoundError
+ newOptions = cson.loads(f.read())
+ elif ext in {'.yml', '.yaml'}:
+ if yaml is None:
+ raise ModuleNotFoundError
+ newOptions = yaml.load(f)
+ else:
+ newOptions = json.loads(f.read())
+ except (IOError, ModuleNotFoundError):
+ self.setDefaults()
+ else:
+ for key in self.options.keys():
+ if key in newOptions:
+ assert isinstance(newOptions[key], type(self.options[key]))
+ else:
+ newOptions[key] = self.options[key]
+ self.options = newOptions
+ finally:
+ f.close()
+
+ def setDefaults(self):
+ self.options = self.defaultOptions()
+ if sys.platform[:3] == 'win': # for windows, wince, win32, etc
+ # setAsyPathFromWindowsRegistry()
+ pass
+ folder = os.path.expanduser("~/.asy/")
+ defaultPath = os.path.join(folder, self.configName + '.cson')
+ shutil.copy2(self._defualtOptLocation, defaultPath)
+
+
+# TODO: Figure out how to merge this back.
+"""
+def setAsyPathFromWindowsRegistry():
+ if os.name == 'nt':
+ import _winreg as registry
+ # test both registry locations
+ try:
+ key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Asymptote")
+ options['asyPath'] = registry.QueryValueEx(key, "Path")[0] + "\\asy.exe"
+ registry.CloseKey(key)
+ except:
+ key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,
+ "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Asymptote")
+ options['asyPath'] = registry.QueryValueEx(key, "InstallLocation")[0] + "\\asy.exe"
+ registry.CloseKey(key)
+"""
+
+
+class BasicConfigs:
+ _configPath = list(configs.__path__)[0]
+ defaultOpt = xasyOptions(
+ 'xasyconfig', os.path.join(_configPath, 'xasyconfig.cson'))
+ keymaps = xasyOptions('xasykeymap', os.path.join(
+ _configPath, 'xasykeymap.cson'))
Deleted: trunk/Build/source/utils/asymptote/GUI/xasyOptionsDialog.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyOptionsDialog.py 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/GUI/xasyOptionsDialog.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,234 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyOptionsDialog implements a dialog window to allow users to edit
-# their preferences and specify program options
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-
-import os
-import sys
-import xasyOptions
-import xasyColorPicker
-
-if sys.version_info >= (3, 0):
- from tkinter import *
- from tkinter import simpledialog, messagebox, filedialog
-else:
- # python2
- from Tkinter import *
- import tkSimpleDialog as simpledialog
- import tkMessageBox as messagebox
- import tkFileDialog as filedialog
- # import tkColorChooser as colorchooser
-
-class xasyOptionsDlg(simpledialog.Dialog):
- """A dialog to interact with users about their preferred settings"""
- def __init__(self,master=None):
- simpledialog.Dialog.__init__(self,master,"xasy Options")
-
- def body(self,master):
- optFrame = Frame(master)
- optFrame.grid(row=0,column=0,sticky=N+S+E+W)
-
- asyGrp = LabelFrame(optFrame,text="Asymptote",padx=5,pady=5)
- asyGrp.grid(row=0,column=0,sticky=E+W)
- asyGrp.rowconfigure(0,weight=1)
- asyGrp.rowconfigure(1,weight=1)
- asyGrp.columnconfigure(0,weight=1)
- asyGrp.columnconfigure(0,weight=2)
- Label(asyGrp,text="Command").grid(row=0,column=0,sticky=W)
- self.ap = Entry(asyGrp)
- self.ap.insert(END,xasyOptions.options['asyPath'])
- self.ap.grid(row=0,column=1,sticky=E+W)
- Button(asyGrp,text="...",command=self.findAsyPath).grid(row=0,column=2,sticky=E+W)
- self.showDebug = BooleanVar()
- self.showDebug.set(xasyOptions.options['showDebug'])
- self.sd = Checkbutton(asyGrp,text="Show debugging info in console",var=self.showDebug)
- self.sd.grid(row=1,column=0,columnspan=2,sticky=W)
-
- editGrp = LabelFrame(optFrame,text="External Editor",padx=5,pady=5)
- editGrp.grid(row=1,column=0,sticky=E+W)
- editGrp.rowconfigure(0,weight=1)
- editGrp.rowconfigure(1,weight=1)
- editGrp.columnconfigure(0,weight=1)
- editGrp.columnconfigure(0,weight=2)
- Label(editGrp,text="Program").grid(row=0,column=0,sticky=W)
- self.ee = Entry(editGrp)
- self.ee.insert(END,xasyOptions.options['externalEditor'])
- self.ee.grid(row=0,column=1,sticky=E+W)
- Button(editGrp,text="...",command=self.findEEPath).grid(row=0,column=2,sticky=E+W)
-
- penGrp = LabelFrame(optFrame,text="Default Pen",padx=5,pady=5)
- penGrp.grid(row=2,column=0,sticky=E+W)
- penGrp.rowconfigure(0,weight=1)
- penGrp.rowconfigure(1,weight=1)
- penGrp.rowconfigure(2,weight=1)
- penGrp.columnconfigure(1,weight=1)
- Label(penGrp,text="Color").grid(row=0,column=0,sticky=E)
- self.pc = xasyOptions.options['defPenColor']
- Button(penGrp,text="Change",command=self.changePenColor).grid(row=0,column=1,sticky=W)
- Label(penGrp,text="Width").grid(row=1,column=0,sticky=E)
- self.pw = Entry(penGrp)
- self.pw.insert(END,str(xasyOptions.options['defPenWidth']))
- self.pw.grid(row=1,column=1,sticky=E+W)
- Label(penGrp,text="Options").grid(row=2,column=0,sticky=E)
- self.po = Entry(penGrp)
- self.po.insert(END,xasyOptions.options['defPenOptions'])
- self.po.grid(row=2,column=1,sticky=E+W)
-
- dispGrp = LabelFrame(optFrame,text="Display Options",padx=5,pady=5)
- dispGrp.grid(row=3,column=0,sticky=E+W)
- dispGrp.rowconfigure(0,weight=1)
- dispGrp.rowconfigure(1,weight=1)
- dispGrp.rowconfigure(2,weight=1)
- dispGrp.rowconfigure(3,weight=1)
- dispGrp.columnconfigure(0,weight=1)
- dispGrp.columnconfigure(1,weight=1)
- dispGrp.columnconfigure(2,weight=1)
- self.showAxes = BooleanVar()
- self.showAxes.set(xasyOptions.options['showAxes'])
- self.sa = Checkbutton(dispGrp,text="Show Axes",var=self.showAxes)
- self.sa.grid(row=0,column=0,sticky=W)
- self.ac = xasyOptions.options['axesColor']
- Button(dispGrp,text="Color...",command=self.changeAxesColor).grid(row=1,column=0)
- Label(dispGrp,text="x").grid(row=0,column=1,padx=5,sticky=E)
- self.axs = Entry(dispGrp,width=6)
- self.axs.insert(END,xasyOptions.options['axisX'])
- self.axs.grid(row=0,column=2,sticky=W+E)
- Label(dispGrp,text="y").grid(row=1,column=1,padx=5,sticky=E)
- self.ays = Entry(dispGrp,width=6)
- self.ays.insert(END,xasyOptions.options['axisY'])
- self.ays.grid(row=1,column=2,sticky=W+E)
-
- self.showGrid = BooleanVar()
- self.showGrid.set(xasyOptions.options['showGrid'])
- self.sg = Checkbutton(dispGrp,text="Show Grid",var=self.showGrid)
- self.sg.grid(row=4,column=0,sticky=W)
- self.gc = xasyOptions.options['gridColor']
- Button(dispGrp,text="Color...",command=self.changeGridColor).grid(row=3,column=0)
- Label(dispGrp,text="x").grid(row=2,column=1,padx=5,sticky=E)
- self.gxs = Entry(dispGrp,width=6)
- self.gxs.insert(END,xasyOptions.options['gridX'])
- self.gxs.grid(row=2,column=2,sticky=W+E)
- Label(dispGrp,text="y").grid(row=3,column=1,padx=5,sticky=E)
- self.gys = Entry(dispGrp,width=6)
- self.gys.insert(END,xasyOptions.options['gridY'])
- self.gys.grid(row=3,column=2,sticky=W+E)
-
- def findEEPath(self):
- if sys.platform[:3] == 'win': #for windows, wince, win32, etc
- file=filedialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Choose External Editor",parent=self)
- else:
- file=filedialog.askopenfile(filetypes=[("All files","*")],title="Choose External Editor",parent=self)
- if file != None:
- name = os.path.abspath(file.name)
- file.close()
- self.ee.delete(0,END)
- self.ee.insert(END,name)
- self.validate()
-
- def findAsyPath(self):
- if sys.platform[:3] == 'win': #for windows, wince, win32, etc
- file=filedialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Find Asymptote Executable",parent=self)
- else:
- file=filedialog.askopenfile(filetypes=[("All files","*")],title="Find Asymptote Executable",parent=self)
- if file != None:
- name = os.path.abspath(file.name)
- file.close()
- self.ap.delete(0,END)
- self.ap.insert(END,name)
- self.validate()
-
- def getAColor(self,color):
- result = xasyColorPicker.xasyColorDlg(self).getColor(xasyColorPicker.makeRGBfromTkColor(color))
- return xasyColorPicker.RGB255hex(xasyColorPicker.RGBreal255(result))
-
- def changeAxesColor(self):
- self.ac = self.getAColor(self.ac)
-
- def changeGridColor(self):
- self.gc = self.getAColor(self.gc)
-
- def changePenColor(self):
- self.pc = self.getAColor(self.pc)
-
- def apply(self):
- xasyOptions.options['externalEditor'] = self.ee.get()
- xasyOptions.options['asyPath'] = self.ap.get()
- xasyOptions.options['showDebug'] = bool(self.showDebug.get())
-
- xasyOptions.options['defPenColor'] = self.pc
- xasyOptions.options['defPenWidth'] = float(self.pw.get())
- xasyOptions.options['defPenOptions'] = self.po.get()
-
- xasyOptions.options['showAxes'] = bool(self.showAxes.get())
- xasyOptions.options['axesColor'] = self.ac
- xasyOptions.options['tickColor'] = self.ac
- xasyOptions.options['axisX'] = int(self.axs.get())
- xasyOptions.options['axisY'] = int(self.ays.get())
- xasyOptions.options['showGrid'] = bool(self.showGrid.get())
- xasyOptions.options['gridColor'] = self.gc
- xasyOptions.options['gridX'] = int(self.gxs.get())
- xasyOptions.options['gridY'] = int(self.gys.get())
- xasyOptions.save()
-
- def validateAColor(self,color):
- hexdigits = '0123456789abcdef'
- if len(self.pc) != 7 or self.pc[0] != '#' or sum([1 for a in self.pc[1:] if a in hexdigits]) != 6:
- return False
- else:
- return True
-
- def validate(self):
- """Validate the data entered into the dialog"""
- #validate the color
- hexdigits = '0123456789abcdef'
- if not self.validateAColor(self.pc):
- messagebox.showerror("xasy Options","Invalid pen color.\r\n"+self.pc,parent=self)
- return False
- #validate the width
- try:
- test = float(self.pw.get())
- except:
- messagebox.showerror("xasy Options","Pen width must be a number.",parent=self)
- return False
-
- #validate the options
- #nothing to do
-
- #validate the axis spacing
- try:
- test = int(self.axs.get())
- test = int(self.ays.get())
- except:
- messagebox.showerror("xasy Options","Axes' x- and y-spacing must be numbers.",parent=self)
- return False
-
- #validate the grid spacing
- try:
- test = int(self.gxs.get())
- test = int(self.gys.get())
- except:
- messagebox.showerror("xasy Options","Grid's x- and y-spacing must be numbers.",parent=self)
- return False
-
- if not self.validateAColor(self.ac):
- messagebox.showerror("xasy Options","Invalid axis color.\r\n"+self.ac,parent=self)
- return False
-
- if not self.validateAColor(self.gc):
- messagebox.showerror("xasy Options","Invalid grid color.\r\n"+self.gc,parent=self)
- return False
-
- return True
-
-if __name__ == '__main__':
- root = Tk()
- xasyOptions.load()
- d = xasyOptionsDlg(root)
- print (d.result)
Added: trunk/Build/source/utils/asymptote/GUI/xasyStrings.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyStrings.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/xasyStrings.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+
+import gettext
+
+p = property
+
+class xasyString:
+ def __init__(self, lang=None):
+ s = self
+ if lang is None:
+ _ = lambda x: x
+ else:
+ lng = gettext.translation('base', localedir='GUI/locale', languages=[lang])
+ lng.install()
+ _ = lng.gettext
+
+ s.rotate = _('Rotate')
+ s.scale = _('Scale')
+ s.translate = _('Translate')
+
+ s.fileOpenFailed = _('File Opening Failed.')
+ s.fileOpenFailedText = _('File could not be opened.')
+ s.asyfyComplete = _('Ready.')
Property changes on: trunk/Build/source/utils/asymptote/GUI/xasyStrings.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/xasySvg.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasySvg.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/xasySvg.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtGui as Qg
+import PyQt5.QtWidgets as Qw
+import io
+import subprocess
+import sys
+
+class SvgObject():
+ def __init__(self, file: str):
+ self.file=file
+
+ def render(self, dpi:int) -> Qg.QImage:
+ try:
+ rawDataProc = subprocess.Popen(['rsvg-convert', '--dpi-x', str(dpi),
+ '--dpi-y', str(dpi), self.file],
+ stdout=subprocess.PIPE)
+ except:
+ Qw.QMessageBox.about(None,'rsvg-convert missing','Please install rsvg-convert version >= 2.40 in your path.')
+ sys.exit(-1)
+
+ return Qg.QImage.fromData(rawDataProc.stdout.read(), 'PNG')
Property changes on: trunk/Build/source/utils/asymptote/GUI/xasySvg.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/xasyTransform.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyTransform.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/xasyTransform.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+import xasy2asy as x2a
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import numpy as np
+import math
+
+
+class xasyTransform:
+ @classmethod
+ def makeRotTransform(cls, theta, origin):
+ if isinstance(origin, Qc.QPointF) or isinstance(origin, Qc.QPoint):
+ origin = (origin.x(), origin.y())
+ rotMat = (math.cos(theta), -math.sin(theta), math.sin(theta), math.cos(theta))
+ shift = x2a.asyTransform((0, 0, 1 - rotMat[0], -rotMat[1], -rotMat[2], 1 - rotMat[3])) * origin
+ return x2a.asyTransform((shift[0], shift[1], rotMat[0], rotMat[1], rotMat[2], rotMat[3]))
+
+ @classmethod
+ def makeScaleTransform(cls, sx, sy, origin):
+ if isinstance(origin, Qc.QPointF) or isinstance(origin, Qc.QPoint):
+ origin = (origin.x(), origin.y())
+ shiftMat = x2a.asyTransform((0, 0, 1 - sx, 0, 0, 1 - sy)) * origin
+ return x2a.asyTransform((shiftMat[0], shiftMat[1], sx, 0, 0, sy))
+
Property changes on: trunk/Build/source/utils/asymptote/GUI/xasyTransform.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/xasyUtils.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyUtils.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/xasyUtils.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+
+import re
+import typing as ty
+import math
+import itertools
+
+def tuple2StrWOspaces(val: tuple) -> str:
+ newStr = ','.join(['{:.6g}'.format(value) for value in val])
+ return '({0})'.format(newStr)
+
+def tryParse(val, typ=float):
+ try:
+ return typ(val)
+ except ValueError:
+ return None
+
+def funcOnList(list1: ty.Union[ty.List, ty.Tuple], list2: ty.Union[ty.List, ty.Tuple], func: ty.Callable) -> tuple:
+ """Returns [f(x[i], y[i]) : i in 1, ..., n - 1] in order with f as func
+ and x and y as list1 and 2. """
+
+ assert len(list1) == len(list2)
+ return tuple([func(list1[i], list2[i]) for i in range(len(list1))])
+
+
+def listize(str, typ, delim='()') -> list:
+ str = str.strip(delim)
+ raw_elem = str.split(',')
+ final_list = []
+ if isinstance(typ, (list, tuple)):
+ for i in range(len(raw_elem)):
+ if i < len(typ):
+ curr_typ = typ[i]
+ else:
+ curr_typ = typ[-1]
+ final_list.append(curr_typ(raw_elem[i].strip()))
+ else:
+ for elem in raw_elem:
+ final_list.append(typ(elem.strip()))
+ return final_list
+
+def twonorm(vec: ty.Iterable[ty.Union[float, int]]) -> float:
+ rawSquared = sum(map(lambda x: x*x, vec))
+ return math.sqrt(rawSquared)
+
+def tryParseKey(raw_key):
+ """Returns None if raw key is not in #.# format"""
+ # See https://regex101.com/r/6G9MZD/1/
+ # for the regex data
+ return re.fullmatch(r'^(\d+)\.(\d+)$', raw_key)
Property changes on: trunk/Build/source/utils/asymptote/GUI/xasyUtils.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Build/source/utils/asymptote/GUI/xasyValidator.py
===================================================================
--- trunk/Build/source/utils/asymptote/GUI/xasyValidator.py (rev 0)
+++ trunk/Build/source/utils/asymptote/GUI/xasyValidator.py 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+
+def validateFloat(text):
+ try:
+ float(text)
+ return True
+ except ValueError:
+ return False
+
+
+if __name__ == '__main__':
+ assert validateFloat('0.5')
+ assert not validateFloat('.-')
Property changes on: trunk/Build/source/utils/asymptote/GUI/xasyValidator.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Build/source/utils/asymptote/Makefile.in
===================================================================
--- trunk/Build/source/utils/asymptote/Makefile.in 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/Makefile.in 2019-01-10 18:49:48 UTC (rev 49658)
@@ -21,6 +21,8 @@
SHAREDLIBS = $(filter-out -lGL -lGLU -lglut -pthread $(GCLIBS), $(LIBS))
vpath %.cc prc
+vpath %.ui GUI/windows
+vpath %.py GUI/pyUIClass
CAMP = camperror path drawpath drawlabel picture psfile texfile util settings \
guide flatguide knot drawfill path3 drawpath3 drawsurface \
@@ -45,12 +47,13 @@
FILES = $(COREFILES) main
-SYMBOLSH = opsymbols.h allsymbols.h
+SYMBOLSH = opsymbols.h allsymbols.h $(SYMBOL_FILES:=.symbols.h)
DIST = camp.tab.h camp.tab.cc lex.yy.cc runtime.cc keywords.cc \
asy-keywords.el $(RUNTIME_FILES:=.cc) $(RUNTIME_FILES:=.h) asy.list \
- $(SYMBOLSH) $(SYMBOL_FILES:=.symbols.h)
+ $(SYMBOLSH)
NAME = asy
XNAME = x$(NAME)
+UIFILES = $(wildcard GUI/windows/*.ui)
CLEAN = camp.output base/version.asy doc/version.texi \
GUI/xasyVersion.py $(XNAME) doc/asy-latex.pdf $(SYMBOLSH)
EXTRA = asy-mode.el asy-init.el asy.vim asy_filetype.vim asy-kate.sh \
@@ -58,7 +61,7 @@
EXEXTRA = piicon.eps *.views *.dat *.bib
DOCEXTRA = *.asy *.csv *.dat latexusage.tex externalprc.tex pixel.pdf
KEYWORDS = base $(ASYMPTOTE_SITEDIR)
-LATEXFILES = asymptote.sty asycolors.sty ocg.sty latexmkrc
+LATEXFILES = asymptote.sty asycolors.sty ocg.sty latexmkrc
CONTEXTFILES = colo-asy.tex
ASY = ./asy -dir base -config "" -render=0
@@ -107,6 +110,7 @@
export prefix docdir exampledir mandir infodir INSTALL MAKE DESTDIR TEXI2DVI
asy: version
+ -pyrcc5 GUI/res/icons.qrc -o GUI/icons_rc.py
if test -n "$(MSDOS)"; then \
$(CXX) $(OPTS) -o $(NAME) $(FILES:=.o) revision.o asy.o $(DOSLIBS); \
else \
@@ -114,7 +118,7 @@
$(CXX) $(OPTS) -o $(NAME) $(FILES:=.o) revision.o $(LIBS); \
fi
-version: $(GCLIB) $(FILES:=.o)
+version: $(GCLIB) $(FILES:=.o) $(UIFILES:.ui=.py)
if test ! -s revision.cc -o "$(revision)" != "$(last)"; then \
echo $(REVISION)\"$(revision)\"\; > revision.cc; \
fi
@@ -124,7 +128,7 @@
echo @set VERSION $(revision) > doc/version.texi
echo @set Datadir @datadir@ >> doc/version.texi
- echo "#!/usr/bin/env python" > GUI/xasyVersion.py
+ echo "#!/usr/bin/env python3" > GUI/xasyVersion.py
echo xasyVersion = \"$(revision)\" >> GUI/xasyVersion.py
if test -n "$(MSDOS)"; then \
@@ -221,8 +225,10 @@
grep -v three_\* | grep -v featpost3D | xargs $(ASY) -l >> asy.list
$(PERL) ./asy-list.pl asy.list $(revision)
-install: asy-keywords.el install-texhash install-man
+install-notexhash: asy-keywords.el install-asy install-man
+install: install-notexhash install-texhash
+
install-all: install install-html
install-texhash: install-asy
@@ -231,8 +237,9 @@
fi
install-asy: asy sty
- ${INSTALL} -d $(bindir) $(asydir) $(GUIdir) $(exampledir) \
- $(animationsdir)
+ ${INSTALL} -d $(bindir) $(asydir) $(exampledir) $(animationsdir)
+ ${INSTALL} -d $(GUIdir) $(GUIdir)/pyUIClass $(GUIdir)/configs \
+ $(GUIdir)/res $(GUIdir)/res/icons
-${INSTALL} -d $(latexdir)
-${INSTALL} -d $(contextdir)
${INSTALL} -p -m 755 $(NAME) $(bindir)
@@ -239,6 +246,10 @@
${INSTALL} -p -m 644 base/*.asy $(addprefix base/,$(EXTRA)) \
asy-keywords.el $(asydir)
${INSTALL} -p -m 755 GUI/*.py $(GUIdir)
+ ${INSTALL} -p -m 644 GUI/pyUIClass/*.py $(GUIdir)/pyUIClass
+ ${INSTALL} -p -m 644 GUI/configs/*.cson $(GUIdir)/configs
+ ${INSTALL} -p -m 644 GUI/res/icons.qrc $(GUIdir)/res
+ ${INSTALL} -p -m 644 GUI/res/icons/*.svg $(GUIdir)/res/icons
ln -sf @datadir@/asymptote/GUI/xasy.py $(bindir)/$(XNAME)
${INSTALL} -p -m 644 examples/*.asy $(addprefix examples/,$(EXEXTRA)) \
doc/extra/*.asy $(addprefix doc/,$(DOCEXTRA)) $(exampledir)
@@ -276,7 +287,7 @@
-rmdir $(contextdir)
-cd $(bindir) && rm -f $(NAME) $(XNAME)
-uninstall-man:
+uninstall-man:
cd doc && $(MAKE) uninstall
uninstall-docdir:
@@ -316,22 +327,24 @@
./wce
$(MAKE) -C tests all
-.SUFFIXES: .c .cc .o .d
-.cc.o:
+.SUFFIXES: .c .cc .o .d .ui .py
+%.o: %.cc
$(CXX) $(OPTS) $(INCL) -o $@ -c $<
-.cc.d:
+%.d: %.cc
@echo Creating $@; \
rm -f $@; \
${CXX} $(MAKEDEPEND) $(INCL) $(MDOPTS) $< > $@.$$$$ 2>/dev/null && \
sed 's,\($*\)\.o[ :]*,\1.o \1.pic.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-.c.d:
+%.d: %.c
@echo Creating $@; \
rm -f $@; \
${CC} $(MAKEDEPEND) $(INCL) $(MDOPTS) $< > $@.$$$$ 2>/dev/null && \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
-
+%.py: %.ui
+ mkdir -p GUI/pyUIClass
+ -pyuic5 -o GUI/pyUIClass/$(notdir $@) $<
# Compile for the shared library. OpenGL must be disabled as it causes
# crashes inside a shared library.
%.pic.o: %.cc
@@ -351,4 +364,3 @@
config.status: configure
./config.status --recheck
-
Added: trunk/Build/source/utils/asymptote/Pipfile
===================================================================
--- trunk/Build/source/utils/asymptote/Pipfile (rev 0)
+++ trunk/Build/source/utils/asymptote/Pipfile 2019-01-10 18:49:48 UTC (rev 49658)
@@ -0,0 +1,11 @@
+[[source]]
+url = "https://pypi.org/simple"
+verify_ssl = true
+name = "pypi"
+
+[packages]
+
+[dev-packages]
+
+[requires]
+python_version = "3.6"
Modified: trunk/Build/source/utils/asymptote/README
===================================================================
--- trunk/Build/source/utils/asymptote/README 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/README 2019-01-10 18:49:48 UTC (rev 49658)
@@ -47,8 +47,22 @@
libraries. This version of Asymptote also ships with the dll libraries
noted below.
-The source code for the 2.7.0 cygwin1.dll is available under the GPL license:
-https://cygwin.com/snapshots/x86/cygwin-20170203-src.tar.xz
+The source code for the x86_64 2.9.0-3 cygwin1.dll is available under the
+GPL license:
+https://cygwin.com/snapshots/x86_64/cygwin-20170823-src.tar.xz
+The source code for the i386 2.10.0-1 cygwin1.dll is available under the
+GPL license:
+https://cygwin.com/snapshots/x86/cygwin-20171219-src.tar.xz
+
The source code for freeglut.dll is available under the X-Consortium license:
http://prdownloads.sourceforge.net/freeglut/freeglut-2.8.1.tar.gz
+
+Source for various icons is available under the MIT license from
+https://github.com/driftyco/ionicons/archive/v2.0.1.zip
+https://github.com/iconic/open-iconic/archive/master.zip
+under the CC-BY-SA 4.0 license:
+http://www.entypo.com/
+and under a CC license:
+http://www.zondicons.com/zondicons.zip
+
\ No newline at end of file
Modified: trunk/Build/source/utils/asymptote/ReleaseNotes
===================================================================
--- trunk/Build/source/utils/asymptote/ReleaseNotes 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/ReleaseNotes 2019-01-10 18:49:48 UTC (rev 49658)
@@ -1,3 +1,28 @@
+Release Notes for Version 2.47
+
+Further shipout and scaling problems were fixed. Unused files were removed.
+Multiple-page documents now produce PS instead of EPS output.
+
+Release Notes for Version 2.46
+
+The pen width is now accounted for in the bbox function. The relative
+alignment of a label to a path now transforms correctly with picture
+rotation. Various shipout issues were fixed. The ghostscript library
+location from the MSWindows registry is now ignored for compatibility
+with TeXLive.
+
+Release Notes for Version 2.45
+
+The xasy graphical front end for Asymptote has been rewritten to
+support code reordering, using Qt5 and scalable vector graphics.
+An uninitialized counter was fixed. A stable=true option was added to sort.
+The restricted simplex method has been replaced by a complete simplex
+solver that handles general size constraints. The rpc library has been
+replaced by the tirpc library. The dvips utility is forced to respect
+EPS requirements again. The system ghostscript library is now used by
+default for dvisvgm. Make clean now removes GSL symbols. The MSWindows
+system path is no longer modified by the installer. A CLZ bug was fixed.
+
Release Notes for Version 2.44
Floating point exceptions are masked again under CYGWIN, pending strtod bug fix
Modified: trunk/Build/source/utils/asymptote/arrayop.h
===================================================================
--- trunk/Build/source/utils/asymptote/arrayop.h 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/arrayop.h 2019-01-10 18:49:48 UTC (rev 49658)
@@ -355,7 +355,7 @@
vm::item it=pop(s);
bool defaultfile=isdefault(it);
camp::ofile *f=defaultfile ? &camp::Stdout : vm::get<camp::ofile*>(it);
- if(!f->enabled()) return;
+ if(!f->isOpen() || !f->enabled()) return;
size_t asize=checkArray(a);
size_t Asize=checkArray(A);
@@ -407,11 +407,13 @@
void writeArray2(vm::stack *s)
{
array *a=pop<array*>(s);
- camp::file *f=pop<camp::file*>(s,&camp::Stdout);
+ vm::item it=pop(s);
+ bool defaultfile=isdefault(it);
+ camp::ofile *f=defaultfile ? &camp::Stdout : vm::get<camp::ofile*>(it);
+ if(!f->isOpen() || !f->enabled()) return;
size_t size=checkArray(a);
if(f->Standard()) interact::lines=0;
- else if(!f->isOpen()) return;
try {
for(size_t i=0; i < size; i++) {
@@ -437,11 +439,13 @@
void writeArray3(vm::stack *s)
{
array *a=pop<array*>(s);
- camp::file *f=pop<camp::file*>(s,&camp::Stdout);
+ vm::item it=pop(s);
+ bool defaultfile=isdefault(it);
+ camp::ofile *f=defaultfile ? &camp::Stdout : vm::get<camp::ofile*>(it);
+ if(!f->isOpen() || !f->enabled()) return;
size_t size=checkArray(a);
if(f->Standard()) interact::lines=0;
- else if(!f->isOpen()) return;
try {
for(size_t i=0; i < size;) {
Modified: trunk/Build/source/utils/asymptote/asy-keywords.el
===================================================================
--- trunk/Build/source/utils/asymptote/asy-keywords.el 2019-01-10 01:23:27 UTC (rev 49657)
+++ trunk/Build/source/utils/asymptote/asy-keywords.el 2019-01-10 18:49:48 UTC (rev 49658)
@@ -2,16 +2,16 @@
;; This file is automatically generated by asy-list.pl.
;; Changes will be overwritten.
;;
-(defvar asy-keywords-version "2.44")
+(defvar asy-keywords-version "2.47")
(defvar asy-keyword-name '(
and controls tension atleast curl if else while for do return break continue struct typedef new access import unravel from include quote static public private restricted this explicit true false null cycle newframe operator ))
(defvar asy-type-name '(
-Braid FitResult Label Legend Solution TreeNode abscissa arc arrowhead binarytree binarytreeNode block bool bool3 bounds bqe circle conic coord coordsys cputime ellipse evaluatedpoint file filltype frame grid3 guide horner hsv hyperbola indexedTransform int inversion key light line linefit marginT marker mass object pair parabola patch path path3 pen picture point position positionedvector projection rational real revolution scaleT scientific segment side slice solution splitface string surface tensionSpecifier ticklocate ticksgridT tickvalues transform transformation tree triangle trilinear triple vector vertex void ))
+Braid FitResult Label Legend Solution TreeNode abscissa arc arrowhead binarytree binarytreeNode block bool bool3 bounds bqe circle conic coord coordsys cputime ellipse evaluatedpoint file filltype frame grid3 guide horner hsv hyperbola int inversion key light line linefit marginT marker mass node object pair parabola patch path path3 pen picture point position positionedvector projection rational real revolution scaleT scientific segment side simplex slice solution splitface string surface tensionSpecifier ticklocate ticksgridT tickvalues transform transformation tree triangle trilinear triple vector vertex void ))
(defvar asy-function-name '(
-AND Arc ArcArrow ArcArrows Arrow Arrows AtA Automatic AvantGarde B03 B13 B23 B33 BBox BWRainbow BWRainbow2 Bar Bars BeginArcArrow BeginArrow BeginBar BeginDotMargin BeginMargin BeginPenMargin Blank Bookman Bottom BottomTop Bounds Break Broken BrokenLog CLZ CTZ Ceil Circle CircleBarIntervalMarker Cos Courier CrossIntervalMarker DOSendl DOSnewl DefaultFormat DefaultLogFormat Degrees Dir DotMargin DotMargins Dotted Draw Drawline Embed EndArcArrow EndArrow EndBar EndDotMargin EndMargin EndPenMargin Fill FillDraw Floor Format Full Gaussian Gaussrand Gaussrandpair Gradient Grayscale Helvetica Hermite HookHead InOutTicks InTicks Jn Label Landscape Left LeftRight LeftTicks Legend Linear Log LogFormat Margin Margins Mark MidArcArrow MidArrow NOT NewCenturySchoolBook NoBox NoMargin NoModifier NoTicks NoTicks3 NoZero NoZeroFormat None OR OmitFormat OmitTick OmitTickInterval OmitTickIntervals OutTicks Ox Oy Palatino PaletteTicks Pen PenMargin PenMargins Pentype Portrait RadialShade RadialShadeDraw Rainbow Range Relative Right RightTicks Rotate Round SQR Scale ScaleX ScaleY ScaleZ Seascape Shift Sin Slant Spline StickIntervalMarker Straight Symbol Tan TeXify Ticks Ticks3 TildeIntervalMarker TimesRoman Top TrueMargin UnFill UpsideDown Wheel X XEquals XOR XY XYEquals XYZero XYgrid XZEquals XZZero XZero XZgrid Y YEquals YXgrid YZ YZEquals YZZero YZero YZgrid Yn Z ZX ZXgrid ZYgrid ZapfChancery ZapfDingbats _begingroup3 _cputime _draw _eval _findroot _image _labelpath _projection _strokepath _texpath aCos aSin aTan abort abs accel acos acosh acot acsc activatequote add addArrow addMargins addSaveFunction addpenarc addpenline addseg adjust alias align all altitude angabscissa angle angledegrees angpoint animate annotate anticomplementary antipedal apply approximate arc arcarrowsize arccircle arcdir arcfromcenter arcfromfocus arclength arcnodesnumber arcpoint arcsubtended arcsubtendedcenter arctime arctopath array arrow arrow2 arrowbase arrowbasepoints arrowsize ascii asec asin asinh ask assert asy asycode asydir asyfigure!
asyfilecode asyinclude asywrite atan atan2 atanh atbreakpoint atexit attach attract atupdate autoformat autoscale autoscale3 axes axes3 axialshade axis axiscoverage azimuth babel background bangles bar barmarksize barsize basealign baseline bbox beep begin beginclip begingroup beginpoint between bevel bezier bezierP bezierPP bezierPPP bezulate bibliography bibliographystyle binarytree binarytreeNode binomial bins bisector bisectorpoint bispline bitreverse blend blockconnector box bqe brace breakpoint breakpoints brick buildRestoreDefaults buildRestoreThunk buildcycle bulletcolor byte calculateScaling canonical canonicalcartesiansystem cartesiansystem case1 case2 case3 cbrt cd ceil center centerToFocus centroid cevian change2 changecoordsys checkSegment check_fpt_zero checkconditionlength checker checkincreasing checklengths checkposition checkpt checkptincube checktriangle choose circle circlebarframe circlemarkradius circlenodesnumber circumcenter circumcircle clamped clear clip clipdraw close cmyk code colatitude collect collinear color colorless colors colorspace comma compassmark complement complementary concat concurrent cone conic conicnodesnumber conictype conj connect containmentTree contains contour contour3 controlSpecifier convert coordinates coordsys copy copyPairOrTriple cos cosh cot countIntersections cputime crop cropcode cross crossframe crosshatch crossmarksize csc cubicroots curabscissa curlSpecifier curpoint currentarrow currentexitfunction currentmomarrow currentpolarconicroutine curve cut cutafter cutbefore cyclic cylinder deactivatequote debugger deconstruct defaultdir defaultformat defaultpen defined degenerate degrees delete deletepreamble determinant diagonal diamond diffdiv dir dirSpecifier dirtime display distance divisors do_overpaint dot dotframe dotsize downcase draw drawAll drawDoubleLine drawFermion drawGhost drawGluon drawMomArrow drawPRCcylinder drawPRCdisk drawPRCsphere drawPRCtube drawPhoton drawScalar drawVertex drawVertexBox drawVertexBoxO drawVertexBoxX drawVertexO drawVer!
texOX drawVertexTriangle drawVertexTriangleO drawVertexX drawarrow drawarrow2 drawbeziertriangle drawline drawpixel drawstrokepath drawtick duplicate elle ellipse ellipsenodesnumber embed embed3 embedplayer empty enclose end endScript endclip endgroup endgroup3 endl endpoint endpoints eof eol equation equations erase erasestep erf erfc error errorbar errorbars eval excenter excircle exit exitXasyMode exitfunction exp expfactors expi expm1 exradius extend extension extouch fabs factorial fermat fft fhorner figure file filecode fill filldraw filloutside fillrule filltype find findall findroot finite finiteDifferenceJacobian firstcut firstframe fit fit2 fixedscaling floor flush fmdefaults fmod focusToCenter font fontcommand fontsize foot format frac frequency fromCenter fromFocus fspline functionshade gamma gcd generate_random_backtrace generateticks gergonne getc getint getpair getreal getstring gettriple gluon gouraudshade graph graphic graphicscale gray grestore grid grid3 gsave halfbox hatch hdiffdiv hermite hex histogram history hline hprojection hsv hyperbola hyperbolanodesnumber hyperlink hypot identity image implicitsurface incenter incentral incircle increasing incrementposition indexedTransform indexedfigure initXasyMode initdefaults initialized input inradius insert inside insphere integrate interactive interior interp interpolate intersect intersection intersectionpoint intersectionpoints intersections intouch inverse inversion invisible is3D isDuplicate isnan isogonal isogonalconjugate isotomic isotomicconjugate isparabola italic item jobname key kurtosis kurtosisexcess label labelaxis labelmargin labelpath labels labeltick labelx labelx3 labely labely3 labelz labelz3 lastcut latex latitude latticeshade layer layout lcm ldexp leastsquares legend legenditem length lexorder lift light limits line linear linecap lineinversion linejoin linemargin lineskip linetype linewidth link list lm_enorm lm_evaluate_default lm_lmdif lm_lmpar lm_minimize lm_print_default lm_print_quiet lm_qrfac lm_qrsolv locale locate !
locatefile location log log10 log1p logaxiscoverage longitude lookup make3dgrid makeNode makecircle makedraw makepen maketriangle map margin markangle markangleradius markanglespace markarc marker markinterval marknodes markrightangle markthin markuniform mass masscenter massformat math max max3 maxAfterTransform maxbezier maxbound maxcoords maxlength maxratio maxtimes mean medial median midpoint min min3 minAfterTransform minbezier minbound minipage minratio mintimes miterlimit mktemp momArrowPath momarrowsize monotonic multifigure nGrad nativeformat natural needshipout newl newpage newslide newton newtree nextframe nextnormal nextpage nib nodabscissa none norm normalout normalvideo nosetpagesize notaknot nowarn numberpage nurb object offset onpath opacity opposite orient orientation origin orthic orthocentercenter outformat outline outname outprefix output overloadedMessage overwrite pack pad pairs palette parabola parabolanodesnumber parallel parallelogram partialsum patchwithnormals path path3 pathbetween pathinface pattern pause pdf pedal periodic perp perpendicular perpendicularmark phantom phi1 phi2 phi3 photon piecewisestraight point polar polarconicroutine polargraph polygon popcount postcontrol postscript pow10 ppoint prc prc0 prconly precision precontrol prepend printBytecode print_random_addresses progress project projection projecttospan projecttospan_findcoeffs purge pwhermite quadpatches quadrant quadraticroots quantize quarticroots quotient radialshade radians radicalcenter radicalline radius rand randompath rd readline realmult realquarticroots rectangle rectangular rectify reflect relabscissa relative relativedistance reldir relpoint reltime remainder remark removeDuplicates rename replace report resetdefaultpen restore restoredefaults reverse reversevideo rf rfind rgb rgba rgbint rms rotate rotateO rotation round roundbox roundedpath roundrectangle samecoordsys sameside sample save savedefaults saveline scale scale3 scaleO scaleT scaleless scientific search searchtree sec secondaryX secondaryY!
seconds section sector seek seekeof segment segmentlimits sequence setpens sgn sgnd sharpangle sharpdegrees shift shiftless shipout shipout3 show simeq simpson sin sinh size size3 skewness skip slant sleep slice slope slopefield solve solveBVP sort sourceline sphere split sqrt square srand standardizecoordsys startScript stdev step stickframe stickmarksize stickmarkspace stop straight straightness string stripdirectory stripextension stripfile stripsuffix strokepath subdivide subitem subpath substr sum surface symmedial symmedian system tab tableau tan tangent tangential tangents tanh tell tensionSpecifier tensorshade tex texcolor texify texpath texpreamble texreset texshipout texsize textpath thick thin tick tickMax tickMax3 tickMin tickMin3 ticklabelshift ticklocate tildeframe tildemarksize tile tiling time times title titlepage topbox transform transformation transpose trembleFuzz triangle triangleAbc triangleabc triangletoquads trianglewithnormals triangulate tricoef tridiagonal trilinear trim truepoint tube uncycle unfill uniform unique unit unitrand unitsize unityroot unstraighten upcase updatefunction uperiodic upscale uptodate usepackage usersetting usetypescript usleep value variance variancebiased vbox vector vectorfield verbatim view vline vperiodic vprojection warn warning windingnumber write xaxis xaxis3 xaxis3At xaxisAt xequals xlimits xpart xscale xscaleO xtick xtick3 xtrans yaxis yaxis3 yaxis3At yaxisAt yequals ylimits ypart yscale yscaleO ytick ytick3 ytrans zaxis3 zaxis3At zero zlimits zpart ztick ztick3 ztrans ))
+AND Arc ArcArrow ArcArrows Arrow Arrows AtA Automatic AvantGarde B03 B13 B23 B33 BBox BWRainbow BWRainbow2 Bar Bars BeginArcArrow BeginArrow BeginBar BeginDotMargin BeginMargin BeginPenMargin Blank Bookman Bottom BottomTop Bounds Break Broken BrokenLog CLZ CTZ Ceil Circle CircleBarIntervalMarker Cos Courier CrossIntervalMarker DOSendl DOSnewl DefaultFormat DefaultLogFormat Degrees Dir DotMargin DotMargins Dotted Draw Drawline Embed EndArcArrow EndArrow EndBar EndDotMargin EndMargin EndPenMargin Fill FillDraw Floor Format Full Gaussian Gaussrand Gaussrandpair Gradient Grayscale Helvetica Hermite HookHead InOutTicks InTicks Jn Label Landscape Left LeftRight LeftTicks Legend Linear Log LogFormat Margin Margins Mark MidArcArrow MidArrow NOT NewCenturySchoolBook NoBox NoMargin NoModifier NoTicks NoTicks3 NoZero NoZeroFormat None OR OmitFormat OmitTick OmitTickInterval OmitTickIntervals OutTicks Ox Oy Palatino PaletteTicks Pen PenMargin PenMargins Pentype Portrait RGB RadialShade RadialShadeDraw Rainbow Range Relative Right RightTicks Rotate Round SQR Scale ScaleX ScaleY ScaleZ Seascape Shift Sin Slant Spline StickIntervalMarker Straight Symbol Tan TeXify Ticks Ticks3 TildeIntervalMarker TimesRoman Top TrueMargin UnFill UpsideDown Wheel X XEquals XOR XY XYEquals XYZero XYgrid XZEquals XZZero XZero XZgrid Y YEquals YXgrid YZ YZEquals YZZero YZero YZgrid Yn Z ZX ZXgrid ZYgrid ZapfChancery ZapfDingbats _begingroup3 _cputime _draw _eval _findroot _image _labelpath _projection _shipout _strokepath _texpath aCos aSin aTan abort abs accel acos acosh acot acsc activatequote add addArrow addMargins addSaveFunction addpenarc addpenline addseg adjust alias align all altitude angabscissa angle angledegrees angpoint animate annotate anticomplementary antipedal apply approximate arc arcarrowsize arccircle arcdir arcfromcenter arcfromfocus arclength arcnodesnumber arcpoint arcsubtended arcsubtendedcenter arctime arctopath array arrow arrow2 arrowbase arrowbasepoints arrowsize ascii asec asin asinh ask assert asy asycode asy!
dir asyfigure asyfilecode asyinclude asywrite atan atan2 atanh atbreakpoint atexit attach attract atupdate autoformat autoscale autoscale3 axes axes3 axialshade axis axiscoverage azimuth babel background bangles bar barmarksize barsize basealign baseline bbox beep begin beginclip begingroup beginpoint between bevel bezier bezierP bezierPP bezierPPP bezulate bibliography bibliographystyle binarytree binarytreeNode binomial bins bisector bisectorpoint bispline bitreverse blend blockconnector box bqe brace breakpoint breakpoints brick buildRestoreDefaults buildRestoreThunk buildcycle bulletcolor byte calculateScaling canonical canonicalcartesiansystem cartesiansystem case1 case2 case3 cbrt cd ceil center centerToFocus centroid cevian change2 changecoordsys checkSegment check_fpt_zero checkconditionlength checker checkincreasing checklengths checkposition checkpt checkptincube checktriangle choose circle circlebarframe circlemarkradius circlenodesnumber circumcenter circumcircle clamped clear clip clipdraw close cmyk code colatitude collect collinear color colorless colors colorspace comma compassmark complement complementary concat concurrent cone conic conicnodesnumber conictype conj connect containmentTree contains contour contour3 controlSpecifier convert coordinates coordsys copy copyPairOrTriple cos cosh cot countIntersections cputime crop cropcode cross crossframe crosshatch crossmarksize csc cubicroots curabscissa curlSpecifier curpoint currentarrow currentexitfunction currentmomarrow currentpolarconicroutine curve cut cutafter cutbefore cyclic cylinder deactivatequote debugger deconstruct defaultdir defaultformat defaultpen defined degenerate degrees delete deletepreamble determinant diagonal diamond diffdiv dir dirSpecifier dirtime display distance divisors do_overpaint dot dotframe dotsize downcase draw drawAll drawDoubleLine drawFermion drawGhost drawGluon drawMomArrow drawPRCcylinder drawPRCdisk drawPRCsphere drawPRCtube drawPhoton drawScalar drawVertex drawVertexBox drawVertexBoxO drawVertexBoxX drawVe!
rtexO drawVertexOX drawVertexTriangle drawVertexTriangleO drawVertexX drawarrow drawarrow2 drawbeziertriangle drawline drawpixel drawstrokepath drawtick duplicate elle ellipse ellipsenodesnumber embed embed3 embedplayer empty enclose end endclip endgroup endgroup3 endl endpoint endpoints eof eol equation equations erase erasestep erf erfc error errorbar errorbars eval excenter excircle exit exitfunction exp expfactors expi expm1 exradius extend extension extouch fabs factorial fermat fft fhorner figure file filecode fill filldraw filloutside fillrule filltype find findall findroot finite finiteDifferenceJacobian firstcut firstframe fit fit2 fixedscaling floor flush fmdefaults fmod focusToCenter font fontcommand fontsize foot format frac frequency fromCenter fromFocus fspline functionshade gamma gcd generate_random_backtrace generateticks gergonne getc getint getpair getreal getstring gettriple gluon gouraudshade graph graphic graphicscale gray grestore grid grid3 gsave halfbox hatch hdiffdiv hermite hex histogram history hline hprojection hsv hyperbola hyperbolanodesnumber hyperlink hypot identity image implicitsurface incenter incentral incircle increasing incrementposition indexedfigure initdefaults initialized input inradius insert inside insphere integrate interactive interior interp interpolate intersect intersection intersectionpoint intersectionpoints intersections intouch inverse inversion invisible is3D isDuplicate isnan isogonal isogonalconjugate isotomic isotomicconjugate isparabola italic item jobname key kurtosis kurtosisexcess label labelaxis labelmargin labelpath labels labeltick labelx labelx3 labely labely3 labelz labelz3 lastcut latex latitude latticeshade layer layout lcm ldexp leastsquares legend legenditem length lexorder lift light limits line linear linecap lineinversion linejoin linemargin lineskip linetype linewidth link list lm_enorm lm_evaluate_default lm_lmdif lm_lmpar lm_minimize lm_print_default lm_print_quiet lm_qrfac lm_qrsolv locale locate locatefile location log log10 log1p loga!
xiscoverage longitude lookup make3dgrid makeNode makecircle makedraw makepen maketriangle map margin markangle markangleradius markanglespace markarc marker markinterval marknodes markrightangle markthin markuniform mass masscenter massformat math max max3 maxAfterTransform maxbezier maxbound maxcoords maxlength maxratio maxtimes mean medial median midpoint min min3 minAfterTransform minbezier minbound minipage minratio mintimes miterlimit mktemp momArrowPath momarrowsize monotonic multifigure nGrad nativeformat natural newl newpage newslide newton newtree nextframe nextnormal nextpage nib nodabscissa node none norm normalout normalvideo nosetpagesize notaknot nowarn numberpage nurb object offset onpath opacity opposite orient orientation origin orthic orthocentercenter outformat outline outname outprefix output overloadedMessage overwrite pack pad pairs palette parabola parabolanodesnumber parallel parallelogram partialsum patchwithnormals path path3 pathbetween pathinface pattern pause pdf pedal periodic perp perpendicular perpendicularmark phantom phi1 phi2 phi3 photon piecewisestraight point polar polarconicroutine polargraph polygon popcount postcontrol postscript pow10 ppoint prc prc0 prconly precision precontrol prepend printBytecode print_random_addresses progress project projection projecttospan projecttospan_findcoeffs purge pwhermite quadpatches quadrant quadraticroots quantize quarticroots quotient radialshade radians radicalcenter radicalline radius rand randompath rd readline realmult realquarticroots rectangle rectangular rectify reflect relabscissa relative relativedistance reldir relpoint reltime remainder remark removeDuplicates rename replace report resetdefaultpen restore restoredefaults reverse reversevideo rf rfind rgb rgba rgbint rms rotate rotateO rotation round roundbox roundedpath roundrectangle samecoordsys sameside sample save savedefaults saveline scale scale3 scaleO scaleT scaleless scientific search searchtree sec secondaryX secondaryY seconds section sector seek seekeof segment se!
gmentlimits sequence setpens sgn sgnd sharpangle sharpdegrees shift shiftless shipout shipout3 show simeq simplex simpson sin sinh size size3 skewness skip slant sleep slice slope slopefield solve solveBVP sort sourceline sphere split sqrt square srand standardizecoordsys stdev step stickframe stickmarksize stickmarkspace stop straight straightness string stripdirectory stripextension stripfile stripsuffix strokepath subdivide subitem subpath substr sum surface symmedial symmedian system tab tableau tan tangent tangential tangents tanh tell tensionSpecifier tensorshade tex texcolor texify texpath texpreamble texreset texshipout texsize textpath thick thin tick tickMax tickMax3 tickMin tickMin3 ticklabelshift ticklocate tildeframe tildemarksize tile tiling time times title titlepage topbox toplocation transform transformation transpose trembleFuzz triangle triangleAbc triangleabc triangletoquads trianglewithnormals triangulate tricoef tridiagonal trilinear trim truepoint tube uncycle unfill uniform unique unit unitrand unitsize unityroot unstraighten upcase updatefunction uperiodic upscale uptodate usepackage usersetting usetypescript usleep value variance variancebiased vbox vector vectorfield verbatim view vline vperiodic vprojection warn warning windingnumber write xasyKEY xaxis xaxis3 xaxis3At xaxisAt xequals xlimits xmap xpart xscale xscaleO xtick xtick3 xtrans yaxis yaxis3 yaxis3At yaxisAt yequals ylimits ypart yscale yscaleO ytick ytick3 ytrans zaxis3 zaxis3At zero zlimits zpart ztick ztick3 ztrans ))
(defvar asy-variable-name '(
-AliceBlue Align Allow AntiqueWhite Apricot Aqua Aquamarine Aspect Azure BeginPoint Beige Bisque Bittersweet Black BlanchedAlmond Blue BlueGreen BlueViolet Both Break BrickRed Brown BurlyWood BurntOrange CCW CW CadetBlue CarnationPink Center Centered Cerulean Chartreuse Chocolate Coeff Coral CornflowerBlue Cornsilk Crimson Crop Cyan Dandelion DarkBlue DarkCyan DarkGoldenrod DarkGray DarkGreen DarkKhaki DarkMagenta DarkOliveGreen DarkOrange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DefaultHead DimGray DodgerBlue Dotted Down Draw E ENE EPS ESE E_Euler E_PC E_RK2 E_RK3BS Emerald EndPoint Euler Fill FillDraw FireBrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold Goldenrod Gray Green GreenYellow Honeydew HookHead Horizontal HotPink I IgnoreAspect IndianRed Indigo Ivory JOIN_IN JOIN_OUT JungleGreen Khaki LM_DWARF LM_MACHEP LM_SQRT_DWARF LM_SQRT_GIANT LM_USERTOL Label Lavender LavenderBlush LawnGreen Left LeftJustified LeftSide LemonChiffon LightBlue LightCoral LightCyan LightGoldenrodYellow LightGreen LightGrey LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateGray LightSteelBlue LightYellow Lime LimeGreen Linear Linen Log Logarithmic Magenta Mahogany Mark MarkFill MarkPath Maroon Max MediumAquamarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue MediumSpringGreen MediumTurquoise MediumVioletRed Melon MidPoint MidnightBlue Min MintCream MistyRose Moccasin Move MoveQuiet Mulberry N NE NNE NNW NULL_VERTEX NW NavajoWhite Navy NavyBlue NoAlign NoCrop NoFill NoSide OldLace Olive OliveDrab OliveGreen Orange OrangeRed Orchid Ox Oy PC PaleGoldenrod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip Peach PeachPuff Periwinkle Peru PineGreen Pink Plum PowderBlue ProcessBlue Purple RK2 RK3 RK3BS RK4 RK5 RK5DP RK5F RawSienna Red RedOrange RedViolet Rhodamine Right RightJustified RightSide RosyBrown RoyalBlue RoyalPurple RubineRed S SE SSE SSW SW SaddleBrown Salmon SandyBrown SeaGreen Seashell Sepia Sienna S!
ilver SimpleHead SkyBlue SlateBlue SlateGray Snow SpringGreen SteelBlue Suppress SuppressQuiet Tan TeXHead Teal TealBlue Thistle Ticksize Tomato Turquoise UnFill Up VERSION Value Vertical Violet VioletRed W WNW WSW Wheat White WhiteSmoke WildStrawberry XHIGH XLOW XYAlign YAlign YHIGH YLOW Yellow YellowGreen YellowOrange ZHIGH ZLOW aboveequationskip addpenarc addpenline align allowstepping angularsystem animationdelay appendsuffix arcarrowangle arcarrowfactor arrow2sizelimit arrowangle arrowbarb arrowdir arrowfactor arrowhookfactor arrowlength arrowsizelimit arrowtexfactor authorpen axis axiscoverage axislabelfactor background backgroundcolor backgroundpen barfactor barmarksizefactor basealign baselinetemplate bernstein beveljoin bigvertexpen bigvertexsize black blue bm bottom bp bracedefaultratio braceinnerangle bracemidangle braceouterangle brown bullet byfoci byvertices camerafactor chartreuse circlemarkradiusfactor circlenodesnumberfactor circleprecision circlescale cm codefile codepen codeskip colorPen coloredNodes coloredSegments conditionlength conicnodesfactor count cputimeformat crossmarksizefactor currentcoordsys currentlight currentpatterns currentpen currentpicture currentposition currentprojection curvilinearsystem cuttings cyan darkblue darkbrown darkcyan darkgray darkgreen darkgrey darkmagenta darkolive darkred dashdotted dashed datepen dateskip debuggerlines debugging deepblue deepcyan deepgray deepgreen deepgrey deepmagenta deepred deepyellow default defaultControl defaultS defaultbackpen defaultcoordsys defaultexcursion defaultfilename defaultformat defaultmassformat defaultpen defaultseparator diagnostics differentlengths dot dotfactor dotframe dotted doublelinepen doublelinespacing down duplicateFuzz ellipsenodesnumberfactor eps epsgeo epsilon evenodd expansionfactor extendcap fermionpen figureborder figuremattpen file3 firstnode firststep foregroundcolor fuchsia fuzz gapfactor ghostpen gluonamplitude gluonpen gluonratio gray green grey hatchepsilon havepagenumber heavyblue heavycyan heavygray!
heavygreen heavygrey heavymagenta heavyred hline hwratio hyperbolanodesnumberfactor identity4 ignore inXasyMode inch inches includegraphicscommand inf infinity institutionpen intMax intMin invert invisible itempen itemskip itemstep labelmargin landscape lastnode left legendhskip legendlinelength legendmargin legendmarkersize legendmaxrelativewidth legendvskip lightblue lightcyan lightgray lightgreen lightgrey lightmagenta lightolive lightred lightyellow linemargin lm_infmsg lm_shortmsg longdashdotted longdashed magenta magneticRadius mantissaBits markangleradius markangleradiusfactor markanglespace markanglespacefactor maxrefinements mediumblue mediumcyan mediumgray mediumgreen mediumgrey mediummagenta mediumred mediumyellow middle minDistDefault minblockheight minblockwidth mincirclediameter minipagemargin minipagewidth minvertexangle miterjoin mm momarrowfactor momarrowlength momarrowmargin momarrowoffset momar