summaryrefslogtreecommitdiff
path: root/Build/source/utils/asymptote/GUI
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/utils/asymptote/GUI')
-rw-r--r--Build/source/utils/asymptote/GUI/CustMatTransform.py102
-rw-r--r--Build/source/utils/asymptote/GUI/DebugFlags.py6
-rw-r--r--Build/source/utils/asymptote/GUI/GuidesManager.py52
-rw-r--r--Build/source/utils/asymptote/GUI/InplaceAddObj.py356
-rw-r--r--Build/source/utils/asymptote/GUI/PrimitiveShape.py66
-rw-r--r--Build/source/utils/asymptote/GUI/SetCustomAnchor.py44
-rwxr-xr-xBuild/source/utils/asymptote/GUI/UndoRedoStack.py132
-rw-r--r--Build/source/utils/asymptote/GUI/Widg_addLabel.py96
-rw-r--r--Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py31
-rw-r--r--Build/source/utils/asymptote/GUI/Widg_editBezier.py53
-rw-r--r--Build/source/utils/asymptote/GUI/Window1.py1918
-rw-r--r--Build/source/utils/asymptote/GUI/__init__.py1
-rw-r--r--Build/source/utils/asymptote/GUI/configs/__init__.py1
-rw-r--r--Build/source/utils/asymptote/GUI/configs/xasyconfig.cson62
-rw-r--r--Build/source/utils/asymptote/GUI/configs/xasykeymap.cson26
-rw-r--r--Build/source/utils/asymptote/GUI/icons_rc.py2721
-rw-r--r--Build/source/utils/asymptote/GUI/labelEditor.py154
-rw-r--r--Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po24
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py174
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py120
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py56
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py141
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py49
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py95
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py97
-rw-r--r--Build/source/utils/asymptote/GUI/pyUIClass/window1.py964
-rw-r--r--Build/source/utils/asymptote/GUI/requirements.txt4
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons.qrc45
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/anchor.svg1
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg11
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg11
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-camera.svg12
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-close.svg12
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg17
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-delete.svg10
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-done.svg13
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-expand.svg12
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg10
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-hand.svg15
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-locate.svg16
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg12
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg13
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg11
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg8
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg8
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/bucket.asy26
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/bucket.svg15
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/center.asy6
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/center.svg12
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy7
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg15
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/check.svg9
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg13
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg13
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/circle.svg11
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/close-round.svg9
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy7
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg21
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy7
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg21
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/code.svg14
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/edit.svg13
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/eye.svg15
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg18
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/grid.svg32
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg13
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/opencurve.asy7
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/opencurve.svg21
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy7
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg21
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/plus-round.svg9
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/save.svg10
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/social-python.svg21
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg1
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/text.svg6
-rw-r--r--Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg12
-rw-r--r--Build/source/utils/asymptote/GUI/setup.py13
-rw-r--r--Build/source/utils/asymptote/GUI/windows/custMatTransform.ui356
-rw-r--r--Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui230
-rw-r--r--Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui109
-rw-r--r--Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui287
-rw-r--r--Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui91
-rw-r--r--Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui170
-rw-r--r--Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui150
-rw-r--r--Build/source/utils/asymptote/GUI/windows/window1.ui2198
-rwxr-xr-xBuild/source/utils/asymptote/GUI/xasy.py19
-rwxr-xr-xBuild/source/utils/asymptote/GUI/xasy2asy.py1414
-rw-r--r--Build/source/utils/asymptote/GUI/xasyArgs.py23
-rw-r--r--Build/source/utils/asymptote/GUI/xasyBezierInterface.py375
-rwxr-xr-xBuild/source/utils/asymptote/GUI/xasyFile.py83
-rwxr-xr-xBuild/source/utils/asymptote/GUI/xasyOptions.py159
-rw-r--r--Build/source/utils/asymptote/GUI/xasyStrings.py23
-rw-r--r--Build/source/utils/asymptote/GUI/xasySvg.py22
-rw-r--r--Build/source/utils/asymptote/GUI/xasyTransform.py24
-rw-r--r--Build/source/utils/asymptote/GUI/xasyUtils.py50
-rw-r--r--Build/source/utils/asymptote/GUI/xasyValidator.py13
96 files changed, 14003 insertions, 0 deletions
diff --git a/Build/source/utils/asymptote/GUI/CustMatTransform.py b/Build/source/utils/asymptote/GUI/CustMatTransform.py
new file mode 100644
index 00000000000..563907fc502
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/CustMatTransform.py
@@ -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))
diff --git a/Build/source/utils/asymptote/GUI/DebugFlags.py b/Build/source/utils/asymptote/GUI/DebugFlags.py
new file mode 100644
index 00000000000..8a7eb4b282e
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/DebugFlags.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+keepFiles = False
+printFoutTranscript = False
+printDeconstTranscript = False
+forceRasterizationSVG = False
diff --git a/Build/source/utils/asymptote/GUI/GuidesManager.py b/Build/source/utils/asymptote/GUI/GuidesManager.py
new file mode 100644
index 00000000000..5467843377a
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/GuidesManager.py
@@ -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()
diff --git a/Build/source/utils/asymptote/GUI/InplaceAddObj.py b/Build/source/utils/asymptote/GUI/InplaceAddObj.py
new file mode 100644
index 00000000000..132969dad19
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/InplaceAddObj.py
@@ -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
diff --git a/Build/source/utils/asymptote/GUI/PrimitiveShape.py b/Build/source/utils/asymptote/GUI/PrimitiveShape.py
new file mode 100644
index 00000000000..c75e014079f
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/PrimitiveShape.py
@@ -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)
diff --git a/Build/source/utils/asymptote/GUI/SetCustomAnchor.py b/Build/source/utils/asymptote/GUI/SetCustomAnchor.py
new file mode 100644
index 00000000000..ad5925cddb4
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/SetCustomAnchor.py
@@ -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')
diff --git a/Build/source/utils/asymptote/GUI/UndoRedoStack.py b/Build/source/utils/asymptote/GUI/UndoRedoStack.py
new file mode 100755
index 00000000000..7285b15ff2f
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/UndoRedoStack.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+###########################################################################
+#
+# UndoRedoStack implements the usual undo/redo capabilities of a GUI
+#
+# Author: Orest Shardt
+# Created: July 23, 2007
+#
+###########################################################################
+
+
+class 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
+
+
+class endActionGroup:
+ pass
+
+
+class actionStack:
+ def __init__(self):
+ self.clear()
+
+ 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 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 changesMade(self):
+ if len(self.undoStack) != self.commitLevel:
+ return True
+ else:
+ return False
+
+ 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)
diff --git a/Build/source/utils/asymptote/GUI/Widg_addLabel.py b/Build/source/utils/asymptote/GUI/Widg_addLabel.py
new file mode 100644
index 00000000000..776d3e02df9
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/Widg_addLabel.py
@@ -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()
diff --git a/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py b/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py
new file mode 100644
index 00000000000..b9b9a77f7a1
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py
@@ -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)
diff --git a/Build/source/utils/asymptote/GUI/Widg_editBezier.py b/Build/source/utils/asymptote/GUI/Widg_editBezier.py
new file mode 100644
index 00000000000..3a3cbab94ab
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/Widg_editBezier.py
@@ -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()
diff --git a/Build/source/utils/asymptote/GUI/Window1.py b/Build/source/utils/asymptote/GUI/Window1.py
new file mode 100644
index 00000000000..1f7b67b1fa1
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/Window1.py
@@ -0,0 +1,1918 @@
+#!/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:
+ center = 0
+ origin = 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()
+ global devicePixelRatio
+ devicePixelRatio=self.devicePixelRatio()
+ self.ui.setupUi(self)
+ self.ui.menubar.setNativeMenuBar(False)
+
+ 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
+ self.tx=0
+ self.ty=0
+
+ # 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.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.translate(0, -1),
+ 'moveDown': lambda: self.translate(0, 1),
+ 'moveLeft': lambda: self.translate(-1, 0),
+ 'moveRight': lambda: self.translate(1, 0),
+
+ '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 translate(self, x:int , y:int):
+ "x, y indicates update button orientation on the cartesian plane."
+ if self.lockX:
+ x = 0
+ if self.lockY:
+ y = 0
+ self.tx += x
+ self.ty += y
+ self.newTransform=Qg.QTransform.fromTranslate(self.tx,self.ty)
+ 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)
+ factor=0.5/devicePixelRatio;
+ cx, cy = self.canvSize.width()*factor, self.canvSize.height()*factor
+
+ 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 = 'https://asymptote.sourceforge.io/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: https://asymptote.sourceforge.io/")
+
+ 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()*devicePixelRatio
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+ self.canvasPixmap = Qg.QPixmap(self.canvSize)
+ self.canvasPixmap.setDevicePixelRatio(devicePixelRatio)
+ self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
+ self.canvasPixmap.setDevicePixelRatio(devicePixelRatio)
+
+ 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 candidate 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.tx=0
+ self.ty=0
+ 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
+
+ factor=0.5/devicePixelRatio;
+ cx, cy = self.canvSize.width()*factor, self.canvSize.height()*factor
+ 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.topLeft()
+ elif self.anchorMode == AnchorMode.topRight:
+ self.currentAnchor = self.currentBoundingBox.topRight()
+ elif self.anchorMode == AnchorMode.bottomLeft:
+ self.currentAnchor = self.currentBoundingBox.bottomLeft()
+ elif self.anchorMode == AnchorMode.bottomRight:
+ self.currentAnchor = self.currentBoundingBox.bottomRight()
+ 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 = devicePixelRatio*self.ui.imgFrame.size()
+ self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+ factor=0.5/devicePixelRatio;
+ x, y = self.canvSize.width()*factor, self.canvSize.height()*factor
+
+ self.canvasPixmap = Qg.QPixmap(self.canvSize)
+ self.canvasPixmap.setDevicePixelRatio(devicePixelRatio)
+
+ self.canvasPixmap.fill()
+
+ self.finalPixmap = Qg.QPixmap(self.canvSize)
+ self.finalPixmap.setDevicePixelRatio(devicePixelRatio)
+
+ self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
+ self.postCanvasPixmap.setDevicePixelRatio(devicePixelRatio)
+
+ 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.setDevicePixelRatio(devicePixelRatio)
+ self.finalPixmap.fill(Qc.Qt.black)
+ with Qg.QPainter(self.finalPixmap) as finalPainter:
+ drawPoint = Qc.QPoint(0, 0)
+ 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
+
+ factor=0.5/devicePixelRatio;
+ cx, cy = self.canvSize.width()*factor, self.canvSize.height()*factor
+
+ x_range = (cx + (2 * abs(panX)))/self.magnification
+ y_range = (cy + (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.canvasPixmap.fill()
+ preCanvas = painter
+
+ 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()
+
+ subprocess.Popen(args=self.getExternalEditor(asypath=self.filename));
+
+ 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:
+ editor = os.getenv("VISUAL")
+ if(editor == None) :
+ editor = os.getenv("EDITOR")
+ if(editor == None) :
+ rawExternalEditor = self.settings['externalEditor']
+ rawExtEditorArgs = self.settings['externalEditorArgs']
+ else:
+ s = editor.split()
+ rawExternalEditor = s[0]
+ rawExtEditorArgs = s[1:]+["$asypath"]
+
+ 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))
diff --git a/Build/source/utils/asymptote/GUI/__init__.py b/Build/source/utils/asymptote/GUI/__init__.py
new file mode 100644
index 00000000000..e5a0d9b4834
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/__init__.py
@@ -0,0 +1 @@
+#!/usr/bin/env python3
diff --git a/Build/source/utils/asymptote/GUI/configs/__init__.py b/Build/source/utils/asymptote/GUI/configs/__init__.py
new file mode 100644
index 00000000000..5f7ce86af66
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/configs/__init__.py
@@ -0,0 +1 @@
+#!/usr/bin/env python3 \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson b/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson
new file mode 100644
index 00000000000..c87f8c5b531
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson
@@ -0,0 +1,62 @@
+# Default Options for xasy
+
+# External editor. $asypath will be replaced by the current file.
+externalEditor: "vi"
+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
+
+# Overrides
+
+Windows:
+ externalEditor: "notepad.exe"
+
+Darwin:
+ externalEditor: "open"
+ externalEditorArgs: ["-a","TextEdit","$asypath"]
diff --git a/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson b/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson
new file mode 100644
index 00000000000..1e3e3b0a11e
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson
@@ -0,0 +1,26 @@
+# 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'
+moveLeft: 'Left'
+moveRight: 'Right'
+
+scrollUp: 'Shift+Up'
+scrollDown: 'Shift+Down'
+scrollLeft: 'Shift+Left'
+scrollRight: 'Shift+Right'
+
+zoomIn: 'Ctrl+Up'
+zoomOut: 'Ctrl+Down' \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/icons_rc.py b/Build/source/utils/asymptote/GUI/icons_rc.py
new file mode 100644
index 00000000000..5f463238c02
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/icons_rc.py
@@ -0,0 +1,2721 @@
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created by: The Resource Compiler for PyQt5 (Qt v5.12.5)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore
+
+qt_resource_data = b"\
+\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\x1c\
+\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\
+\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x27\x31\x2e\x31\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\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\
+\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\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\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\
+\x39\x39\x39\x37\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\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x32\
+\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\x36\
+\x32\x2e\x32\x33\x32\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\
+\x36\x32\x2e\x32\x33\x32\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\x35\
+\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\
+\x35\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\
+\x35\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\x34\x2e\x30\x31\x35\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\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\
+\x35\x38\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\
+\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x33\x32\x2e\x31\x32\x4c\x20\
+\x36\x32\x2e\x32\x33\x32\x35\x20\x2d\x33\x32\x2e\x31\x32\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\x34\x2e\x30\x31\x35\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\x35\
+\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\
+\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\x32\x2e\
+\x31\x32\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\x33\x32\x2e\x31\
+\x32\x20\x2d\x36\x32\x2e\x32\x33\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\x34\x2e\x30\x31\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\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\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\x04\xa2\
+\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\
+\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x27\x31\x2e\x31\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\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\
+\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\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\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\
+\x39\x39\x39\x37\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\
+\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x43\x20\x34\
+\x2e\x31\x35\x35\x35\x36\x20\x2d\x33\x39\x2e\x32\x37\x34\x35\x20\
+\x36\x2e\x39\x38\x34\x37\x33\x20\x2d\x34\x36\x2e\x31\x30\x34\x37\
+\x20\x31\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\
+\x39\x43\x20\x32\x37\x2e\x34\x34\x31\x31\x20\x2d\x36\x37\x2e\x37\
+\x32\x36\x39\x20\x35\x33\x2e\x33\x30\x32\x31\x20\x2d\x36\x31\x2e\
+\x35\x34\x30\x35\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\
+\x2e\x35\x30\x32\x32\x43\x20\x35\x37\x2e\x36\x32\x37\x20\x2d\x33\
+\x32\x2e\x36\x35\x31\x39\x20\x35\x30\x2e\x35\x38\x35\x36\x20\x2d\
+\x32\x33\x2e\x35\x36\x32\x31\x20\x34\x30\x2e\x36\x37\x39\x34\x20\
+\x2d\x32\x32\x2e\x35\x32\x38\x31\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\
+\x32\x2e\x35\x30\x39\x33\x37\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\x35\x38\x2e\x34\x36\
+\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x39\x35\x37\x33\
+\x35\x27\x20\x63\x79\x3d\x27\x2d\x33\x32\x2e\x31\x32\x27\x20\x66\
+\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\
+\x27\x36\x2e\x30\x32\x32\x35\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\x35\x38\x2e\x34\x36\
+\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x31\x31\x2e\x39\x30\x33\
+\x36\x27\x20\x63\x79\x3d\x27\x2d\x35\x31\x2e\x33\x30\x33\x39\x27\
+\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\
+\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\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\x35\x38\x2e\
+\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\
+\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x35\x36\x2e\x31\
+\x35\x32\x33\x27\x20\x63\x79\x3d\x27\x2d\x34\x32\x2e\x35\x30\x32\
+\x32\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\
+\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\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\x35\
+\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\
+\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x34\x30\
+\x2e\x36\x37\x39\x34\x27\x20\x63\x79\x3d\x27\x2d\x32\x32\x2e\x35\
+\x32\x38\x31\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\
+\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\
+\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\
+\x3e\
+\x00\x00\x04\x3d\
+\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\
+\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x27\x31\x2e\x31\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\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\
+\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\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\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\
+\x39\x39\x39\x37\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\
+\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x4c\x20\x31\
+\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\x39\x4c\
+\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\x2e\x35\x30\x32\
+\x32\x4c\x20\x34\x30\x2e\x36\x37\x39\x34\x20\x2d\x32\x32\x2e\x35\
+\x32\x38\x31\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\x32\x2e\x35\x30\x39\
+\x33\x37\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\
+\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\
+\x20\x63\x78\x3d\x27\x33\x2e\x39\x35\x37\x33\x35\x27\x20\x63\x79\
+\x3d\x27\x2d\x33\x32\x2e\x31\x32\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\
+\x32\x35\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\
+\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\
+\x20\x63\x78\x3d\x27\x31\x31\x2e\x39\x30\x33\x36\x27\x20\x63\x79\
+\x3d\x27\x2d\x35\x31\x2e\x33\x30\x33\x39\x27\x20\x66\x69\x6c\x6c\
+\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\
+\x30\x32\x32\x35\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\x35\x38\x2e\x34\x36\x36\x39\x20\
+\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\
+\x6c\x65\x20\x63\x78\x3d\x27\x35\x36\x2e\x31\x35\x32\x33\x27\x20\
+\x63\x79\x3d\x27\x2d\x34\x32\x2e\x35\x30\x32\x32\x27\x20\x66\x69\
+\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\
+\x36\x2e\x30\x32\x32\x35\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\x35\x38\x2e\x34\x36\x36\
+\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\
+\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x34\x30\x2e\x36\x37\x39\x34\
+\x27\x20\x63\x79\x3d\x27\x2d\x32\x32\x2e\x35\x32\x38\x31\x27\x20\
+\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\
+\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\
+\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\xf2\
+\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\x35\x31\x32\x70\x78\
+\x22\x20\x79\x3d\x22\x35\x31\x32\x70\x78\x22\x0d\x0a\x09\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\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\
+\x20\x30\x29\x27\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\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\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\x04\x4e\
+\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\
+\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x27\x31\x2e\x31\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\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\
+\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\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\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\
+\x39\x39\x39\x37\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\
+\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x4c\x20\x31\
+\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\x39\x4c\
+\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\x2e\x35\x30\x32\
+\x32\x4c\x20\x34\x30\x2e\x36\x37\x39\x34\x20\x2d\x32\x32\x2e\x35\
+\x32\x38\x31\x4c\x20\x33\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\
+\x2e\x31\x32\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\x32\x2e\x35\x30\
+\x39\x33\x37\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\
+\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\
+\x65\x20\x63\x78\x3d\x27\x33\x2e\x39\x35\x37\x33\x35\x27\x20\x63\
+\x79\x3d\x27\x2d\x33\x32\x2e\x31\x32\x27\x20\x66\x69\x6c\x6c\x3d\
+\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\
+\x32\x32\x35\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\
+\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\
+\x65\x20\x63\x78\x3d\x27\x31\x31\x2e\x39\x30\x33\x36\x27\x20\x63\
+\x79\x3d\x27\x2d\x35\x31\x2e\x33\x30\x33\x39\x27\x20\x66\x69\x6c\
+\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\
+\x2e\x30\x32\x32\x35\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\x35\x38\x2e\x34\x36\x36\x39\
+\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x63\x78\x3d\x27\x35\x36\x2e\x31\x35\x32\x33\x27\
+\x20\x63\x79\x3d\x27\x2d\x34\x32\x2e\x35\x30\x32\x32\x27\x20\x66\
+\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\
+\x27\x36\x2e\x30\x32\x32\x35\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\x35\x38\x2e\x34\x36\
+\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x34\x30\x2e\x36\x37\x39\
+\x34\x27\x20\x63\x79\x3d\x27\x2d\x32\x32\x2e\x35\x32\x38\x31\x27\
+\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\
+\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\
+\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x01\x69\
+\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\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\x3e\x3c\x67\x20\x74\x72\x61\
+\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x32\
+\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\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\x67\
+\x3e\x3c\x2f\x73\x76\x67\x3e\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\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\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\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\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\x36\
+\x34\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\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\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\x02\xa1\
+\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\x35\x31\x32\x70\x78\x22\x20\
+\x79\x3d\x22\x35\x31\x32\x70\x78\x22\x0d\x0a\x09\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\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\
+\x29\x27\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\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\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\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\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\x03\xe6\
+\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\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\x74\x72\
+\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\
+\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\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\x67\x3e\x0d\x0a\x3c\x2f\x73\
+\x76\x67\x3e\x0d\x0a\
+\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\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\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\x01\x1c\
+\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\x35\x31\
+\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x35\x31\x32\
+\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x34\x38\x20\x30\x20\x30\x20\x34\x38\x20\x34\
+\x38\x20\x34\x38\x29\x27\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\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\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\x21\
+\x00\
+\x00\x07\xaf\x78\x9c\xdd\x55\x4d\x6f\x9c\x30\x10\xbd\xf7\x57\x4c\
+\xd5\x83\xdb\x03\xc6\xdf\x86\x28\x24\x52\x57\xea\x29\xbd\x25\x97\
+\xde\x68\xf0\x82\x9b\x5d\x58\x01\x5d\xb6\xff\xbe\x66\xd7\x60\x4a\
+\xaa\xf4\x92\x43\x15\x90\x30\xf3\x18\xbf\x99\xe7\xf1\x98\xeb\xdb\
+\xd3\x7e\x07\x47\xd3\x76\xb6\xa9\x33\x44\x31\x41\x60\xea\xc7\xa6\
+\xb0\x75\x99\xa1\x87\xfb\x2f\x51\x82\x6e\x6f\xde\x5d\xbf\x8f\x22\
+\xb8\xaf\x6c\x07\x5b\xbb\x33\x30\xe4\x1d\x94\xa6\x36\x6d\xde\x9b\
+\x02\xbe\xff\x82\xe2\x68\xbb\x63\xb9\x07\x86\x13\x88\x22\xe7\xef\
+\xac\x25\x2b\x45\xe0\xe2\xd4\x5d\x86\xaa\xbe\x3f\x5c\xc5\xf1\x30\
+\x0c\x78\xe0\xb8\x69\xcb\x98\x11\x42\x62\xe7\xef\x5d\xae\x4e\x3b\
+\x5b\x3f\xfd\xcd\x91\xa6\x69\x1a\x9f\xbf\x22\x18\x6c\xd1\x57\x19\
+\x52\x1c\x3b\x50\x1d\x7a\x04\x95\xb1\x65\xd5\x4f\x90\x1e\xa1\xa3\
+\x35\xc3\xe7\xe6\x94\x21\xa9\xb0\x20\xa9\x00\xc9\x71\x22\x13\x0e\
+\x7e\x9a\x1f\x35\x72\x09\x97\x60\x8b\x0c\x1d\xf2\xd2\xd0\x8b\xd9\
+\xb7\x79\xdd\x6d\x9b\x76\x9f\xa1\x7d\xde\xb7\xf6\xf4\x91\x38\x67\
+\xc5\x94\x00\x32\xde\x93\x31\x71\x53\xaa\x47\xf2\x4f\xe3\xec\x43\
+\xde\x57\xe0\xe8\xbe\x42\x8a\xb9\xd0\x82\x41\xc4\x38\x26\x94\xde\
+\x05\xc0\xbf\x3c\x47\x36\xcf\x90\x7f\x03\x8b\x39\x12\x53\x29\x29\
+\x05\x9a\x62\x29\x38\x85\x88\x62\x2d\x95\x54\xc0\x19\xa6\x6c\x36\
+\x37\x20\x04\x56\xa9\x4a\x83\x83\x14\x38\x49\x99\x0a\x14\x33\x30\
+\xe7\xfa\x02\x32\x09\x9c\x01\xae\xb0\xd2\x42\x6e\x02\x22\x08\x4e\
+\x94\x4a\x42\x64\xf7\xc2\x94\x14\x53\x6a\xde\xdc\x84\xdc\x27\x87\
+\x59\xdd\x44\x31\x03\x3e\xca\xdd\x7a\xa5\xbf\xa1\x71\xab\xee\x32\
+\xf4\x41\x6f\xc7\x1b\xc5\xae\x2e\x71\xf9\x8a\xa5\x0d\x42\x53\xac\
+\x29\x49\x97\x42\xdd\xbe\x22\x9c\x2d\x84\x6a\xcc\x09\xd5\xb3\xd0\
+\x8b\xb9\x14\xea\x1d\x82\x50\x4f\x11\x84\x4e\x51\x02\x22\xb1\xa4\
+\x89\x0c\x24\x17\x76\x1f\xe3\x3c\x2c\xaa\x7c\x81\x43\xd2\x7e\xf2\
+\x5a\xc5\xbc\x6e\x75\x53\x1b\x04\x5d\xdf\x36\x4f\xc6\xad\x22\x39\
+\x5f\x13\x10\xb9\x2e\x34\x8f\xf9\x21\x43\x6d\xf3\xb3\x2e\xfe\x80\
+\x7f\x34\xb6\x5e\xe3\x7b\xdb\x9b\x76\x67\xdd\xe0\x4e\x03\x82\x09\
+\xd7\x72\xfe\xe6\x5b\x99\xbb\x7c\x38\x65\xaf\x5f\xa7\xf5\x0a\xbe\
+\xe1\x1e\xf4\x0a\xdf\x5c\x09\x5f\x68\x35\xc9\x30\x4b\xf4\xe2\x4c\
+\x51\x0c\x8b\x84\xcf\x67\x8a\x37\x17\xad\x36\x39\x84\x6a\x79\x8a\
+\xf5\x46\xf9\x6f\x96\xf1\xf2\x70\xbf\xc8\x9b\xdf\xf9\x80\xe2\xe1\
+\
+\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\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\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\x04\xd5\
+\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\
+\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x27\x31\x2e\x31\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\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\
+\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\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\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\
+\x39\x39\x39\x37\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\
+\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x43\x20\x32\
+\x2e\x32\x38\x39\x32\x32\x20\x2d\x33\x39\x2e\x33\x31\x31\x33\x20\
+\x36\x2e\x33\x36\x37\x30\x32\x20\x2d\x34\x36\x2e\x32\x33\x38\x36\
+\x20\x31\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\
+\x39\x43\x20\x32\x39\x2e\x36\x36\x38\x37\x20\x2d\x36\x37\x2e\x35\
+\x35\x36\x38\x20\x35\x35\x2e\x32\x32\x39\x32\x20\x2d\x36\x30\x2e\
+\x36\x34\x32\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\x2e\
+\x35\x30\x32\x32\x43\x20\x35\x36\x2e\x36\x31\x33\x36\x20\x2d\x33\
+\x33\x2e\x34\x33\x38\x31\x20\x34\x39\x2e\x31\x31\x33\x32\x20\x2d\
+\x32\x36\x2e\x35\x39\x35\x39\x20\x34\x30\x2e\x36\x37\x39\x34\x20\
+\x2d\x32\x32\x2e\x35\x32\x38\x31\x43\x20\x32\x35\x2e\x33\x39\x39\
+\x35\x20\x2d\x31\x35\x2e\x31\x35\x38\x32\x20\x37\x2e\x31\x39\x39\
+\x33\x35\x20\x2d\x31\x38\x2e\x31\x34\x33\x36\x20\x33\x2e\x39\x35\
+\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\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\x32\x2e\x35\x30\x39\x33\x37\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\x35\x38\
+\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\
+\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x39\
+\x35\x37\x33\x35\x27\x20\x63\x79\x3d\x27\x2d\x33\x32\x2e\x31\x32\
+\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\
+\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\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\x35\x38\
+\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\
+\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x31\x31\x2e\
+\x39\x30\x33\x36\x27\x20\x63\x79\x3d\x27\x2d\x35\x31\x2e\x33\x30\
+\x33\x39\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\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\
+\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\
+\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x35\
+\x36\x2e\x31\x35\x32\x33\x27\x20\x63\x79\x3d\x27\x2d\x34\x32\x2e\
+\x35\x30\x32\x32\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\
+\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\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\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\
+\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\
+\x27\x34\x30\x2e\x36\x37\x39\x34\x27\x20\x63\x79\x3d\x27\x2d\x32\
+\x32\x2e\x35\x32\x38\x31\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\
+\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\
+\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\
+\x73\x76\x67\x3e\
+\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\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\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\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x32\x34\x20\x30\x20\
+\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\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\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\
+\x3e\x0d\x0a\
+\x00\x00\x04\xaa\
+\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\x32\x34\x70\x78\x22\x20\x79\
+\x3d\x22\x32\x34\x70\x78\x22\x0d\x0a\x09\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\x74\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\
+\x28\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\
+\x3e\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\x67\x3e\x0d\
+\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x05\xd4\
+\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\
+\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x27\x31\x2e\x31\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\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\
+\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\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\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\
+\x39\x39\x39\x37\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\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x35\
+\x34\x2e\x38\x39\x32\x36\x20\x2d\x33\x39\x2e\x37\x31\x30\x39\x43\
+\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x34\x33\x2e\x39\x30\x33\
+\x32\x20\x34\x34\x2e\x36\x39\x36\x39\x20\x2d\x34\x37\x2e\x33\x30\
+\x31\x37\x20\x33\x32\x2e\x31\x32\x20\x2d\x34\x37\x2e\x33\x30\x31\
+\x37\x43\x20\x31\x39\x2e\x35\x34\x33\x31\x20\x2d\x34\x37\x2e\x33\
+\x30\x31\x37\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x34\x33\x2e\
+\x39\x30\x33\x32\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x33\x39\
+\x2e\x37\x31\x30\x39\x43\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\
+\x33\x35\x2e\x35\x31\x38\x35\x20\x31\x39\x2e\x35\x34\x33\x31\x20\
+\x2d\x33\x32\x2e\x31\x32\x20\x33\x32\x2e\x31\x32\x20\x2d\x33\x32\
+\x2e\x31\x32\x43\x20\x34\x34\x2e\x36\x39\x36\x39\x20\x2d\x33\x32\
+\x2e\x31\x32\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x33\x35\x2e\
+\x35\x31\x38\x35\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x33\x39\
+\x2e\x37\x31\x30\x39\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\x33\x2e\
+\x35\x31\x33\x31\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\x35\x36\x2e\x34\x30\x39\x34\
+\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x70\x61\x74\
+\x68\x20\x64\x3d\x27\x4d\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\
+\x33\x39\x2e\x37\x31\x30\x39\x4c\x20\x39\x2e\x33\x34\x37\x34\x32\
+\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x4c\x20\x39\x2e\x33\x34\x37\
+\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x43\x20\x39\x2e\x33\
+\x34\x37\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x20\x39\x2e\
+\x33\x34\x37\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x20\x39\
+\x2e\x33\x34\x37\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x43\
+\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x35\x2e\x31\x35\x35\x31\
+\x31\x20\x31\x39\x2e\x35\x34\x33\x31\x20\x2d\x31\x2e\x37\x35\x36\
+\x35\x36\x20\x33\x32\x2e\x31\x32\x20\x2d\x31\x2e\x37\x35\x36\x35\
+\x36\x43\x20\x34\x34\x2e\x36\x39\x36\x39\x20\x2d\x31\x2e\x37\x35\
+\x36\x35\x36\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x35\x2e\x31\
+\x35\x35\x31\x31\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x39\x2e\
+\x33\x34\x37\x34\x32\x4c\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\
+\x39\x2e\x33\x34\x37\x34\x32\x4c\x20\x35\x34\x2e\x38\x39\x32\x36\
+\x20\x2d\x33\x39\x2e\x37\x31\x30\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\x33\x2e\x35\x31\x33\x31\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\x35\x36\x2e\x34\
+\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\
+\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x35\x34\x2e\x38\x39\x32\
+\x36\x20\x2d\x33\x39\x2e\x37\x31\x30\x39\x43\x20\x35\x34\x2e\x38\
+\x39\x32\x36\x20\x2d\x35\x32\x2e\x32\x38\x37\x38\x20\x34\x34\x2e\
+\x36\x39\x36\x39\x20\x2d\x36\x32\x2e\x34\x38\x33\x34\x20\x33\x32\
+\x2e\x31\x32\x20\x2d\x36\x32\x2e\x34\x38\x33\x34\x43\x20\x31\x39\
+\x2e\x35\x34\x33\x31\x20\x2d\x36\x32\x2e\x34\x38\x33\x34\x20\x39\
+\x2e\x33\x34\x37\x34\x32\x20\x2d\x35\x32\x2e\x32\x38\x37\x38\x20\
+\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x33\x39\x2e\x37\x31\x30\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\x33\x2e\x35\x31\x33\x31\x32\x27\
+\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\
+\x76\x67\x3e\
+\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\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\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\xf5\
+\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\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\x74\x72\x61\
+\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x32\
+\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\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\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\
+\x67\x3e\x0d\x0a\
+\x00\x00\x03\x7c\
+\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\
+\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\
+\x6f\x6e\x3d\x27\x31\x2e\x31\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\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\
+\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\
+\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\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\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\
+\x39\x39\x39\x37\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\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x32\
+\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\x36\
+\x32\x2e\x32\x33\x32\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\
+\x36\x32\x2e\x32\x33\x32\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\x35\
+\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\
+\x35\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\
+\x35\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\x34\x2e\x30\x31\x35\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\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\
+\x35\x38\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\
+\x20\x34\x37\x2e\x31\x37\x36\x32\x20\x2d\x33\x32\x2e\x31\x32\x43\
+\x20\x34\x37\x2e\x31\x37\x36\x32\x20\x2d\x34\x30\x2e\x34\x33\x35\
+\x33\x20\x34\x30\x2e\x34\x33\x35\x33\x20\x2d\x34\x37\x2e\x31\x37\
+\x36\x32\x20\x33\x32\x2e\x31\x32\x20\x2d\x34\x37\x2e\x31\x37\x36\
+\x32\x43\x20\x32\x33\x2e\x38\x30\x34\x37\x20\x2d\x34\x37\x2e\x31\
+\x37\x36\x32\x20\x31\x37\x2e\x30\x36\x33\x37\x20\x2d\x34\x30\x2e\
+\x34\x33\x35\x33\x20\x31\x37\x2e\x30\x36\x33\x37\x20\x2d\x33\x32\
+\x2e\x31\x32\x43\x20\x31\x37\x2e\x30\x36\x33\x37\x20\x2d\x32\x33\
+\x2e\x38\x30\x34\x37\x20\x32\x33\x2e\x38\x30\x34\x37\x20\x2d\x31\
+\x37\x2e\x30\x36\x33\x37\x20\x33\x32\x2e\x31\x32\x20\x2d\x31\x37\
+\x2e\x30\x36\x33\x37\x43\x20\x34\x30\x2e\x34\x33\x35\x33\x20\x2d\
+\x31\x37\x2e\x30\x36\x33\x37\x20\x34\x37\x2e\x31\x37\x36\x32\x20\
+\x2d\x32\x33\x2e\x38\x30\x34\x37\x20\x34\x37\x2e\x31\x37\x36\x32\
+\x20\x2d\x33\x32\x2e\x31\x32\x5a\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\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\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\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\x09\
+\x0b\x9e\x89\x07\
+\x00\x63\
+\x00\x68\x00\x65\x00\x63\x00\x6b\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\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\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\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\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\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\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\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\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\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\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\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\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\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\x08\
+\x08\xc8\x55\xe7\
+\x00\x73\
+\x00\x61\x00\x76\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\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\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\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\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\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\x07\
+\x0c\xf8\x5a\x07\
+\x00\x65\
+\x00\x79\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\x08\
+\x0c\xf7\x55\x87\
+\x00\x74\
+\x00\x65\x00\x78\x00\x74\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\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\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\x08\
+\x08\xf7\x57\x07\
+\x00\x67\
+\x00\x72\x00\x69\x00\x64\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\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\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\x08\
+\x05\xa8\x57\x87\
+\x00\x63\
+\x00\x6f\x00\x64\x00\x65\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\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\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\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\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\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\x03\xba\x00\x00\x00\x00\x00\x01\x00\x00\x4e\x94\
+\x00\x00\x05\x64\x00\x00\x00\x00\x00\x01\x00\x00\x7a\x42\
+\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x19\x83\
+\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\x2a\x5e\
+\x00\x00\x05\xf4\x00\x00\x00\x00\x00\x01\x00\x00\x86\xcf\
+\x00\x00\x04\x6e\x00\x01\x00\x00\x00\x01\x00\x00\x62\xf8\
+\x00\x00\x04\x94\x00\x00\x00\x00\x00\x01\x00\x00\x65\x1d\
+\x00\x00\x04\xfc\x00\x00\x00\x00\x00\x01\x00\x00\x6c\xf3\
+\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xa6\
+\x00\x00\x05\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x75\x94\
+\x00\x00\x01\x44\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x04\
+\x00\x00\x02\x46\x00\x00\x00\x00\x00\x01\x00\x00\x32\x88\
+\x00\x00\x01\xa8\x00\x00\x00\x00\x00\x01\x00\x00\x24\x90\
+\x00\x00\x03\x7a\x00\x00\x00\x00\x00\x01\x00\x00\x4a\xaa\
+\x00\x00\x00\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x12\x4c\
+\x00\x00\x03\x46\x00\x00\x00\x00\x00\x01\x00\x00\x47\x54\
+\x00\x00\x03\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x5a\x07\
+\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x80\
+\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x50\
+\x00\x00\x02\x7a\x00\x00\x00\x00\x00\x01\x00\x00\x37\x56\
+\x00\x00\x02\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x3a\x56\
+\x00\x00\x01\xfa\x00\x00\x00\x00\x00\x01\x00\x00\x2d\x88\
+\x00\x00\x04\xbe\x00\x01\x00\x00\x00\x01\x00\x00\x68\x57\
+\x00\x00\x05\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x80\x1a\
+\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x16\x8d\
+\x00\x00\x02\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x40\x6b\
+\x00\x00\x06\x32\x00\x00\x00\x00\x00\x01\x00\x00\x8a\xc8\
+\x00\x00\x02\xce\x00\x00\x00\x00\x00\x01\x00\x00\x3c\xfb\
+\x00\x00\x00\x72\x00\x00\x00\x00\x00\x01\x00\x00\x07\x70\
+\x00\x00\x02\x20\x00\x00\x00\x00\x00\x01\x00\x00\x30\x05\
+\x00\x00\x03\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x42\xec\
+\x00\x00\x01\x66\x00\x00\x00\x00\x00\x01\x00\x00\x1e\xd1\
+\x00\x00\x04\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x6a\x38\
+\x00\x00\x04\x20\x00\x00\x00\x00\x00\x01\x00\x00\x5c\xad\
+\x00\x00\x03\xe2\x00\x00\x00\x00\x00\x01\x00\x00\x56\x18\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x23\x23\
+\x00\x00\x05\x20\x00\x00\x00\x00\x00\x01\x00\x00\x71\xcc\
+\x00\x00\x05\xa2\x00\x00\x00\x00\x00\x01\x00\x00\x83\x64\
+\x00\x00\x05\xd2\x00\x00\x00\x00\x00\x01\x00\x00\x83\xd4\
+\x00\x00\x04\x36\x00\x00\x00\x00\x00\x01\x00\x00\x5d\xcd\
+"
+
+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\x03\xba\x00\x00\x00\x00\x00\x01\x00\x00\x4e\x94\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x05\x64\x00\x00\x00\x00\x00\x01\x00\x00\x7a\x42\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x01\x12\x00\x00\x00\x00\x00\x01\x00\x00\x19\x83\
+\x00\x00\x01\x77\xb9\x14\x85\x49\
+\x00\x00\x01\xce\x00\x00\x00\x00\x00\x01\x00\x00\x2a\x5e\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x05\xf4\x00\x00\x00\x00\x00\x01\x00\x00\x86\xcf\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x04\x6e\x00\x01\x00\x00\x00\x01\x00\x00\x62\xf8\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x04\x94\x00\x00\x00\x00\x00\x01\x00\x00\x65\x1d\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x04\xfc\x00\x00\x00\x00\x00\x01\x00\x00\x6c\xf3\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x00\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xa6\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x05\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x75\x94\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x01\x44\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x04\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x02\x46\x00\x00\x00\x00\x00\x01\x00\x00\x32\x88\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x01\xa8\x00\x00\x00\x00\x00\x01\x00\x00\x24\x90\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x03\x7a\x00\x00\x00\x00\x00\x01\x00\x00\x4a\xaa\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x00\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x12\x4c\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x03\x46\x00\x00\x00\x00\x00\x01\x00\x00\x47\x54\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x03\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x5a\x07\
+\x00\x00\x01\x77\xb9\x14\x85\x49\
+\x00\x00\x00\x8a\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x80\
+\x00\x00\x01\x77\xb9\x14\x85\x49\
+\x00\x00\x00\x4c\x00\x00\x00\x00\x00\x01\x00\x00\x03\x50\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x02\x7a\x00\x00\x00\x00\x00\x01\x00\x00\x37\x56\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x02\xb8\x00\x00\x00\x00\x00\x01\x00\x00\x3a\x56\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x01\xfa\x00\x00\x00\x00\x00\x01\x00\x00\x2d\x88\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x04\xbe\x00\x01\x00\x00\x00\x01\x00\x00\x68\x57\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x05\x7e\x00\x00\x00\x00\x00\x01\x00\x00\x80\x1a\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x16\x8d\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x02\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x40\x6b\
+\x00\x00\x01\x77\xb9\x14\x85\x49\
+\x00\x00\x06\x32\x00\x00\x00\x00\x00\x01\x00\x00\x8a\xc8\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x02\xce\x00\x00\x00\x00\x00\x01\x00\x00\x3c\xfb\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x00\x72\x00\x00\x00\x00\x00\x01\x00\x00\x07\x70\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x02\x20\x00\x00\x00\x00\x00\x01\x00\x00\x30\x05\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x03\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x42\xec\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x01\x66\x00\x00\x00\x00\x00\x01\x00\x00\x1e\xd1\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x04\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x6a\x38\
+\x00\x00\x01\x77\xb9\x14\x85\x49\
+\x00\x00\x04\x20\x00\x00\x00\x00\x00\x01\x00\x00\x5c\xad\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x03\xe2\x00\x00\x00\x00\x00\x01\x00\x00\x56\x18\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x77\xb9\x14\x85\x4a\
+\x00\x00\x01\x8e\x00\x00\x00\x00\x00\x01\x00\x00\x23\x23\
+\x00\x00\x01\x77\xb9\x14\x85\x49\
+\x00\x00\x05\x20\x00\x00\x00\x00\x00\x01\x00\x00\x71\xcc\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x05\xa2\x00\x00\x00\x00\x00\x01\x00\x00\x83\x64\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x05\xd2\x00\x00\x00\x00\x00\x01\x00\x00\x83\xd4\
+\x00\x00\x01\x77\xb9\x14\x85\x4b\
+\x00\x00\x04\x36\x00\x00\x00\x00\x00\x01\x00\x00\x5d\xcd\
+\x00\x00\x01\x77\xb9\x14\x85\x49\
+"
+
+qt_version = [int(v) for v in 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()
diff --git a/Build/source/utils/asymptote/GUI/labelEditor.py b/Build/source/utils/asymptote/GUI/labelEditor.py
new file mode 100644
index 00000000000..76bc8d7d0a1
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/labelEditor.py
@@ -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_()
diff --git a/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po b/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po
new file mode 100644
index 00000000000..507fd335610
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/locale/th/LC_MESSAGES/base.po
@@ -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@ualberta.ca>\n"
+"Language-Team: English <kde-i18n-doc@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 "หมุน"
+
+
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py b/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py
new file mode 100644
index 00000000000..d0bddd46458
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py
@@ -0,0 +1,174 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/custMatTransform.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py b/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py
new file mode 100644
index 00000000000..3cb24c9e2fe
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py
@@ -0,0 +1,120 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/labelTextEditor.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py b/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py
new file mode 100644
index 00000000000..9b76e5d6d0e
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py
@@ -0,0 +1,56 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/setCustomAnchor.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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"))
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py
new file mode 100644
index 00000000000..0412fc550d5
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_addLabel.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
new file mode 100644
index 00000000000..2c91681bce6
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_addPolyOpt.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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"))
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py b/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py
new file mode 100644
index 00000000000..d39e49e4b98
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_editBezier.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py b/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py
new file mode 100644
index 00000000000..a38790bdecd
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widgetPointEditor.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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
diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/window1.py b/Build/source/utils/asymptote/GUI/pyUIClass/window1.py
new file mode 100644
index 00000000000..6180d5fed3f
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/pyUIClass/window1.py
@@ -0,0 +1,964 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/window1.ui'
+#
+# Created by: PyQt5 UI code generator 5.13.1
+#
+# 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(1000, 600)
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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(24, 24))
+ self.btnViewCode.setBaseSize(QtCore.QSize(20, 20))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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.setIconSize(QtCore.QSize(16, 16))
+ 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, 1000, 29))
+ 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", "Zoom"))
+ 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", "Center"))
+ self.comboAnchor.setItemText(0, _translate("MainWindow", "Center"))
+ self.comboAnchor.setItemText(1, _translate("MainWindow", "Origin"))
+ 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
diff --git a/Build/source/utils/asymptote/GUI/requirements.txt b/Build/source/utils/asymptote/GUI/requirements.txt
new file mode 100644
index 00000000000..47966fe275d
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/requirements.txt
@@ -0,0 +1,4 @@
+numpy==1.11.0
+cson==0.7
+PyQt5==5.11
+rsvg-convert==2.42.3
diff --git a/Build/source/utils/asymptote/GUI/res/icons.qrc b/Build/source/utils/asymptote/GUI/res/icons.qrc
new file mode 100644
index 00000000000..50928ef9b74
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons.qrc
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/anchor.svg b/Build/source/utils/asymptote/GUI/res/icons/anchor.svg
new file mode 100644
index 00000000000..1f10fc544af
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/anchor.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="512px" height="512px" viewBox="0 0 512 512"><g transform='matrix(24 0 0 24 0 0)'><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"/></g></svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg b/Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg
new file mode 100644
index 00000000000..79cfe814a1b
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-arrow-back.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg b/Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg
new file mode 100644
index 00000000000..d63794dcc0a
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-arrow-forward.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-camera.svg b/Build/source/utils/asymptote/GUI/res/icons/android-camera.svg
new file mode 100644
index 00000000000..73aeaabe49c
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-camera.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-close.svg b/Build/source/utils/asymptote/GUI/res/icons/android-close.svg
new file mode 100644
index 00000000000..aee0f9f630e
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-close.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg b/Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg
new file mode 100644
index 00000000000..d700fe6b9d2
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-color-palette.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-delete.svg b/Build/source/utils/asymptote/GUI/res/icons/android-delete.svg
new file mode 100644
index 00000000000..49cfa5ade43
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-delete.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-done.svg b/Build/source/utils/asymptote/GUI/res/icons/android-done.svg
new file mode 100644
index 00000000000..4bcb946f058
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-done.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-expand.svg b/Build/source/utils/asymptote/GUI/res/icons/android-expand.svg
new file mode 100644
index 00000000000..51be003c07a
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-expand.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg b/Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg
new file mode 100644
index 00000000000..fa77fea2154
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-folder-open.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-hand.svg b/Build/source/utils/asymptote/GUI/res/icons/android-hand.svg
new file mode 100644
index 00000000000..5035d875be1
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-hand.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-locate.svg b/Build/source/utils/asymptote/GUI/res/icons/android-locate.svg
new file mode 100644
index 00000000000..e2dd098cbd3
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-locate.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg b/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg
new file mode 100644
index 00000000000..d36fa657c03
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-off.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg b/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg
new file mode 100644
index 00000000000..1f7f54c0f24
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-radio-button-on.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg b/Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg
new file mode 100644
index 00000000000..066f7d22c6b
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/android-refresh.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg b/Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg
new file mode 100644
index 00000000000..1d4263f45a2
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/arrow-move.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg b/Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg
new file mode 100644
index 00000000000..a9c3b3cc140
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/arrow-resize.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/bucket.asy b/Build/source/utils/asymptote/GUI/res/icons/bucket.asy
new file mode 100644
index 00000000000..87447436981
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/bucket.asy
@@ -0,0 +1,26 @@
+// Empty bucket: asy bucket -f svg
+// Filled bucket: asy bucket -f svg -u fill=true -o filledbucket
+
+defaultpen(3.5);
+
+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));
+
+shipout(pad(64,64));
diff --git a/Build/source/utils/asymptote/GUI/res/icons/bucket.svg b/Build/source/utils/asymptote/GUI/res/icons/bucket.svg
new file mode 100644
index 00000000000..4a41e9873b2
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/bucket.svg
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 54.8926 -39.7109C 54.8926 -43.9032 44.6969 -47.3017 32.12 -47.3017C 19.5431 -47.3017 9.34742 -43.9032 9.34742 -39.7109C 9.34742 -35.5185 19.5431 -32.12 32.12 -32.12C 44.6969 -32.12 54.8926 -35.5185 54.8926 -39.7109Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 9.34742 -39.7109L 9.34742 -9.34742L 9.34742 -9.34742C 9.34742 -9.34742 9.34742 -9.34742 9.34742 -9.34742C 9.34742 -5.15511 19.5431 -1.75656 32.12 -1.75656C 44.6969 -1.75656 54.8926 -5.15511 54.8926 -9.34742L 54.8926 -9.34742L 54.8926 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 54.8926 -39.7109C 54.8926 -52.2878 44.6969 -62.4834 32.12 -62.4834C 19.5431 -62.4834 9.34742 -52.2878 9.34742 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/center.asy b/Build/source/utils/asymptote/GUI/res/icons/center.asy
new file mode 100644
index 00000000000..6241190ebb5
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/center.asy
@@ -0,0 +1,6 @@
+defaultpen(4);
+
+draw(scale(2)*shift(-0.5,-0.5)*unitsquare);
+fill(scale(0.5)*unitcircle);
+
+shipout(pad(64,64));
diff --git a/Build/source/utils/asymptote/GUI/res/icons/center.svg b/Build/source/utils/asymptote/GUI/res/icons/center.svg
new file mode 100644
index 00000000000..9a7cb1b17d7
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/center.svg
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 2.0075 -2.0075L 62.2325 -2.0075L 62.2325 -62.2325L 2.0075 -62.2325L 2.0075 -2.0075Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 47.1762 -32.12C 47.1762 -40.4353 40.4353 -47.1762 32.12 -47.1762C 23.8047 -47.1762 17.0637 -40.4353 17.0637 -32.12C 17.0637 -23.8047 23.8047 -17.0637 32.12 -17.0637C 40.4353 -17.0637 47.1762 -23.8047 47.1762 -32.12Z' fill='#000000'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy b/Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy
new file mode 100644
index 00000000000..49205ead816
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/centerorigin.asy
@@ -0,0 +1,7 @@
+defaultpen(4);
+
+draw(scale(2)*shift(-0.5,-0.5)*unitsquare);
+draw((-1,0)--(1,0));
+draw((0,-1)--(0,1));
+
+shipout(pad(64,64));
diff --git a/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg b/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg
new file mode 100644
index 00000000000..ee3cca26293
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg
@@ -0,0 +1,15 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 2.0075 -2.0075L 62.2325 -2.0075L 62.2325 -62.2325L 2.0075 -62.2325L 2.0075 -2.0075Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 2.0075 -32.12L 62.2325 -32.12' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 32.12 -2.0075L 32.12 -62.2325' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/check.svg b/Build/source/utils/asymptote/GUI/res/icons/check.svg
new file mode 100644
index 00000000000..08ee56d87de
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/check.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg b/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg
new file mode 100644
index 00000000000..4035c688e8f
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-left.svg
@@ -0,0 +1,13 @@
+<?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 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g transform='matrix(24 0 0 24 0 0)'>
+<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"/>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg b/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg
new file mode 100644
index 00000000000..f6e3a5e89c7
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/chevron-with-circle-right.svg
@@ -0,0 +1,13 @@
+<?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 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g transform='matrix(24 0 0 24 0 0)'>
+<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"/>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/circle.svg b/Build/source/utils/asymptote/GUI/res/icons/circle.svg
new file mode 100644
index 00000000000..e344602bcbe
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/circle.svg
@@ -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="Circle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="512px" y="512px"
+ viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g transform='matrix(24 0 0 24 0 0)'>
+<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"/>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/close-round.svg b/Build/source/utils/asymptote/GUI/res/icons/close-round.svg
new file mode 100644
index 00000000000..d8b5554c5c1
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/close-round.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy
new file mode 100644
index 00000000000..80e70619717
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy
@@ -0,0 +1,7 @@
+defaultpen(2.5);
+
+path p=W..NW..ENE..0.5*SE..cycle;
+draw(p);
+dot(p,linewidth(12));
+
+shipout(pad(64,64));
diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg
new file mode 100644
index 00000000000..32cf982cf1c
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg
@@ -0,0 +1,21 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<path d='M 3.95735 -32.12C 2.28922 -39.3113 6.36702 -46.2386 11.9036 -51.3039C 29.6687 -67.5568 55.2292 -60.642 56.1523 -42.5022C 56.6136 -33.4381 49.1132 -26.5959 40.6794 -22.5281C 25.3995 -15.1582 7.19935 -18.1436 3.95735 -32.12Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy
new file mode 100644
index 00000000000..612bdcf010a
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy
@@ -0,0 +1,7 @@
+defaultpen(2.5);
+
+path p=W--NW--ENE--0.5*SE--cycle;
+draw(p);
+dot(p,linewidth(12));
+
+shipout(pad(64,64));
diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg
new file mode 100644
index 00000000000..89e2c5f2303
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg
@@ -0,0 +1,21 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<path d='M 3.95735 -32.12L 11.9036 -51.3039L 56.1523 -42.5022L 40.6794 -22.5281L 3.95735 -32.12Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/code.svg b/Build/source/utils/asymptote/GUI/res/icons/code.svg
new file mode 100644
index 00000000000..b62357776a9
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/code.svg
@@ -0,0 +1,14 @@
+<?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="24px" y="24px"
+ viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g transform='matrix(24 0 0 24 0 0)'><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"/>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/edit.svg b/Build/source/utils/asymptote/GUI/res/icons/edit.svg
new file mode 100644
index 00000000000..a0be3454e12
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/edit.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/eye.svg b/Build/source/utils/asymptote/GUI/res/icons/eye.svg
new file mode 100644
index 00000000000..6b64633fce1
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/eye.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg b/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg
new file mode 100644
index 00000000000..d2197375b9f
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg
@@ -0,0 +1,18 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 9.34742 -23.011L 9.34742 -9.34742L 9.34742 -9.34742C 9.34742 -9.34742 9.34742 -9.34742 9.34742 -9.34742C 9.34742 -5.15511 19.5431 -1.75656 32.12 -1.75656C 44.6969 -1.75656 54.8926 -5.15511 54.8926 -9.34742L 54.8926 -9.34742L 54.8926 -23.011L 54.8926 -36.6745C 54.8926 -40.8668 44.6969 -44.2654 32.12 -44.2654C 19.5431 -44.2654 9.34742 -40.8668 9.34742 -36.6745L 9.34742 -23.011Z' fill='#7f7f7f'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 54.8926 -39.7109C 54.8926 -43.9032 44.6969 -47.3017 32.12 -47.3017C 19.5431 -47.3017 9.34742 -43.9032 9.34742 -39.7109C 9.34742 -35.5185 19.5431 -32.12 32.12 -32.12C 44.6969 -32.12 54.8926 -35.5185 54.8926 -39.7109Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 9.34742 -39.7109L 9.34742 -9.34742L 9.34742 -9.34742C 9.34742 -9.34742 9.34742 -9.34742 9.34742 -9.34742C 9.34742 -5.15511 19.5431 -1.75656 32.12 -1.75656C 44.6969 -1.75656 54.8926 -5.15511 54.8926 -9.34742L 54.8926 -9.34742L 54.8926 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'>
+<path d='M 54.8926 -39.7109C 54.8926 -52.2878 44.6969 -62.4834 32.12 -62.4834C 19.5431 -62.4834 9.34742 -52.2878 9.34742 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/grid.svg b/Build/source/utils/asymptote/GUI/res/icons/grid.svg
new file mode 100644
index 00000000000..456e5011317
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/grid.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg b/Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg
new file mode 100644
index 00000000000..1e93ba4f952
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/magnifying-glass.svg
@@ -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="Magnifying_glass" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
+ y="0px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g transform='matrix(24 0 0 24 0 0)'>
+<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"/>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy b/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy
new file mode 100644
index 00000000000..e8fca0f2e81
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy
@@ -0,0 +1,7 @@
+defaultpen(2.5);
+
+path p=W..NW..ENE..0.5*SE;
+draw(p);
+dot(p,linewidth(12));
+
+shipout(pad(64,64));
diff --git a/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg b/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg
new file mode 100644
index 00000000000..3c02ba29060
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg
@@ -0,0 +1,21 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<path d='M 3.95735 -32.12C 4.15556 -39.2745 6.98473 -46.1047 11.9036 -51.3039C 27.4411 -67.7269 53.3021 -61.5405 56.1523 -42.5022C 57.627 -32.6519 50.5856 -23.5621 40.6794 -22.5281' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy
new file mode 100644
index 00000000000..22f7b09da72
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy
@@ -0,0 +1,7 @@
+defaultpen(2.5);
+
+path p=W--NW--ENE--0.5*SE;
+draw(p);
+dot(p,linewidth(12));
+
+shipout(pad(64,64));
diff --git a/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg
new file mode 100644
index 00000000000..5386aa64332
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg
@@ -0,0 +1,21 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.8 -->
+<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<path d='M 3.95735 -32.12L 11.9036 -51.3039L 56.1523 -42.5022L 40.6794 -22.5281' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'>
+<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/>
+</g>
+</g>
+</svg> \ No newline at end of file
diff --git a/Build/source/utils/asymptote/GUI/res/icons/plus-round.svg b/Build/source/utils/asymptote/GUI/res/icons/plus-round.svg
new file mode 100644
index 00000000000..465d937802b
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/plus-round.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/save.svg b/Build/source/utils/asymptote/GUI/res/icons/save.svg
new file mode 100644
index 00000000000..7f9cbd56d3f
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/save.svg
@@ -0,0 +1,10 @@
+<?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="512px" y="512px"
+ viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g transform='matrix(24 0 0 24 0 0)'>
+<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"/>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/social-python.svg b/Build/source/utils/asymptote/GUI/res/icons/social-python.svg
new file mode 100644
index 00000000000..35fcdde7c10
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/social-python.svg
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg b/Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg
new file mode 100644
index 00000000000..bbbf3336529
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/subdirectory-left.svg
@@ -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
diff --git a/Build/source/utils/asymptote/GUI/res/icons/text.svg b/Build/source/utils/asymptote/GUI/res/icons/text.svg
new file mode 100644
index 00000000000..90ea4c07bdb
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/text.svg
@@ -0,0 +1,6 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="512px" height="512px"
+ viewBox="0 0 512 512">
+<g transform='matrix(48 0 0 48 48 48)'>
+ <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" />
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg b/Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg
new file mode 100644
index 00000000000..b9320724ab7
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/res/icons/triangle-stroked-15.svg
@@ -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="64px" height="64px"
+ 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>
diff --git a/Build/source/utils/asymptote/GUI/setup.py b/Build/source/utils/asymptote/GUI/setup.py
new file mode 100644
index 00000000000..e49e3468d7f
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/setup.py
@@ -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="https://asymptote.sourceforge.io",
+ download_url="https://sourceforge.net/projects/asymptote/"
+)
diff --git a/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui b/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui
new file mode 100644
index 00000000000..4612f277c94
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/custMatTransform.ui
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui b/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui
new file mode 100644
index 00000000000..06cd31bd1ae
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/labelTextEditor.ui
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui b/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui
new file mode 100644
index 00000000000..5a4b14676e6
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/setCustomAnchor.ui
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui b/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui
new file mode 100644
index 00000000000..40bc4ddc602
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/widg_addLabel.ui
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui b/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui
new file mode 100644
index 00000000000..b8bde4236a9
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui b/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui
new file mode 100644
index 00000000000..cca3aaaa2d9
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/widg_editBezier.ui
@@ -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 &amp; 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>
diff --git a/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui b/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui
new file mode 100644
index 00000000000..c3e486ad5a6
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/widgetPointEditor.ui
@@ -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>
diff --git a/Build/source/utils/asymptote/GUI/windows/window1.ui b/Build/source/utils/asymptote/GUI/windows/window1.ui
new file mode 100644
index 00000000000..ed7c964e154
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/windows/window1.ui
@@ -0,0 +1,2198 @@
+<?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>1000</width>
+ <height>600</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 resource="../res/icons.qrc">
+ <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 resource="../res/icons.qrc">
+ <normaloff>:/icons/android-arrow-forward.svg</normaloff>:/icons/android-arrow-forward.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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Open file&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-folder-open.svg</normaloff>:/icons/android-folder-open.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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Save file&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/save.svg</normaloff>:/icons/save.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="btnViewCode">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>24</width>
+ <height>24</height>
+ </size>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ <property name="toolTip">
+ <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Edit code&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/code.svg</normaloff>:/icons/code.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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Screenshot&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-camera.svg</normaloff>:/icons/android-camera.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>
+ <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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Toggle display axes&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/plus-round.svg</normaloff>:/icons/plus-round.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Toggle grid&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/grid.svg</normaloff>:/icons/grid.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>Zoom</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/magnifying-glass.svg</normaloff>:/icons/magnifying-glass.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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Center&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/center.svg</normaloff>:/icons/center.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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Center about origin&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/centerorigin.svg</normaloff>:/icons/centerorigin.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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Lock transform to X axis&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>X</string>
+ </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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Lock transform to Y axis&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string>Y</string>
+ </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>
+ <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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Bézier editor&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </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="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Delete&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-delete.svg</normaloff>:/icons/android-delete.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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 resource="../res/icons.qrc">
+ <normaloff>:/icons/android-hand.svg</normaloff>:/icons/android-hand.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="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 resource="../res/icons.qrc">
+ <normaloff>:/icons/arrow-move.svg</normaloff>:/icons/arrow-move.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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 resource="../res/icons.qrc">
+ <normaloff>:/icons/arrow-resize.svg</normaloff>:/icons/arrow-resize.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="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 resource="../res/icons.qrc">
+ <normaloff>:/icons/android-refresh.svg</normaloff>:/icons/android-refresh.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>
+ <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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set custom anchor&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/anchor.svg</normaloff>:/icons/anchor.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Anchor&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="layoutDirection">
+ <enum>Qt::LeftToRight</enum>
+ </property>
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ <property name="currentText">
+ <string>Center</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>Center</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Origin</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 resource="../res/icons.qrc">
+ <normaloff>:/icons/eye.svg</normaloff>:/icons/eye.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/android-expand.svg</normaloff>:/icons/android-expand.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="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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/chevron-with-circle-left.svg</normaloff>:/icons/chevron-with-circle-left.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="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 resource="../res/icons.qrc">
+ <normaloff>:/icons/chevron-with-circle-right.svg</normaloff>:/icons/chevron-with-circle-right.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>
+ <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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Toggle fill/outline&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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 resource="../res/icons.qrc">
+ <normaloff>:/icons/bucket.svg</normaloff>
+ <normalon>:/icons/filledbucket.svg</normalon>:/icons/bucket.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Current pen width&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Current pen color&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Set color&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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 resource="../res/icons.qrc">
+ <normaloff>:/icons/android-color-palette.svg</normaloff>:/icons/android-color-palette.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Open polygon&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/openpolygon.svg</normaloff>:/icons/openpolygon.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 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Closed polygon&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/closedpolygon.svg</normaloff>:/icons/closedpolygon.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 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Open Bézier curve&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/opencurve.svg</normaloff>:/icons/opencurve.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 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Closed Bézier curve&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/closedcurve.svg</normaloff>:/icons/closedcurve.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 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Regular polygon&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/triangle-stroked-15.svg</normaloff>:/icons/triangle-stroked-15.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 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Circle&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../res/icons.qrc">
+ <normaloff>:/icons/circle.svg</normaloff>:/icons/circle.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 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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Text&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+ </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="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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 resource="../res/icons.qrc">
+ <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 resource="../res/icons.qrc">
+ <normaloff>:/icons/subdirectory-left.svg</normaloff>:/icons/subdirectory-left.svg</iconset>
+ </property>
+ <property name="iconSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </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>1000</width>
+ <height>29</height>
+ </rect>
+ </property>
+ <widget class="QMenu" name="menuFIle">
+ <property name="title">
+ <string>&amp;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>&amp;Edit</string>
+ </property>
+ <addaction name="actionUndo"/>
+ <addaction name="actionRedo"/>
+ <addaction name="separator"/>
+ </widget>
+ <widget class="QMenu" name="menuOptions">
+ <property name="title">
+ <string>Optio&amp;ns</string>
+ </property>
+ <addaction name="actionSettings"/>
+ </widget>
+ <widget class="QMenu" name="menuHelp">
+ <property name="title">
+ <string>&amp;Help</string>
+ </property>
+ <addaction name="actionManual"/>
+ <addaction name="actionAbout"/>
+ </widget>
+ <widget class="QMenu" name="menuTools">
+ <property name="title">
+ <string>&amp;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>&amp;About</string>
+ </property>
+ </action>
+ <action name="actionManual">
+ <property name="text">
+ <string>&amp;Manual</string>
+ </property>
+ </action>
+ <action name="actionSettings">
+ <property name="text">
+ <string>&amp;Settings</string>
+ </property>
+ </action>
+ <action name="actionPause">
+ <property name="text">
+ <string>Pause </string>
+ </property>
+ </action>
+ <action name="actionSaveAs">
+ <property name="text">
+ <string>&amp;Save As</string>
+ </property>
+ </action>
+ <action name="actionEnterCommand">
+ <property name="text">
+ <string>&amp;Enter Command</string>
+ </property>
+ </action>
+ <action name="actionQuit">
+ <property name="text">
+ <string>&amp;Quit</string>
+ </property>
+ </action>
+ <action name="actionUndo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Undo</string>
+ </property>
+ </action>
+ <action name="actionRedo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Redo</string>
+ </property>
+ </action>
+ <action name="actionShow_Grid">
+ <property name="text">
+ <string>&amp;Show Grid</string>
+ </property>
+ </action>
+ <action name="actionShow_Local_Grid">
+ <property name="text">
+ <string>Show &amp;Local Grid</string>
+ </property>
+ </action>
+ <action name="actionTransform">
+ <property name="text">
+ <string>&amp;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>
diff --git a/Build/source/utils/asymptote/GUI/xasy.py b/Build/source/utils/asymptote/GUI/xasy.py
new file mode 100755
index 00000000000..7a8ee9b2f71
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasy.py
@@ -0,0 +1,19 @@
+#!/usr/bin/env python3
+
+import sys,signal,os
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtCore as Qc
+from Window1 import MainWindow1
+
+def main(args):
+ Qw.QApplication.setAttribute(Qc.Qt.AA_UseHighDpiPixmaps,True)
+ Qw.QApplication.setAttribute(Qc.Qt.AA_EnableHighDpiScaling,True)
+ qtApp = Qw.QApplication(args)
+ signal.signal(signal.SIGINT,signal.SIG_DFL)
+ mainWin1 = MainWindow1()
+ mainWin1.show()
+ return qtApp.exec_()
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv) or 0)
diff --git a/Build/source/utils/asymptote/GUI/xasy2asy.py b/Build/source/utils/asymptote/GUI/xasy2asy.py
new file mode 100755
index 00000000000..12bccb453cf
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasy2asy.py
@@ -0,0 +1,1414 @@
+#!/usr/bin/env python3
+
+###########################################################################
+#
+# xasy2asy provides a Python interface to Asymptote
+#
+#
+# Authors: Orest Shardt, Supakorn Rassameemasmuang, and John C. Bowman
+#
+###########################################################################
+
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import PyQt5.QtSvg as Qs
+
+import numpy as np
+
+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
+
+import xasyUtils as xu
+import xasyArgs as xa
+import xasyOptions as xo
+import xasySvg as xs
+
+class AsymptoteEngine:
+ xasy=chr(4)+"\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']
+
+ 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
+
+ self.args=['-xasy', '-noV', '-q', '-inpipe=' + str(rx), '-outpipe=' + str(wa), '-o', self.tmpdir]
+
+ self.asyPath = path
+ self.asyProcess = 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 wait(self):
+ if self.asyProcess.returncode is not None:
+ return
+ else:
+ return self.asyProcess.wait()
+
+ def __enter__(self):
+ self.start()
+ return self
+
+ def __exit__(self, exc_type, exc_val, exc_tb):
+ self.stop()
+ self.wait()
+
+ @property
+ def tempDirName(self):
+ return self.tmpdir
+
+ def startThenStop(self):
+ self.start()
+ self.stop()
+ self.wait()
+
+ @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))
+
+def yflip():
+ return asyTransform((0, 0, 1, 0, 0, -1))
+
+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 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"""
+ @staticmethod
+ def getColorFromQColor(color):
+ return color.redF(), color.greenF(), color.blueF()
+
+ @staticmethod
+ def convertToQColor(color):
+ r, g, b = color
+ return Qg.QColor.fromRgbF(r, g, b)
+
+ @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 __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)
+
+ @property
+ def asyEngine(self):
+ return self._asyengine
+
+ @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, 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
+
+ @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
+
+ return newObj
+
+ @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 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
+
+ @property
+ def isEmpty(self):
+ return len(self.nodeSet) == 0
+
+ @property
+ def isDrawable(self):
+ return len(self.nodeSet) >= 2
+
+ def toQPainterPath(self) -> Qg.QPainterPath:
+ return self.toQPainterPathCurve() if self.containsCurve else self.toQPainterPathLine()
+
+ def toQPainterPathLine(self):
+ 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]
+
+ painterPath.lineTo(*node)
+
+ return painterPath
+
+
+ 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=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 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 getFontSizeText(self):
+ if self.fontSize is not None:
+ return '+fontsize({:.6g})'.format(self.fontSize)
+ else:
+ return ''
+
+ 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, transfKey=None, keyIndex=0):
+ self.image = image
+ self.format = format
+ self.bbox = bbox
+ self.IDTag = None
+ self.key = transfKey
+ self.keyIndex = keyIndex
+
+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, ps2asymap=identity()):
+ """Update the item's code: to be overriden"""
+ with io.StringIO() as rawCode:
+ transfCode = self.getTransformCode()
+ objCode = self.getObjectCode()
+
+ rawCode.write(transfCode)
+ rawCode.write(objCode)
+ self.asyCode = rawCode.getvalue()
+
+ return len(transfCode.splitlines()), len(objCode.splitlines())
+
+ @property
+ def asyengine(self):
+ return self._asyengine
+
+ @asyengine.setter
+ def asyengine(self, value):
+ self._asyengine = value
+
+ 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(self.asyengine.tempDirName+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()
+ cwd=os.getcwd();
+ os.chdir(self.asyengine.tempDirName)
+ 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()
+ os.chdir(cwd);
+
+ 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 = "_{:d}.{:s}".format(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 raw_text != "Error\n":
+ if text == "Error\n":
+ self.imageHandleQueue.put(("ERROR", fin.readline()))
+ else:
+ render()
+
+ self.asy2psmap = asyTransform(xu.listize(fin.readline().rstrip(),float))
+ else:
+ self.asy2psmap = identity()
+ 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, 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]}
+
+ @property
+ def asyengine(self):
+ return self._asyengine
+
+ @asyengine.setter
+ def asyengine(self, value: AsymptoteEngine):
+ self._asyengine = value
+ self.path.asyengine = value
+
+ def setKey(self, newKey=None):
+ transform = self.transfKeymap[self.transfKey][0]
+
+ self.transfKey = newKey
+ self.transfKeymap = {self.transfKey: [transform]}
+
+ def generateDrawObjects(self, forceUpdate=False):
+ raise NotImplementedError
+
+ 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 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:
+ del self.path.nodeSet[-1]
+ del self.path.linkSet[-1]
+ self.path.computed = False
+ self.asyfied = False
+
+ 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 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 getObjectCode(self, asy2psmap=identity()):
+ return 'draw(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n'
+
+ def getTransformCode(self, asy2psmap=identity()):
+ transf = self.transfKeymap[self.transfKey][0]
+ if transf == identity():
+ return ''
+ else:
+ return xasyItem.setKeyFormatStr.format(self.transfKey, transf.getCode(asy2psmap))+'\n'
+
+ 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, 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]
+
+ self.transfKey = newKey
+ self.transfKeymap = {self.transfKey: [transform]}
+
+ 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 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, 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 = {}
+
+ self.script = script
+ self.key2imagemap = {}
+ self.namedUnsetKeys = {}
+ self.keyPrefix = ''
+ self.scriptAsyfied = False
+ self.updatedPrefix = True
+
+ def clearTransform(self):
+ """Reset the transforms for each of the deconstructed images"""
+ # self.transform = [identity()] * len(self.imageList)
+ keyCount = {}
+
+ for im in self.imageList:
+ if im.key not in keyCount.keys():
+ keyCount[im.key] = 1
+ else:
+ keyCount[im.key] += 1
+
+ for key in keyCount:
+ self.transfKeymap[key] = [identity()] * keyCount[key]
+
+ 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 getTransformCode(self, asy2psmap=identity()):
+ with io.StringIO() as rawAsyCode:
+ if self.transfKeymap:
+ for key in self.transfKeymap.keys():
+ val = self.transfKeymap[key]
+
+ 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
diff --git a/Build/source/utils/asymptote/GUI/xasyArgs.py b/Build/source/utils/asymptote/GUI/xasyArgs.py
new file mode 100644
index 00000000000..045f4bc6692
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyArgs.py
@@ -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())
diff --git a/Build/source/utils/asymptote/GUI/xasyBezierInterface.py b/Build/source/utils/asymptote/GUI/xasyBezierInterface.py
new file mode 100644
index 00000000000..0a5c689bffe
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyBezierInterface.py
@@ -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
diff --git a/Build/source/utils/asymptote/GUI/xasyFile.py b/Build/source/utils/asymptote/GUI/xasyFile.py
new file mode 100755
index 00000000000..eee6d69a856
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyFile.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+###########################################################################
+#
+# xasyFile implements the loading, parsing, and saving of an xasy file.
+#
+#
+# Author: Orest Shardt
+# Created: June 29, 2007
+#
+############################################################################
+
+from string import *
+import xasy2asy as x2a
+import io
+import re
+
+
+class xasyParseError(Exception):
+ """A parsing error"""
+ pass
+
+
+class xasyFileError(Exception):
+ """An i/o error or other error not related to parsing"""
+ pass
+
+
+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:
+ key = testMatch.group(1)
+ rawStr = testMatch.group(2)
+ rawStrArray = rawStr.split(',')
+
+ if len(rawStrArray) != 6:
+ return None
+ transf = [float(val.strip()) for val in rawStrArray]
+ return key, x2a.asyTransform(transf)
+
+
+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)
+
+ # see https://regex101.com/r/RgeBVc/2 for regex
+
+ 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, asy2psmap):
+ """Write a list of xasyItems to a file"""
+ for item in xasyItems:
+ file.write(item.getTransformCode(asy2psmap))
+
+ for item in xasyItems:
+ file.write(item.getObjectCode(asy2psmap))
+
+ file.write('size('+str(asy2psmap*x2a.yflip())+'); '+ x2a.xasyItem.resizeComment+'\n')
diff --git a/Build/source/utils/asymptote/GUI/xasyOptions.py b/Build/source/utils/asymptote/GUI/xasyOptions.py
new file mode 100755
index 00000000000..1923990fae6
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyOptions.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python3
+###########################################################################
+#
+# xasyOptions provides a mechanism for storing and restoring a user's
+# preferences.
+#
+#
+# Author: Orest Shardt
+# Created: June 29, 2007
+#
+###########################################################################
+
+import json
+import sys
+import io
+import os
+import platform
+import shutil
+
+import configs
+
+try:
+ import cson
+except ModuleNotFoundError:
+ cson = None
+
+try:
+ pass
+# import yaml
+except ModuleNotFoundError:
+ yaml = None
+
+class xasyOptions:
+ def defaultOptions(self):
+ if self._defaultOptions is None:
+ f = io.open(self._defaultOptLocation)
+ try:
+ opt = cson.loads(f.read())
+ finally:
+ f.close()
+ self._defaultOptions = opt
+ return self._defaultOptions
+
+ def overrideSettings(self):
+ settingsName = platform.system()
+
+ if settingsName not in self.options:
+ return
+
+ for key in self.options[settingsName]:
+ self.options[key] = self.options[settingsName][key]
+
+
+ def settingsFileLocation(self):
+ folder = os.path.expanduser("~/.asy/")
+
+ searchOrder = ['.cson', '.yaml', '.json', '']
+
+ 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'))
+
+ def __init__(self, configName, defaultConfigLocation):
+ self.configName = configName
+ self.defaultConfigName = defaultConfigLocation
+
+ self._defaultOptions = None
+ self._defaultOptLocation = os.path.join(defaultConfigLocation)
+
+ self.options = self.defaultOptions()
+ self.load()
+ self.overrideSettings()
+
+ 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._defaultOptLocation, 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'))
diff --git a/Build/source/utils/asymptote/GUI/xasyStrings.py b/Build/source/utils/asymptote/GUI/xasyStrings.py
new file mode 100644
index 00000000000..53f83a64f14
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyStrings.py
@@ -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.')
diff --git a/Build/source/utils/asymptote/GUI/xasySvg.py b/Build/source/utils/asymptote/GUI/xasySvg.py
new file mode 100644
index 00000000000..a5325f9bdd6
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasySvg.py
@@ -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')
diff --git a/Build/source/utils/asymptote/GUI/xasyTransform.py b/Build/source/utils/asymptote/GUI/xasyTransform.py
new file mode 100644
index 00000000000..928e9011f0a
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyTransform.py
@@ -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))
+
diff --git a/Build/source/utils/asymptote/GUI/xasyUtils.py b/Build/source/utils/asymptote/GUI/xasyUtils.py
new file mode 100644
index 00000000000..255e8b6addc
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyUtils.py
@@ -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)
diff --git a/Build/source/utils/asymptote/GUI/xasyValidator.py b/Build/source/utils/asymptote/GUI/xasyValidator.py
new file mode 100644
index 00000000000..264e105441d
--- /dev/null
+++ b/Build/source/utils/asymptote/GUI/xasyValidator.py
@@ -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('.-')