texlive[50168] Master: asymptote 2.47 support files

commits+karl at tug.org commits+karl at tug.org
Thu Feb 28 19:48:49 CET 2019


Revision: 50168
          http://tug.org/svn/texlive?view=revision&revision=50168
Author:   karl
Date:     2019-02-28 19:48:48 +0100 (Thu, 28 Feb 2019)
Log Message:
-----------
asymptote 2.47 support files

Modified Paths:
--------------
    trunk/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py
    trunk/Master/texmf-dist/asymptote/GUI/xasy.py
    trunk/Master/texmf-dist/asymptote/GUI/xasy2asy.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyFile.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyOptions.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyVersion.py
    trunk/Master/texmf-dist/asymptote/animation.asy
    trunk/Master/texmf-dist/asymptote/asy-keywords.el
    trunk/Master/texmf-dist/asymptote/asymptote.py
    trunk/Master/texmf-dist/asymptote/bsp.asy
    trunk/Master/texmf-dist/asymptote/plain.asy
    trunk/Master/texmf-dist/asymptote/plain_Label.asy
    trunk/Master/texmf-dist/asymptote/plain_boxes.asy
    trunk/Master/texmf-dist/asymptote/plain_constants.asy
    trunk/Master/texmf-dist/asymptote/plain_pens.asy
    trunk/Master/texmf-dist/asymptote/plain_picture.asy
    trunk/Master/texmf-dist/asymptote/plain_scaling.asy
    trunk/Master/texmf-dist/asymptote/plain_shipout.asy
    trunk/Master/texmf-dist/asymptote/rational.asy
    trunk/Master/texmf-dist/asymptote/simplex.asy
    trunk/Master/texmf-dist/asymptote/slide.asy
    trunk/Master/texmf-dist/asymptote/three.asy
    trunk/Master/texmf-dist/asymptote/version.asy
    trunk/Master/texmf-dist/doc/asymptote/CAD.pdf
    trunk/Master/texmf-dist/doc/asymptote/TeXShopAndAsymptote.pdf
    trunk/Master/texmf-dist/doc/asymptote/asy-latex.pdf
    trunk/Master/texmf-dist/doc/asymptote/asyRefCard.pdf
    trunk/Master/texmf-dist/doc/asymptote/asymptote.pdf
    trunk/Master/texmf-dist/doc/asymptote/examples/p-orbital.asy
    trunk/Master/texmf-dist/doc/asymptote/examples/planes.asy
    trunk/Master/texmf-dist/doc/info/asy-faq.info
    trunk/Master/texmf-dist/doc/info/asymptote.info
    trunk/Master/texmf-dist/doc/man/man1/asy.1
    trunk/Master/texmf-dist/doc/man/man1/asy.man1.pdf
    trunk/Master/texmf-dist/doc/man/man1/xasy.man1.pdf
    trunk/Master/tlpkg/asymptote/asy.exe
    trunk/Master/tlpkg/asymptote64/asy.exe

Added Paths:
-----------
    trunk/Master/texmf-dist/asymptote/GUI/CustMatTransform.py
    trunk/Master/texmf-dist/asymptote/GUI/DebugFlags.py
    trunk/Master/texmf-dist/asymptote/GUI/GuidesManager.py
    trunk/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py
    trunk/Master/texmf-dist/asymptote/GUI/PrimitiveShape.py
    trunk/Master/texmf-dist/asymptote/GUI/SetCustomAnchor.py
    trunk/Master/texmf-dist/asymptote/GUI/Widg_addLabel.py
    trunk/Master/texmf-dist/asymptote/GUI/Widg_addPolyOpt.py
    trunk/Master/texmf-dist/asymptote/GUI/Widg_editBezier.py
    trunk/Master/texmf-dist/asymptote/GUI/Window1.py
    trunk/Master/texmf-dist/asymptote/GUI/__init__.py
    trunk/Master/texmf-dist/asymptote/GUI/configs/
    trunk/Master/texmf-dist/asymptote/GUI/configs/xasyconfig.cson
    trunk/Master/texmf-dist/asymptote/GUI/configs/xasykeymap.cson
    trunk/Master/texmf-dist/asymptote/GUI/icons_rc.py
    trunk/Master/texmf-dist/asymptote/GUI/labelEditor.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/custMatTransform.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/labelTextEditor.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/setCustomAnchor.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addLabel.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_editBezier.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widgetPointEditor.py
    trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/window1.py
    trunk/Master/texmf-dist/asymptote/GUI/res/
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/anchor.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-back.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-forward.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-camera.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-close.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-color-palette.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-delete.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-done.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-expand.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-folder-open.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-hand.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-locate.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-off.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-on.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-refresh.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-move.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-resize.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/bucket.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/center.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/centerorigin.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/check.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-left.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-right.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/circle.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/close-round.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedcurve.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedpolygon.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/code.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/edit.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/eye.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/filledbucket.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/grid.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/magnifying-glass.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/opencurve.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/openpolygon.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/plus-round.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/save.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/social-python.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/subdirectory-left.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/text.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons/triangle-stroked-15.svg
    trunk/Master/texmf-dist/asymptote/GUI/res/icons.qrc
    trunk/Master/texmf-dist/asymptote/GUI/setup.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyArgs.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyBezierInterface.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyStrings.py
    trunk/Master/texmf-dist/asymptote/GUI/xasySvg.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyTransform.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyUtils.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyValidator.py
    trunk/Master/texmf-dist/asymptote/rationalSimplex.asy
    trunk/Master/texmf-dist/doc/asymptote/examples/slope.asy

Removed Paths:
-------------
    trunk/Master/texmf-dist/asymptote/GUI/CubicBezier.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyActions.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyMainWin.py
    trunk/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py
    trunk/Master/texmf-dist/asymptote/plain_xasy.asy

Deleted: trunk/Master/texmf-dist/asymptote/GUI/CubicBezier.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/CubicBezier.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/CubicBezier.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,104 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# Convert a Bezier curve to a polyline
-#
-# Once Tk supports "RawCurves" this will not be needed.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-import math
-
-def norm(vector):
-  """Return the norm of a vector"""
-  return math.sqrt(vector[0]**2+vector[1]**2)
-
-def splitLine(end0,end1,t):
-  """Split a line at the distance t, with t in (0,1)"""
-  return (end0[0]+t*(end1[0]-end0[0]),end0[1]+t*(end1[1]-end0[1]))
-
-def splitBezier(node0,control0,control1,node1,t):
-  """Find the nodes and control points for the segments of a Bezier curve split at t"""
-  a = splitLine(node0,control0,t)
-  b = splitLine(control0,control1,t)
-  c = splitLine(control1,node1,t)
-  d = splitLine(a,b,t)
-  e = splitLine(b,c,t)
-  f = splitLine(d,e,t)#this is the point on the curve at t
-  return ([node0,a,d,f],[f,e,c,node1])
-
-def BezierWidth(node0,control0,control1,node1):
-  """Compute the distance of the control points from the node-node axis"""
-  deltax = node1[0] - node0[0]
-  deltay = node1[1] - node0[1]
-  length = norm((deltax,deltay))
-  if length == 0:
-    y1 = control0[1]-node0[1]
-    y2 = control1[1]-node0[1]
-  else:
-    cosine = deltax/length
-    sine = deltay/length
-    y1 = cosine*(control0[1]-node0[1])-sine*(control0[0]-node0[0])
-    y2 = cosine*(control1[1]-node0[1])-sine*(control1[0]-node0[0])
-  if y1*y2 >= 0:
-    #same sign
-    return max(abs(y1),abs(y2))
-  else:
-    #opposite sign
-    return abs(y1)+abs(y2)
-
-#If the above algorithm fails, this one will work, but it is far from elegant
-#def computeIntermediates(steps,node0,control0,control1,node1):
-  #pointList = []
-  #for a in range(0,100,100/steps)+[100]:
-   #t = a/100.0
-   #t1 = 1-t
-   #x = node0[0]*t1**3+3*control0[0]*t*t1**2+3*control1[0]*t**2*t1+node1[0]*t**3
-   #y = node0[1]*t1**3+3*control0[1]*t*t1**2+3*control1[1]*t**2*t1+node1[1]*t**3
-   #pointList.append((x,y))
-  #return pointList
-#def makeBezier(steps,node0,control0,control1,node1):
- #if len(node0)!=2 or len(control0)!=2 or len(control1)!=2 or len(node1)!=2:
-  #return -1
- #else:
-  #return [node0]+computeIntermediates(steps,node0,control0,control1,node1)+[node1]
-
-def makeBezierIntermediates(node0,control0,control1,node1,epsilon):
-  """Find the points, excluding node0, to be used as the line segment endpoints"""
-  if(BezierWidth(node0,control0,control1,node1) <= epsilon):
-    return [node1]
-  else:
-    splitUp = splitBezier(node0,control0,control1,node1,0.5)
-    return makeBezierIntermediates(*splitUp[0]+[epsilon])+makeBezierIntermediates(*splitUp[1]+[epsilon])
-
-def makeBezier(node0,control0,control1,node1,epsilon=1):
-  """Return the vertices to be used in the polyline representation of a Bezier curve"""
-  return [node0]+makeBezierIntermediates(node0,control0,control1,node1,epsilon)
-
-if __name__ == '__main__':
-  pointList = makeBezier((-80,0),(-150,40),(150,120),(80,0),0.5)
-  from timeit import Timer
-  t = Timer('makeBezier((-80,0),(-40,-40),(40,120),(80,0),1)','from __main__ import makeBezier')
-  print (pointList)
-  print (len(pointList))
-  iterations = 1000
-  time = t.timeit(iterations)
-  print ("{:d} iterations took {:f} seconds ({:f} ms for each).".format(iterations,time,1000.0*time/iterations))
-  points = []
-  for point in pointList:
-    points.append(point[0])
-    points.append(-point[1])
-  if sys.version_info >= (3, 0):
-    from tkinter import *
-  else:
-    from Tkinter import *
-  root = Tk()
-  canv = Canvas(root,scrollregion=(-100,-100,100,100))
-  canv.pack()
-  canv.create_line(points)
-  for point in pointList:
-   canv.create_oval(point[0],-point[1],point[0],-point[1],fill='red',outline='red')
-  root.mainloop()

Added: trunk/Master/texmf-dist/asymptote/GUI/CustMatTransform.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/CustMatTransform.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/CustMatTransform.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,102 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import numpy as np
+import xasy2asy as x2a
+from pyUIClass.custMatTransform import Ui_Dialog
+
+
+class CustMatTransform(Qw.QDialog):
+    def __init__(self):
+        super().__init__()
+        self.ui = Ui_Dialog()
+        self.ui.setupUi(self)
+
+        self.ui.btnAccept.clicked.connect(self.accept)
+        self.ui.btnCancel.clicked.connect(self.reject)
+        self.ui.btnReset.clicked.connect(self.resetDialog)
+
+        self.mainTransformation = Qg.QTransform()
+        self.mainTransformation.scale(1, -1)
+
+        self.matrixLineInputs = [
+            self.ui.lineMat00, self.ui.lineMat01, self.ui.lineMatTx,
+            self.ui.lineMat10, self.ui.lineMat11, self.ui.lineMatTy]
+
+        validator = Qg.QDoubleValidator()
+        for lineInput in self.matrixLineInputs:
+            lineInput.setValidator(validator)
+            lineInput.textChanged.connect(self.handleUpdateText)
+
+    def show(self):
+        super().show()
+        self.createCanvas()
+        self.updatePreview()
+
+    def createCanvas(self):
+        self.canvSize = self.ui.imgPreview.size()
+        self.previewPixmap = Qg.QPixmap(self.canvSize)
+        tx, ty = self.canvSize.width() / 2, self.canvSize.height() / 2
+        self.mainTransformation.translate(tx, -ty)
+
+    def handleUpdateText(self, text):
+        if str(text) not in {'.', '-', '.-', '-.'} and str(text):
+            self.updatePreview()
+            self.ui.btnAccept.setEnabled(True)
+        else:
+            self.previewPixmap.fill()
+            self.ui.imgPreview.setPixmap(self.previewPixmap)
+            self.ui.btnAccept.setEnabled(False)
+
+    def updatePreview(self):
+        self.previewPixmap.fill()
+        canvas = Qg.QPainter(self.previewPixmap)
+        if not canvas.isActive():
+            return
+        canvas.setTransform(self.mainTransformation)
+
+        canvas.save()
+        canvas.setPen(Qc.Qt.lightGray)
+        self.drawBasicGrid(canvas)
+        transform = x2a.asyTransform.fromNumpyMatrix(self.getTransformationMatrix())
+        canvTransform = transform.toQTransform()
+        canvas.setTransform(canvTransform, True)
+
+        canvas.setPen(Qc.Qt.black)
+
+        if canvTransform.isInvertible():
+            self.drawBasicGrid(canvas, False)
+
+            if canvTransform.determinant() <= 0:
+                canvas.setPen(Qc.Qt.red)
+
+            canvas.drawRect(Qc.QRect(Qc.QPoint(0, 0), Qc.QSize(20, 20)))
+
+        self.ui.imgPreview.setPixmap(self.previewPixmap)
+
+    def resetDialog(self):
+        self.ui.lineMatTx.setText('0')
+        self.ui.lineMatTx.setText('0')
+
+        self.ui.lineMat00.setText('1')
+        self.ui.lineMat01.setText('0')
+        self.ui.lineMat10.setText('0')
+        self.ui.lineMat11.setText('1')
+
+    def drawBasicGrid(self, canvas, grid=True):
+        canvas.drawLine(Qc.QLine(-9999, 0, 9999, 0))
+        canvas.drawLine(Qc.QLine(0, -9999, 0, 9999))
+
+        fromIter, toIter = -7, 7
+        gridSize = 20
+        if grid:
+            for iterIndex in range(fromIter, toIter + 1):
+                canvas.drawLine(Qc.QLine(-9999, iterIndex * gridSize, 9999, iterIndex * gridSize))
+                canvas.drawLine(Qc.QLine(iterIndex * gridSize, -9999, iterIndex * gridSize, 9999))
+
+    def getTransformationMatrix(self):
+        rawMatrixNum = [float(lineInput.text()) for lineInput in self.matrixLineInputs]
+        rawMatrixNum.extend([0, 0, 1])
+        return np.matrix(rawMatrixNum).reshape((3, 3))


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/CustMatTransform.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/DebugFlags.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/DebugFlags.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/DebugFlags.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+keepFiles = False
+printFoutTranscript = False
+printDeconstTranscript = False
+forceRasterizationSVG = False


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/DebugFlags.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/GuidesManager.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/GuidesManager.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/GuidesManager.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import numpy as np
+
+class Guide:
+    def __init__(self, pen=None):
+        if pen is None:
+            pen = Qg.QPen()
+        assert isinstance(pen, Qg.QPen)
+        self.pen = pen
+
+    def drawShape(self, pen):
+        assert isinstance(pen, Qg.QPainter)
+        pen.save()
+        pen.setPen(self.pen)
+
+class LineGuide(Guide):
+    def __init__(self, origin, direction, pen=None):
+        super().__init__(pen)
+        self.origin = origin
+        self.direction = direction
+
+    def drawShape(self, pen):
+        super().drawShape(pen)
+        p1 = self.origin + (9999 * Qc.QPointF(np.cos(self.direction), np.sin(self.direction)))
+        p2 = self.origin - (9999 * Qc.QPointF(np.cos(self.direction), np.sin(self.direction)))
+        pen.drawLine(Qc.QLineF(p1, p2))
+        pen.restore()
+
+class ArcGuide(Guide):
+    @classmethod
+    def radTo16Deg(cls, radians):
+        return int(round(np.rad2deg(radians) * 16))
+
+    def __init__(self, center=None, radius=1, startAng=0, endAng=(2*np.pi), pen=None):
+        if center is None:
+            center = Qc.QPointF(0, 0)
+        super().__init__(pen)
+        self.center = center
+        self.radius = int(radius)
+        self.startAng = startAng
+        self.endAng = endAng
+
+    def drawShape(self, pen):
+        super().drawShape(pen)
+        assert isinstance(pen, Qg.QPainter)
+        x, y = int(round(self.center.x())), int(round(self.center.y()))
+        pen.drawArc(x - self.radius, y - self.radius, 2 * self.radius, 2 * self.radius, ArcGuide.radTo16Deg(self.startAng),
+                    -ArcGuide.radTo16Deg(self.endAng - self.startAng))
+        pen.restore()


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/GuidesManager.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,356 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtCore as Qc
+import PyQt5.QtGui as Qg
+import xasy2asy as x2a
+
+import PrimitiveShape
+import math
+
+import Widg_addPolyOpt
+import Widg_addLabel
+
+
+class InplaceObjProcess(Qc.QObject):
+    objectCreated = Qc.pyqtSignal(Qc.QObject)
+    objectUpdated = Qc.pyqtSignal()
+
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self._active = False
+        pass
+
+    @property
+    def active(self):
+        return self._active
+
+    def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+        raise NotImplementedError
+
+    def mouseMove(self, pos, event: Qg.QMouseEvent):
+        raise NotImplementedError
+
+    def mouseRelease(self):
+        raise NotImplementedError
+
+    def forceFinalize(self):
+        raise NotImplementedError
+
+    def getPreview(self):
+        return None
+
+    def getObject(self):
+        raise NotImplementedError
+
+    def getXasyObject(self):
+        raise NotImplementedError
+
+    def postDrawPreview(self, canvas: Qg.QPainter):
+        pass
+
+    def createOptWidget(self, info):
+        return None
+
+
+class AddCircle(InplaceObjProcess):
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.center = Qc.QPointF(0, 0)
+        self.radius = 0
+
+    def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+        x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+        self.radius = 0
+        self.center.setX(x)
+        self.center.setY(y)
+        self.fill = info['fill']
+        self._active = True
+
+    def mouseMove(self, pos, event):
+        self.radius = PrimitiveShape.PrimitiveShape.euclideanNorm(pos, self.center)
+
+    def mouseRelease(self):
+        self.objectCreated.emit(self.getXasyObject())
+        self._active = False
+
+    def getPreview(self):
+        x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.center)
+        boundRect = Qc.QRectF(x - self.radius, y - self.radius, 2 * self.radius, 2 * self.radius)
+        # because the internal image is flipped...
+        newPath = Qg.QPainterPath()
+        newPath.addEllipse(boundRect)
+        # newPath.addRect(boundRect)
+        return newPath
+
+    def getObject(self):
+        return PrimitiveShape.PrimitiveShape.circle(self.center, self.radius)
+
+    def getXasyObject(self):
+        if self.fill:
+            newObj = x2a.xasyFilledShape(self.getObject(), None)
+        else:
+            newObj = x2a.xasyShape(self.getObject(), None)
+        return newObj
+
+    def forceFinalize(self):
+        self.mouseRelease()
+
+
+class AddLabel(InplaceObjProcess):
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.alignMode = None
+        self.opt = None
+        self.text = None
+        self.anchor = Qc.QPointF(0, 0)
+        self._active = False
+
+    def createOptWidget(self, info):
+        self.opt = Widg_addLabel.Widg_addLabel(info)
+        return self.opt
+
+    def getPreview(self):
+        return None
+
+    def mouseRelease(self):
+        self.objectCreated.emit(self.getXasyObject())
+        self._active = False
+
+    def mouseMove(self, pos, event):
+        x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+        self.anchor.setX(x)
+        self.anchor.setY(y)
+
+    def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+        if self.opt is not None:
+            self.text = self.opt.labelText
+        x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+        self.anchor.setX(x)
+        self.anchor.setY(y)
+
+        self.alignMode = info['align']
+        self.fontSize = info['fontSize']
+        self._active = True
+
+    def getObject(self):
+        finalTuple = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.anchor)
+        return {'txt': self.text, 'align': str(self.alignMode), 'anchor': finalTuple}
+
+    def getXasyObject(self):
+        text = self.text
+        align = str(self.alignMode)
+        anchor = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.anchor)
+        newLabel = x2a.xasyText(text=text, location=anchor, pen=None,
+                                align=align, asyengine=None, fontsize=self.fontSize)
+        newLabel.asyfied = False
+        return newLabel
+
+    def forceFinalize(self):
+        self.mouseRelease()
+
+
+class AddBezierShape(InplaceObjProcess):
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.asyengine = None
+        self.basePath = None
+        self.basePathPreview = None
+        self.closedPath = None
+        self.info = None
+        self.fill = False
+        self.opt = None
+
+        # list of "committed" points with Linkage information.
+        # Linkmode should be to the last point.
+        # (x, y, linkmode), (u, v, lm2) <==> (x, y) <=lm2=> (u, v)
+        self.pointsList = []
+        self.currentPoint = Qc.QPointF(0, 0)
+        self.pendingPoint = None
+        self.useLegacy = False
+
+    def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+        x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+        self.currentPoint.setX(x)
+        self.currentPoint.setY(y)
+        self.info = info
+
+        if not self._active:
+            self._active = True
+            self.fill = info['fill']
+            self.asyengine = info['asyengine']
+            self.closedPath = info['closedPath']
+            self.useBezierBase = info['useBezier']
+            self.useLegacy = self.info['options']['useLegacyDrawMode']
+            self.pointsList.clear()
+            self.pointsList.append((x, y, None))
+        else:
+            # see http://doc.qt.io/archives/qt-4.8/qt.html#MouseButton-enum
+            if (int(mouseEvent.buttons()) if mouseEvent is not None else 0) & 0x2 and self.useLegacy:
+                self.forceFinalize()
+
+    def _getLinkType(self):
+        if self.info['useBezier']:
+            return '..'
+        else:
+            return '--'
+
+    def mouseMove(self, pos, event):
+        # in postscript coords.
+        if self._active:
+            x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+
+            if self.useLegacy or int(event.buttons()) != 0:
+                self.currentPoint.setX(x)
+                self.currentPoint.setY(y)
+            else:
+                self.forceFinalize()
+
+
+    def createOptWidget(self, info):
+        return None
+        # self.opt = Widg_addBezierInPlace.Widg_addBezierInplace(info)
+        # return self.opt
+
+    def finalizeClosure(self):
+        if self.active:
+            self.closedPath = True
+            self.forceFinalize()
+
+    def mouseRelease(self):
+        x, y = self.currentPoint.x(), self.currentPoint.y()
+        self.pointsList.append((x, y, self._getLinkType()))
+        # self.updateBasePath()
+
+    def updateBasePath(self):
+        self.basePath = x2a.asyPath(asyengine=self.asyengine, forceCurve=self.useBezierBase)
+        newNode = [(x, y) for x, y, _ in self.pointsList]
+        newLink = [lnk for *args, lnk in self.pointsList[1:]]
+        if self.useLegacy:
+            newNode += [(self.currentPoint.x(), self.currentPoint.y())]
+            newLink += [self._getLinkType()]
+        if self.closedPath:
+            newNode.append('cycle')
+            newLink.append(self._getLinkType())
+        self.basePath.initFromNodeList(newNode, newLink)
+
+        if self.useBezierBase:
+            self.basePath.computeControls()
+
+    def updateBasePathPreview(self):
+        self.basePathPreview = x2a.asyPath(
+            asyengine=self.asyengine, forceCurve=self.useBezierBase)
+        newNode = [(x, y) for x, y, _ in self.pointsList] + [(self.currentPoint.x(), self.currentPoint.y())]
+        newLink = [lnk for *args, lnk in self.pointsList[1:]] + [self._getLinkType()]
+        if self.closedPath:
+            newNode.append('cycle')
+            newLink.append(self._getLinkType())
+        self.basePathPreview.initFromNodeList(newNode, newLink)
+
+        if self.useBezierBase:
+            self.basePathPreview.computeControls()
+
+    def forceFinalize(self):
+        self.updateBasePath()
+        self._active = False
+        self.pointsList.clear()
+        self.objectCreated.emit(self.getXasyObject())
+        self.basePath = None
+
+    def getObject(self):
+        if self.basePath is None:
+            raise RuntimeError('BasePath is None')
+        self.basePath.asyengine = self.asyengine
+        return self.basePath
+
+    def getPreview(self):
+        if self._active:
+            if self.pointsList:
+                self.updateBasePathPreview()
+                newPath = self.basePathPreview.toQPainterPath()
+                return newPath
+
+    def getXasyObject(self):
+        if self.fill:
+            return x2a.xasyFilledShape(self.getObject(), None)
+        else:
+            return x2a.xasyShape(self.getObject(), None)
+
+
+class AddPoly(InplaceObjProcess):
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.center = Qc.QPointF(0, 0)
+        self.currPos = Qc.QPointF(0, 0)
+        self.sides = None
+        self.inscribed = None
+        self.centermode = None
+        self.asyengine = None
+        self.fill = None
+        self.opt = None
+
+    def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+        self._active = True
+        self.sides = info['sides']
+        self.inscribed = info['inscribed']
+        self.centermode = info['centermode']
+        self.fill = info['fill']
+
+        
+        x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+        self.center.setX(x)
+        self.center.setY(y)
+        self.currPos = Qc.QPointF(self.center)
+
+    def mouseMove(self, pos, event):
+        x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos)
+        self.currPos.setX(x)
+        self.currPos.setY(y)
+
+    def mouseRelease(self):
+        if self.active:
+            self.objectCreated.emit(self.getXasyObject())
+            self._active = False
+
+    def forceFinalize(self):
+        self.mouseRelease()
+
+    def getObject(self):
+        if self.inscribed:
+            return PrimitiveShape.PrimitiveShape.inscribedRegPolygon(self.sides, self.center, self._rad(),
+                                                                     self._angle())
+        else:
+            return PrimitiveShape.PrimitiveShape.exscribedRegPolygon(self.sides, self.center, self._rad(),
+                                                                     self._angle())
+
+    def getPreview(self):
+        if self.inscribed:
+            poly = PrimitiveShape.PrimitiveShape.inscribedRegPolygon(self.sides, self.center, self._rad(),
+                                                                     self._angle(), qpoly=True)
+        else:
+            poly = PrimitiveShape.PrimitiveShape.exscribedRegPolygon(self.sides, self.center, self._rad(),
+                                                                     self._angle(), qpoly=True)
+        newPath = Qg.QPainterPath()
+        newPath.addPolygon(poly)
+        return newPath
+
+    def createOptWidget(self, info):
+        self.opt = Widg_addPolyOpt.Widg_addPolyOpt(info)
+        return self.opt
+
+    def _rad(self):
+        return PrimitiveShape.PrimitiveShape.euclideanNorm(self.currPos, self.center)
+
+    def _angle(self):
+        dist_x = self.currPos.x() - self.center.x()
+        dist_y = self.currPos.y() - self.center.y()
+        if dist_x == 0 and dist_y == 0:
+            return 0
+        else:
+            return math.atan2(dist_y, dist_x)
+
+    def getXasyObject(self):
+        if self.fill:
+            newObj = x2a.xasyFilledShape(self.getObject(), None)
+        else:
+            newObj = x2a.xasyShape(self.getObject(), None)
+        return newObj


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/InplaceAddObj.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/PrimitiveShape.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/PrimitiveShape.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/PrimitiveShape.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,66 @@
+#!/usr/bin/env python3
+
+import xasy2asy as x2a
+import numpy as np
+import math
+import PyQt5.QtCore as Qc
+import PyQt5.QtGui as Qg
+
+
+class PrimitiveShape:
+    # The magic number.
+    # see https://www.desmos.com/calculator/lw6j7khikj for unitcircle
+    # optimal_ctl_pt = 0.5447
+
+    @staticmethod
+    def pos_to_tuple(pos):
+        if isinstance(pos, tuple) or isinstance(pos, np.ndarray):
+            return pos
+        elif isinstance(pos, Qc.QPoint) or isinstance(pos, Qc.QPointF):
+            return pos.x(), pos.y()
+        else:
+            raise TypeError("Position must be a valid type!")
+
+    @staticmethod
+    def euclideanNorm(p1, p2):
+        x1, y1 = PrimitiveShape.pos_to_tuple(p1)
+        x2, y2 = PrimitiveShape.pos_to_tuple(p2)
+
+        normSq = ((x1 - x2) ** 2) + ((y1 - y2) ** 2)
+        return math.sqrt(normSq)
+
+    @classmethod
+    def circle(cls, position, radius):
+        pos_x, pos_y = PrimitiveShape.pos_to_tuple(position)
+        newCircle = x2a.asyPath()
+        ptsList = [(pos_x + radius, pos_y), (pos_x, pos_y + radius), (pos_x - radius, pos_y), (pos_x, pos_y - radius),
+                   'cycle']
+        # cycle doesn't work for now.
+        lkList = ['..', '..', '..', '..']
+        newCircle.initFromNodeList(ptsList, lkList)
+        return newCircle
+
+    @classmethod
+    def inscribedRegPolygon(cls, sides, position, radius, starting_rad, qpoly=False):
+        pos_x, pos_y = PrimitiveShape.pos_to_tuple(position)
+        lkList = ['--'] * sides
+        ptsList = []
+        for ang in np.linspace(starting_rad, starting_rad + math.tau, sides, endpoint=False):
+            ptsList.append((pos_x + radius * math.cos(ang), pos_y + radius * math.sin(ang)))
+
+        if qpoly:
+            ptsList.append((pos_x + radius * math.cos(starting_rad), pos_y + radius * math.sin(starting_rad)))
+            qpoints = [Qc.QPointF(x, y) for (x, y) in ptsList]
+            return Qg.QPolygonF(qpoints)
+        else:
+            ptsList.append('cycle')
+            newPoly = x2a.asyPath()
+            newPoly.initFromNodeList(ptsList, lkList)
+            return newPoly
+
+    @classmethod
+    def exscribedRegPolygon(cls, sides, position, length, starting_rad, qpoly=False):
+        ang = math.tau/sides
+        # see notes
+        adjusted_radius = length / math.cos(ang/2)
+        return cls.inscribedRegPolygon(sides, position, adjusted_radius, starting_rad - ang/2, qpoly)


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/PrimitiveShape.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/SetCustomAnchor.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/SetCustomAnchor.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/SetCustomAnchor.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,44 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+from pyUIClass.setCustomAnchor import Ui_Dialog
+
+
+class CustomAnchorDialog(Qw.QDialog):
+
+    def __init__(self):
+        super().__init__()
+        self.ui = Ui_Dialog()
+        self.ui.setupUi(self)
+        self.ui.buttonBox.button(Qw.QDialogButtonBox.Reset).clicked.connect(self.resetDialog)
+
+        validator = Qg.QDoubleValidator()
+
+        self.ui.lineEditX.setValidator(validator)
+        self.ui.lineEditY.setValidator(validator)
+
+        self.ui.lineEditX.textChanged.connect(self.checkTextChanged)
+        self.ui.lineEditY.textChanged.connect(self.checkTextChanged)
+
+    def checkTextChanged(self, text):
+        if str(text) not in {'.', '-', '.-', '-.'} and str(text):
+            self.ui.buttonBox.button(Qw.QDialogButtonBox.Ok).setEnabled(True)
+        else:
+            self.ui.buttonBox.button(Qw.QDialogButtonBox.Ok).setEnabled(False)
+
+    def getPoint(self):
+        xPoint = float(self.ui.lineEditX.text())
+        yPoint = float(self.ui.lineEditY.text())
+
+        return Qc.QPointF(xPoint, yPoint)
+
+    def handleBtnBoxClick(self, button):
+        assert isinstance(button, Qw.QAbstractButton)
+        if button.text() == 'Reset':
+            self.resetDialog()
+
+    def resetDialog(self):
+        self.ui.lineEditX.setText('0')
+        self.ui.lineEditY.setText('0')


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/SetCustomAnchor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Modified: trunk/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 ###########################################################################
 #
 # UndoRedoStack implements the usual undo/redo capabilities of a GUI
@@ -8,110 +8,125 @@
 #
 ###########################################################################
 
+
 class action:
-  def __init__(self,act,inv):
-    self.act = act
-    self.inv = inv
-  def undo(self):
-    #print ("Undo:",self)
-    self.inv()
-  def redo(self):
-    #print ("Redo:",self)
-    self.act()
-  def __str__(self):
-    return "A generic action"
+    def __init__(self, actions):
+        act, inv = actions
+        self.act = act
+        self.inv = inv
 
+    def undo(self):
+        # print ("Undo:",self)
+        self.inv()
+
+    def redo(self):
+        # print ("Redo:",self)
+        self.act()
+
+    def __str__(self):
+        return "A generic action"
+
+
 class beginActionGroup:
-  pass
+    pass
 
+
 class endActionGroup:
-  pass
+    pass
 
+
 class actionStack:
-  def __init__(self):
-    self.clear()
+    def __init__(self):
+        self.clear()
 
-  def add(self,action):
-    self.undoStack.append(action)
-    #print ("Added",action)
-    self.redoStack = []
+    def add(self, action):
+        self.undoStack.append(action)
+        # print ("Added",action)
+        self.redoStack = []
 
-  def undo(self):
-    if len(self.undoStack) > 0:
-      op = self.undoStack.pop()
-      if op is beginActionGroup:
-        level = 1
-        self.redoStack.append(endActionGroup)
-        while level > 0:
-          op=self.undoStack.pop()
-          if op is endActionGroup:
-            level -= 1
-            self.redoStack.append(beginActionGroup)
-          elif op is beginActionGroup:
-            level += 1
-            self.redoStack.append(endActionGroup)
-          else:
-            op.undo()
-            self.redoStack.append(op)
-      elif op is endActionGroup:
-        raise Exception("endActionGroup without previous beginActionGroup")
-      else:
-        self.redoStack.append(op)
-        op.undo()
-      #print ("undid",op)
-    else:
-      pass #print ("nothing to undo")
+    def undo(self):
+        if len(self.undoStack) > 0:
+            op = self.undoStack.pop()
+            if op is beginActionGroup:
+                level = 1
+                self.redoStack.append(endActionGroup)
+                while level > 0:
+                    op = self.undoStack.pop()
+                    if op is endActionGroup:
+                        level -= 1
+                        self.redoStack.append(beginActionGroup)
+                    elif op is beginActionGroup:
+                        level += 1
+                        self.redoStack.append(endActionGroup)
+                    else:
+                        op.undo()
+                        self.redoStack.append(op)
+            elif op is endActionGroup:
+                raise Exception("endActionGroup without previous beginActionGroup")
+            else:
+                self.redoStack.append(op)
+                op.undo()
+                # print ("undid",op)
+        else:
+            pass  # print ("nothing to undo")
 
-  def redo(self):
-    if len(self.redoStack) > 0:
-      op = self.redoStack.pop()
-      if op is beginActionGroup:
-        level = 1
-        self.undoStack.append(endActionGroup)
-        while level > 0:
-          op = self.redoStack.pop()
-          if op is endActionGroup:
-            level -= 1
-            self.undoStack.append(beginActionGroup)
-          elif op is beginActionGroup:
-            level += 1
-            self.undoStack.append(endActionGroup)
-          else:
-            op.redo()
-            self.undoStack.append(op)
-      elif op is endActionGroup:
-        raise Exception("endActionGroup without previous beginActionGroup")
-      else:
-        self.undoStack.append(op)
-        op.redo()
-      #print ("redid",op)
-    else:
-      pass #print ("nothing to redo")
+    def redo(self):
+        if len(self.redoStack) > 0:
+            op = self.redoStack.pop()
+            if op is beginActionGroup:
+                level = 1
+                self.undoStack.append(endActionGroup)
+                while level > 0:
+                    op = self.redoStack.pop()
+                    if op is endActionGroup:
+                        level -= 1
+                        self.undoStack.append(beginActionGroup)
+                    elif op is beginActionGroup:
+                        level += 1
+                        self.undoStack.append(endActionGroup)
+                    else:
+                        op.redo()
+                        self.undoStack.append(op)
+            elif op is endActionGroup:
+                raise Exception("endActionGroup without previous beginActionGroup")
+            else:
+                self.undoStack.append(op)
+                op.redo()
+                # print ("redid",op)
+        else:
+            pass  # print ("nothing to redo")
 
-  def setCommitLevel(self):
-    self.commitLevel = len(self.undoStack)
+    def setCommitLevel(self):
+        self.commitLevel = len(self.undoStack)
 
-  def changesMade(self):
-    if len(self.undoStack) != self.commitLevel:
-      return True
-    else:
-      return False
+    def changesMade(self):
+        if len(self.undoStack) != self.commitLevel:
+            return True
+        else:
+            return False
 
-  def clear(self):
-    self.redoStack = []
-    self.undoStack = []
-    self.commitLevel = 0
+    def clear(self):
+        self.redoStack = []
+        self.undoStack = []
+        self.commitLevel = 0
 
-if __name__=='__main__':
-  import sys
-  def opq():
-    print ("action1")
-  def unopq():
-    print ("inverse1")
-  q = action(opq,unopq)
-  w = action(lambda:sys.stdout.write("action2\n"),lambda:sys.stdout.write("inverse2\n"))
-  e = action(lambda:sys.stdout.write("action3\n"),lambda:sys.stdout.write("inverse3\n"))
-  s = actionStack()
-  s.add(q)
-  s.add(w)
-  s.add(e)
+
+if __name__ == '__main__':
+    import sys
+
+
+    def opq():
+        print("action1")
+
+
+    def unopq():
+        print("inverse1")
+
+
+    q = action(opq, unopq)
+    w = action(lambda: sys.stdout.write("action2\n"), lambda: sys.stdout.write("inverse2\n"))
+    e = action(lambda: sys.stdout.write("action3\n"), lambda: sys.stdout.write("inverse3\n"))
+    s = actionStack()
+    s.add(q)
+    s.add(w)
+    s.add(e)

Added: trunk/Master/texmf-dist/asymptote/GUI/Widg_addLabel.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/Widg_addLabel.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/Widg_addLabel.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,96 @@
+#!/usr/bin/env python3
+
+from pyUIClass.widg_addLabel import Ui_Form
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+
+import labelEditor
+import xasyUtils as xu
+
+
+class Widg_addLabel(Qw.QWidget):
+    def __init__(self, info):
+        super().__init__()
+        self.ui = Ui_Form()
+        self.info = info
+        self.ui.setupUi(self)
+        self.setFixedSize(self.size())
+
+        if 'alignIndex' not in self.info.keys():
+            self.info['alignIndex'] = 0
+
+        if 'shift_x' not in self.info.keys():
+            self.info['shift_x'] = None
+
+        if 'shift_y' not in self.info.keys():
+            self.info['shift_y'] = None
+
+        if 'align' not in self.info.keys():
+            self.info['align'] = (0, 0)
+
+        if self.info['shift_x'] is not None:
+            self.ui.txtShiftX.setText(str(self.info['shift_x']))
+
+        if self.info['shift_y'] is not None:
+            self.ui.txtShiftY.setText(str(self.info['shift_y']))
+
+        
+        self.ui.cmbFontSize.setCurrentText(str(self.info['fontSize']) if self.info['fontSize'] is not None else '-')
+        self.ui.cmbAlign.setCurrentIndex(self.info['alignIndex'])
+
+        validator = Qg.QDoubleValidator()
+
+        self.ui.txtShiftX.setValidator(validator)
+        self.ui.txtShiftY.setValidator(validator)
+        self.ui.cmbFontSize.setValidator(validator)
+
+        self.ui.cmbAlign.currentTextChanged.connect(self.updateCheck)
+        self.ui.cmbAlign.currentIndexChanged.connect(self.cmbIndexUpdate)
+        self.ui.txtShiftX.textEdited.connect(self.shftXUpdate)
+        self.ui.txtShiftY.textEdited.connect(self.shftYUpdate)
+        self.ui.btnAdvancedEdit.clicked.connect(self.btnAdvancedEditClicked)
+        self.ui.cmbFontSize.currentTextChanged.connect(self.cmbFontSizeTextChanged)
+
+        self.updateCheck(self.ui.cmbAlign.currentText())
+
+    def cmbFontSizeTextChanged(self, text: str): 
+        tryParseVal = xu.tryParse(text, float)
+        self.info['fontSize'] = tryParseVal
+
+    def btnAdvancedEditClicked(self):
+        advancedEditDialog = labelEditor.labelEditor(self.ui.txtLabelText.text())
+        advancedEditDialog.show()
+        result = advancedEditDialog.exec_()
+        if result == Qw.QDialog.Accepted:
+            self.ui.txtLabelText.setText(advancedEditDialog.getText())
+
+    @property
+    def labelText(self):
+        return self.ui.txtLabelText.text()
+
+    def updateCheck(self, a0):
+        self.ui.txtShiftX.setEnabled(a0 == 'Custom')
+        self.ui.txtShiftY.setEnabled(a0 == 'Custom')
+
+    def shftXUpdate(self, text):
+        if text:
+            self.info['shift_x'] = float(text)
+            self.updateAlign()
+
+    def shftYUpdate(self, text):
+        if text:
+            self.info['shift_y'] = float(text)
+            self.updateAlign()
+
+    def updateAlign(self):
+        index = self.ui.cmbAlign.currentIndex()
+        self.info['alignIndex'] = index
+        if self.ui.cmbAlign.currentText() == 'Custom':
+            self.info['align'] = (self.info['shift_x'], self.info['shift_y'])
+        elif self.ui.cmbAlign.currentText() == 'None':
+            self.info['align'] = (0, 0)
+        else:
+            self.info['align'] = self.ui.cmbAlign.currentText()
+
+    def cmbIndexUpdate(self, index):
+        self.updateAlign()


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/Widg_addLabel.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/Widg_addPolyOpt.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/Widg_addPolyOpt.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/Widg_addPolyOpt.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,31 @@
+#!/usr/bin/env python3
+
+from pyUIClass.widg_addPolyOpt import Ui_Form
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+
+import sys
+
+
+class Widg_addPolyOpt(Qw.QWidget):
+    def __init__(self, info):
+        super().__init__()
+        self.ui = Ui_Form()
+        self.info = info
+        self.ui.setupUi(self)
+        self.setFixedSize(self.size())
+
+        self.ui.chkInscribed.setChecked(self.info['inscribed'])
+        self.ui.txtSides.setText(str(self.info['sides']))
+        self.ui.txtSides.setValidator(Qg.QIntValidator())
+
+        self.ui.chkInscribed.stateChanged.connect(self.chkInscribedUpdate)
+        self.ui.txtSides.textChanged.connect(self.txtSidesUpdate)
+
+    def chkInscribedUpdate(self, checked):
+        self.info['inscribed'] = checked
+
+    def txtSidesUpdate(self, text):
+        if text:
+            self.info['sides'] = int(text)


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/Widg_addPolyOpt.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/Widg_editBezier.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/Widg_editBezier.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/Widg_editBezier.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,53 @@
+#!/usr/bin/env python3
+
+from pyUIClass.widg_editBezier import Ui_Form
+
+import PyQt5.QtCore as Qc
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+
+class LockMode:
+    noLock = 0
+    angleLock = 1
+    angleAndScaleLock = 2
+
+class Widg_editBezier(Qw.QWidget):
+    def __init__(self, info: dict, enableCurveFeatures: bool=True):
+        super().__init__()
+        self.ui = Ui_Form()
+        self.ui.setupUi(self)
+        self.info = info
+
+        self.ui.chkRecompute.setChecked(self.info['autoRecompute'])
+        self.ui.cmbLockMode.setCurrentIndex(self.info['editBezierlockMode'])
+
+        self.ui.cmbLockMode.currentIndexChanged[int].connect(self.cmbLockIndexChange)
+        self.ui.chkRecompute.stateChanged.connect(self.chkRecomputeChanged)
+
+        self.disableOnAutoRecompute = {self.ui.cmbLockMode, self.ui.btnForceRecompute}
+        self.curveBtnsOnly = {self.ui.cmbLockMode, self.ui.btnForceRecompute, self.ui.chkRecompute}
+
+        for elem in self.curveBtnsOnly:
+            elem.setEnabled(enableCurveFeatures)
+
+    @property
+    def autoRecompute(self) -> bool:
+        return self.ui.chkRecompute.isChecked()
+
+    @property
+    def lockMode(self) -> int:
+        return self.ui.cmbLockMode.currentIndex()
+
+    @Qc.pyqtSlot(int)
+    def cmbLockIndexChange(self, index: int):
+        self.info['editBezierlockMode'] = index
+
+    @Qc.pyqtSlot(int)
+    def chkRecomputeChanged(self, checked: int):
+        isChecked = (checked == 2)
+        for obj in self.disableOnAutoRecompute:
+            obj.setEnabled(not checked)
+        self.info['autoRecompute'] = checked
+        
+        if isChecked:
+            self.ui.btnForceRecompute.clicked.emit()


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/Widg_editBezier.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/Window1.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/Window1.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/Window1.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,1890 @@
+#!/usr/bin/env python3
+
+from pyUIClass.window1 import Ui_MainWindow
+
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import xasyVersion
+
+import numpy as np
+import os
+import json
+import io
+import pathlib
+import webbrowser
+import subprocess
+import tempfile
+import datetime
+import string
+import atexit
+
+import xasyUtils as xu
+import xasy2asy as x2a
+import xasyFile as xf
+import xasyOptions as xo
+import UndoRedoStack as Urs
+import xasyArgs as xa
+import xasyBezierInterface as xbi
+from xasyTransform import xasyTransform as xT
+import xasyStrings as xs
+
+import PrimitiveShape
+import InplaceAddObj
+
+import CustMatTransform
+import SetCustomAnchor
+import GuidesManager
+
+
+class ActionChanges:
+    pass
+
+
+# State Invariance: When ActionChanges is at the top, all state of the program & file
+# is exactly like what it was the event right after that ActionChanges was created.
+
+class TransformationChanges(ActionChanges):
+    def __init__(self, objIndex, transformation, isLocal=False):
+        self.objIndex = objIndex
+        self.transformation = transformation
+        self.isLocal = isLocal
+
+
+class ObjCreationChanges(ActionChanges):
+    def __init__(self, obj):
+        self.object = obj
+
+class HardDeletionChanges(ActionChanges):
+    def __init__(self, obj, pos):
+        self.item = obj
+        self.objIndex = pos
+
+class AnchorMode:
+    origin = 0
+    center = 1
+    topLeft = 2
+    topRight = 3
+    bottomRight = 4
+    bottomLeft = 5
+    customAnchor = 6
+    
+
+class GridMode:
+    cartesian = 0
+    polar = 1
+
+
+class SelectionMode:
+    select = 0
+    pan = 1
+    translate = 2
+    rotate = 3
+    scale = 4
+    delete = 5
+    setAnchor = 6
+    selectEdit = 7
+
+class AddObjectMode:
+    Circle = 0
+    Arc = 1
+    Polygon = 2
+
+class MainWindow1(Qw.QMainWindow):
+    defaultFrameStyle = """
+    QFrame{{ 
+        padding: 4.0;
+        border-radius: 3.0; 
+        background: rgb({0}, {1}, {2})
+    }}
+    """
+
+    def __init__(self):
+        super().__init__()
+        self.ui = Ui_MainWindow()
+        self.ui.setupUi(self)
+
+        self.settings = xo.BasicConfigs.defaultOpt
+        self.keyMaps = xo.BasicConfigs.keymaps
+
+        self.raw_args = Qc.QCoreApplication.arguments()
+        self.args = xa.parseArgs(self.raw_args)
+
+        self.strings = xs.xasyString(self.args.language)
+        self.asy2psmap = x2a.identity()
+
+        if self.settings['asyBaseLocation'] is not None:
+            os.environ['ASYMPTOTE_DIR'] = self.settings['asyBaseLocation']
+
+        if self.args.asypath is not None:
+            asyPath = self.args.asypath
+        else:
+            asyPath = self.settings['asyPath']
+
+        self.asyPath = asyPath
+        self.asyEngine = x2a.AsymptoteEngine(self.asyPath)
+
+        try:
+            self.asyEngine.start()
+        finally:
+            atexit.register(self.asyEngine.cleanup)
+
+        # For initialization purposes
+        self.canvSize = Qc.QSize()
+        self.filename = None
+        self.currDir = None
+        self.mainCanvas = None
+        self.dpi = 300
+        self.canvasPixmap = None
+
+        # Actions
+        # <editor-fold> Connecting Actions
+        self.ui.txtLineWidth.setValidator(Qg.QDoubleValidator())
+
+        self.connectActions()
+        self.connectButtons()
+
+        self.ui.txtLineWidth.returnPressed.connect(self.btnTerminalCommandOnClick)
+        # </editor-fold>
+
+        # Base Transformations
+
+        self.mainTransformation = Qg.QTransform()
+        self.mainTransformation.scale(1, 1)
+        self.localTransform = Qg.QTransform()
+        self.screenTransformation = Qg.QTransform()
+        self.panTranslation = Qg.QTransform()
+
+        # Internal Settings
+        self.magnification = self.args.mag
+        self.inMidTransformation = False
+        self.addMode = None
+        self.currentlySelectedObj = {'key': None, 'allSameKey': set(), 'selectedIndex': None, 'keyIndex': None}
+        self.pendingSelectedObjList = [] 
+        self.pendingSelectedObjIndex = -1
+        
+        self.savedMousePosition = None
+        self.currentBoundingBox = None
+        self.selectionDelta = None
+        self.newTransform = None
+        self.origBboxTransform = None
+        self.deltaAngle = 0
+        self.scaleFactor = 1
+        self.panOffset = [0, 0]
+
+        super().setMouseTracking(True)
+        # setMouseTracking(True)
+        
+        self.undoRedoStack = Urs.actionStack()
+
+        self.lockX = False
+        self.lockY = False
+        self.anchorMode = AnchorMode.center
+        self.currentAnchor = Qc.QPointF(0, 0)
+        self.customAnchor = None
+        self.useGlobalCoords = True
+        self.drawAxes = True
+        self.drawGrid = False
+        self.gridSnap = False  # TODO: for now. turn it on later
+
+        self.fileChanged = False
+
+        self.terminalPythonMode = self.ui.btnTogglePython.isChecked()
+
+        self.savedWindowMousePos = None
+
+        self.finalPixmap = None
+        self.preCanvasPixmap = None
+        self.postCanvasPixmap = None
+        self.previewCurve = None
+        self.mouseDown = False
+
+        self.globalObjectCounter = 0
+
+        self.fileItems = []
+        self.drawObjects = []
+        self.xasyDrawObj = {'drawDict': self.drawObjects}
+
+        self.modeButtons = {
+            self.ui.btnTranslate, self.ui.btnRotate, self.ui.btnScale, # self.ui.btnSelect,
+            self.ui.btnPan, self.ui.btnDeleteMode, self.ui.btnAnchor, 
+            self.ui.btnSelectEdit
+                            }
+
+        self.objButtons = {self.ui.btnCustTransform, self.ui.actionTransform, self.ui.btnSendForwards,
+                           self.ui.btnSendBackwards, self.ui.btnToggleVisible
+                           }
+
+        self.globalTransformOnlyButtons = (self.ui.comboAnchor, self.ui.btnAnchor)
+
+        self.ui.txtTerminalPrompt.setFont(Qg.QFont(self.settings['terminalFont']))
+
+        self.currAddOptionsWgt = None
+        self.currAddOptions = {
+            'options': self.settings, 
+            'inscribed': True,
+            'sides': 3,
+            'centermode': True,
+            'fontSize': None, 
+            'asyengine': self.asyEngine,
+            'fill': self.ui.btnFill.isChecked(),
+            'closedPath': False,
+            'useBezier': True, 
+            'magnification': self.magnification,
+            'editBezierlockMode': xbi.Web.LockMode.angleLock, 
+            'autoRecompute': False
+        }
+
+
+        self.currentModeStack = [SelectionMode.translate]
+        self.drawGridMode = GridMode.cartesian
+        self.setAllInSetEnabled(self.objButtons, False)
+        self._currentPen = x2a.asyPen()
+        self.currentGuides = []
+        self.selectAsGroup = self.settings['groupObjDefault']
+
+        # commands switchboard
+        self.commandsFunc = {
+            'quit': Qc.QCoreApplication.quit,
+            'undo': self.btnUndoOnClick,
+            'redo': self.btnRedoOnClick,
+            'manual': self.actionManual,
+            'about': self.actionAbout,
+            'loadFile': self.btnLoadFileonClick,
+            'save': self.actionSave,
+            'saveAs': self.actionSaveAs,
+            'transform': self.btnCustTransformOnClick,
+            'commandPalette': self.enterCustomCommand,
+            'clearGuide': self.clearGuides,
+            'finalizeAddObj': self.finalizeAddObj,
+            'finalizeCurve': self.finalizeCurve, 
+            'finalizeCurveClosed': self.finalizeCurveClosed, 
+            'setMag': self.setMagPrompt,
+            'deleteObject': self.btnSelectiveDeleteOnClick, 
+            'anchorMode': self.switchToAnchorMode,
+            'moveUp': lambda: self.arrowButtons(0, 1, False), 
+            'moveDown': lambda: self.arrowButtons(0, -1, False),
+
+            'scrollLeft': lambda: self.arrowButtons(-1, 0, True),
+            'scrollRight': lambda: self.arrowButtons(1, 0, True),
+            'scrollUp': lambda: self.arrowButtons(0, 1, True),
+            'scrollDown': lambda: self.arrowButtons(0, -1, True), 
+
+            'zoomIn': lambda: self.arrowButtons(0, 1, False, True), 
+            'zoomOut': lambda: self.arrowButtons(0, -1, False, True)
+        }
+
+        self.hiddenKeys = set()
+
+        # Coordinates Label
+
+        self.coordLabel = Qw.QLabel(self.ui.statusbar)
+        self.ui.statusbar.addPermanentWidget(self.coordLabel)
+
+        # Settings Initialization
+        # from xasyoptions config file
+        self.loadKeyMaps()
+        self.setupXasyOptions()
+
+        self.colorDialog = Qw.QColorDialog(x2a.asyPen.convertToQColor(self._currentPen.color), self)
+        self.initPenInterface()
+
+    def arrowButtons(self, x:int , y:int, shift: bool=False, ctrl: bool=False):
+        "x, y indicates update button orientation on the cartesian plane."
+        if not (shift or ctrl):
+            self.changeSelection(y)
+        elif not (shift and ctrl):
+            self.mouseWheel(30*x, 30*y)
+        self.quickUpdate()
+
+    def cleanup(self):
+        self.asyengine.cleanup()
+
+    def getScrsTransform(self):
+        # pipeline:
+        # assuming origin <==> top left
+        # (Pan) * (Translate) * (Flip the images) * (Zoom) * (Obj transform) * (Base Information) 
+
+        # pipeline --> let x, y be the postscript point
+        # p = (mx + cx + panoffset, -ny + cy + panoffset)
+        cx, cy = self.canvSize.width() / 2, self.canvSize.height() / 2
+
+        newTransf = Qg.QTransform()
+        newTransf.translate(*self.panOffset)
+        newTransf.translate(cx, cy)
+        newTransf.scale(1, 1)
+        newTransf.scale(self.magnification, self.magnification)
+
+        return newTransf
+
+    def finalizeCurve(self):
+        if self.addMode is not None:
+            if self.addMode.active and isinstance(self.addMode, InplaceAddObj.AddBezierShape):
+                self.addMode.forceFinalize()
+                self.fileChanged = True
+
+    def finalizeCurveClosed(self):
+        if self.addMode is not None:
+            if self.addMode.active and isinstance(self.addMode, InplaceAddObj.AddBezierShape):
+                self.addMode.finalizeClosure()
+                self.fileChanged = True
+
+    def getAllBoundingBox(self) -> Qc.QRectF:
+        newRect = Qc.QRectF()
+        for majitem in self.drawObjects:
+            for minitem in majitem:
+                newRect = newRect.united(minitem.boundingBox)
+        return newRect
+
+    def finalizeAddObj(self):
+        if self.addMode is not None:
+            if self.addMode.active:
+                self.addMode.forceFinalize()
+                self.fileChanged = True
+
+    def openAndReloadSettings(self):
+        settingsFile = self.settings.settingsFileLocation()
+        subprocess.run(args=self.getExternalEditor(asypath=settingsFile))
+        self.settings.load()
+        self.quickUpdate()
+
+    def setMagPrompt(self):
+        commandText, result = Qw.QInputDialog.getText(self, '', 'Enter magnification:')
+        if result:
+            self.magnification = float(commandText)
+            self.currAddOptions['magnification'] = self.magnification
+            self.quickUpdate()
+
+    def btnTogglePythonOnClick(self, checked):
+        self.terminalPythonMode = checked
+
+    def internationalize(self):
+        self.ui.btnRotate.setToolTip(self.strings.rotate)
+
+    def handleArguments(self):
+        if self.args.filename is not None:
+            self.loadFile(self.args.filename)
+        else:
+            self.initializeEmptyFile()
+
+        if self.args.language != 'en':
+            self.internationalize()
+
+    def initPenInterface(self):
+        self.ui.txtLineWidth.setText(str(self._currentPen.width))
+        self.updateFrameDispColor()
+
+    def updateFrameDispColor(self):
+        r, g, b = [int(x * 255) for x in self._currentPen.color]
+        self.ui.frameCurrColor.setStyleSheet(MainWindow1.defaultFrameStyle.format(r, g, b))
+
+    def initDebug(self):
+        debugFunc = {
+        }
+        self.commandsFunc = {**self.commandsFunc, **debugFunc}
+
+    def dbgRecomputeCtrl(self):
+        if isinstance(self.addMode, xbi.InteractiveBezierEditor):
+            self.addMode.recalculateCtrls()
+            self.quickUpdate()
+
+    def objectUpdated(self):
+        self.removeAddMode()
+        self.clearSelection()
+        self.asyfyCanvas()
+
+    def connectActions(self):
+        self.ui.actionQuit.triggered.connect(lambda: self.execCustomCommand('quit'))
+        self.ui.actionUndo.triggered.connect(lambda: self.execCustomCommand('undo'))
+        self.ui.actionRedo.triggered.connect(lambda: self.execCustomCommand('redo'))
+        self.ui.actionTransform.triggered.connect(lambda: self.execCustomCommand('transform'))
+
+        self.ui.actionOpen.triggered.connect(self.actionOpen)
+        self.ui.actionSave.triggered.connect(self.actionSave)
+        self.ui.actionSaveAs.triggered.connect(self.actionSaveAs)
+        self.ui.actionManual.triggered.connect(self.actionManual)
+        self.ui.actionAbout.triggered.connect(self.actionAbout)
+        self.ui.actionSettings.triggered.connect(self.openAndReloadSettings)
+        self.ui.actionEnterCommand.triggered.connect(self.enterCustomCommand)
+        self.ui.actionExportAsymptote.triggered.connect(self.btnExportAsyOnClick)
+
+    def setupXasyOptions(self):
+        if self.settings['debugMode']:
+            self.initDebug()
+        newColor = Qg.QColor(self.settings['defaultPenColor'])
+        newWidth = self.settings['defaultPenWidth']
+
+        self._currentPen.setColorFromQColor(newColor)
+        self._currentPen.setWidth(newWidth)
+
+    def connectButtons(self):
+        # Button initialization
+        self.ui.btnUndo.clicked.connect(self.btnUndoOnClick)
+        self.ui.btnRedo.clicked.connect(self.btnRedoOnClick)
+        self.ui.btnLoadFile.clicked.connect(self.btnLoadFileonClick)
+        self.ui.btnSave.clicked.connect(self.btnSaveonClick)
+        self.ui.btnQuickScreenshot.clicked.connect(self.btnQuickScreenshotOnClick)
+
+        # self.ui.btnExportAsy.clicked.connect(self.btnExportAsyOnClick)
+
+        self.ui.btnDrawAxes.clicked.connect(self.btnDrawAxesOnClick)
+#        self.ui.btnAsyfy.clicked.connect(lambda: self.asyfyCanvas(True))
+        self.ui.btnSetZoom.clicked.connect(self.setMagPrompt)
+        self.ui.btnResetPan.clicked.connect(self.resetPan)
+        self.ui.btnPanCenter.clicked.connect(self.btnPanCenterOnClick)
+
+        self.ui.btnTranslate.clicked.connect(self.btnTranslateonClick)
+        self.ui.btnRotate.clicked.connect(self.btnRotateOnClick)
+        self.ui.btnScale.clicked.connect(self.btnScaleOnClick)
+        # self.ui.btnSelect.clicked.connect(self.btnSelectOnClick)
+        self.ui.btnPan.clicked.connect(self.btnPanOnClick)
+
+        # self.ui.btnDebug.clicked.connect(self.pauseBtnOnClick)
+        self.ui.btnAlignX.clicked.connect(self.btnAlignXOnClick)
+        self.ui.btnAlignY.clicked.connect(self.btnAlignYOnClick)
+        self.ui.comboAnchor.currentIndexChanged.connect(self.handleAnchorComboIndex)
+        self.ui.btnCustTransform.clicked.connect(self.btnCustTransformOnClick)
+        self.ui.btnViewCode.clicked.connect(self.btnLoadEditorOnClick)
+
+        self.ui.btnAnchor.clicked.connect(self.btnAnchorModeOnClick)
+
+        self.ui.btnSelectColor.clicked.connect(self.btnColorSelectOnClick)
+        self.ui.txtLineWidth.textEdited.connect(self.txtLineWithEdited)
+
+        # self.ui.btnCreateCurve.clicked.connect(self.btnCreateCurveOnClick)
+        self.ui.btnDrawGrid.clicked.connect(self.btnDrawGridOnClick)
+
+        self.ui.btnAddCircle.clicked.connect(self.btnAddCircleOnClick)
+        self.ui.btnAddPoly.clicked.connect(self.btnAddPolyOnClick)
+        self.ui.btnAddLabel.clicked.connect(self.btnAddLabelOnClick)
+        # self.ui.btnAddBezierInplace.clicked.connect(self.btnAddBezierInplaceOnClick)
+        self.ui.btnClosedCurve.clicked.connect(self.btnAddClosedCurveOnClick)
+        self.ui.btnOpenCurve.clicked.connect(self.btnAddOpenCurveOnClick)
+        self.ui.btnClosedPoly.clicked.connect(self.btnAddClosedLineOnClick)
+        self.ui.btnOpenPoly.clicked.connect(self.btnAddOpenLineOnClick)
+
+        self.ui.btnFill.clicked.connect(self.btnFillOnClick)
+
+        self.ui.btnSendBackwards.clicked.connect(self.btnSendBackwardsOnClick)
+        self.ui.btnSendForwards.clicked.connect(self.btnSendForwardsOnClick)
+        # self.ui.btnDelete.clicked.connect(self.btnSelectiveDeleteOnClick)
+        self.ui.btnDeleteMode.clicked.connect(self.btnDeleteModeOnClick)
+        # self.ui.btnSoftDelete.clicked.connect(self.btnSoftDeleteOnClick)
+        self.ui.btnToggleVisible.clicked.connect(self.btnSetVisibilityOnClick)
+        
+        self.ui.btnEnterCommand.clicked.connect(self.btnTerminalCommandOnClick)
+        self.ui.btnTogglePython.clicked.connect(self.btnTogglePythonOnClick)
+        self.ui.btnSelectEdit.clicked.connect(self.btnSelectEditOnClick)
+
+    def btnDeleteModeOnClick(self):
+        self.currentModeStack = [SelectionMode.delete]
+        self.ui.statusbar.showMessage('Delete Mode')
+        self.clearSelection()
+        self.updateChecks()
+
+    def btnTerminalCommandOnClick(self):
+        if self.terminalPythonMode:
+            exec(self.ui.txtTerminalPrompt.text())
+            self.fileChanged = True
+        else:
+            pass
+            # TODO: How to handle this case?
+            # Like AutoCAD? 
+        self.ui.txtTerminalPrompt.clear()
+
+    def btnFillOnClick(self, checked): 
+        self.currAddOptions['fill'] = checked
+        self.ui.btnOpenCurve.setEnabled(not checked)
+        self.ui.btnOpenPoly.setEnabled(not checked)
+
+    def btnSelectEditOnClick(self):
+        self.ui.statusbar.showMessage('Edit mode')
+        self.currentModeStack = [SelectionMode.selectEdit]
+        self.updateChecks()
+
+    @property
+    def currentPen(self):
+        return x2a.asyPen.fromAsyPen(self._currentPen)
+        pass
+    def debug(self):
+        print('Put a breakpoint here.')
+
+    def execPythonCmd(self):
+        commandText, result = Qw.QInputDialog.getText(self, '', 'enter python cmd')
+        if result:
+            exec(commandText)
+
+    def deleteAddOptions(self):
+        if self.currAddOptionsWgt is not None:
+            self.currAddOptionsWgt.hide()
+            self.ui.addOptionLayout.removeWidget(self.currAddOptionsWgt)
+            self.currAddOptionsWgt = None
+
+    def updateOptionWidget(self):
+        try:
+            self.addMode.objectCreated.disconnect()
+        except Exception:
+            pass
+
+        self.currentModeStack[-1] = None
+        self.addMode.objectCreated.connect(self.addInPlace)
+        self.updateModeBtnsOnly()
+
+
+        self.deleteAddOptions()
+
+        self.currAddOptionsWgt = self.addMode.createOptWidget(self.currAddOptions)
+        if self.currAddOptionsWgt is not None:
+            self.ui.addOptionLayout.addWidget(self.currAddOptionsWgt)
+
+    def addInPlace(self, obj):
+        obj.asyengine = self.asyEngine
+        obj.pen = self.currentPen
+        obj.onCanvas = self.xasyDrawObj
+        obj.setKey(str(self.globalObjectCounter))
+        self.globalObjectCounter = self.globalObjectCounter + 1
+
+        self.fileItems.append(obj)
+        self.fileChanged = True
+        self.addObjCreationUrs(obj)
+        self.asyfyCanvas()
+
+    def addObjCreationUrs(self, obj):
+        newAction = self.createAction(ObjCreationChanges(obj))
+        self.undoRedoStack.add(newAction)
+        self.checkUndoRedoButtons()
+
+    def clearGuides(self):
+        self.currentGuides.clear()
+        self.quickUpdate()
+
+    def btnAddCircleOnClick(self):
+        self.addMode = InplaceAddObj.AddCircle(self)
+        self.ui.statusbar.showMessage('')
+        self.updateOptionWidget()
+
+    LegacyHint='Click and drag to draw; right click or space bar to finalize'
+    Hint='Click and drag to draw; release and click in place to add node; continue dragging'
+    HintClose=' or c to close.'
+
+    def drawHint(self):
+        if self.settings['useLegacyDrawMode']:
+            self.ui.statusbar.showMessage(self.LegacyHint+'.')
+        else:
+            self.ui.statusbar.showMessage(self.Hint+'.')
+
+    def drawHintOpen(self):
+        if self.settings['useLegacyDrawMode']:
+            self.ui.statusbar.showMessage(self.LegacyHint+self.HintClose)
+        else:
+            self.ui.statusbar.showMessage(self.Hint+self.HintClose)
+
+    def btnAddBezierInplaceOnClick(self):
+        self.addMode = InplaceAddObj.AddBezierShape(self)
+        self.updateOptionWidget()
+
+    def btnAddOpenLineOnClick(self):
+        self.currAddOptions['useBezier'] = False
+        self.currAddOptions['closedPath'] = False
+        self.drawHintOpen()
+        self.btnAddBezierInplaceOnClick()
+
+    def btnAddClosedLineOnClick(self):
+        self.currAddOptions['useBezier'] = False
+        self.currAddOptions['closedPath'] = True
+        self.drawHint()
+        self.btnAddBezierInplaceOnClick()
+
+    def btnAddOpenCurveOnClick(self):
+        self.currAddOptions['useBezier'] = True
+        self.currAddOptions['closedPath'] = False
+        self.drawHintOpen()
+        self.btnAddBezierInplaceOnClick()
+
+    def btnAddClosedCurveOnClick(self):
+        self.currAddOptions['useBezier'] = True
+        self.currAddOptions['closedPath'] = True
+        self.drawHint()
+        self.btnAddBezierInplaceOnClick()
+
+    def btnAddPolyOnClick(self):
+        self.addMode = InplaceAddObj.AddPoly(self)
+        self.ui.statusbar.showMessage('')
+        self.updateOptionWidget()
+
+    def btnAddLabelOnClick(self):
+        self.addMode = InplaceAddObj.AddLabel(self)
+        self.ui.statusbar.showMessage('')
+        self.updateOptionWidget()
+
+    def updateCurve(self, valid, newCurve):
+        self.previewCurve = newCurve
+        self.quickUpdate()
+
+    def addTransformationChanges(self, objIndex, transform, isLocal=False):
+        self.undoRedoStack.add(self.createAction(TransformationChanges(objIndex, 
+                            transform, isLocal)))
+        self.checkUndoRedoButtons()
+
+    def btnSendForwardsOnClick(self):
+        if self.currentlySelectedObj['selectedIndex'] is not None:
+            maj, minor = self.currentlySelectedObj['selectedIndex']
+            selectedObj = self.drawObjects[maj][minor]
+            index = self.fileItems.index(selectedObj.parent())
+
+            self.clearSelection()
+            if index == len(self.fileItems) - 1:
+                return
+            else:
+                self.fileItems[index], self.fileItems[index + 1] = self.fileItems[index + 1], self.fileItems[index]
+                self.asyfyCanvas()
+
+    def btnSelectiveDeleteOnClick(self):
+        if self.currentlySelectedObj['selectedIndex'] is not None:
+            maj, minor = self.currentlySelectedObj['selectedIndex']
+            selectedObj = self.drawObjects[maj][minor]
+
+            parent = selectedObj.parent()
+
+            if isinstance(parent, x2a.xasyScript):
+                self.hiddenKeys.add((selectedObj.key, selectedObj.keyIndex))
+                self.softDeleteObj((maj, minor))
+            else:
+                index = self.fileItems.index(selectedObj.parent())
+
+                self.undoRedoStack.add(self.createAction(
+                    HardDeletionChanges(selectedObj.parent(), index)
+                ))
+                self.checkUndoRedoButtons()
+                
+                self.fileItems.remove(selectedObj.parent())
+
+            self.fileChanged = True
+            self.clearSelection()
+            self.asyfyCanvas()
+        else:
+            result = self.selectOnHover()
+            if result:
+                self.btnSelectiveDeleteOnClick()
+
+    def btnSetVisibilityOnClick(self):
+        if self.currentlySelectedObj['selectedIndex'] is not None:
+            maj, minor = self.currentlySelectedObj['selectedIndex']
+            selectedObj = self.drawObjects[maj][minor]
+
+            self.hiddenKeys.symmetric_difference_update({(selectedObj.key, selectedObj.keyIndex)})
+            self.clearSelection()
+            self.quickUpdate()
+
+    def btnSendBackwardsOnClick(self):
+        if self.currentlySelectedObj['selectedIndex'] is not None:
+            maj, minor = self.currentlySelectedObj['selectedIndex']
+            selectedObj = self.drawObjects[maj][minor]
+            index = self.fileItems.index(selectedObj.parent())
+
+            self.clearSelection()
+            if index == 0:
+                return
+            else:
+                self.fileItems[index], self.fileItems[index - 1] = self.fileItems[index - 1], self.fileItems[index]
+                self.asyfyCanvas()
+
+
+    def btnUndoOnClick(self):
+        self.undoRedoStack.undo()
+        self.checkUndoRedoButtons()
+
+    def btnRedoOnClick(self):
+        self.undoRedoStack.redo()
+        self.checkUndoRedoButtons()
+
+    def checkUndoRedoButtons(self):
+        self.ui.btnUndo.setEnabled(self.undoRedoStack.changesMade())
+        self.ui.actionUndo.setEnabled(self.undoRedoStack.changesMade())
+
+        self.ui.btnRedo.setEnabled(len(self.undoRedoStack.redoStack) > 0)
+        self.ui.actionRedo.setEnabled(len(self.undoRedoStack.redoStack) > 0)
+
+    def handleUndoChanges(self, change):
+        assert isinstance(change, ActionChanges)
+        if isinstance(change, TransformationChanges):
+            self.transformObject(change.objIndex, change.transformation.inverted(), change.isLocal)
+        elif isinstance(change, ObjCreationChanges):
+            self.fileItems.pop()
+        elif isinstance(change, HardDeletionChanges):
+            self.fileItems.insert(change.objIndex, change.item)
+        self.asyfyCanvas()
+
+    def handleRedoChanges(self, change):
+        assert isinstance(change, ActionChanges)
+        if isinstance(change, TransformationChanges):
+            self.transformObject(
+                 change.objIndex, change.transformation, change.isLocal)
+        elif isinstance(change, ObjCreationChanges):
+            self.fileItems.append(change.object)
+        elif isinstance(change, HardDeletionChanges):
+            self.fileItems.remove(change.item)
+        self.asyfyCanvas()
+
+    #  is this a "pythonic" way?
+    def createAction(self, changes):
+        def _change():
+            return self.handleRedoChanges(changes)
+
+        def _undoChange():
+            return self.handleUndoChanges(changes)
+
+        return Urs.action((_change, _undoChange))
+
+    def execCustomCommand(self, command):
+        if command in self.commandsFunc:
+            self.commandsFunc[command]()
+        else:
+            self.ui.statusbar.showMessage('Command {0} not found'.format(command))
+
+    def enterCustomCommand(self):
+        commandText, result = Qw.QInputDialog.getText(self, 'Enter Custom Command', 'Enter Custom Command')
+        if result:
+            self.execCustomCommand(commandText)
+
+    def addItemFromPath(self, path):
+        newItem = x2a.xasyShape(path, self.asyEngine, pen=self.currentPen)
+        self.fileItems.append(newItem)
+        self.fileChanged = True
+        self.asyfyCanvas()
+
+    def actionManual(self):
+        asyManualURL = 'http://asymptote.sourceforge.net/asymptote.pdf'
+        webbrowser.open_new(asyManualURL)
+
+    def actionAbout(self):
+        Qw.QMessageBox.about(self,"xasy","This is xasy "+xasyVersion.xasyVersion+"; a graphical front end to the Asymptote vector graphics language: http://asymptote.sourceforge.net/")
+
+    def btnExportAsyOnClick(self):
+        diag = Qw.QFileDialog(self)
+        diag.setAcceptMode(Qw.QFileDialog.AcceptSave)
+
+        formatId = {
+            'pdf': {
+                'name': 'PDF Files',
+                'ext': ['*.pdf']
+            },
+            'svg': {
+                'name': 'Scalable Vector Graphics',
+                'ext': ['*.svg']
+            },
+            'eps': {
+                'name': 'Postscript Files',
+                'ext': ['*.eps']
+            },
+            'png': {
+                'name': 'Portable Network Graphics',
+                'ext': ['*.png']
+            },
+            '*': {
+                'name': 'Any Files',
+                'ext': ['*.*']
+            }
+        }
+
+        formats = ['pdf', 'svg', 'eps', 'png', '*']
+
+        formatText = ';;'.join('{0:s} ({1:s})'.format(formatId[form]['name'], ' '.join(formatId[form]['ext']))
+                               for form in formats)
+
+        if self.currDir is not None:
+            diag.setDirectory(self.currDir)
+            rawFile = os.path.splitext(os.path.basename(self.filename))[0] + '.pdf'
+            diag.selectFile(rawFile)
+
+        diag.setNameFilter(formatText)
+        diag.show()
+        result = diag.exec_()
+
+        if result != diag.Accepted:
+            return
+
+        finalFiles = diag.selectedFiles()
+
+        with io.StringIO() as finalCode:
+            xf.saveFile(finalCode, self.fileItems, self.asy2psmap)
+            finalString = finalCode.getvalue()
+
+        for file in finalFiles:
+            ext = os.path.splitext(file)
+            if len(ext) < 2:
+                ext = 'pdf'
+            else:
+                ext = ext[1][1:]
+
+            with subprocess.Popen(args=[self.asyPath, '-f{0}'.format(ext), '-o{0}'.format(file), '-'], encoding='utf-8',
+                                  stdin=subprocess.PIPE) as asy:
+                print('test:', finalString)
+                asy.stdin.write(finalString)
+                asy.stdin.close()
+                asy.wait(timeout=35)
+
+
+    def loadKeyMaps(self):
+        """Inverts the mapping of the key
+           Input map is in format 'Action' : 'Key Sequence' """
+        for action, key in self.keyMaps.options.items():
+            shortcut = Qw.QShortcut(self)
+            shortcut.setKey(Qg.QKeySequence(key))
+
+            # hate doing this, but python doesn't have explicit way to pass a
+            # string to a lambda without an identifier
+            # attached to it.
+            exec('shortcut.activated.connect(lambda: self.execCustomCommand("{0}"))'.format(action),
+                 {'self': self, 'shortcut': shortcut})
+
+    def initializeButtons(self):
+        self.ui.btnDrawAxes.setChecked(self.settings['defaultShowAxes'])
+        self.btnDrawAxesOnClick(self.settings['defaultShowAxes'])
+
+        self.ui.btnDrawGrid.setChecked(self.settings['defaultShowGrid'])
+        self.btnDrawGridOnClick(self.settings['defaultShowGrid'])
+
+    def erase(self):
+        self.fileItems.clear()
+        self.fileChanged = False
+
+    def actionOpen(self):
+        if self.fileChanged:
+            save="Save current file?"
+            reply=Qw.QMessageBox.question(self,'Message',save,Qw.QMessageBox.Yes,
+                                        Qw.QMessageBox.No)
+            if reply == Qw.QMessageBox.Yes:
+                self.actionSave()
+
+        filename = Qw.QFileDialog.getOpenFileName(self, 'Open Asymptote File','', '*.asy')
+        if filename[0]:
+            self.loadFile(filename[0])
+
+    def actionSave(self):
+        if self.filename is None:
+            self.actionSaveAs()
+        else:
+            saveFile = io.open(self.filename, 'w')
+            xf.saveFile(saveFile, self.fileItems, self.asy2psmap)
+            saveFile.close()
+            self.updateScript()
+
+    def updateScript(self):
+        for item in self.fileItems:
+            if isinstance(item, x2a.xasyScript):
+                if item.updatedCode:
+                    item.setScript(item.updatedCode)
+                    item.updatedCode = None
+
+    def actionSaveAs(self):
+        saveLocation = Qw.QFileDialog.getSaveFileName(self, 'Save File')[0]
+        if saveLocation:
+            saveFile = io.open(saveLocation, 'w')
+            xf.saveFile(saveFile, self.fileItems, self.asy2psmap)
+            saveFile.close()
+            self.filename = saveLocation
+            self.updateScript()
+            
+
+    def btnQuickScreenshotOnClick(self):
+        saveLocation = Qw.QFileDialog.getSaveFileName(self, 'Save Screenshot','')
+        if saveLocation[0]:
+            self.ui.imgLabel.pixmap().save(saveLocation[0])
+
+    def btnLoadFileonClick(self):
+        self.actionOpen()
+
+    def btnSaveonClick(self):
+        self.actionSave()
+
+    @Qc.pyqtSlot(int)
+    def handleAnchorComboIndex(self, index: int):
+        self.anchorMode = index
+        if self.anchorMode == AnchorMode.customAnchor:
+            if self.customAnchor is not None:
+                self.anchorMode = AnchorMode.customAnchor
+            else:
+                self.ui.comboAnchor.setCurrentIndex(AnchorMode.center)
+                self.anchorMode = AnchorMode.center
+        self.quickUpdate()
+    def btnColorSelectOnClick(self):
+        self.colorDialog.show()
+        result = self.colorDialog.exec()
+        if result == Qw.QDialog.Accepted:
+            self._currentPen.setColorFromQColor(self.colorDialog.selectedColor())
+            self.updateFrameDispColor()
+
+    def txtLineWithEdited(self, text):
+        new_val = xu.tryParse(text, float)
+        if new_val is not None:
+            if new_val > 0:
+                self._currentPen.setWidth(new_val)
+
+    def isReady(self):
+        return self.mainCanvas is not None
+
+    def resizeEvent(self, resizeEvent):
+        # super().resizeEvent(resizeEvent)
+        assert isinstance(resizeEvent, Qg.QResizeEvent)
+
+        if self.isReady():
+            if self.mainCanvas.isActive():
+                self.mainCanvas.end()
+            self.canvSize = self.ui.imgFrame.size()
+            self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+            self.canvasPixmap = Qg.QPixmap(self.canvSize)
+            # self.canvasPixmap.setDevicePixelRatio(3)
+            self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
+
+            self.quickUpdate()
+
+    def show(self):
+        super().show()
+        self.createMainCanvas()  # somehow, the coordinates doesn't get updated until after showing.
+        self.initializeButtons()
+        self.postShow()
+
+    def postShow(self):
+        self.handleArguments()
+
+    def roundPositionSnap(self, oldPoint):
+        minorGridSize = self.settings['gridMajorAxesSpacing'] / (self.settings['gridMinorAxesCount'] + 1)
+        if isinstance(oldPoint, list) or isinstance(oldPoint, tuple):
+            return [round(val / minorGridSize) * minorGridSize for val in oldPoint]
+        elif isinstance(oldPoint, Qc.QPoint) or isinstance(oldPoint, Qc.QPointF):
+            x, y = oldPoint.x(), oldPoint.y()
+            x = round(x / minorGridSize) * minorGridSize
+            y = round(y / minorGridSize) * minorGridSize
+            return Qc.QPointF(x, y)
+        else:
+            raise Exception
+
+    def getAsyCoordinates(self):
+        canvasPosOrig = self.getCanvasCoordinates()
+        return canvasPosOrig, canvasPosOrig
+
+    def mouseMoveEvent(self, mouseEvent: Qg.QMouseEvent):  # TODO: Actually refine grid snapping...
+        if not self.ui.imgLabel.underMouse() and not self.mouseDown:
+            return 
+
+        self.updateMouseCoordLabel()
+        asyPos, canvasPos = self.getAsyCoordinates()
+
+        # add mode 
+        if self.addMode is not None:
+            if self.addMode.active:
+                self.addMode.mouseMove(asyPos, mouseEvent)
+                self.quickUpdate()
+            return
+
+        # pan mode
+        if self.currentModeStack[-1] == SelectionMode.pan and int(mouseEvent.buttons()) and self.savedWindowMousePos is not None:
+            mousePos = self.getWindowCoordinates()
+            newPos = mousePos - self.savedWindowMousePos
+
+            tx, ty = newPos.x(), newPos.y()
+
+            if self.lockX:
+                tx = 0
+            if self.lockY:
+                ty = 0
+
+            self.panOffset[0] += tx
+            self.panOffset[1] += ty
+
+            self.savedWindowMousePos = self.getWindowCoordinates()
+            self.quickUpdate()
+            return
+
+        # otherwise, in transformation 
+        if self.inMidTransformation:
+            if self.currentModeStack[-1] == SelectionMode.translate:
+                newPos = canvasPos - self.savedMousePosition
+                if self.gridSnap:
+                    newPos = self.roundPositionSnap(newPos)  # actually round to the nearest minor grid afterwards...
+
+                self.tx, self.ty = newPos.x(), newPos.y()
+
+                if self.lockX:
+                    self.tx = 0
+                if self.lockY:
+                    self.ty = 0
+                self.newTransform = Qg.QTransform.fromTranslate(self.tx, self.ty)
+
+            elif self.currentModeStack[-1] == SelectionMode.rotate:
+                if self.gridSnap:
+                    canvasPos = self.roundPositionSnap(canvasPos)
+
+                adjustedSavedMousePos = self.savedMousePosition - self.currentAnchor
+                adjustedCanvasCoords = canvasPos - self.currentAnchor
+
+                origAngle = np.arctan2(adjustedSavedMousePos.y(), adjustedSavedMousePos.x())
+                newAng = np.arctan2(adjustedCanvasCoords.y(), adjustedCanvasCoords.x())
+                self.deltaAngle = newAng - origAngle
+                self.newTransform = xT.makeRotTransform(self.deltaAngle, self.currentAnchor).toQTransform()
+
+            elif self.currentModeStack[-1] == SelectionMode.scale:
+                if self.gridSnap:
+                    canvasPos = self.roundPositionSnap(canvasPos)
+                    x, y = int(round(canvasPos.x())), int(round(canvasPos.y()))  # otherwise it crashes...
+                    canvasPos = Qc.QPoint(x, y)
+
+                originalDeltaPts = self.savedMousePosition - self.currentAnchor
+                scaleFactor = Qc.QPointF.dotProduct(canvasPos - self.currentAnchor, originalDeltaPts) /\
+                    (xu.twonorm((originalDeltaPts.x(), originalDeltaPts.y())) ** 2)
+                if not self.lockX:
+                    self.scaleFactorX = scaleFactor
+                else:
+                    self.scaleFactorX = 1
+
+                if not self.lockY:
+                    self.scaleFactorY = scaleFactor
+                else:
+                    self.scaleFactorY = 1
+
+                self.newTransform = xT.makeScaleTransform(self.scaleFactorX, self.scaleFactorY, self.currentAnchor).\
+                    toQTransform()
+
+            self.quickUpdate()
+            return
+
+        # otherwise, select a candinate for selection
+
+        if self.currentlySelectedObj['selectedIndex'] is None:
+            selectedIndex, selKeyList = self.selectObject()
+            if selectedIndex is not None:
+                if self.pendingSelectedObjList != selKeyList:
+                    self.pendingSelectedObjList = selKeyList
+                    self.pendingSelectedObjIndex = -1
+            else:
+                self.pendingSelectedObjList.clear()
+                self.pendingSelectedObjIndex = -1
+            self.quickUpdate()
+            return 
+
+
+    def mouseReleaseEvent(self, mouseEvent):
+        assert isinstance(mouseEvent, Qg.QMouseEvent) 
+        if not self.mouseDown:
+            return
+
+        self.mouseDown = False
+        if self.addMode is not None:
+            self.addMode.mouseRelease()
+        if self.inMidTransformation:
+            self.clearSelection()
+        self.inMidTransformation = False
+        self.quickUpdate()
+
+    def clearSelection(self):
+        if self.currentlySelectedObj['selectedIndex'] is not None:
+            self.releaseTransform()
+        self.setAllInSetEnabled(self.objButtons, False)
+        self.currentlySelectedObj['selectedIndex'] = None
+        self.currentlySelectedObj['key'] = None
+
+        self.currentlySelectedObj['allSameKey'].clear()
+        self.newTransform = Qg.QTransform()
+        self.currentBoundingBox = None
+        self.quickUpdate()
+
+    def changeSelection(self, offset):
+        if self.pendingSelectedObjList:
+            if offset > 0:
+                if self.pendingSelectedObjIndex + offset <= -1:
+                    self.pendingSelectedObjIndex = self.pendingSelectedObjIndex + offset
+            else:
+                if self.pendingSelectedObjIndex + offset >= -len(self.pendingSelectedObjList):
+                    self.pendingSelectedObjIndex = self.pendingSelectedObjIndex + offset
+
+    def mouseWheel(self, rawAngleX: float, rawAngle: float, defaultModifiers: int=0):
+        keyModifiers = int(Qw.QApplication.keyboardModifiers())
+        keyModifiers = keyModifiers | defaultModifiers
+        if keyModifiers & int(Qc.Qt.ControlModifier):
+            oldMag = self.magnification
+
+            cx, cy = self.canvSize.width() / 2, self.canvSize.height() / 2
+            centerPoint = Qc.QPointF(cx, cy) * self.getScrsTransform().inverted()[0]
+
+            self.magnification += (rawAngle/100)
+
+            if self.magnification < self.settings['minimumMagnification']:
+                self.magnification = self.settings['minimumMagnification']
+            elif self.magnification > self.settings['maximumMagnification']:
+                self.magnification = self.settings['maximumMagnification']
+
+            # set the new pan. Let c be the fixed point (center point),
+            # Let m the old mag, n the new mag
+
+            # find t2 such that
+            # mc + t1 = nc + t2 ==> t2 = (m - n)c + t1
+
+            centerPoint = (oldMag - self.magnification) * centerPoint
+
+            self.panOffset = [
+                self.panOffset[0] + centerPoint.x(),
+                self.panOffset[1] + centerPoint.y()
+            ]
+
+            self.currAddOptions['magnification'] = self.magnification
+
+            if self.addMode is xbi.InteractiveBezierEditor:
+                self.addMode.setSelectionBoundaries()
+
+        elif keyModifiers & (int(Qc.Qt.ShiftModifier) | int(Qc.Qt.AltModifier)):
+            self.panOffset[1] += rawAngle/1
+            self.panOffset[0] -= rawAngleX/1
+        # handle scrolling
+        else:
+            # process selection layer change
+            if rawAngle >= 15:
+                self.changeSelection(1)
+            elif rawAngle <= -15:
+                self.changeSelection(-1)
+        self.quickUpdate()
+
+    def wheelEvent(self, event: Qg.QWheelEvent):
+        rawAngle = event.angleDelta().y() / 8
+        rawAngleX = event.angleDelta().x() / 8
+        self.mouseWheel(rawAngleX, rawAngle)
+
+    def selectOnHover(self):
+        """Returns True if selection happened, False otherwise.
+        """
+        if self.pendingSelectedObjList:
+            selectedIndex = self.pendingSelectedObjList[self.pendingSelectedObjIndex]
+            self.pendingSelectedObjList.clear()
+
+            maj, minor = selectedIndex
+
+            self.currentlySelectedObj['selectedIndex'] = selectedIndex
+            self.currentlySelectedObj['key'],  self.currentlySelectedObj['allSameKey'] = self.selectObjectSet(
+            )
+
+            self.currentBoundingBox = self.drawObjects[maj][minor].boundingBox
+
+            if self.selectAsGroup:
+                for selItems in self.currentlySelectedObj['allSameKey']:
+                    obj = self.drawObjects[selItems[0]][selItems[1]]
+                    self.currentBoundingBox = self.currentBoundingBox.united(obj.boundingBox)
+
+            self.origBboxTransform = self.drawObjects[maj][minor].transform.toQTransform()
+            self.newTransform = Qg.QTransform()
+            return True
+        else:
+            return False
+
+    def mousePressEvent(self, mouseEvent: Qg.QMouseEvent):
+        # we make an exception for bezier curve
+        bezierException = False
+        if self.addMode is not None:
+            if self.addMode.active and isinstance(self.addMode, InplaceAddObj.AddBezierShape):
+                bezierException = True
+                
+        if not self.ui.imgLabel.underMouse() and not bezierException:
+            return
+
+        self.mouseDown = True
+        asyPos, self.savedMousePosition = self.getAsyCoordinates()
+
+        if self.addMode is not None:
+            self.addMode.mouseDown(asyPos, self.currAddOptions, mouseEvent)
+        elif self.currentModeStack[-1] == SelectionMode.pan:
+            self.savedWindowMousePos = self.getWindowCoordinates()
+        elif self.currentModeStack[-1] == SelectionMode.setAnchor:
+            self.customAnchor = self.savedMousePosition
+            self.currentModeStack.pop()
+
+            self.anchorMode = AnchorMode.customAnchor
+            self.ui.comboAnchor.setCurrentIndex(AnchorMode.customAnchor)
+            self.updateChecks()
+            self.quickUpdate()
+        elif self.inMidTransformation:
+            pass
+        elif self.pendingSelectedObjList:
+            self.selectOnHover()
+
+            if self.currentModeStack[-1] in {SelectionMode.translate, SelectionMode.rotate, SelectionMode.scale}:
+                self.setAllInSetEnabled(self.objButtons, False)
+                self.inMidTransformation = True
+                self.setAnchor()
+            elif self.currentModeStack[-1] == SelectionMode.delete:
+                self.btnSelectiveDeleteOnClick()
+            elif self.currentModeStack[-1] == SelectionMode.selectEdit:
+                self.setupSelectEdit()
+            else:
+                self.setAllInSetEnabled(self.objButtons, True)
+                self.inMidTransformation = False
+                self.setAnchor()
+
+        else:
+            self.setAllInSetEnabled(self.objButtons, False)
+            self.currentBoundingBox = None
+            self.inMidTransformation = False
+            self.clearSelection()
+
+        self.quickUpdate()
+
+    def removeAddMode(self):
+        self.addMode = None
+        self.deleteAddOptions()
+
+    def editFinalized(self):
+        self.addMode.forceFinalize()
+        self.removeAddMode()
+        self.fileChanged = True
+        self.quickUpdate()
+
+    def editRejected(self):
+        self.addMode.resetObj()
+        self.editFinalized()
+
+    def setupSelectEdit(self):
+        """For Select-Edit mode. For now, if the object selected is a bezier curve, opens up a bezier editor"""
+        maj, minor = self.currentlySelectedObj['selectedIndex']
+        obj = self.fileItems[maj]
+        if isinstance(obj, x2a.xasyDrawnItem):
+            # bezier path
+            self.addMode = xbi.InteractiveBezierEditor(self, obj, self.currAddOptions)
+            self.addMode.objectUpdated.connect(self.objectUpdated)
+            self.addMode.editAccepted.connect(self.editFinalized)
+            self.addMode.editRejected.connect(self.editRejected)
+            self.updateOptionWidget()
+            self.currentModeStack[-1] = SelectionMode.selectEdit
+            self.fileChanged = True
+        else:
+            self.clearSelection()
+        self.quickUpdate()
+
+    def setAnchor(self):
+        if self.anchorMode == AnchorMode.center:
+            self.currentAnchor = self.currentBoundingBox.center()
+        elif self.anchorMode == AnchorMode.topLeft:
+            self.currentAnchor = self.currentBoundingBox.bottomLeft()  # due to internal image being flipped
+        elif self.anchorMode == AnchorMode.topRight:
+            self.currentAnchor = self.currentBoundingBox.bottomRight()
+        elif self.anchorMode == AnchorMode.bottomLeft:
+            self.currentAnchor = self.currentBoundingBox.topLeft()
+        elif self.anchorMode == AnchorMode.bottomRight:
+            self.currentAnchor = self.currentBoundingBox.topRight()
+        elif self.anchorMode == AnchorMode.customAnchor:
+            self.currentAnchor = self.customAnchor
+        else:
+            self.currentAnchor = Qc.QPointF(0, 0)
+
+        if self.anchorMode != AnchorMode.origin:
+            pass
+            # TODO: Record base points/bbox before hand and use that for
+            # anchor?
+            # adjTransform =
+            # self.drawObjects[selectedIndex].transform.toQTransform()
+            # self.currentAnchor = adjTransform.map(self.currentAnchor)
+
+
+    def releaseTransform(self):
+        if self.newTransform.isIdentity():
+            return
+        newTransform = x2a.asyTransform.fromQTransform(self.newTransform)
+        objKey = self.currentlySelectedObj['selectedIndex']
+        self.addTransformationChanges(objKey, newTransform, not self.useGlobalCoords)
+        self.transformObject(objKey, newTransform, not self.useGlobalCoords)
+
+    def adjustTransform(self, appendTransform):
+        self.screenTransformation = self.screenTransformation * appendTransform
+
+    def createMainCanvas(self):
+        self.canvSize = self.ui.imgFrame.size()
+        self.ui.imgFrame.setSizePolicy(Qw.QSizePolicy.Ignored, Qw.QSizePolicy.Ignored)
+        x, y = self.canvSize.width() / 2, self.canvSize.height() / 2
+
+        self.canvasPixmap = Qg.QPixmap(self.canvSize)
+        self.canvasPixmap.fill()
+
+        self.finalPixmap = Qg.QPixmap(self.canvSize)
+
+        self.preCanvasPixmap = Qg.QPixmap(self.canvSize)
+        self.postCanvasPixmap = Qg.QPixmap(self.canvSize)
+
+        self.mainCanvas = Qg.QPainter(self.canvasPixmap)
+        self.mainCanvas.setRenderHint(Qg.QPainter.Antialiasing)
+        self.mainCanvas.setRenderHint(Qg.QPainter.SmoothPixmapTransform)
+        self.mainCanvas.setRenderHint(Qg.QPainter.HighQualityAntialiasing)
+        self.xasyDrawObj['canvas'] = self.mainCanvas
+
+        self.mainTransformation = Qg.QTransform()
+        self.mainTransformation.scale(1, 1)
+        self.mainTransformation.translate(x, y)
+
+        self.mainCanvas.setTransform(self.getScrsTransform(), True)
+
+        self.ui.imgLabel.setPixmap(self.canvasPixmap)
+
+    def resetPan(self):
+        self.panOffset = [0, 0]
+        self.quickUpdate()
+
+    def btnPanCenterOnClick(self):
+        newCenter = self.getAllBoundingBox().center()
+
+        # adjust to new magnification
+        # technically, doable through getscrstransform()
+        # and subtract pan offset and center points
+        # but it's much more work...
+        newCenter = self.magnification * newCenter
+        self.panOffset = [-newCenter.x(), newCenter.y()]
+        
+        self.quickUpdate()
+
+    def selectObject(self):
+        if not self.ui.imgLabel.underMouse():
+            return None, []
+        canvasCoords = self.getCanvasCoordinates()
+        highestDrawPriority = -np.inf
+        collidedObjKey = None
+        rawObjNumList = []
+        for objKeyMaj in range(len(self.drawObjects)):
+            for objKeyMin in range(len(self.drawObjects[objKeyMaj])):
+                obj = self.drawObjects[objKeyMaj][objKeyMin]
+                if obj.collide(canvasCoords) and (obj.key, obj.keyIndex) not in self.hiddenKeys:
+                    rawObjNumList.append(((objKeyMaj, objKeyMin), obj.drawOrder))
+                    if obj.drawOrder > highestDrawPriority:
+                        collidedObjKey = (objKeyMaj, objKeyMin)
+        if collidedObjKey is not None:
+            rawKey = self.drawObjects[collidedObjKey[0]][collidedObjKey[1]].key
+#            self.ui.statusbar.showMessage('Collide with {0}, Key is {1}'.format(str(collidedObjKey), rawKey), 2500)
+            self.ui.statusbar.showMessage('Key: {0}'.format(rawKey), 2500)
+            return collidedObjKey, [rawObj[0] for rawObj in sorted(rawObjNumList, key=lambda ordobj: ordobj[1])]
+        else:
+            return None, []
+
+    def selectObjectSet(self):
+        objKey = self.currentlySelectedObj['selectedIndex']
+        if objKey is None:
+            return set()
+        assert isinstance(objKey, (tuple, list)) and len(objKey) == 2
+        rawObj = self.drawObjects[objKey[0]][objKey[1]]
+        rawKey = rawObj.key
+        rawSet = {objKey}
+        for objKeyMaj in range(len(self.drawObjects)):
+            for objKeyMin in range(len(self.drawObjects[objKeyMaj])):
+                obj = self.drawObjects[objKeyMaj][objKeyMin]
+                if obj.key == rawKey:
+                    rawSet.add((objKeyMaj, objKeyMin))
+        return rawKey, rawSet
+
+    def getCanvasCoordinates(self):
+        # assert self.ui.imgLabel.underMouse()
+        uiPos = self.mapFromGlobal(Qg.QCursor.pos())
+        canvasPos = self.ui.imgLabel.mapFrom(self, uiPos)
+
+        # Issue: For magnification, should xasy treats this at xasy level, or asy level?
+        return canvasPos * self.getScrsTransform().inverted()[0]
+
+    def getWindowCoordinates(self):
+        # assert self.ui.imgLabel.underMouse()
+        return self.mapFromGlobal(Qg.QCursor.pos())
+        
+    def refreshCanvas(self):
+        if self.mainCanvas.isActive():
+            self.mainCanvas.end()
+        self.mainCanvas.begin(self.canvasPixmap)
+        self.mainCanvas.setTransform(self.getScrsTransform())
+
+    def asyfyCanvas(self, force=False):
+        self.drawObjects = []
+        self.populateCanvasWithItems(force)
+        self.quickUpdate()
+        if self.currentModeStack[-1] == SelectionMode.translate:
+            self.ui.statusbar.showMessage(self.strings.asyfyComplete)
+
+    def updateMouseCoordLabel(self):
+        *args, canvasPos = self.getAsyCoordinates()
+        nx, ny = self.asy2psmap.inverted() * (canvasPos.x(), canvasPos.y())
+        self.coordLabel.setText('{0:.2f}, {1:.2f}    '.format(nx, ny))
+
+    def quickUpdate(self):
+        self.updateMouseCoordLabel()
+        self.refreshCanvas()
+
+        self.preDraw(self.mainCanvas)
+        self.quickDraw()
+
+        self.mainCanvas.end()
+        self.postDraw()
+        self.updateScreen()
+
+    def quickDraw(self):
+        assert self.isReady()
+        dpi = self.magnification * self.dpi
+        activeItem = None
+        for majorItem in self.drawObjects:
+            for item in majorItem:
+                # hidden objects - toggleable
+                if (item.key, item.keyIndex) in self.hiddenKeys:
+                    continue
+                isSelected = item.key == self.currentlySelectedObj['key']
+                if not self.selectAsGroup and isSelected and self.currentlySelectedObj['selectedIndex'] is not None:
+                    maj, min_ = self.currentlySelectedObj['selectedIndex']
+                    isSelected = isSelected and item is self.drawObjects[maj][min_]
+                if isSelected and self.settings['enableImmediatePreview']:
+                    activeItem = item
+                    if self.useGlobalCoords:
+                        item.draw(self.newTransform, canvas=self.mainCanvas, dpi=dpi)
+                    else:
+                        item.draw(self.newTransform, applyReverse=True, canvas=self.mainCanvas, dpi=dpi)
+                else:
+                    item.draw(canvas=self.mainCanvas, dpi=dpi)
+
+        if self.settings['drawSelectedOnTop']:
+            if self.pendingSelectedObjList:
+                maj, minor = self.pendingSelectedObjList[self.pendingSelectedObjIndex]
+                self.drawObjects[maj][minor].draw(canvas=self.mainCanvas, dpi=dpi)
+            # and apply the preview too... 
+            elif activeItem is not None:
+                if self.useGlobalCoords:
+                    activeItem.draw(self.newTransform, canvas=self.mainCanvas, dpi=dpi)
+                else:
+                    activeItem.draw(self.newTransform, applyReverse=True, canvas=self.mainCanvas, dpi=dpi)
+                activeItem = None
+
+    def updateScreen(self):
+        self.finalPixmap = Qg.QPixmap(self.canvSize)
+        self.finalPixmap.fill(Qc.Qt.black)
+        with Qg.QPainter(self.finalPixmap) as finalPainter:
+            drawPoint = Qc.QPoint(0, 0)
+            # finalPainter.drawPixmap(drawPoint, self.preCanvasPixmap)
+            finalPainter.drawPixmap(drawPoint, self.canvasPixmap)
+            finalPainter.drawPixmap(drawPoint, self.postCanvasPixmap)
+        self.ui.imgLabel.setPixmap(self.finalPixmap)
+
+    def drawCartesianGrid(self, preCanvas):
+        majorGrid = self.settings['gridMajorAxesSpacing'] * self.asy2psmap.xx
+        minorGridCount = self.settings['gridMinorAxesCount']
+
+        majorGridCol = Qg.QColor(self.settings['gridMajorAxesColor'])
+        minorGridCol = Qg.QColor(self.settings['gridMinorAxesColor'])
+
+        panX, panY = self.panOffset
+
+        x_range = (self.canvSize.width() / 2 + (2 * abs(panX)))/self.magnification
+        y_range = (self.canvSize.height() / 2 + (2 * abs(panY)))/self.magnification
+
+        for x in np.arange(0, 2 * x_range + 1, majorGrid):  # have to do
+            # this in two stages...
+            preCanvas.setPen(minorGridCol)
+            for xMinor in range(1, minorGridCount + 1):
+                xCoord = x + ((xMinor / (minorGridCount + 1)) * majorGrid)
+                preCanvas.drawLine(Qc.QLine(xCoord, -9999, xCoord, 9999))
+                preCanvas.drawLine(Qc.QLine(-xCoord, -9999, -xCoord, 9999))
+
+        for y in np.arange(0, 2 * y_range + 1, majorGrid):
+            preCanvas.setPen(minorGridCol)
+            for yMinor in range(1, minorGridCount + 1):
+                yCoord = y + ((yMinor / (minorGridCount + 1)) * majorGrid)
+                preCanvas.drawLine(Qc.QLine(-9999, yCoord, 9999, yCoord))
+                preCanvas.drawLine(Qc.QLine(-9999, -yCoord, 9999, -yCoord))
+
+            preCanvas.setPen(majorGridCol)
+            preCanvas.drawLine(Qc.QLine(-9999, y, 9999, y))
+            preCanvas.drawLine(Qc.QLine(-9999, -y, 9999, -y))
+
+        for x in np.arange(0, 2 * x_range + 1, majorGrid):
+            preCanvas.setPen(majorGridCol)
+            preCanvas.drawLine(Qc.QLine(x, -9999, x, 9999))
+            preCanvas.drawLine(Qc.QLine(-x, -9999, -x, 9999))
+
+    def drawPolarGrid(self, preCanvas):
+        center = Qc.QPointF(0, 0)
+        majorGridCol = Qg.QColor(self.settings['gridMajorAxesColor'])
+        minorGridCol = Qg.QColor(self.settings['gridMinorAxesColor'])
+        majorGrid = self.settings['gridMajorAxesSpacing']
+        minorGridCount = self.settings['gridMinorAxesCount']
+
+        majorAxisAng = (np.pi/4)  # 45 degrees - for now.
+        minorAxisCount = 2  # 15 degrees each
+
+        subRadiusSize = int(round((majorGrid / (minorGridCount + 1))))
+        subAngleSize = majorAxisAng / (minorAxisCount + 1)
+
+        for radius in range(majorGrid, 9999 + 1, majorGrid):
+            preCanvas.setPen(majorGridCol)
+            preCanvas.drawEllipse(center, radius, radius)
+
+            preCanvas.setPen(minorGridCol)
+
+            for minorRing in range(minorGridCount):
+                subRadius = round(radius - (subRadiusSize * (minorRing + 1)))
+                preCanvas.drawEllipse(center, subRadius, subRadius)
+
+        currAng = majorAxisAng
+        while currAng <= (2 * np.pi):
+            preCanvas.setPen(majorGridCol)
+            p1 = center + (9999 * Qc.QPointF(np.cos(currAng), np.sin(currAng)))
+            preCanvas.drawLine(Qc.QLineF(center, p1))
+
+            preCanvas.setPen(minorGridCol)
+            for minorAngLine in range(minorAxisCount):
+                newAng = currAng - (subAngleSize * (minorAngLine + 1))
+                p1 = center + (9999 * Qc.QPointF(np.cos(newAng), np.sin(newAng)))
+                preCanvas.drawLine(Qc.QLineF(center, p1))
+
+            currAng = currAng + majorAxisAng
+
+    def preDraw(self, painter):
+        # self.preCanvasPixmap.fill(Qc.Qt.white)
+        self.canvasPixmap.fill()
+        preCanvas = painter
+
+        # preCanvas = Qg.QPainter(self.preCanvasPixmap)
+        preCanvas.setTransform(self.getScrsTransform())
+
+        if self.drawAxes:
+            preCanvas.setPen(Qc.Qt.gray)
+            preCanvas.drawLine(Qc.QLine(-9999, 0, 9999, 0))
+            preCanvas.drawLine(Qc.QLine(0, -9999, 0, 9999))
+
+        if self.drawGrid:
+            if self.drawGridMode == GridMode.cartesian:
+                self.drawCartesianGrid(painter)
+            elif self.drawGridMode == GridMode.polar:
+                self.drawPolarGrid(painter)
+
+        if self.currentGuides:
+            for guide in self.currentGuides:
+                guide.drawShape(preCanvas)
+        # preCanvas.end()
+
+    def drawAddModePreview(self, painter):
+        if self.addMode is not None:
+            if self.addMode.active:
+                # Preview Object
+                if self.addMode.getPreview() is not None:
+                    painter.setPen(self.currentPen.toQPen())
+                    painter.drawPath(self.addMode.getPreview())
+                self.addMode.postDrawPreview(painter)
+                
+
+    def drawTransformPreview(self, painter):
+        if self.currentBoundingBox is not None and self.currentlySelectedObj['selectedIndex'] is not None:
+            painter.save()
+            maj, minor = self.currentlySelectedObj['selectedIndex']
+            selObj = self.drawObjects[maj][minor]
+            if not self.useGlobalCoords:
+                painter.save()
+                painter.setTransform(
+                    selObj.transform.toQTransform(), True)
+                # painter.setTransform(selObj.baseTransform.toQTransform(), True)
+                painter.setPen(Qc.Qt.gray)
+                painter.drawLine(Qc.QLine(-9999, 0, 9999, 0))
+                painter.drawLine(Qc.QLine(0, -9999, 0, 9999))
+                painter.setPen(Qc.Qt.black)
+                painter.restore()
+
+                painter.setTransform(selObj.getInteriorScrTransform(
+                    self.newTransform).toQTransform(), True)
+                painter.drawRect(selObj.localBoundingBox)
+            else:
+                painter.setTransform(self.newTransform, True)
+                painter.drawRect(self.currentBoundingBox)
+            painter.restore()
+
+    def postDraw(self):
+        self.postCanvasPixmap.fill(Qc.Qt.transparent)
+        with Qg.QPainter(self.postCanvasPixmap) as postCanvas:
+            postCanvas.setRenderHints(self.mainCanvas.renderHints())
+            postCanvas.setTransform(self.getScrsTransform())
+
+            self.drawTransformPreview(postCanvas)
+
+            if self.pendingSelectedObjList:
+                maj, minor = self.pendingSelectedObjList[self.pendingSelectedObjIndex]
+                postCanvas.drawRect(self.drawObjects[maj][minor].boundingBox)
+                
+            self.drawAddModePreview(postCanvas)
+
+            if self.customAnchor is not None and self.anchorMode == AnchorMode.customAnchor:
+                self.drawAnchorCursor(postCanvas)
+
+            # postCanvas.drawRect(self.getAllBoundingBox())
+
+    def drawAnchorCursor(self, painter):
+        painter.drawEllipse(self.customAnchor, 6, 6)
+        newCirclePath = Qg.QPainterPath()
+        newCirclePath.addEllipse(self.customAnchor, 2, 2)
+
+        painter.fillPath(newCirclePath, Qg.QColor.fromRgb(0, 0, 0))
+
+    def updateModeBtnsOnly(self):
+        if self.currentModeStack[-1] == SelectionMode.translate:
+            activeBtn = self.ui.btnTranslate
+        elif self.currentModeStack[-1] == SelectionMode.rotate:
+            activeBtn = self.ui.btnRotate
+        elif self.currentModeStack[-1] == SelectionMode.scale:
+            activeBtn = self.ui.btnScale
+        elif self.currentModeStack[-1] == SelectionMode.pan:
+            activeBtn = self.ui.btnPan
+        elif self.currentModeStack[-1] == SelectionMode.setAnchor:
+            activeBtn = self.ui.btnAnchor
+        elif self.currentModeStack[-1] == SelectionMode.delete:
+            activeBtn = self.ui.btnDeleteMode
+        elif self.currentModeStack[-1] == SelectionMode.selectEdit:
+            activeBtn = self.ui.btnSelectEdit
+        else:
+            activeBtn = None
+
+        
+        disableFill = isinstance(self.addMode, InplaceAddObj.AddBezierShape) and not self.currAddOptions['closedPath']
+        self.ui.btnFill.setEnabled(not disableFill)
+        if disableFill and self.ui.btnFill.isEnabled():
+            self.ui.btnFill.setChecked(not disableFill)
+
+
+        for button in self.modeButtons:
+            button.setChecked(button is activeBtn)
+
+    def updateChecks(self):
+        self.removeAddMode()
+        self.updateModeBtnsOnly()
+        self.quickUpdate()
+
+    def btnAlignXOnClick(self, checked):
+        self.lockY = checked
+        if self.lockX:
+            self.lockX = False
+            self.ui.btnAlignY.setChecked(False)
+
+    def btnAlignYOnClick(self, checked):
+        self.lockX = checked
+        if self.lockY:
+            self.lockY = False
+            self.ui.btnAlignX.setChecked(False)
+
+    def btnAnchorModeOnClick(self):
+        if self.currentModeStack[-1] != SelectionMode.setAnchor:
+            self.currentModeStack.append(SelectionMode.setAnchor)
+            self.updateChecks()
+
+    def switchToAnchorMode(self):
+        if self.currentModeStack[-1] != SelectionMode.setAnchor:
+            self.currentModeStack.append(SelectionMode.setAnchor)
+            self.updateChecks()
+
+    def btnTranslateonClick(self):
+        self.currentModeStack = [SelectionMode.translate]
+        self.ui.statusbar.showMessage('Translate mode')
+        self.clearSelection()
+        self.updateChecks()
+
+    def btnRotateOnClick(self):
+        self.currentModeStack = [SelectionMode.rotate]
+        self.ui.statusbar.showMessage('Rotate mode')
+        self.clearSelection()
+        self.updateChecks()
+
+    def btnScaleOnClick(self):
+        self.currentModeStack = [SelectionMode.scale]
+        self.ui.statusbar.showMessage('Scale mode')
+        self.clearSelection()
+        self.updateChecks()
+
+    def btnPanOnClick(self):
+        self.currentModeStack = [SelectionMode.pan]
+        self.ui.statusbar.showMessage('Pan mode')
+        self.clearSelection()
+        self.updateChecks()
+
+    def btnWorldCoordsOnClick(self, checked):
+        self.useGlobalCoords = checked
+        if not self.useGlobalCoords:
+            self.ui.comboAnchor.setCurrentIndex(AnchorMode.origin)
+        self.setAllInSetEnabled(self.globalTransformOnlyButtons, checked)
+
+    def setAllInSetEnabled(self, widgetSet, enabled):
+        for widget in widgetSet:
+            widget.setEnabled(enabled)
+
+    def btnDrawAxesOnClick(self, checked):
+        self.drawAxes = checked
+        self.quickUpdate()
+
+    def btnDrawGridOnClick(self, checked):
+        self.drawGrid = checked
+        self.quickUpdate()
+
+    def btnCustTransformOnClick(self):
+        matrixDialog = CustMatTransform.CustMatTransform()
+        matrixDialog.show()
+        result = matrixDialog.exec_()
+        if result == Qw.QDialog.Accepted:
+            objKey = self.currentlySelectedObj['selectedIndex']
+            self.transformObject(objKey,
+                matrixDialog.getTransformationMatrix(), not
+                self.useGlobalCoords)
+
+        # for now, unless we update the bouding box transformation.
+        self.clearSelection()
+        self.quickUpdate()
+
+    def btnLoadEditorOnClick(self):
+        if self.fileChanged:
+            save = "Save current file?"
+            reply = Qw.QMessageBox.question(self, 'Message', save, Qw.QMessageBox.Yes,
+                                            Qw.QMessageBox.No)
+            if reply == Qw.QMessageBox.Yes:
+                self.actionSave()
+                
+        rawExternalEditor = self.settings['externalEditor']
+        rawExtEditorArgs = self.settings['externalEditorArgs']
+        execEditor = [rawExternalEditor]
+
+        for arg in rawExtEditorArgs:
+            execEditor.append(string.Template(
+                arg).substitute(asypath=(self.filename)))
+
+        subprocess.Popen(args=execEditor)
+
+    def btnAddCodeOnClick(self):
+        header = """
+// xasy object created at $time 
+// Object Number: $uid
+// This header is automatically generated by xasy. 
+// Your code here
+"""
+        header = string.Template(header).substitute(time=str(datetime.datetime.now()), uid=str(self.globalObjectCounter))
+                
+        with tempfile.TemporaryDirectory() as tmpdir:
+            newPath = os.path.join(tmpdir, 'tmpcode.asy')
+            f = io.open(newPath, 'w')
+            f.write(header)
+            f.close()
+
+            subprocess.run(args=self.getExternalEditor(asypath=newPath))
+
+            f = io.open(newPath, 'r')
+            newItem = x2a.xasyScript(engine=self.asyEngine, canvas=self.xasyDrawObj)
+            newItem.setScript(f.read())
+            f.close()
+
+        # newItem.replaceKey(str(self.globalObjectCounter) + ':')
+        self.fileItems.append(newItem)
+        self.addObjCreationUrs(newItem)
+        self.asyfyCanvas()
+
+        self.globalObjectCounter = self.globalObjectCounter + 1
+    def softDeleteObj(self, objKey):
+        maj, minor = objKey
+        drawObj = self.drawObjects[maj][minor]
+        item = drawObj.originalObj
+        key = drawObj.key
+        keyIndex = drawObj.keyIndex
+
+
+        item.transfKeymap[key][keyIndex].deleted = True
+        # item.asyfied = False
+
+    def getSelectedObjInfo(self, objIndex):
+        maj, minor = objIndex
+        drawObj = self.drawObjects[maj][minor]
+        item = drawObj.originalObj
+        key = drawObj.key
+        keyIndex = drawObj.keyIndex
+
+        return item, key, keyIndex
+
+    def transformObjKey(self, item, key, keyIndex, transform, applyFirst=False, drawObj=None):
+        if isinstance(transform, np.ndarray):
+            obj_transform = x2a.asyTransform.fromNumpyMatrix(transform)
+        elif isinstance(transform, Qg.QTransform):
+            assert transform.isAffine()
+            obj_transform = x2a.asyTransform.fromQTransform(transform)
+        else:
+            obj_transform = transform
+
+        scr_transform = obj_transform
+
+        if not applyFirst:
+            item.transfKeymap[key][keyIndex] = obj_transform * \
+                item.transfKeymap[key][keyIndex]
+            if drawObj is not None:
+                drawObj.transform = scr_transform * drawObj.transform
+        else:
+            item.transfKeymap[key][keyIndex] = item.transfKeymap[key][keyIndex] * obj_transform
+            if drawObj is not None:
+                drawObj.transform = drawObj.transform * scr_transform
+
+        if self.selectAsGroup:
+            for (maj2, min2) in self.currentlySelectedObj['allSameKey']:
+                if (maj2, min2) == (maj, minor):
+                    continue
+                obj = self.drawObjects[maj2][min2]
+                newIndex = obj.keyIndex
+                if not applyFirst:
+                    item.transfKeymap[key][newIndex] = obj_transform * \
+                        item.transfKeymap[key][newIndex]
+                    obj.transform = scr_transform * obj.transform
+                else:
+                    item.transfKeymap[key][newIndex] = item.transfKeymap[key][newIndex] * obj_transform
+                    obj.transform = obj.transform * scr_transform
+
+        self.fileChanged = True
+        self.quickUpdate()
+
+    def transformObject(self, objKey, transform, applyFirst=False):
+        maj, minor = objKey
+        drawObj = self.drawObjects[maj][minor]
+        item, key, keyIndex = self.getSelectedObjInfo(objKey)
+        self.transformObjKey(item, key, keyIndex, transform, applyFirst, drawObj)
+
+    def initializeEmptyFile(self):
+        pass
+
+    def getExternalEditor(self, **kwargs) -> str:
+        rawExternalEditor = self.settings['externalEditor']
+        rawExtEditorArgs = self.settings['externalEditorArgs']
+        execEditor = [rawExternalEditor]
+
+        for arg in rawExtEditorArgs:
+            execEditor.append(string.Template(arg).substitute(**kwargs))
+
+        return execEditor
+
+
+    def loadFile(self, name):
+        filename = os.path.abspath(name)
+        if not os.path.isfile(filename):
+            filename = filename + '.asy'
+
+        if not os.path.isfile(filename):
+            self.ui.statusbar.showMessage('File {0} not found'.format(filename))
+            return
+
+        self.ui.statusbar.showMessage('Load {0}'.format(filename))
+        self.filename = filename
+        self.currDir = os.path.dirname(self.filename)
+
+        self.erase()
+
+        f = open(self.filename, 'rt')
+        try:
+            rawFileStr = f.read()
+        except IOError:
+            Qw.QMessageBox.critical(self, self.strings.fileOpenFailed, self.strings.fileOpenFailedText)
+        else:
+            rawText, transfDict, maxKey = xf.extractTransformsFromFile(rawFileStr)
+            item = x2a.xasyScript(canvas=self.xasyDrawObj, engine=self.asyEngine, transfKeyMap=transfDict)
+
+            item.setScript(rawText)
+            self.fileItems.append(item)
+            self.asyfyCanvas(True)
+
+            maxKey2 = item.getMaxKeyCounter()
+            self.asy2psmap = item.asy2psmap
+            self.globalObjectCounter = max(maxKey + 1, maxKey2)
+        finally:
+            f.close()
+
+    def populateCanvasWithItems(self, forceUpdate=False):
+        self.itemCount = 0
+        for item in self.fileItems:
+            self.drawObjects.append(item.generateDrawObjects(forceUpdate))


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/Window1.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/__init__.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/__init__.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/__init__.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1 @@
+#!/usr/bin/env python3
\ No newline at end of file


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/__init__.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/configs/xasyconfig.cson
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/configs/xasyconfig.cson	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/configs/xasyconfig.cson	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,57 @@
+# Default Options for xasy
+
+# External editor. $asypath will be replaced by the current file. 
+externalEditor: "emacs"
+externalEditorArgs: ["$asypath"]
+
+# Path to Asymptote executable
+asyPath: "asy"
+
+# Overwrites the ASYMPTOTE_DIR Environment variable if set. Otherwise, leaves asymptote to decide. 
+asyBaseLocation: null
+
+# Show Debugging Information
+showDebug: false
+
+# Default Pen Options
+defaultPenOptions: ""
+
+# Default Pen Color 
+defaultPenColor: "#000000"
+
+# 
+defaultPenWidth: 0.5
+useLegacyDrawMode: false
+enableImmediatePreview: true
+useDegrees: false
+groupObjDefault: false
+
+# 
+terminalFont: "Courier"
+terminalFontSize: 9
+
+# 
+defaultShowAxes: true
+defaultShowGrid: false
+defaultGridSnap: false
+
+# Draw Selected Objects on top of the frame
+drawSelectedOnTop: true
+
+# Grid Settings
+
+gridMajorAxesColor: "#858585"
+gridMinorAxesColor: "#dddddd"
+gridMajorAxesSpacing: 5
+gridMinorAxesCount: 9
+
+# Magnification Settings
+minimumMagnification: 0.01
+maximumMagnification: 100
+
+# Debug Mode
+debugMode: true
+
+# Settings Override for Windows
+windows:
+    externalEditor: "notepad.exe"

Added: trunk/Master/texmf-dist/asymptote/GUI/configs/xasykeymap.cson
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/configs/xasykeymap.cson	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/configs/xasykeymap.cson	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,24 @@
+# Default Keymaps for xasy
+
+commandPalette: "Ctrl+P"
+quit: "Ctrl+Q"
+deleteObject: "Del"
+
+finalizeCurve: "Space"
+finalizeCurveClosed: "c"
+
+anchorMode: "Ctrl+A"
+
+undo: 'Ctrl+Z'
+redo: 'Ctrl+Y'
+
+moveUp: 'Up'
+moveDown: 'Down'
+
+scrollUp: 'Shift+Up'
+scrollDown: 'Shift+Down'
+scrollLeft: 'Shift+Left'
+scrollRight: 'Shift+Right'
+
+zoomIn: 'Ctrl+Up'
+zoomOut: 'Ctrl+Down'
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/icons_rc.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/icons_rc.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/icons_rc.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,2680 @@
+# -*- coding: utf-8 -*-
+
+# Resource object code
+#
+# Created by: The Resource Compiler for PyQt5 (Qt v5.10.1)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x04\x10\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\x76\x65\x72\x73\
+\x69\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\
+\x38\x33\x20\x31\x38\x2e\x37\x35\x20\x31\x38\x2e\x37\x35\x27\x20\
+\x77\x69\x64\x74\x68\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\
+\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x27\x3e\x0a\x3c\
+\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\
+\x20\x36\x33\x2e\x32\x33\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\
+\x68\x20\x64\x3d\x27\x4d\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x20\
+\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\x34\
+\x20\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\
+\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\x38\x2e\x36\
+\x35\x37\x33\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\
+\x38\x2e\x36\x35\x37\x33\x34\x20\x38\x2e\x36\x35\x37\x33\x34\x5a\
+\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\
+\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\
+\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\
+\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\
+\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x35\x30\x35\x36\x32\x27\
+\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\
+\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\
+\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\x20\x36\x33\x2e\x32\x33\
+\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\
+\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x20\x2d\x30\x4c\x20\x38\x2e\
+\x36\x35\x37\x33\x34\x20\x30\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\
+\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\
+\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\
+\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\
+\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\
+\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\
+\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\
+\x2e\x35\x30\x35\x36\x32\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\
+\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\
+\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\
+\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x37\x38\x34\
+\x34\x20\x36\x33\x2e\x32\x33\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\
+\x74\x68\x20\x64\x3d\x27\x4d\x20\x30\x20\x38\x2e\x36\x35\x37\x33\
+\x34\x4c\x20\x30\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x27\x20\x66\
+\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\
+\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\
+\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\
+\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\
+\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\
+\x64\x74\x68\x3d\x27\x31\x2e\x35\x30\x35\x36\x32\x27\x2f\x3e\x0a\
+\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\xc9\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\
+\x3d\x22\x34\x38\x30\x2c\x32\x35\x36\x20\x33\x38\x34\x2c\x31\x36\
+\x30\x20\x33\x38\x34\x2c\x32\x33\x36\x20\x32\x37\x36\x2c\x32\x33\
+\x36\x20\x32\x37\x36\x2c\x31\x32\x38\x20\x33\x35\x32\x2c\x31\x32\
+\x38\x20\x32\x35\x36\x2c\x33\x32\x20\x31\x36\x30\x2c\x31\x32\x38\
+\x20\x32\x33\x36\x2c\x31\x32\x38\x20\x32\x33\x36\x2c\x32\x33\x36\
+\x20\x31\x32\x38\x2c\x32\x33\x36\x20\x31\x32\x38\x2c\x31\x36\x30\
+\x20\x33\x32\x2c\x32\x35\x36\x20\x31\x32\x38\x2c\x33\x35\x32\x20\
+\x0d\x0a\x09\x31\x32\x38\x2c\x32\x37\x36\x20\x32\x33\x36\x2c\x32\
+\x37\x36\x20\x32\x33\x36\x2c\x33\x38\x34\x20\x31\x36\x30\x2c\x33\
+\x38\x34\x20\x32\x35\x36\x2c\x34\x38\x30\x20\x33\x35\x32\x2c\x33\
+\x38\x34\x20\x32\x37\x35\x2e\x38\x2c\x33\x38\x34\x20\x32\x37\x35\
+\x2e\x34\x2c\x32\x37\x35\x2e\x35\x20\x33\x38\x34\x2c\x32\x37\x35\
+\x2e\x38\x20\x33\x38\x34\x2c\x33\x35\x32\x20\x22\x2f\x3e\x0d\x0a\
+\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x93\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4d\x61\x67\x6e\x69\x66\x79\x69\x6e\x67\x5f\x67\x6c\x61\
+\x73\x73\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x79\x3d\x22\
+\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\
+\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\x62\x6c\x65\x2d\
+\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\x6e\x65\x77\x20\
+\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\x6d\x6c\x3a\x73\
+\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\
+\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x37\x2e\x35\
+\x34\x35\x2c\x31\x35\x2e\x34\x36\x37\x6c\x2d\x33\x2e\x37\x37\x39\
+\x2d\x33\x2e\x37\x37\x39\x63\x30\x2e\x35\x37\x2d\x30\x2e\x39\x33\
+\x35\x2c\x30\x2e\x38\x39\x38\x2d\x32\x2e\x30\x33\x35\x2c\x30\x2e\
+\x38\x39\x38\x2d\x33\x2e\x32\x31\x63\x30\x2d\x33\x2e\x34\x31\x37\
+\x2d\x32\x2e\x39\x36\x31\x2d\x36\x2e\x33\x37\x37\x2d\x36\x2e\x33\
+\x37\x38\x2d\x36\x2e\x33\x37\x37\x0d\x0a\x09\x43\x34\x2e\x38\x36\
+\x39\x2c\x32\x2e\x31\x2c\x32\x2e\x31\x2c\x34\x2e\x38\x37\x2c\x32\
+\x2e\x31\x2c\x38\x2e\x32\x38\x37\x63\x30\x2c\x33\x2e\x34\x31\x36\
+\x2c\x32\x2e\x39\x36\x31\x2c\x36\x2e\x33\x37\x37\x2c\x36\x2e\x33\
+\x37\x37\x2c\x36\x2e\x33\x37\x37\x63\x31\x2e\x31\x33\x37\x2c\x30\
+\x2c\x32\x2e\x32\x2d\x30\x2e\x33\x30\x39\x2c\x33\x2e\x31\x31\x35\
+\x2d\x30\x2e\x38\x34\x34\x6c\x33\x2e\x37\x39\x39\x2c\x33\x2e\x38\
+\x30\x31\x0d\x0a\x09\x63\x30\x2e\x33\x37\x32\x2c\x30\x2e\x33\x37\
+\x31\x2c\x30\x2e\x39\x37\x35\x2c\x30\x2e\x33\x37\x31\x2c\x31\x2e\
+\x33\x34\x36\x2c\x30\x6c\x30\x2e\x39\x34\x33\x2d\x30\x2e\x39\x34\
+\x33\x43\x31\x38\x2e\x30\x35\x31\x2c\x31\x36\x2e\x33\x30\x37\x2c\
+\x31\x37\x2e\x39\x31\x36\x2c\x31\x35\x2e\x38\x33\x38\x2c\x31\x37\
+\x2e\x35\x34\x35\x2c\x31\x35\x2e\x34\x36\x37\x7a\x20\x4d\x34\x2e\
+\x30\x30\x34\x2c\x38\x2e\x32\x38\x37\x0d\x0a\x09\x63\x30\x2d\x32\
+\x2e\x33\x36\x36\x2c\x31\x2e\x39\x31\x37\x2d\x34\x2e\x32\x38\x33\
+\x2c\x34\x2e\x32\x38\x32\x2d\x34\x2e\x32\x38\x33\x63\x32\x2e\x33\
+\x36\x36\x2c\x30\x2c\x34\x2e\x34\x37\x34\x2c\x32\x2e\x31\x30\x37\
+\x2c\x34\x2e\x34\x37\x34\x2c\x34\x2e\x34\x37\x34\x63\x30\x2c\x32\
+\x2e\x33\x36\x35\x2d\x31\x2e\x39\x31\x38\x2c\x34\x2e\x32\x38\x33\
+\x2d\x34\x2e\x32\x38\x33\x2c\x34\x2e\x32\x38\x33\x0d\x0a\x09\x43\
+\x36\x2e\x31\x31\x31\x2c\x31\x32\x2e\x37\x36\x2c\x34\x2e\x30\x30\
+\x34\x2c\x31\x30\x2e\x36\x35\x32\x2c\x34\x2e\x30\x30\x34\x2c\x38\
+\x2e\x32\x38\x37\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x0d\x0a\
+\x00\x00\x03\x46\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x33\x37\x2e\x35\
+\x2c\x33\x38\x36\x2e\x36\x4c\x33\x30\x36\x2e\x39\x2c\x32\x35\x36\
+\x6c\x31\x33\x30\x2e\x36\x2d\x31\x33\x30\x2e\x36\x63\x31\x34\x2e\
+\x31\x2d\x31\x34\x2e\x31\x2c\x31\x34\x2e\x31\x2d\x33\x36\x2e\x38\
+\x2c\x30\x2d\x35\x30\x2e\x39\x63\x2d\x31\x34\x2e\x31\x2d\x31\x34\
+\x2e\x31\x2d\x33\x36\x2e\x38\x2d\x31\x34\x2e\x31\x2d\x35\x30\x2e\
+\x39\x2c\x30\x4c\x32\x35\x36\x2c\x32\x30\x35\x2e\x31\x4c\x31\x32\
+\x35\x2e\x34\x2c\x37\x34\x2e\x35\x0d\x0a\x09\x63\x2d\x31\x34\x2e\
+\x31\x2d\x31\x34\x2e\x31\x2d\x33\x36\x2e\x38\x2d\x31\x34\x2e\x31\
+\x2d\x35\x30\x2e\x39\x2c\x30\x63\x2d\x31\x34\x2e\x31\x2c\x31\x34\
+\x2e\x31\x2d\x31\x34\x2e\x31\x2c\x33\x36\x2e\x38\x2c\x30\x2c\x35\
+\x30\x2e\x39\x4c\x32\x30\x35\x2e\x31\x2c\x32\x35\x36\x4c\x37\x34\
+\x2e\x35\x2c\x33\x38\x36\x2e\x36\x63\x2d\x31\x34\x2e\x31\x2c\x31\
+\x34\x2e\x31\x2d\x31\x34\x2e\x31\x2c\x33\x36\x2e\x38\x2c\x30\x2c\
+\x35\x30\x2e\x39\x0d\x0a\x09\x63\x31\x34\x2e\x31\x2c\x31\x34\x2e\
+\x31\x2c\x33\x36\x2e\x38\x2c\x31\x34\x2e\x31\x2c\x35\x30\x2e\x39\
+\x2c\x30\x4c\x32\x35\x36\x2c\x33\x30\x36\x2e\x39\x6c\x31\x33\x30\
+\x2e\x36\x2c\x31\x33\x30\x2e\x36\x63\x31\x34\x2e\x31\x2c\x31\x34\
+\x2e\x31\x2c\x33\x36\x2e\x38\x2c\x31\x34\x2e\x31\x2c\x35\x30\x2e\
+\x39\x2c\x30\x43\x34\x35\x31\x2e\x35\x2c\x34\x32\x33\x2e\x34\x2c\
+\x34\x35\x31\x2e\x35\x2c\x34\x30\x30\x2e\x36\x2c\x34\x33\x37\x2e\
+\x35\x2c\x33\x38\x36\x2e\x36\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\
+\x76\x67\x3e\x0d\x0a\
+\x00\x00\x00\xdd\
+\x3c\
+\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x38\x22\
+\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x38\x22\x20\x76\x69\x65\x77\
+\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x38\x20\x38\x22\x3e\x0a\x20\
+\x20\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x30\x20\x30\x76\x32\
+\x68\x2e\x35\x63\x30\x2d\x2e\x35\x35\x2e\x34\x35\x2d\x31\x20\x31\
+\x2d\x31\x68\x31\x2e\x35\x76\x35\x2e\x35\x63\x30\x20\x2e\x32\x38\
+\x2d\x2e\x32\x32\x2e\x35\x2d\x2e\x35\x2e\x35\x68\x2d\x2e\x35\x76\
+\x31\x68\x34\x76\x2d\x31\x68\x2d\x2e\x35\x63\x2d\x2e\x32\x38\x20\
+\x30\x2d\x2e\x35\x2d\x2e\x32\x32\x2d\x2e\x35\x2d\x2e\x35\x76\x2d\
+\x35\x2e\x35\x68\x31\x2e\x35\x63\x2e\x35\x35\x20\x30\x20\x31\x20\
+\x2e\x34\x35\x20\x31\x20\x31\x68\x2e\x35\x76\x2d\x32\x68\x2d\x38\
+\x7a\x22\x20\x2f\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\x7f\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\
+\x3d\x22\x32\x38\x38\x2c\x39\x36\x20\x33\x33\x37\x2e\x39\x2c\x31\
+\x34\x35\x2e\x39\x20\x32\x37\x34\x2c\x32\x30\x39\x2e\x37\x20\x32\
+\x37\x34\x2c\x32\x30\x39\x2e\x37\x20\x31\x34\x35\x2e\x39\x2c\x33\
+\x33\x37\x2e\x39\x20\x39\x36\x2c\x32\x38\x38\x20\x39\x36\x2c\x34\
+\x31\x36\x20\x32\x32\x34\x2c\x34\x31\x36\x20\x31\x37\x34\x2e\x31\
+\x2c\x33\x36\x36\x2e\x31\x20\x33\x35\x37\x2e\x34\x2c\x31\x38\x32\
+\x2e\x39\x20\x33\x36\x36\x2e\x31\x2c\x31\x37\x34\x2e\x31\x20\x0d\
+\x0a\x09\x34\x31\x36\x2c\x32\x32\x34\x20\x34\x31\x36\x2c\x39\x36\
+\x20\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x22\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x4c\x20\x2d\x36\x2e\x36\x34\x30\x35\x37\
+\x20\x2d\x31\x32\x2e\x30\x34\x35\x4c\x20\x38\x2e\x36\x37\x36\x33\
+\x32\x20\x2d\x36\x2e\x35\x31\x38\x37\x31\x4c\x20\x33\x2e\x33\x32\
+\x30\x32\x38\x20\x36\x2e\x30\x32\x32\x35\x27\x20\x66\x69\x6c\x6c\
+\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\
+\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\
+\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\
+\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\
+\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
+\x3d\x27\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\
+\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\
+\x39\x31\x31\x38\x27\x20\x63\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\
+\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\
+\x35\x37\x27\x20\x63\x79\x3d\x27\x2d\x31\x32\x2e\x30\x34\x35\x27\
+\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\
+\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\
+\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\
+\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\
+\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\
+\x2e\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\
+\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\
+\x37\x36\x33\x32\x27\x20\x63\x79\x3d\x27\x2d\x36\x2e\x35\x31\x38\
+\x37\x31\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\
+\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\
+\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\
+\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\
+\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\
+\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\
+\x33\x2e\x33\x32\x30\x32\x38\x27\x20\x63\x79\x3d\x27\x36\x2e\x30\
+\x32\x32\x35\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\
+\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\
+\x3e\x0a\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\
+\x3e\
+\x00\x00\x03\xb5\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x68\x65\x76\x72\x6f\x6e\x5f\x63\x69\x72\x63\x6c\x65\
+\x64\x5f\x72\x69\x67\x68\x74\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x0d\x0a\x09\x20\x78\x3d\x22\x30\x70\x78\
+\x22\x20\x79\x3d\x22\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\
+\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\
+\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\
+\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\
+\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x4d\x31\x31\x2c\x31\x30\x4c\x38\x2e\x36\x39\x38\x2c\x37\x2e\x34\
+\x39\x34\x63\x2d\x30\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x38\x2d\
+\x30\x2e\x31\x39\x36\x2d\x30\x2e\x35\x31\x39\x2c\x30\x2d\x30\x2e\
+\x37\x31\x38\x63\x30\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2c\
+\x30\x2e\x35\x31\x35\x2d\x30\x2e\x31\x39\x37\x2c\x30\x2e\x37\x31\
+\x2c\x30\x6c\x32\x2e\x38\x30\x37\x2c\x32\x2e\x38\x36\x34\x0d\x0a\
+\x09\x63\x30\x2e\x31\x39\x36\x2c\x30\x2e\x31\x39\x39\x2c\x30\x2e\
+\x31\x39\x36\x2c\x30\x2e\x35\x32\x2c\x30\x2c\x30\x2e\x37\x31\x37\
+\x6c\x2d\x32\x2e\x38\x30\x37\x2c\x32\x2e\x38\x36\x34\x63\x2d\x30\
+\x2e\x31\x39\x35\x2c\x30\x2e\x31\x39\x39\x2d\x30\x2e\x35\x31\x34\
+\x2c\x30\x2e\x31\x39\x38\x2d\x30\x2e\x37\x31\x2c\x30\x63\x2d\x30\
+\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2d\x30\x2e\x31\x39\x36\
+\x2d\x30\x2e\x35\x31\x38\x2c\x30\x2d\x30\x2e\x37\x31\x37\x4c\x31\
+\x31\x2c\x31\x30\x7a\x20\x4d\x31\x30\x2c\x30\x2e\x34\x0d\x0a\x09\
+\x63\x35\x2e\x33\x30\x32\x2c\x30\x2c\x39\x2e\x36\x2c\x34\x2e\x32\
+\x39\x38\x2c\x39\x2e\x36\x2c\x39\x2e\x36\x63\x30\x2c\x35\x2e\x33\
+\x30\x33\x2d\x34\x2e\x32\x39\x38\x2c\x39\x2e\x36\x2d\x39\x2e\x36\
+\x2c\x39\x2e\x36\x53\x30\x2e\x34\x2c\x31\x35\x2e\x33\x30\x33\x2c\
+\x30\x2e\x34\x2c\x31\x30\x43\x30\x2e\x34\x2c\x34\x2e\x36\x39\x38\
+\x2c\x34\x2e\x36\x39\x38\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\
+\x34\x7a\x20\x4d\x31\x30\x2c\x31\x38\x2e\x33\x35\x34\x0d\x0a\x09\
+\x63\x34\x2e\x36\x31\x33\x2c\x30\x2c\x38\x2e\x33\x35\x34\x2d\x33\
+\x2e\x37\x34\x2c\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\
+\x30\x2d\x34\x2e\x36\x31\x34\x2d\x33\x2e\x37\x34\x31\x2d\x38\x2e\
+\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\
+\x2d\x34\x2e\x36\x31\x35\x2c\x30\x2d\x38\x2e\x33\x35\x34\x2c\x33\
+\x2e\x37\x34\x2d\x38\x2e\x33\x35\x34\x2c\x38\x2e\x33\x35\x34\x0d\
+\x0a\x09\x43\x31\x2e\x36\x34\x35\x2c\x31\x34\x2e\x36\x31\x34\x2c\
+\x35\x2e\x33\x38\x35\x2c\x31\x38\x2e\x33\x35\x34\x2c\x31\x30\x2c\
+\x31\x38\x2e\x33\x35\x34\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\
+\x67\x3e\x0d\x0a\
+\x00\x00\x02\x79\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x31\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x67\x3e\x0d\x0a\x09\x09\x09\x3c\x70\x6f\x6c\
+\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\x31\x38\x36\
+\x2e\x33\x30\x31\x2c\x33\x33\x39\x2e\x38\x39\x33\x20\x39\x36\x2c\
+\x32\x34\x39\x2e\x34\x36\x31\x20\x36\x34\x2c\x32\x37\x39\x2e\x39\
+\x36\x38\x20\x31\x38\x36\x2e\x33\x30\x31\x2c\x34\x30\x32\x20\x34\
+\x34\x38\x2c\x31\x34\x30\x2e\x35\x30\x36\x20\x34\x31\x36\x2c\x31\
+\x31\x30\x20\x09\x09\x09\x22\x2f\x3e\x0d\x0a\x09\x09\x3c\x2f\x67\
+\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\
+\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x79\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x6f\x64\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\
+\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\
+\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\
+\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\x79\x3d\
+\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\
+\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\
+\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\
+\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\
+\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\
+\x35\x2e\x37\x31\x39\x2c\x31\x34\x2e\x37\x35\x63\x2d\x30\x2e\x32\
+\x33\x36\x2c\x30\x2d\x30\x2e\x34\x37\x34\x2d\x30\x2e\x30\x38\x33\
+\x2d\x30\x2e\x36\x36\x34\x2d\x30\x2e\x32\x35\x32\x4c\x2d\x30\x2e\
+\x30\x30\x35\x2c\x31\x30\x6c\x35\x2e\x33\x34\x31\x2d\x34\x2e\x37\
+\x34\x38\x43\x35\x2e\x37\x34\x38\x2c\x34\x2e\x38\x38\x37\x2c\x36\
+\x2e\x33\x38\x2c\x34\x2e\x39\x32\x32\x2c\x36\x2e\x37\x34\x37\x2c\
+\x35\x2e\x33\x33\x35\x0d\x0a\x09\x63\x30\x2e\x33\x36\x37\x2c\x30\
+\x2e\x34\x31\x33\x2c\x30\x2e\x33\x33\x2c\x31\x2e\x30\x34\x35\x2d\
+\x30\x2e\x30\x38\x33\x2c\x31\x2e\x34\x31\x32\x4c\x33\x2e\x30\x30\
+\x35\x2c\x31\x30\x6c\x33\x2e\x33\x37\x38\x2c\x33\x2e\x30\x30\x32\
+\x63\x30\x2e\x34\x31\x33\x2c\x30\x2e\x33\x36\x37\x2c\x30\x2e\x34\
+\x35\x2c\x30\x2e\x39\x39\x39\x2c\x30\x2e\x30\x38\x33\x2c\x31\x2e\
+\x34\x31\x32\x0d\x0a\x09\x43\x36\x2e\x32\x36\x39\x2c\x31\x34\x2e\
+\x36\x33\x37\x2c\x35\x2e\x39\x39\x34\x2c\x31\x34\x2e\x37\x35\x2c\
+\x35\x2e\x37\x31\x39\x2c\x31\x34\x2e\x37\x35\x7a\x20\x4d\x31\x34\
+\x2e\x36\x36\x34\x2c\x31\x34\x2e\x37\x34\x38\x4c\x32\x30\x2e\x30\
+\x30\x35\x2c\x31\x30\x6c\x2d\x35\x2e\x30\x36\x2d\x34\x2e\x34\x39\
+\x38\x63\x2d\x30\x2e\x34\x31\x33\x2d\x30\x2e\x33\x36\x37\x2d\x31\
+\x2e\x30\x34\x35\x2d\x30\x2e\x33\x33\x2d\x31\x2e\x34\x31\x31\x2c\
+\x30\x2e\x30\x38\x33\x0d\x0a\x09\x63\x2d\x30\x2e\x33\x36\x37\x2c\
+\x30\x2e\x34\x31\x33\x2d\x30\x2e\x33\x33\x2c\x31\x2e\x30\x34\x35\
+\x2c\x30\x2e\x30\x38\x33\x2c\x31\x2e\x34\x31\x32\x4c\x31\x36\x2e\
+\x39\x39\x35\x2c\x31\x30\x6c\x2d\x33\x2e\x36\x35\x39\x2c\x33\x2e\
+\x32\x35\x32\x63\x2d\x30\x2e\x34\x31\x33\x2c\x30\x2e\x33\x36\x37\
+\x2d\x30\x2e\x34\x35\x2c\x30\x2e\x39\x39\x39\x2d\x30\x2e\x30\x38\
+\x33\x2c\x31\x2e\x34\x31\x32\x43\x31\x33\x2e\x34\x35\x2c\x31\x34\
+\x2e\x38\x38\x37\x2c\x31\x33\x2e\x37\x32\x35\x2c\x31\x35\x2c\x31\
+\x34\x2c\x31\x35\x0d\x0a\x09\x43\x31\x34\x2e\x32\x33\x36\x2c\x31\
+\x35\x2c\x31\x34\x2e\x34\x37\x34\x2c\x31\x34\x2e\x39\x31\x37\x2c\
+\x31\x34\x2e\x36\x36\x34\x2c\x31\x34\x2e\x37\x34\x38\x7a\x20\x4d\
+\x39\x2e\x39\x38\x36\x2c\x31\x36\x2e\x31\x36\x35\x6c\x32\x2d\x31\
+\x32\x63\x30\x2e\x30\x39\x31\x2d\x30\x2e\x35\x34\x35\x2d\x30\x2e\
+\x32\x37\x37\x2d\x31\x2e\x30\x36\x2d\x30\x2e\x38\x32\x32\x2d\x31\
+\x2e\x31\x35\x31\x0d\x0a\x09\x63\x2d\x30\x2e\x35\x34\x37\x2d\x30\
+\x2e\x30\x39\x32\x2d\x31\x2e\x30\x36\x31\x2c\x30\x2e\x32\x37\x37\
+\x2d\x31\x2e\x31\x35\x2c\x30\x2e\x38\x32\x32\x6c\x2d\x32\x2c\x31\
+\x32\x63\x2d\x30\x2e\x30\x39\x31\x2c\x30\x2e\x35\x34\x35\x2c\x30\
+\x2e\x32\x37\x37\x2c\x31\x2e\x30\x36\x2c\x30\x2e\x38\x32\x32\x2c\
+\x31\x2e\x31\x35\x31\x43\x38\x2e\x38\x39\x32\x2c\x31\x36\x2e\x39\
+\x39\x36\x2c\x38\x2e\x39\x34\x36\x2c\x31\x37\x2c\x39\x2e\x30\x30\
+\x31\x2c\x31\x37\x0d\x0a\x09\x43\x39\x2e\x34\x38\x31\x2c\x31\x37\
+\x2c\x39\x2e\x39\x30\x35\x2c\x31\x36\x2e\x36\x35\x33\x2c\x39\x2e\
+\x39\x38\x36\x2c\x31\x36\x2e\x31\x36\x35\x7a\x22\x2f\x3e\x0d\x0a\
+\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x30\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x4c\x20\x2d\x36\x2e\x36\x34\x30\x35\x37\
+\x20\x2d\x31\x32\x2e\x30\x34\x35\x4c\x20\x38\x2e\x36\x37\x36\x33\
+\x32\x20\x2d\x36\x2e\x35\x31\x38\x37\x31\x4c\x20\x33\x2e\x33\x32\
+\x30\x32\x38\x20\x36\x2e\x30\x32\x32\x35\x4c\x20\x2d\x39\x2e\x33\
+\x39\x31\x31\x38\x20\x2d\x30\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\
+\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\
+\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\
+\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\
+\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\
+\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\x39\x31\
+\x31\x38\x27\x20\x63\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\x27\x33\
+\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\
+\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\
+\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x63\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\x35\x37\
+\x27\x20\x63\x79\x3d\x27\x2d\x31\x32\x2e\x30\x34\x35\x27\x20\x72\
+\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\
+\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\
+\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\
+\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\
+\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\
+\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\x3e\x0a\x3c\
+\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\x37\x36\
+\x33\x32\x27\x20\x63\x79\x3d\x27\x2d\x36\x2e\x35\x31\x38\x37\x31\
+\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\
+\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\
+\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\
+\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\
+\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\
+\x38\x2e\x37\x36\x35\x35\x20\x36\x38\x2e\x38\x35\x38\x33\x29\x27\
+\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\
+\x33\x32\x30\x32\x38\x27\x20\x63\x79\x3d\x27\x36\x2e\x30\x32\x32\
+\x35\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\
+\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\
+\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x07\x80\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x39\x33\x2e\x34\x36\
+\x2c\x32\x34\x39\x2e\x30\x35\x36\x63\x33\x2e\x37\x32\x33\x2d\x30\
+\x2e\x36\x37\x2c\x37\x2e\x35\x38\x39\x2d\x31\x2e\x30\x34\x31\x2c\
+\x31\x31\x2e\x35\x38\x36\x2d\x31\x2e\x30\x34\x31\x4c\x32\x30\x31\
+\x2e\x39\x32\x34\x2c\x32\x34\x38\x68\x31\x30\x33\x2e\x38\x32\x33\
+\x63\x34\x2e\x35\x30\x33\x2c\x30\x2c\x38\x2e\x38\x30\x36\x2d\x30\
+\x2e\x36\x31\x37\x2c\x31\x32\x2e\x39\x30\x38\x2d\x31\x2e\x37\x35\
+\x34\x0d\x0a\x09\x09\x63\x31\x39\x2e\x33\x37\x2d\x35\x2e\x33\x36\
+\x33\x2c\x33\x33\x2e\x33\x34\x35\x2d\x32\x32\x2e\x35\x33\x37\x2c\
+\x33\x33\x2e\x33\x34\x35\x2d\x34\x33\x2e\x36\x36\x33\x76\x2d\x33\
+\x30\x2e\x38\x32\x32\x76\x2d\x35\x36\x2e\x34\x30\x32\x63\x30\x2d\
+\x32\x34\x2e\x38\x33\x32\x2d\x32\x31\x2e\x31\x35\x2d\x34\x33\x2e\
+\x34\x38\x34\x2d\x34\x36\x2e\x32\x38\x39\x2d\x34\x37\x2e\x36\x30\
+\x36\x0d\x0a\x09\x09\x63\x2d\x31\x35\x2e\x39\x33\x31\x2d\x32\x2e\
+\x36\x32\x34\x2d\x33\x39\x2e\x32\x35\x38\x2d\x33\x2e\x38\x32\x37\
+\x2d\x35\x35\x2e\x30\x38\x39\x2d\x33\x2e\x37\x34\x39\x63\x2d\x31\
+\x35\x2e\x38\x32\x39\x2c\x30\x2e\x30\x38\x36\x2d\x33\x30\x2e\x39\
+\x38\x31\x2c\x31\x2e\x34\x30\x34\x2d\x34\x34\x2e\x32\x37\x37\x2c\
+\x33\x2e\x37\x34\x39\x43\x31\x36\x37\x2e\x31\x34\x33\x2c\x37\x34\
+\x2e\x35\x37\x36\x2c\x31\x36\x30\x2c\x38\x38\x2e\x39\x32\x38\x2c\
+\x31\x36\x30\x2c\x31\x31\x35\x2e\x33\x35\x39\x56\x31\x34\x34\x68\
+\x39\x36\x0d\x0a\x09\x09\x76\x31\x36\x48\x31\x32\x38\x2e\x38\x32\
+\x63\x2d\x33\x35\x2e\x36\x32\x38\x2c\x30\x2d\x36\x34\x2e\x35\x33\
+\x38\x2c\x34\x32\x2e\x35\x37\x31\x2d\x36\x34\x2e\x38\x31\x33\x2c\
+\x39\x35\x2e\x32\x34\x32\x43\x36\x34\x2e\x30\x30\x35\x2c\x32\x35\
+\x35\x2e\x34\x39\x35\x2c\x36\x34\x2c\x32\x35\x35\x2e\x37\x34\x37\
+\x2c\x36\x34\x2c\x32\x35\x36\x63\x30\x2c\x39\x2e\x35\x32\x33\x2c\
+\x30\x2e\x39\x34\x2c\x31\x38\x2e\x37\x32\x2c\x32\x2e\x36\x38\x35\
+\x2c\x32\x37\x2e\x34\x30\x34\x0d\x0a\x09\x09\x43\x37\x34\x2e\x36\
+\x34\x38\x2c\x33\x32\x33\x2e\x30\x37\x2c\x39\x39\x2e\x34\x35\x31\
+\x2c\x33\x35\x32\x2c\x31\x32\x38\x2e\x38\x32\x2c\x33\x35\x32\x48\
+\x31\x34\x34\x76\x2d\x32\x2e\x36\x36\x32\x76\x2d\x34\x33\x2e\x32\
+\x37\x33\x43\x31\x34\x34\x2c\x32\x37\x39\x2e\x32\x33\x38\x2c\x31\
+\x36\x34\x2e\x31\x34\x36\x2c\x32\x35\x34\x2e\x33\x33\x32\x2c\x31\
+\x39\x33\x2e\x34\x36\x2c\x32\x34\x39\x2e\x30\x35\x36\x7a\x20\x4d\
+\x32\x30\x33\x2e\x36\x35\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x0d\
+\x0a\x09\x09\x63\x2d\x39\x2e\x35\x39\x32\x2c\x30\x2d\x31\x37\x2e\
+\x33\x38\x34\x2d\x37\x2e\x37\x38\x35\x2d\x31\x37\x2e\x33\x38\x34\
+\x2d\x31\x37\x2e\x34\x30\x33\x63\x30\x2d\x39\x2e\x36\x36\x34\x2c\
+\x37\x2e\x37\x37\x34\x2d\x31\x37\x2e\x35\x32\x2c\x31\x37\x2e\x33\
+\x38\x34\x2d\x31\x37\x2e\x35\x32\x63\x39\x2e\x35\x37\x34\x2c\x30\
+\x2c\x31\x37\x2e\x33\x39\x39\x2c\x37\x2e\x38\x35\x35\x2c\x31\x37\
+\x2e\x33\x39\x39\x2c\x31\x37\x2e\x35\x32\x0d\x0a\x09\x09\x43\x32\
+\x32\x31\x2e\x30\x35\x36\x2c\x31\x31\x39\x2e\x32\x31\x37\x2c\x32\
+\x31\x33\x2e\x32\x34\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x2c\x32\
+\x30\x33\x2e\x36\x35\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x7a\x22\
+\x2f\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\
+\x34\x33\x2e\x39\x35\x31\x2c\x32\x32\x32\x2e\x35\x34\x33\x43\x34\
+\x33\x34\x2e\x37\x38\x2c\x31\x38\x36\x2e\x30\x32\x31\x2c\x34\x31\
+\x31\x2e\x30\x33\x33\x2c\x31\x36\x30\x2c\x33\x38\x33\x2e\x31\x38\
+\x2c\x31\x36\x30\x48\x33\x36\x38\x76\x32\x2e\x36\x32\x36\x76\x33\
+\x38\x2e\x30\x34\x36\x63\x30\x2c\x33\x33\x2e\x39\x31\x35\x2d\x32\
+\x32\x2e\x32\x38\x36\x2c\x35\x38\x2e\x34\x37\x34\x2d\x34\x39\x2e\
+\x34\x38\x39\x2c\x36\x32\x2e\x36\x38\x31\x0d\x0a\x09\x09\x63\x2d\
+\x32\x2e\x37\x33\x37\x2c\x30\x2e\x34\x32\x34\x2d\x35\x2e\x34\x38\
+\x33\x2c\x30\x2e\x36\x34\x36\x2d\x38\x2e\x33\x30\x31\x2c\x30\x2e\
+\x36\x34\x36\x48\x32\x30\x36\x2e\x33\x35\x31\x63\x2d\x34\x2e\x35\
+\x31\x38\x2c\x30\x2d\x38\x2e\x39\x30\x34\x2c\x30\x2e\x35\x38\x34\
+\x2d\x31\x33\x2e\x30\x34\x39\x2c\x31\x2e\x36\x37\x32\x43\x31\x37\
+\x34\x2e\x31\x38\x2c\x32\x37\x30\x2e\x36\x38\x39\x2c\x31\x36\x30\
+\x2c\x32\x38\x36\x2e\x36\x2c\x31\x36\x30\x2c\x33\x30\x37\x2e\x32\
+\x33\x36\x76\x33\x32\x2e\x39\x32\x32\x0d\x0a\x09\x09\x76\x35\x34\
+\x2e\x33\x30\x35\x63\x30\x2c\x32\x34\x2e\x38\x33\x32\x2c\x32\x34\
+\x2e\x39\x37\x37\x2c\x33\x39\x2e\x34\x32\x36\x2c\x34\x39\x2e\x34\
+\x38\x31\x2c\x34\x36\x2e\x35\x35\x31\x63\x32\x39\x2e\x33\x32\x37\
+\x2c\x38\x2e\x35\x33\x31\x2c\x36\x31\x2e\x32\x36\x37\x2c\x31\x30\
+\x2e\x30\x36\x38\x2c\x39\x36\x2e\x33\x36\x36\x2c\x30\x43\x33\x32\
+\x39\x2e\x31\x35\x2c\x34\x33\x34\x2e\x33\x35\x34\x2c\x33\x35\x32\
+\x2c\x34\x32\x30\x2e\x38\x39\x33\x2c\x33\x35\x32\x2c\x33\x39\x34\
+\x2e\x34\x36\x33\x56\x33\x36\x38\x0d\x0a\x09\x09\x68\x2d\x39\x36\
+\x76\x2d\x31\x36\x68\x31\x32\x37\x2e\x31\x38\x63\x32\x35\x2e\x32\
+\x34\x2c\x30\x2c\x34\x37\x2e\x31\x30\x37\x2d\x32\x31\x2e\x33\x36\
+\x35\x2c\x35\x37\x2e\x38\x31\x34\x2d\x35\x32\x2e\x35\x34\x39\x43\
+\x34\x34\x35\x2e\x34\x37\x34\x2c\x32\x38\x36\x2e\x34\x30\x34\x2c\
+\x34\x34\x38\x2c\x32\x37\x31\x2e\x36\x34\x31\x2c\x34\x34\x38\x2c\
+\x32\x35\x36\x0d\x0a\x09\x09\x43\x34\x34\x38\x2c\x32\x34\x34\x2e\
+\x32\x33\x32\x2c\x34\x34\x36\x2e\x35\x36\x37\x2c\x32\x33\x32\x2e\
+\x39\x36\x32\x2c\x34\x34\x33\x2e\x39\x35\x31\x2c\x32\x32\x32\x2e\
+\x35\x34\x33\x7a\x20\x4d\x33\x30\x37\x2e\x38\x36\x37\x2c\x33\x38\
+\x32\x2e\x38\x32\x63\x39\x2e\x35\x39\x2c\x30\x2c\x31\x37\x2e\x33\
+\x38\x31\x2c\x37\x2e\x37\x38\x35\x2c\x31\x37\x2e\x33\x38\x31\x2c\
+\x31\x37\x2e\x34\x0d\x0a\x09\x09\x63\x30\x2c\x39\x2e\x36\x35\x2d\
+\x37\x2e\x37\x39\x31\x2c\x31\x37\x2e\x35\x32\x31\x2d\x31\x37\x2e\
+\x33\x38\x31\x2c\x31\x37\x2e\x35\x32\x31\x63\x2d\x39\x2e\x35\x37\
+\x37\x2c\x30\x2d\x31\x37\x2e\x33\x39\x39\x2d\x37\x2e\x38\x37\x31\
+\x2d\x31\x37\x2e\x33\x39\x39\x2d\x31\x37\x2e\x35\x32\x31\x43\x32\
+\x39\x30\x2e\x34\x36\x38\x2c\x33\x39\x30\x2e\x35\x39\x2c\x32\x39\
+\x38\x2e\x32\x37\x34\x2c\x33\x38\x32\x2e\x38\x32\x2c\x33\x30\x37\
+\x2e\x38\x36\x37\x2c\x33\x38\x32\x2e\x38\x32\x7a\x22\x2f\x3e\x0d\
+\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x05\x27\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x31\x32\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\
+\x3e\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\
+\x35\x36\x2c\x36\x34\x43\x31\x35\x30\x2e\x34\x30\x31\x2c\x36\x34\
+\x2c\x36\x34\x2c\x31\x35\x30\x2e\x34\x30\x31\x2c\x36\x34\x2c\x32\
+\x35\x36\x63\x30\x2c\x31\x30\x35\x2e\x36\x30\x34\x2c\x38\x36\x2e\
+\x34\x30\x31\x2c\x31\x39\x32\x2c\x31\x39\x32\x2c\x31\x39\x32\x63\
+\x31\x38\x2e\x31\x33\x36\x2c\x30\x2c\x33\x32\x2d\x31\x33\x2e\x38\
+\x36\x34\x2c\x33\x32\x2d\x33\x32\x0d\x0a\x09\x09\x09\x63\x30\x2d\
+\x38\x2e\x35\x33\x31\x2d\x33\x2e\x31\x39\x38\x2d\x31\x36\x2d\x38\
+\x2e\x35\x33\x31\x2d\x32\x31\x2e\x33\x33\x33\x63\x2d\x35\x2e\x33\
+\x33\x33\x2d\x35\x2e\x33\x33\x34\x2d\x38\x2e\x35\x33\x31\x2d\x31\
+\x32\x2e\x38\x30\x33\x2d\x38\x2e\x35\x33\x31\x2d\x32\x31\x2e\x33\
+\x33\x34\x63\x30\x2d\x31\x38\x2e\x31\x33\x35\x2c\x31\x33\x2e\x38\
+\x36\x34\x2d\x33\x32\x2c\x33\x32\x2d\x33\x32\x68\x33\x38\x2e\x33\
+\x39\x36\x0d\x0a\x09\x09\x09\x63\x35\x38\x2e\x36\x36\x37\x2c\x30\
+\x2c\x31\x30\x36\x2e\x36\x36\x37\x2d\x34\x38\x2c\x31\x30\x36\x2e\
+\x36\x36\x37\x2d\x31\x30\x36\x2e\x36\x36\x36\x43\x34\x34\x38\x2c\
+\x31\x34\x30\x2e\x38\x30\x32\x2c\x33\x36\x31\x2e\x36\x30\x34\x2c\
+\x36\x34\x2c\x32\x35\x36\x2c\x36\x34\x7a\x20\x4d\x31\x33\x38\x2e\
+\x36\x36\x37\x2c\x32\x35\x36\x63\x2d\x31\x38\x2e\x31\x33\x36\x2c\
+\x30\x2d\x33\x32\x2d\x31\x33\x2e\x38\x36\x34\x2d\x33\x32\x2d\x33\
+\x32\x73\x31\x33\x2e\x38\x36\x34\x2d\x33\x32\x2c\x33\x32\x2d\x33\
+\x32\x0d\x0a\x09\x09\x09\x63\x31\x38\x2e\x31\x33\x35\x2c\x30\x2c\
+\x33\x32\x2c\x31\x33\x2e\x38\x36\x34\x2c\x33\x32\x2c\x33\x32\x53\
+\x31\x35\x36\x2e\x38\x30\x32\x2c\x32\x35\x36\x2c\x31\x33\x38\x2e\
+\x36\x36\x37\x2c\x32\x35\x36\x7a\x20\x4d\x32\x30\x32\x2e\x36\x36\
+\x37\x2c\x31\x37\x30\x2e\x36\x36\x37\x63\x2d\x31\x38\x2e\x31\x33\
+\x36\x2c\x30\x2d\x33\x32\x2d\x31\x33\x2e\x38\x36\x35\x2d\x33\x32\
+\x2d\x33\x32\x63\x30\x2d\x31\x38\x2e\x31\x33\x36\x2c\x31\x33\x2e\
+\x38\x36\x34\x2d\x33\x32\x2c\x33\x32\x2d\x33\x32\x0d\x0a\x09\x09\
+\x09\x63\x31\x38\x2e\x31\x33\x35\x2c\x30\x2c\x33\x32\x2c\x31\x33\
+\x2e\x38\x36\x34\x2c\x33\x32\x2c\x33\x32\x43\x32\x33\x34\x2e\x36\
+\x36\x37\x2c\x31\x35\x36\x2e\x38\x30\x32\x2c\x32\x32\x30\x2e\x38\
+\x30\x32\x2c\x31\x37\x30\x2e\x36\x36\x37\x2c\x32\x30\x32\x2e\x36\
+\x36\x37\x2c\x31\x37\x30\x2e\x36\x36\x37\x7a\x20\x4d\x33\x30\x39\
+\x2e\x33\x33\x33\x2c\x31\x37\x30\x2e\x36\x36\x37\x63\x2d\x31\x38\
+\x2e\x31\x33\x35\x2c\x30\x2d\x33\x32\x2d\x31\x33\x2e\x38\x36\x35\
+\x2d\x33\x32\x2d\x33\x32\x0d\x0a\x09\x09\x09\x63\x30\x2d\x31\x38\
+\x2e\x31\x33\x36\x2c\x31\x33\x2e\x38\x36\x35\x2d\x33\x32\x2c\x33\
+\x32\x2d\x33\x32\x63\x31\x38\x2e\x31\x33\x36\x2c\x30\x2c\x33\x32\
+\x2c\x31\x33\x2e\x38\x36\x34\x2c\x33\x32\x2c\x33\x32\x43\x33\x34\
+\x31\x2e\x33\x33\x33\x2c\x31\x35\x36\x2e\x38\x30\x32\x2c\x33\x32\
+\x37\x2e\x34\x36\x39\x2c\x31\x37\x30\x2e\x36\x36\x37\x2c\x33\x30\
+\x39\x2e\x33\x33\x33\x2c\x31\x37\x30\x2e\x36\x36\x37\x7a\x20\x4d\
+\x33\x37\x33\x2e\x33\x33\x33\x2c\x32\x35\x36\x0d\x0a\x09\x09\x09\
+\x63\x2d\x31\x38\x2e\x31\x33\x35\x2c\x30\x2d\x33\x32\x2d\x31\x33\
+\x2e\x38\x36\x34\x2d\x33\x32\x2d\x33\x32\x73\x31\x33\x2e\x38\x36\
+\x35\x2d\x33\x32\x2c\x33\x32\x2d\x33\x32\x63\x31\x38\x2e\x31\x33\
+\x36\x2c\x30\x2c\x33\x32\x2c\x31\x33\x2e\x38\x36\x34\x2c\x33\x32\
+\x2c\x33\x32\x53\x33\x39\x31\x2e\x34\x36\x39\x2c\x32\x35\x36\x2c\
+\x33\x37\x33\x2e\x33\x33\x33\x2c\x32\x35\x36\x7a\x22\x2f\x3e\x0d\
+\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xa2\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x32\x38\x2c\x34\x30\
+\x35\x2e\x34\x32\x39\x43\x31\x32\x38\x2c\x34\x32\x38\x2e\x38\x34\
+\x36\x2c\x31\x34\x37\x2e\x31\x39\x38\x2c\x34\x34\x38\x2c\x31\x37\
+\x30\x2e\x36\x36\x37\x2c\x34\x34\x38\x68\x31\x37\x30\x2e\x36\x36\
+\x37\x43\x33\x36\x34\x2e\x38\x30\x32\x2c\x34\x34\x38\x2c\x33\x38\
+\x34\x2c\x34\x32\x38\x2e\x38\x34\x36\x2c\x33\x38\x34\x2c\x34\x30\
+\x35\x2e\x34\x32\x39\x56\x31\x36\x30\x48\x31\x32\x38\x56\x34\x30\
+\x35\x2e\x34\x32\x39\x7a\x20\x4d\x34\x31\x36\x2c\x39\x36\x0d\x0a\
+\x09\x09\x68\x2d\x38\x30\x6c\x2d\x32\x36\x2e\x37\x38\x35\x2d\x33\
+\x32\x48\x32\x30\x32\x2e\x37\x38\x36\x4c\x31\x37\x36\x2c\x39\x36\
+\x48\x39\x36\x76\x33\x32\x68\x33\x32\x30\x56\x39\x36\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\
+\x0a\
+\x00\x00\x03\x22\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x22\x32\x35\x36\x22\
+\x20\x63\x79\x3d\x22\x32\x38\x30\x22\x20\x72\x3d\x22\x36\x33\x22\
+\x2f\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\
+\x34\x30\x2c\x39\x36\x68\x2d\x38\x38\x6c\x2d\x33\x32\x2d\x33\x32\
+\x48\x31\x39\x32\x6c\x2d\x33\x32\x2c\x33\x32\x48\x37\x32\x63\x2d\
+\x32\x32\x2e\x30\x39\x32\x2c\x30\x2d\x34\x30\x2c\x31\x37\x2e\x39\
+\x30\x38\x2d\x34\x30\x2c\x34\x30\x76\x32\x37\x32\x63\x30\x2c\x32\
+\x32\x2e\x30\x39\x32\x2c\x31\x37\x2e\x39\x30\x38\x2c\x34\x30\x2c\
+\x34\x30\x2c\x34\x30\x68\x33\x36\x38\x63\x32\x32\x2e\x30\x39\x32\
+\x2c\x30\x2c\x34\x30\x2d\x31\x37\x2e\x39\x30\x38\x2c\x34\x30\x2d\
+\x34\x30\x0d\x0a\x09\x09\x56\x31\x33\x36\x43\x34\x38\x30\x2c\x31\
+\x31\x33\x2e\x39\x30\x38\x2c\x34\x36\x32\x2e\x30\x39\x32\x2c\x39\
+\x36\x2c\x34\x34\x30\x2c\x39\x36\x7a\x20\x4d\x32\x35\x36\x2c\x33\
+\x39\x32\x63\x2d\x36\x31\x2e\x38\x35\x35\x2c\x30\x2d\x31\x31\x32\
+\x2d\x35\x30\x2e\x31\x34\x35\x2d\x31\x31\x32\x2d\x31\x31\x32\x73\
+\x35\x30\x2e\x31\x34\x35\x2d\x31\x31\x32\x2c\x31\x31\x32\x2d\x31\
+\x31\x32\x73\x31\x31\x32\x2c\x35\x30\x2e\x31\x34\x35\x2c\x31\x31\
+\x32\x2c\x31\x31\x32\x0d\x0a\x09\x09\x53\x33\x31\x37\x2e\x38\x35\
+\x35\x2c\x33\x39\x32\x2c\x32\x35\x36\x2c\x33\x39\x32\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\
+\x0a\
+\x00\x00\x02\x7d\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x38\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x38\x35\
+\x2c\x32\x37\x37\x2e\x33\x37\x35\x68\x32\x35\x39\x2e\x37\x30\x34\
+\x4c\x32\x32\x35\x2e\x30\x30\x32\x2c\x33\x39\x37\x2e\x30\x37\x37\
+\x4c\x32\x35\x36\x2c\x34\x32\x37\x6c\x31\x37\x31\x2d\x31\x37\x31\
+\x4c\x32\x35\x36\x2c\x38\x35\x6c\x2d\x32\x39\x2e\x39\x32\x32\x2c\
+\x32\x39\x2e\x39\x32\x34\x6c\x31\x31\x38\x2e\x36\x32\x36\x2c\x31\
+\x31\x39\x2e\x37\x30\x31\x48\x38\x35\x56\x32\x37\x37\x2e\x33\x37\
+\x35\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x05\xb7\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x31\x38\x2e\x34\x33\x37\x35\x20\x32\x34\x27\x20\x77\x69\x64\x74\
+\x68\x3d\x27\x31\x38\x2e\x34\x33\x37\x35\x70\x74\x27\x20\x78\x6d\
+\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
+\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\
+\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\
+\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x27\x3e\x0a\x3c\x67\x20\
+\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\
+\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\
+\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x36\x32\x38\x32\x20\x37\
+\x34\x2e\x32\x30\x32\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\
+\x3d\x27\x4d\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\
+\x31\x36\x36\x37\x43\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\
+\x32\x2e\x37\x30\x38\x35\x20\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\
+\x31\x33\x2e\x39\x35\x38\x34\x20\x30\x20\x2d\x31\x33\x2e\x39\x35\
+\x38\x34\x43\x20\x2d\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\x31\x33\
+\x2e\x39\x35\x38\x34\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\
+\x31\x32\x2e\x37\x30\x38\x35\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\
+\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x43\x20\x2d\x38\x2e\x33\x37\
+\x35\x30\x34\x20\x2d\x39\x2e\x36\x32\x34\x39\x32\x20\x2d\x34\x2e\
+\x36\x32\x35\x34\x31\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x30\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x43\x20\x34\x2e\x36\x32\x35\
+\x34\x31\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x38\x2e\x33\x37\
+\x35\x30\x34\x20\x2d\x39\x2e\x36\x32\x34\x39\x32\x20\x38\x2e\x33\
+\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x5a\x27\x20\
+\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\
+\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\
+\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\
+\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\
+\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\
+\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\x3e\
+\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\
+\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\
+\x20\x36\x35\x2e\x36\x32\x38\x32\x20\x37\x34\x2e\x32\x30\x32\x29\
+\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x4c\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x30\x4c\x20\x2d\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x2e\x38\x35\x39\x36\x33\x65\
+\x2d\x31\x35\x43\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\
+\x2e\x32\x33\x39\x37\x35\x65\x2d\x31\x35\x20\x2d\x38\x2e\x33\x37\
+\x35\x30\x34\x20\x2d\x36\x2e\x31\x39\x38\x37\x37\x65\x2d\x31\x36\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x30\x43\x20\x2d\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x31\x2e\x35\x34\x31\x38\x20\x2d\x34\
+\x2e\x36\x32\x35\x34\x31\x20\x32\x2e\x37\x39\x31\x36\x38\x20\x30\
+\x20\x32\x2e\x37\x39\x31\x36\x38\x43\x20\x34\x2e\x36\x32\x35\x34\
+\x31\x20\x32\x2e\x37\x39\x31\x36\x38\x20\x38\x2e\x33\x37\x35\x30\
+\x34\x20\x31\x2e\x35\x34\x31\x38\x20\x38\x2e\x33\x37\x35\x30\x34\
+\x20\x30\x4c\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x30\x4c\x20\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x27\
+\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\
+\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\
+\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\
+\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\x36\x35\x36\x27\x2f\
+\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\
+\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\
+\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\
+\x34\x20\x36\x35\x2e\x36\x32\x38\x32\x20\x37\x34\x2e\x32\x30\x32\
+\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x38\
+\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\x31\x36\x36\x37\x43\
+\x20\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x35\x2e\x37\x39\x32\
+\x31\x20\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\x31\x39\x2e\x35\x34\
+\x31\x38\x20\x30\x20\x2d\x31\x39\x2e\x35\x34\x31\x38\x43\x20\x2d\
+\x34\x2e\x36\x32\x35\x34\x31\x20\x2d\x31\x39\x2e\x35\x34\x31\x38\
+\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x35\x2e\x37\x39\
+\x32\x31\x20\x2d\x38\x2e\x33\x37\x35\x30\x34\x20\x2d\x31\x31\x2e\
+\x31\x36\x36\x37\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\
+\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\
+\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\
+\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\
+\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x03\x26\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x35\x36\x2c\x33\x38\
+\x38\x63\x2d\x37\x32\x2e\x35\x39\x37\x2c\x30\x2d\x31\x33\x32\x2d\
+\x35\x39\x2e\x34\x30\x35\x2d\x31\x33\x32\x2d\x31\x33\x32\x63\x30\
+\x2d\x37\x32\x2e\x36\x30\x31\x2c\x35\x39\x2e\x34\x30\x33\x2d\x31\
+\x33\x32\x2c\x31\x33\x32\x2d\x31\x33\x32\x63\x33\x36\x2e\x33\x2c\
+\x30\x2c\x36\x39\x2e\x32\x39\x39\x2c\x31\x35\x2e\x34\x2c\x39\x32\
+\x2e\x34\x30\x36\x2c\x33\x39\x2e\x36\x30\x31\x4c\x32\x37\x38\x2c\
+\x32\x33\x34\x68\x31\x35\x34\x56\x38\x30\x0d\x0a\x09\x09\x6c\x2d\
+\x35\x31\x2e\x36\x39\x38\x2c\x35\x31\x2e\x37\x30\x32\x43\x33\x34\
+\x38\x2e\x34\x30\x36\x2c\x39\x39\x2e\x37\x39\x38\x2c\x33\x30\x34\
+\x2e\x34\x30\x36\x2c\x38\x30\x2c\x32\x35\x36\x2c\x38\x30\x63\x2d\
+\x39\x36\x2e\x37\x39\x37\x2c\x30\x2d\x31\x37\x36\x2c\x37\x39\x2e\
+\x32\x30\x33\x2d\x31\x37\x36\x2c\x31\x37\x36\x73\x37\x38\x2e\x30\
+\x39\x34\x2c\x31\x37\x36\x2c\x31\x37\x36\x2c\x31\x37\x36\x0d\x0a\
+\x09\x09\x63\x38\x31\x2e\x30\x34\x35\x2c\x30\x2c\x31\x34\x38\x2e\
+\x32\x38\x37\x2d\x35\x34\x2e\x31\x33\x34\x2c\x31\x36\x39\x2e\x34\
+\x30\x31\x2d\x31\x32\x38\x48\x33\x37\x38\x2e\x38\x35\x43\x33\x36\
+\x30\x2e\x31\x30\x35\x2c\x33\x35\x33\x2e\x35\x36\x31\x2c\x33\x31\
+\x31\x2e\x37\x31\x32\x2c\x33\x38\x38\x2c\x32\x35\x36\x2c\x33\x38\
+\x38\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\
+\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x0c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x68\x65\x63\x6b\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\
+\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\
+\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\x79\
+\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\
+\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\
+\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\
+\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\
+\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x4d\x38\x2e\x32\x39\x34\x2c\x31\x36\x2e\x39\x39\x38\x63\x2d\x30\
+\x2e\x34\x33\x35\x2c\x30\x2d\x30\x2e\x38\x34\x37\x2d\x30\x2e\x32\
+\x30\x33\x2d\x31\x2e\x31\x31\x31\x2d\x30\x2e\x35\x35\x33\x4c\x33\
+\x2e\x36\x31\x2c\x31\x31\x2e\x37\x32\x34\x63\x2d\x30\x2e\x34\x36\
+\x35\x2d\x30\x2e\x36\x31\x33\x2d\x30\x2e\x33\x34\x34\x2d\x31\x2e\
+\x34\x38\x36\x2c\x30\x2e\x32\x37\x2d\x31\x2e\x39\x35\x31\x0d\x0a\
+\x09\x63\x30\x2e\x36\x31\x35\x2d\x30\x2e\x34\x36\x37\x2c\x31\x2e\
+\x34\x38\x38\x2d\x30\x2e\x33\x34\x34\x2c\x31\x2e\x39\x35\x33\x2c\
+\x30\x2e\x32\x37\x6c\x32\x2e\x33\x35\x31\x2c\x33\x2e\x31\x30\x34\
+\x6c\x35\x2e\x39\x31\x31\x2d\x39\x2e\x34\x39\x32\x63\x30\x2e\x34\
+\x30\x37\x2d\x30\x2e\x36\x35\x32\x2c\x31\x2e\x32\x36\x37\x2d\x30\
+\x2e\x38\x35\x32\x2c\x31\x2e\x39\x32\x31\x2d\x30\x2e\x34\x34\x35\
+\x0d\x0a\x09\x63\x30\x2e\x36\x35\x33\x2c\x30\x2e\x34\x30\x36\x2c\
+\x30\x2e\x38\x35\x34\x2c\x31\x2e\x32\x36\x36\x2c\x30\x2e\x34\x34\
+\x36\x2c\x31\x2e\x39\x32\x4c\x39\x2e\x34\x37\x38\x2c\x31\x36\x2e\
+\x33\x34\x63\x2d\x30\x2e\x32\x34\x32\x2c\x30\x2e\x33\x39\x31\x2d\
+\x30\x2e\x36\x36\x31\x2c\x30\x2e\x36\x33\x35\x2d\x31\x2e\x31\x32\
+\x2c\x30\x2e\x36\x35\x36\x43\x38\x2e\x33\x33\x36\x2c\x31\x36\x2e\
+\x39\x39\x38\x2c\x38\x2e\x33\x31\x36\x2c\x31\x36\x2e\x39\x39\x38\
+\x2c\x38\x2e\x32\x39\x34\x2c\x31\x36\x2e\x39\x39\x38\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xfc\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x32\x30\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\
+\x3e\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\
+\x35\x36\x2c\x34\x38\x43\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\
+\x2c\x34\x38\x2c\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\x2c\x32\
+\x35\x36\x73\x39\x33\x2e\x36\x30\x31\x2c\x32\x30\x38\x2c\x32\x30\
+\x38\x2c\x32\x30\x38\x73\x32\x30\x38\x2d\x39\x33\x2e\x36\x30\x31\
+\x2c\x32\x30\x38\x2d\x32\x30\x38\x53\x33\x37\x30\x2e\x33\x39\x39\
+\x2c\x34\x38\x2c\x32\x35\x36\x2c\x34\x38\x7a\x20\x4d\x32\x35\x36\
+\x2c\x34\x32\x32\x2e\x33\x39\x39\x0d\x0a\x09\x09\x09\x63\x2d\x39\
+\x31\x2e\x35\x31\x38\x2c\x30\x2d\x31\x36\x36\x2e\x33\x39\x39\x2d\
+\x37\x34\x2e\x38\x38\x32\x2d\x31\x36\x36\x2e\x33\x39\x39\x2d\x31\
+\x36\x36\x2e\x33\x39\x39\x53\x31\x36\x34\x2e\x34\x38\x32\x2c\x38\
+\x39\x2e\x36\x2c\x32\x35\x36\x2c\x38\x39\x2e\x36\x53\x34\x32\x32\
+\x2e\x34\x2c\x31\x36\x34\x2e\x34\x38\x32\x2c\x34\x32\x32\x2e\x34\
+\x2c\x32\x35\x36\x53\x33\x34\x37\x2e\x35\x31\x38\x2c\x34\x32\x32\
+\x2e\x33\x39\x39\x2c\x32\x35\x36\x2c\x34\x32\x32\x2e\x33\x39\x39\
+\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x4c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x32\x31\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\
+\x3e\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\
+\x35\x36\x2c\x31\x35\x32\x63\x2d\x35\x37\x2e\x32\x2c\x30\x2d\x31\
+\x30\x34\x2c\x34\x36\x2e\x38\x2d\x31\x30\x34\x2c\x31\x30\x34\x73\
+\x34\x36\x2e\x38\x2c\x31\x30\x34\x2c\x31\x30\x34\x2c\x31\x30\x34\
+\x73\x31\x30\x34\x2d\x34\x36\x2e\x38\x2c\x31\x30\x34\x2d\x31\x30\
+\x34\x53\x33\x31\x33\x2e\x32\x2c\x31\x35\x32\x2c\x32\x35\x36\x2c\
+\x31\x35\x32\x7a\x20\x4d\x32\x35\x36\x2c\x34\x38\x0d\x0a\x09\x09\
+\x09\x43\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\x2c\x34\x38\x2c\
+\x31\x34\x31\x2e\x36\x30\x31\x2c\x34\x38\x2c\x32\x35\x36\x73\x39\
+\x33\x2e\x36\x30\x31\x2c\x32\x30\x38\x2c\x32\x30\x38\x2c\x32\x30\
+\x38\x73\x32\x30\x38\x2d\x39\x33\x2e\x36\x30\x31\x2c\x32\x30\x38\
+\x2d\x32\x30\x38\x53\x33\x37\x30\x2e\x33\x39\x39\x2c\x34\x38\x2c\
+\x32\x35\x36\x2c\x34\x38\x7a\x20\x4d\x32\x35\x36\x2c\x34\x32\x32\
+\x2e\x34\x0d\x0a\x09\x09\x09\x63\x2d\x39\x31\x2e\x35\x31\x38\x2c\
+\x30\x2d\x31\x36\x36\x2e\x34\x2d\x37\x34\x2e\x38\x38\x33\x2d\x31\
+\x36\x36\x2e\x34\x2d\x31\x36\x36\x2e\x34\x53\x31\x36\x34\x2e\x34\
+\x38\x32\x2c\x38\x39\x2e\x36\x2c\x32\x35\x36\x2c\x38\x39\x2e\x36\
+\x53\x34\x32\x32\x2e\x34\x2c\x31\x36\x34\x2e\x34\x38\x32\x2c\x34\
+\x32\x32\x2e\x34\x2c\x32\x35\x36\x53\x33\x34\x37\x2e\x35\x31\x38\
+\x2c\x34\x32\x32\x2e\x34\x2c\x32\x35\x36\x2c\x34\x32\x32\x2e\x34\
+\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\x64\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\x0d\x0a\x09\
+\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x35\x36\x2c\x31\
+\x37\x36\x63\x2d\x34\x34\x2e\x30\x30\x34\x2c\x30\x2d\x38\x30\x2e\
+\x30\x30\x31\x2c\x33\x36\x2d\x38\x30\x2e\x30\x30\x31\x2c\x38\x30\
+\x63\x30\x2c\x34\x34\x2e\x30\x30\x34\x2c\x33\x35\x2e\x39\x39\x37\
+\x2c\x38\x30\x2c\x38\x30\x2e\x30\x30\x31\x2c\x38\x30\x63\x34\x34\
+\x2e\x30\x30\x35\x2c\x30\x2c\x37\x39\x2e\x39\x39\x39\x2d\x33\x35\
+\x2e\x39\x39\x36\x2c\x37\x39\x2e\x39\x39\x39\x2d\x38\x30\x0d\x0a\
+\x09\x09\x09\x43\x33\x33\x35\x2e\x39\x39\x39\x2c\x32\x31\x32\x2c\
+\x33\x30\x30\x2e\x30\x30\x35\x2c\x31\x37\x36\x2c\x32\x35\x36\x2c\
+\x31\x37\x36\x7a\x20\x4d\x34\x34\x36\x2e\x39\x33\x38\x2c\x32\x33\
+\x34\x2e\x36\x36\x37\x63\x2d\x39\x2e\x36\x30\x35\x2d\x38\x38\x2e\
+\x35\x33\x31\x2d\x38\x31\x2e\x30\x37\x34\x2d\x31\x36\x30\x2d\x31\
+\x36\x39\x2e\x36\x30\x35\x2d\x31\x36\x39\x2e\x35\x39\x39\x56\x33\
+\x32\x68\x2d\x34\x32\x2e\x36\x36\x36\x76\x33\x33\x2e\x30\x36\x37\
+\x0d\x0a\x09\x09\x09\x63\x2d\x38\x38\x2e\x35\x33\x31\x2c\x39\x2e\
+\x35\x39\x39\x2d\x31\x36\x30\x2c\x38\x31\x2e\x30\x36\x38\x2d\x31\
+\x36\x39\x2e\x36\x30\x34\x2c\x31\x36\x39\x2e\x35\x39\x39\x48\x33\
+\x32\x76\x34\x32\x2e\x36\x36\x37\x68\x33\x33\x2e\x30\x36\x32\x63\
+\x39\x2e\x36\x30\x34\x2c\x38\x38\x2e\x35\x33\x31\x2c\x38\x31\x2e\
+\x30\x37\x32\x2c\x31\x36\x30\x2c\x31\x36\x39\x2e\x36\x30\x34\x2c\
+\x31\x36\x39\x2e\x36\x30\x34\x56\x34\x38\x30\x68\x34\x32\x2e\x36\
+\x36\x36\x76\x2d\x33\x33\x2e\x30\x36\x32\x0d\x0a\x09\x09\x09\x63\
+\x38\x38\x2e\x35\x33\x31\x2d\x39\x2e\x36\x30\x34\x2c\x31\x36\x30\
+\x2d\x38\x31\x2e\x30\x37\x33\x2c\x31\x36\x39\x2e\x36\x30\x35\x2d\
+\x31\x36\x39\x2e\x36\x30\x34\x48\x34\x38\x30\x76\x2d\x34\x32\x2e\
+\x36\x36\x37\x48\x34\x34\x36\x2e\x39\x33\x38\x7a\x20\x4d\x32\x35\
+\x36\x2c\x34\x30\x35\x2e\x33\x33\x33\x63\x2d\x38\x32\x2e\x31\x33\
+\x37\x2c\x30\x2d\x31\x34\x39\x2e\x33\x33\x34\x2d\x36\x37\x2e\x31\
+\x39\x38\x2d\x31\x34\x39\x2e\x33\x33\x34\x2d\x31\x34\x39\x2e\x33\
+\x33\x33\x0d\x0a\x09\x09\x09\x63\x30\x2d\x38\x32\x2e\x31\x33\x36\
+\x2c\x36\x37\x2e\x31\x39\x37\x2d\x31\x34\x39\x2e\x33\x33\x33\x2c\
+\x31\x34\x39\x2e\x33\x33\x34\x2d\x31\x34\x39\x2e\x33\x33\x33\x63\
+\x38\x32\x2e\x31\x33\x35\x2c\x30\x2c\x31\x34\x39\x2e\x33\x33\x32\
+\x2c\x36\x37\x2e\x31\x39\x38\x2c\x31\x34\x39\x2e\x33\x33\x32\x2c\
+\x31\x34\x39\x2e\x33\x33\x33\x43\x34\x30\x35\x2e\x33\x33\x32\x2c\
+\x33\x33\x38\x2e\x31\x33\x35\x2c\x33\x33\x38\x2e\x31\x33\x35\x2c\
+\x34\x30\x35\x2e\x33\x33\x33\x2c\x32\x35\x36\x2c\x34\x30\x35\x2e\
+\x33\x33\x33\x7a\x0d\x0a\x09\x09\x09\x22\x2f\x3e\x0d\x0a\x09\x3c\
+\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\
+\x3e\x0d\x0a\
+\x00\x00\x03\x36\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\x3d\
+\x22\x33\x39\x36\x2e\x37\x39\x35\x2c\x33\x39\x36\x2e\x38\x20\x33\
+\x32\x30\x2c\x33\x39\x36\x2e\x38\x20\x33\x32\x30\x2c\x34\x34\x38\
+\x20\x34\x34\x38\x2c\x34\x34\x38\x20\x34\x34\x38\x2c\x33\x32\x30\
+\x20\x33\x39\x36\x2e\x37\x39\x35\x2c\x33\x32\x30\x20\x09\x22\x2f\
+\x3e\x0d\x0a\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\
+\x6e\x74\x73\x3d\x22\x33\x39\x36\x2e\x38\x2c\x31\x31\x35\x2e\x32\
+\x30\x35\x20\x33\x39\x36\x2e\x38\x2c\x31\x39\x32\x20\x34\x34\x38\
+\x2c\x31\x39\x32\x20\x34\x34\x38\x2c\x36\x34\x20\x33\x32\x30\x2c\
+\x36\x34\x20\x33\x32\x30\x2c\x31\x31\x35\x2e\x32\x30\x35\x20\x09\
+\x22\x2f\x3e\x0d\x0a\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\
+\x6f\x69\x6e\x74\x73\x3d\x22\x31\x31\x35\x2e\x32\x30\x35\x2c\x31\
+\x31\x35\x2e\x32\x20\x31\x39\x32\x2c\x31\x31\x35\x2e\x32\x20\x31\
+\x39\x32\x2c\x36\x34\x20\x36\x34\x2c\x36\x34\x20\x36\x34\x2c\x31\
+\x39\x32\x20\x31\x31\x35\x2e\x32\x30\x35\x2c\x31\x39\x32\x20\x09\
+\x22\x2f\x3e\x0d\x0a\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\
+\x6f\x69\x6e\x74\x73\x3d\x22\x31\x31\x35\x2e\x32\x2c\x33\x39\x36\
+\x2e\x37\x39\x35\x20\x31\x31\x35\x2e\x32\x2c\x33\x32\x30\x20\x36\
+\x34\x2c\x33\x32\x30\x20\x36\x34\x2c\x34\x34\x38\x20\x31\x39\x32\
+\x2c\x34\x34\x38\x20\x31\x39\x32\x2c\x33\x39\x36\x2e\x37\x39\x35\
+\x20\x09\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\
+\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xf7\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x31\x37\x2e\x34\
+\x2c\x32\x32\x34\x48\x32\x38\x38\x56\x39\x34\x2e\x36\x63\x30\x2d\
+\x31\x36\x2e\x39\x2d\x31\x34\x2e\x33\x2d\x33\x30\x2e\x36\x2d\x33\
+\x32\x2d\x33\x30\x2e\x36\x63\x2d\x31\x37\x2e\x37\x2c\x30\x2d\x33\
+\x32\x2c\x31\x33\x2e\x37\x2d\x33\x32\x2c\x33\x30\x2e\x36\x56\x32\
+\x32\x34\x48\x39\x34\x2e\x36\x43\x37\x37\x2e\x37\x2c\x32\x32\x34\
+\x2c\x36\x34\x2c\x32\x33\x38\x2e\x33\x2c\x36\x34\x2c\x32\x35\x36\
+\x0d\x0a\x09\x63\x30\x2c\x31\x37\x2e\x37\x2c\x31\x33\x2e\x37\x2c\
+\x33\x32\x2c\x33\x30\x2e\x36\x2c\x33\x32\x48\x32\x32\x34\x76\x31\
+\x32\x39\x2e\x34\x63\x30\x2c\x31\x36\x2e\x39\x2c\x31\x34\x2e\x33\
+\x2c\x33\x30\x2e\x36\x2c\x33\x32\x2c\x33\x30\x2e\x36\x63\x31\x37\
+\x2e\x37\x2c\x30\x2c\x33\x32\x2d\x31\x33\x2e\x37\x2c\x33\x32\x2d\
+\x33\x30\x2e\x36\x56\x32\x38\x38\x68\x31\x32\x39\x2e\x34\x63\x31\
+\x36\x2e\x39\x2c\x30\x2c\x33\x30\x2e\x36\x2d\x31\x34\x2e\x33\x2c\
+\x33\x30\x2e\x36\x2d\x33\x32\x0d\x0a\x09\x43\x34\x34\x38\x2c\x32\
+\x33\x38\x2e\x33\x2c\x34\x33\x34\x2e\x33\x2c\x32\x32\x34\x2c\x34\
+\x31\x37\x2e\x34\x2c\x32\x32\x34\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x52\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\
+\x64\x3d\x22\x4d\x34\x33\x37\x2e\x33\x33\x34\x2c\x31\x34\x34\x48\
+\x32\x35\x36\x2e\x30\x30\x36\x6c\x2d\x34\x32\x2e\x36\x36\x38\x2d\
+\x34\x38\x48\x37\x34\x2e\x36\x36\x36\x43\x35\x31\x2e\x31\x39\x37\
+\x2c\x39\x36\x2c\x33\x32\x2c\x31\x31\x35\x2e\x31\x39\x38\x2c\x33\
+\x32\x2c\x31\x33\x38\x2e\x36\x36\x37\x76\x32\x33\x34\x2e\x36\x36\
+\x36\x43\x33\x32\x2c\x33\x39\x36\x2e\x38\x30\x32\x2c\x35\x31\x2e\
+\x31\x39\x37\x2c\x34\x31\x36\x2c\x37\x34\x2e\x36\x36\x36\x2c\x34\
+\x31\x36\x68\x33\x36\x32\x2e\x36\x36\x38\x0d\x0a\x09\x43\x34\x36\
+\x30\x2e\x38\x30\x33\x2c\x34\x31\x36\x2c\x34\x38\x30\x2c\x33\x39\
+\x36\x2e\x38\x30\x32\x2c\x34\x38\x30\x2c\x33\x37\x33\x2e\x33\x33\
+\x33\x56\x31\x38\x36\x2e\x36\x36\x37\x43\x34\x38\x30\x2c\x31\x36\
+\x33\x2e\x31\x39\x38\x2c\x34\x36\x30\x2e\x38\x30\x33\x2c\x31\x34\
+\x34\x2c\x34\x33\x37\x2e\x33\x33\x34\x2c\x31\x34\x34\x7a\x20\x4d\
+\x34\x34\x38\x2c\x33\x37\x33\x2e\x33\x33\x33\x0d\x0a\x09\x63\x30\
+\x2c\x35\x2e\x37\x38\x32\x2d\x34\x2e\x38\x38\x35\x2c\x31\x30\x2e\
+\x36\x36\x37\x2d\x31\x30\x2e\x36\x36\x36\x2c\x31\x30\x2e\x36\x36\
+\x37\x48\x37\x34\x2e\x36\x36\x36\x43\x36\x38\x2e\x38\x38\x34\x2c\
+\x33\x38\x34\x2c\x36\x34\x2c\x33\x37\x39\x2e\x31\x31\x35\x2c\x36\
+\x34\x2c\x33\x37\x33\x2e\x33\x33\x33\x56\x31\x37\x36\x68\x33\x37\
+\x33\x2e\x33\x33\x34\x63\x35\x2e\x37\x38\x31\x2c\x30\x2c\x31\x30\
+\x2e\x36\x36\x36\x2c\x34\x2e\x38\x38\x35\x2c\x31\x30\x2e\x36\x36\
+\x36\x2c\x31\x30\x2e\x36\x36\x37\x0d\x0a\x09\x56\x33\x37\x33\x2e\
+\x33\x33\x33\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\
+\x0a\
+\x00\x00\x05\xca\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\
+\x64\x3d\x22\x4d\x34\x35\x30\x2e\x36\x37\x39\x2c\x32\x37\x33\x2e\
+\x35\x63\x2d\x31\x34\x2e\x35\x38\x35\x2d\x31\x34\x2e\x35\x37\x37\
+\x2d\x33\x36\x2e\x30\x35\x34\x2d\x31\x35\x2e\x38\x39\x2d\x35\x30\
+\x2e\x36\x33\x39\x2d\x31\x2e\x33\x31\x32\x6c\x2d\x34\x31\x2e\x36\
+\x38\x37\x2c\x34\x31\x2e\x36\x36\x34\x63\x2d\x31\x30\x2e\x38\x35\
+\x32\x2c\x31\x30\x2e\x38\x33\x36\x2d\x32\x33\x2e\x39\x33\x2c\x31\
+\x30\x2e\x38\x35\x39\x2d\x33\x31\x2e\x35\x36\x34\x2c\x31\x2e\x38\
+\x35\x32\x0d\x0a\x09\x63\x2d\x35\x2e\x30\x35\x37\x2d\x35\x2e\x39\
+\x36\x38\x2d\x33\x2e\x30\x36\x31\x2d\x32\x34\x2e\x33\x37\x34\x2d\
+\x31\x2e\x36\x34\x34\x2d\x33\x36\x2e\x30\x34\x39\x6c\x32\x30\x2e\
+\x39\x30\x37\x2d\x31\x37\x31\x2e\x38\x34\x39\x63\x31\x2e\x38\x36\
+\x37\x2d\x31\x35\x2e\x33\x35\x33\x2d\x39\x2e\x30\x37\x2d\x33\x30\
+\x2e\x31\x38\x35\x2d\x32\x34\x2e\x34\x33\x2d\x33\x32\x2e\x30\x35\
+\x31\x0d\x0a\x09\x63\x2d\x31\x35\x2e\x33\x35\x38\x2d\x31\x2e\x38\
+\x36\x37\x2d\x32\x39\x2e\x33\x32\x32\x2c\x39\x2e\x39\x33\x39\x2d\
+\x33\x31\x2e\x31\x39\x31\x2c\x32\x35\x2e\x32\x38\x39\x4c\x32\x36\
+\x37\x2e\x33\x37\x2c\x32\x33\x36\x2e\x30\x32\x31\x63\x2d\x31\x2e\
+\x32\x30\x35\x2c\x33\x2e\x33\x35\x38\x2d\x33\x2e\x37\x39\x2c\x33\
+\x2e\x39\x33\x38\x2d\x34\x2e\x30\x38\x31\x2d\x30\x2e\x35\x38\x32\
+\x4c\x32\x35\x35\x2e\x34\x34\x2c\x36\x30\x0d\x0a\x09\x63\x30\x2d\
+\x31\x35\x2e\x34\x36\x35\x2d\x31\x32\x2e\x35\x34\x32\x2d\x32\x38\
+\x2d\x32\x38\x2e\x30\x31\x34\x2d\x32\x38\x63\x2d\x31\x35\x2e\x34\
+\x37\x33\x2c\x30\x2d\x32\x38\x2e\x30\x31\x35\x2c\x31\x32\x2e\x35\
+\x33\x35\x2d\x32\x38\x2e\x30\x31\x35\x2c\x32\x38\x6c\x2d\x30\x2e\
+\x35\x35\x32\x2c\x31\x37\x36\x2e\x37\x35\x32\x63\x30\x2e\x31\x34\
+\x36\x2c\x32\x2e\x30\x34\x2d\x31\x2e\x36\x30\x34\x2c\x32\x2e\x36\
+\x32\x34\x2d\x31\x2e\x39\x32\x2c\x30\x2e\x32\x39\x34\x4c\x31\x37\
+\x32\x2e\x30\x31\x36\x2c\x39\x39\x2e\x30\x37\x37\x0d\x0a\x09\x63\
+\x2d\x32\x2e\x37\x35\x2d\x31\x35\x2e\x32\x31\x39\x2d\x31\x37\x2e\
+\x33\x32\x33\x2d\x32\x36\x2e\x32\x30\x33\x2d\x33\x32\x2e\x35\x34\
+\x38\x2d\x32\x33\x2e\x34\x35\x33\x63\x2d\x31\x35\x2e\x32\x32\x37\
+\x2c\x32\x2e\x37\x34\x38\x2d\x32\x35\x2e\x33\x33\x39\x2c\x31\x38\
+\x2e\x31\x38\x37\x2d\x32\x32\x2e\x35\x39\x31\x2c\x33\x33\x2e\x34\
+\x30\x33\x6c\x32\x32\x2e\x31\x39\x33\x2c\x31\x36\x31\x2e\x34\x35\
+\x35\x0d\x0a\x09\x63\x30\x2e\x30\x32\x33\x2c\x32\x2e\x38\x37\x32\
+\x2d\x30\x2e\x39\x34\x31\x2c\x34\x2e\x35\x31\x33\x2d\x32\x2e\x33\
+\x30\x38\x2c\x30\x2e\x38\x33\x31\x6c\x2d\x33\x33\x2e\x31\x30\x39\
+\x2d\x38\x38\x2e\x35\x31\x37\x63\x2d\x35\x2e\x31\x38\x2d\x31\x34\
+\x2e\x35\x37\x32\x2d\x32\x31\x2e\x31\x39\x36\x2d\x32\x33\x2e\x30\
+\x36\x35\x2d\x33\x35\x2e\x37\x37\x36\x2d\x31\x37\x2e\x38\x38\x39\
+\x0d\x0a\x09\x63\x2d\x31\x34\x2e\x35\x37\x39\x2c\x35\x2e\x31\x37\
+\x37\x2d\x32\x32\x2e\x32\x30\x31\x2c\x32\x32\x2e\x30\x36\x31\x2d\
+\x31\x37\x2e\x30\x32\x33\x2c\x33\x36\x2e\x36\x33\x31\x6c\x35\x38\
+\x2e\x30\x34\x32\x2c\x31\x38\x39\x2e\x36\x32\x35\x63\x30\x2e\x33\
+\x30\x33\x2c\x31\x2e\x30\x34\x36\x2c\x30\x2e\x36\x32\x34\x2c\x32\
+\x2e\x30\x38\x35\x2c\x30\x2e\x39\x35\x33\x2c\x33\x2e\x31\x31\x38\
+\x6c\x30\x2e\x31\x32\x31\x2c\x30\x2e\x33\x39\x0d\x0a\x09\x63\x30\
+\x2e\x30\x31\x31\x2c\x30\x2e\x30\x33\x31\x2c\x30\x2e\x30\x32\x35\
+\x2c\x30\x2e\x30\x35\x38\x2c\x30\x2e\x30\x33\x35\x2c\x30\x2e\x30\
+\x38\x38\x43\x31\x32\x36\x2e\x30\x37\x39\x2c\x34\x34\x34\x2e\x32\
+\x33\x33\x2c\x31\x37\x32\x2e\x35\x37\x2c\x34\x38\x30\x2c\x32\x32\
+\x37\x2e\x34\x32\x37\x2c\x34\x38\x30\x63\x33\x35\x2e\x31\x31\x36\
+\x2c\x30\x2c\x37\x31\x2e\x35\x39\x31\x2d\x31\x32\x2e\x33\x37\x38\
+\x2c\x39\x39\x2e\x33\x35\x37\x2d\x33\x33\x2e\x36\x37\x32\x0d\x0a\
+\x09\x63\x30\x2e\x30\x30\x31\x2c\x30\x2c\x30\x2e\x30\x30\x33\x2d\
+\x30\x2e\x30\x30\x32\x2c\x30\x2e\x30\x30\x33\x2d\x30\x2e\x30\x30\
+\x32\x63\x32\x39\x2e\x39\x39\x2d\x31\x38\x2e\x30\x35\x31\x2c\x31\
+\x32\x36\x2e\x30\x37\x31\x2d\x31\x32\x31\x2e\x33\x34\x37\x2c\x31\
+\x32\x36\x2e\x30\x37\x31\x2d\x31\x32\x31\x2e\x33\x34\x37\x43\x34\
+\x36\x37\x2e\x34\x34\x35\x2c\x33\x31\x30\x2e\x34\x30\x32\x2c\x34\
+\x36\x35\x2e\x32\x36\x36\x2c\x32\x38\x38\x2e\x30\x38\x2c\x34\x35\
+\x30\x2e\x36\x37\x39\x2c\x32\x37\x33\x2e\x35\x7a\x22\x2f\x3e\x0d\
+\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x04\xbd\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x39\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x43\x20\x2d\x39\x2e\x39\x36\x38\x36\x31\
+\x20\x2d\x33\x2e\x38\x33\x30\x30\x34\x20\x2d\x38\x2e\x35\x35\x37\
+\x30\x36\x20\x2d\x37\x2e\x35\x31\x39\x34\x34\x20\x2d\x36\x2e\x36\
+\x34\x30\x35\x37\x20\x2d\x31\x30\x2e\x32\x31\x37\x31\x43\x20\x2d\
+\x30\x2e\x34\x39\x31\x30\x38\x39\x20\x2d\x31\x38\x2e\x38\x37\x33\
+\x33\x20\x38\x2e\x33\x35\x36\x37\x36\x20\x2d\x31\x35\x2e\x31\x39\
+\x30\x36\x20\x38\x2e\x36\x37\x36\x33\x32\x20\x2d\x35\x2e\x35\x32\
+\x39\x34\x38\x43\x20\x38\x2e\x38\x33\x36\x20\x2d\x30\x2e\x37\x30\
+\x32\x30\x30\x38\x20\x36\x2e\x32\x33\x39\x36\x38\x20\x32\x2e\x39\
+\x34\x32\x30\x37\x20\x33\x2e\x33\x32\x30\x32\x38\x20\x35\x2e\x31\
+\x30\x38\x35\x37\x43\x20\x2d\x31\x2e\x39\x36\x38\x39\x31\x20\x39\
+\x2e\x30\x33\x33\x37\x31\x20\x2d\x38\x2e\x32\x36\x38\x39\x35\x20\
+\x37\x2e\x34\x34\x33\x37\x20\x2d\x39\x2e\x33\x39\x31\x31\x38\x20\
+\x2d\x30\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\
+\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\
+\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\
+\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\
+\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\x36\
+\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\
+\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\
+\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x39\
+\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\
+\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\x39\x31\x31\x38\x27\x20\x63\
+\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\
+\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\
+\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\
+\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\
+\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\
+\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x39\x2e\x37\
+\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\
+\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\x35\x37\x27\x20\x63\x79\x3d\
+\x27\x2d\x31\x30\x2e\x32\x31\x37\x31\x27\x20\x72\x3d\x27\x33\x2e\
+\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\
+\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\
+\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\
+\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\
+\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\
+\x36\x39\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\
+\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\x37\x36\x33\x32\x27\x20\
+\x63\x79\x3d\x27\x2d\x35\x2e\x35\x32\x39\x34\x38\x27\x20\x72\x3d\
+\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x39\x2e\x37\x36\x38\x38\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x33\x32\x30\x32\
+\x38\x27\x20\x63\x79\x3d\x27\x35\x2e\x31\x30\x38\x35\x37\x27\x20\
+\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\
+\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\
+\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x04\xca\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\x72\
+\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\x75\
+\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x39\x2e\x32\x2e\x31\x2c\x20\
+\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\x2d\
+\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\x6e\
+\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\x20\
+\x20\x2d\x2d\x3e\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x73\
+\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\
+\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\x2f\x2f\
+\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\
+\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\x73\x2f\
+\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\x67\x31\
+\x31\x2e\x64\x74\x64\x22\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\
+\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x0a\x09\x20\x69\x64\x3d\
+\x22\x73\x76\x67\x34\x36\x31\x39\x22\x20\x69\x6e\x6b\x73\x63\x61\
+\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x39\x31\
+\x2b\x64\x65\x76\x65\x6c\x2b\x6f\x73\x78\x6d\x65\x6e\x75\x20\x72\
+\x31\x32\x39\x31\x31\x22\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\
+\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x74\x72\x69\x61\x6e\x67\x6c\
+\x65\x2d\x73\x74\x72\x6f\x6b\x65\x64\x2d\x31\x35\x2e\x73\x76\x67\
+\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\x65\x63\x6f\x6d\x6d\x6f\
+\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\x22\x20\x78\x6d\x6c\x6e\
+\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\
+\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\
+\x73\x2f\x31\x2e\x31\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\
+\x6b\x73\x63\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\
+\x6e\x61\x6d\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\
+\x61\x70\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\
+\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\
+\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\
+\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\
+\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\
+\x20\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\
+\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\
+\x30\x30\x2f\x73\x76\x67\x22\x0a\x09\x20\x78\x6d\x6c\x6e\x73\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\
+\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\
+\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\
+\x79\x3d\x22\x30\x70\x78\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\
+\x35\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\x35\x70\
+\x78\x22\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\
+\x30\x20\x31\x35\x20\x31\x35\x22\x20\x73\x74\x79\x6c\x65\x3d\x22\
+\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\
+\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\x31\x35\x20\x31\x35\x3b\
+\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\
+\x73\x65\x72\x76\x65\x22\x3e\x0a\x3c\x70\x61\x74\x68\x20\x69\x64\
+\x3d\x22\x72\x65\x63\x74\x33\x33\x33\x38\x22\x20\x69\x6e\x6b\x73\
+\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\
+\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x73\x6f\x64\
+\x69\x70\x6f\x64\x69\x3a\x6e\x6f\x64\x65\x74\x79\x70\x65\x73\x3d\
+\x22\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x22\x20\x64\
+\x3d\x22\x4d\x37\x2e\x35\x32\x34\x33\x2c\x31\x2e\x35\x30\x30\x34\
+\x0a\x09\x43\x37\x2e\x32\x34\x32\x39\x2c\x31\x2e\x34\x39\x31\x33\
+\x2c\x36\x2e\x39\x37\x38\x37\x2c\x31\x2e\x36\x34\x32\x33\x2c\x36\
+\x2e\x38\x33\x33\x36\x2c\x31\x2e\x38\x39\x35\x32\x6c\x2d\x35\x2e\
+\x35\x2c\x39\x2e\x38\x36\x39\x32\x43\x31\x2e\x30\x32\x31\x38\x2c\
+\x31\x32\x2e\x33\x30\x37\x38\x2c\x31\x2e\x33\x39\x35\x2c\x31\x32\
+\x2e\x39\x39\x39\x39\x2c\x32\x2c\x31\x33\x68\x31\x31\x0a\x09\x63\
+\x30\x2e\x36\x30\x35\x2d\x30\x2e\x30\x30\x30\x31\x2c\x30\x2e\x39\
+\x37\x38\x32\x2d\x30\x2e\x36\x39\x32\x32\x2c\x30\x2e\x36\x36\x36\
+\x34\x2d\x31\x2e\x32\x33\x35\x35\x6c\x2d\x35\x2e\x35\x2d\x39\x2e\
+\x38\x36\x39\x32\x43\x38\x2e\x30\x33\x30\x32\x2c\x31\x2e\x36\x35\
+\x37\x39\x2c\x37\x2e\x37\x38\x38\x34\x2c\x31\x2e\x35\x30\x39\x32\
+\x2c\x37\x2e\x35\x32\x34\x33\x2c\x31\x2e\x35\x30\x30\x34\x7a\x20\
+\x4d\x37\x2e\x35\x2c\x33\x2e\x38\x39\x39\x33\x6c\x34\x2e\x31\x32\
+\x36\x37\x2c\x37\x2e\x34\x37\x30\x34\x0a\x09\x48\x33\x2e\x33\x37\
+\x33\x33\x4c\x37\x2e\x35\x2c\x33\x2e\x38\x39\x39\x33\x7a\x22\x2f\
+\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\
+\x00\x00\x04\x8d\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x32\x34\x70\x74\x27\x20\x76\x65\x72\x73\x69\x6f\x6e\
+\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x27\
+\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\x38\x33\x20\
+\x32\x34\x20\x32\x34\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x32\x34\
+\x70\x74\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\
+\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\
+\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\
+\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\
+\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\
+\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\
+\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\
+\x37\x36\x35\x35\x20\x36\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\
+\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x2d\x39\x2e\x33\x39\
+\x31\x31\x38\x20\x2d\x30\x43\x20\x2d\x39\x2e\x33\x32\x32\x35\x37\
+\x20\x2d\x33\x2e\x37\x37\x37\x38\x33\x20\x2d\x38\x2e\x33\x34\x33\
+\x32\x34\x20\x2d\x37\x2e\x33\x38\x34\x34\x34\x20\x2d\x36\x2e\x36\
+\x34\x30\x35\x37\x20\x2d\x31\x30\x2e\x31\x32\x39\x38\x43\x20\x2d\
+\x31\x2e\x32\x36\x32\x31\x39\x20\x2d\x31\x38\x2e\x38\x30\x31\x37\
+\x20\x37\x2e\x36\x38\x39\x37\x31\x20\x2d\x31\x35\x2e\x35\x33\x35\
+\x31\x20\x38\x2e\x36\x37\x36\x33\x32\x20\x2d\x35\x2e\x34\x38\x32\
+\x32\x43\x20\x39\x2e\x31\x38\x36\x37\x39\x20\x2d\x30\x2e\x32\x38\
+\x30\x38\x37\x37\x20\x36\x2e\x37\x34\x39\x33\x37\x20\x34\x2e\x35\
+\x31\x38\x38\x37\x20\x33\x2e\x33\x32\x30\x32\x38\x20\x35\x2e\x30\
+\x36\x34\x38\x39\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\
+\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\
+\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\
+\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x37\x35\
+\x36\x35\x36\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\
+\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\
+\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\
+\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\
+\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\
+\x65\x20\x63\x78\x3d\x27\x2d\x39\x2e\x33\x39\x31\x31\x38\x27\x20\
+\x63\x79\x3d\x27\x2d\x30\x27\x20\x72\x3d\x27\x33\x2e\x30\x31\x31\
+\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\
+\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\
+\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\
+\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\x20\x36\x39\x2e\
+\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\
+\x63\x78\x3d\x27\x2d\x36\x2e\x36\x34\x30\x35\x37\x27\x20\x63\x79\
+\x3d\x27\x2d\x31\x30\x2e\x31\x32\x39\x38\x27\x20\x72\x3d\x27\x33\
+\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\
+\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\x35\x35\
+\x20\x36\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x63\x78\x3d\x27\x38\x2e\x36\x37\x36\x33\x32\x27\
+\x20\x63\x79\x3d\x27\x2d\x35\x2e\x34\x38\x32\x32\x27\x20\x72\x3d\
+\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\x3d\x27\
+\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\
+\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\
+\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x38\x2e\x37\x36\
+\x35\x35\x20\x36\x39\x2e\x38\x31\x32\x33\x29\x27\x3e\x0a\x3c\x63\
+\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x33\x32\x30\x32\
+\x38\x27\x20\x63\x79\x3d\x27\x35\x2e\x30\x36\x34\x38\x39\x27\x20\
+\x72\x3d\x27\x33\x2e\x30\x31\x31\x32\x35\x27\x20\x66\x69\x6c\x6c\
+\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\
+\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x03\xeb\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\
+\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\
+\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\
+\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\
+\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\
+\x0a\x3c\x67\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\
+\x4d\x32\x35\x36\x2c\x31\x32\x38\x63\x2d\x38\x31\x2e\x39\x2c\x30\
+\x2d\x31\x34\x35\x2e\x37\x2c\x34\x38\x2e\x38\x2d\x32\x32\x34\x2c\
+\x31\x32\x38\x63\x36\x37\x2e\x34\x2c\x36\x37\x2e\x37\x2c\x31\x32\
+\x34\x2c\x31\x32\x38\x2c\x32\x32\x34\x2c\x31\x32\x38\x63\x39\x39\
+\x2e\x39\x2c\x30\x2c\x31\x37\x33\x2e\x34\x2d\x37\x36\x2e\x34\x2c\
+\x32\x32\x34\x2d\x31\x32\x36\x2e\x36\x0d\x0a\x09\x09\x43\x34\x32\
+\x38\x2e\x32\x2c\x31\x39\x38\x2e\x36\x2c\x33\x35\x34\x2e\x38\x2c\
+\x31\x32\x38\x2c\x32\x35\x36\x2c\x31\x32\x38\x7a\x20\x4d\x32\x35\
+\x36\x2c\x33\x34\x37\x2e\x33\x63\x2d\x34\x39\x2e\x34\x2c\x30\x2d\
+\x38\x39\x2e\x36\x2d\x34\x31\x2d\x38\x39\x2e\x36\x2d\x39\x31\x2e\
+\x33\x63\x30\x2d\x35\x30\x2e\x34\x2c\x34\x30\x2e\x32\x2d\x39\x31\
+\x2e\x33\x2c\x38\x39\x2e\x36\x2d\x39\x31\x2e\x33\x73\x38\x39\x2e\
+\x36\x2c\x34\x31\x2c\x38\x39\x2e\x36\x2c\x39\x31\x2e\x33\x0d\x0a\
+\x09\x09\x43\x33\x34\x35\x2e\x36\x2c\x33\x30\x36\x2e\x34\x2c\x33\
+\x30\x35\x2e\x34\x2c\x33\x34\x37\x2e\x33\x2c\x32\x35\x36\x2c\x33\
+\x34\x37\x2e\x33\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x67\x3e\x0d\x0a\
+\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x35\x36\x2c\
+\x32\x32\x34\x63\x30\x2d\x37\x2e\x39\x2c\x32\x2e\x39\x2d\x31\x35\
+\x2e\x31\x2c\x37\x2e\x36\x2d\x32\x30\x2e\x37\x63\x2d\x32\x2e\x35\
+\x2d\x30\x2e\x34\x2d\x35\x2d\x30\x2e\x36\x2d\x37\x2e\x36\x2d\x30\
+\x2e\x36\x63\x2d\x32\x38\x2e\x38\x2c\x30\x2d\x35\x32\x2e\x33\x2c\
+\x32\x33\x2e\x39\x2d\x35\x32\x2e\x33\x2c\x35\x33\x2e\x33\x63\x30\
+\x2c\x32\x39\x2e\x34\x2c\x32\x33\x2e\x35\x2c\x35\x33\x2e\x33\x2c\
+\x35\x32\x2e\x33\x2c\x35\x33\x2e\x33\x0d\x0a\x09\x09\x09\x73\x35\
+\x32\x2e\x33\x2d\x32\x33\x2e\x39\x2c\x35\x32\x2e\x33\x2d\x35\x33\
+\x2e\x33\x63\x30\x2d\x32\x2e\x33\x2d\x30\x2e\x32\x2d\x34\x2e\x36\
+\x2d\x30\x2e\x34\x2d\x36\x2e\x39\x63\x2d\x35\x2e\x35\x2c\x34\x2e\
+\x33\x2d\x31\x32\x2e\x33\x2c\x36\x2e\x39\x2d\x31\x39\x2e\x38\x2c\
+\x36\x2e\x39\x43\x32\x37\x30\x2e\x33\x2c\x32\x35\x36\x2c\x32\x35\
+\x36\x2c\x32\x34\x31\x2e\x37\x2c\x32\x35\x36\x2c\x32\x32\x34\x7a\
+\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\
+\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x6c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\
+\x0d\x0a\x09\x09\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x31\x37\x38\
+\x2e\x38\x34\x36\x22\x20\x79\x3d\x22\x39\x32\x2e\x30\x38\x37\x22\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x6d\x61\x74\x72\
+\x69\x78\x28\x2d\x30\x2e\x37\x30\x37\x31\x20\x2d\x30\x2e\x37\x30\
+\x37\x31\x20\x30\x2e\x37\x30\x37\x31\x20\x2d\x30\x2e\x37\x30\x37\
+\x31\x20\x32\x32\x34\x2e\x33\x34\x37\x36\x20\x36\x33\x31\x2e\x31\
+\x34\x39\x38\x29\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x32\x38\
+\x2e\x30\x38\x35\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x33\x35\
+\x34\x2e\x30\x34\x39\x22\x2f\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\
+\x20\x64\x3d\x22\x4d\x34\x37\x31\x2e\x37\x32\x33\x2c\x38\x38\x2e\
+\x33\x39\x33\x6c\x2d\x34\x38\x2e\x31\x31\x35\x2d\x34\x38\x2e\x31\
+\x31\x34\x63\x2d\x31\x31\x2e\x37\x32\x33\x2d\x31\x31\x2e\x37\x32\
+\x34\x2d\x33\x31\x2e\x35\x35\x38\x2d\x31\x30\x2e\x38\x39\x36\x2d\
+\x34\x34\x2e\x33\x30\x34\x2c\x31\x2e\x38\x35\x6c\x2d\x34\x35\x2e\
+\x32\x30\x32\x2c\x34\x35\x2e\x32\x30\x33\x6c\x39\x30\x2e\x35\x36\
+\x39\x2c\x39\x30\x2e\x35\x36\x38\x6c\x34\x35\x2e\x32\x30\x32\x2d\
+\x34\x35\x2e\x32\x30\x32\x0d\x0a\x09\x09\x43\x34\x38\x32\x2e\x36\
+\x31\x36\x2c\x31\x31\x39\x2e\x39\x35\x32\x2c\x34\x38\x33\x2e\x34\
+\x34\x35\x2c\x31\x30\x30\x2e\x31\x31\x36\x2c\x34\x37\x31\x2e\x37\
+\x32\x33\x2c\x38\x38\x2e\x33\x39\x33\x7a\x22\x2f\x3e\x0d\x0a\x09\
+\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\x3d\
+\x22\x36\x34\x2e\x30\x32\x31\x2c\x33\x36\x33\x2e\x32\x35\x32\x20\
+\x33\x32\x2c\x34\x38\x30\x20\x31\x34\x38\x2e\x37\x33\x37\x2c\x34\
+\x34\x37\x2e\x39\x37\x39\x20\x09\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\x7d\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x38\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x32\
+\x37\x2c\x32\x33\x34\x2e\x36\x32\x35\x48\x31\x36\x37\x2e\x32\x39\
+\x36\x6c\x31\x31\x39\x2e\x37\x30\x32\x2d\x31\x31\x39\x2e\x37\x30\
+\x32\x4c\x32\x35\x36\x2c\x38\x35\x4c\x38\x35\x2c\x32\x35\x36\x6c\
+\x31\x37\x31\x2c\x31\x37\x31\x6c\x32\x39\x2e\x39\x32\x32\x2d\x32\
+\x39\x2e\x39\x32\x34\x4c\x31\x36\x37\x2e\x32\x39\x36\x2c\x32\x37\
+\x37\x2e\x33\x37\x35\x48\x34\x32\x37\x56\x32\x33\x34\x2e\x36\x32\
+\x35\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\xc4\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x68\x65\x76\x72\x6f\x6e\x5f\x63\x69\x72\x63\x6c\x65\
+\x64\x5f\x6c\x65\x66\x74\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\
+\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\
+\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\
+\x6c\x69\x6e\x6b\x22\x0d\x0a\x09\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\
+\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\
+\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\
+\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\
+\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\
+\x31\x31\x2e\x33\x30\x32\x2c\x36\x2e\x37\x37\x36\x63\x2d\x30\x2e\
+\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2d\x30\x2e\x35\x31\x35\x2d\
+\x30\x2e\x31\x39\x37\x2d\x30\x2e\x37\x31\x2c\x30\x4c\x37\x2e\x37\
+\x38\x35\x2c\x39\x2e\x36\x34\x31\x63\x2d\x30\x2e\x31\x39\x36\x2c\
+\x30\x2e\x31\x39\x39\x2d\x30\x2e\x31\x39\x36\x2c\x30\x2e\x35\x32\
+\x2c\x30\x2c\x30\x2e\x37\x31\x37\x6c\x32\x2e\x38\x30\x37\x2c\x32\
+\x2e\x38\x36\x34\x0d\x0a\x09\x63\x30\x2e\x31\x39\x35\x2c\x30\x2e\
+\x31\x39\x39\x2c\x30\x2e\x35\x31\x34\x2c\x30\x2e\x31\x39\x38\x2c\
+\x30\x2e\x37\x31\x2c\x30\x63\x30\x2e\x31\x39\x36\x2d\x30\x2e\x31\
+\x39\x37\x2c\x30\x2e\x31\x39\x36\x2d\x30\x2e\x35\x31\x38\x2c\x30\
+\x2d\x30\x2e\x37\x31\x37\x4c\x39\x2c\x31\x30\x6c\x32\x2e\x33\x30\
+\x32\x2d\x32\x2e\x35\x30\x36\x43\x31\x31\x2e\x34\x39\x38\x2c\x37\
+\x2e\x32\x39\x36\x2c\x31\x31\x2e\x34\x39\x38\x2c\x36\x2e\x39\x37\
+\x36\x2c\x31\x31\x2e\x33\x30\x32\x2c\x36\x2e\x37\x37\x36\x7a\x0d\
+\x0a\x09\x20\x4d\x31\x30\x2c\x30\x2e\x34\x63\x2d\x35\x2e\x33\x30\
+\x32\x2c\x30\x2d\x39\x2e\x36\x2c\x34\x2e\x32\x39\x38\x2d\x39\x2e\
+\x36\x2c\x39\x2e\x36\x63\x30\x2c\x35\x2e\x33\x30\x33\x2c\x34\x2e\
+\x32\x39\x38\x2c\x39\x2e\x36\x2c\x39\x2e\x36\x2c\x39\x2e\x36\x73\
+\x39\x2e\x36\x2d\x34\x2e\x32\x39\x37\x2c\x39\x2e\x36\x2d\x39\x2e\
+\x36\x43\x31\x39\x2e\x36\x2c\x34\x2e\x36\x39\x38\x2c\x31\x35\x2e\
+\x33\x30\x32\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\x34\x7a\x20\
+\x4d\x31\x30\x2c\x31\x38\x2e\x33\x35\x34\x0d\x0a\x09\x63\x2d\x34\
+\x2e\x36\x31\x35\x2c\x30\x2d\x38\x2e\x33\x35\x34\x2d\x33\x2e\x37\
+\x34\x2d\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x30\x2d\
+\x34\x2e\x36\x31\x34\x2c\x33\x2e\x37\x33\x39\x2d\x38\x2e\x33\x35\
+\x34\x2c\x38\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x34\x2e\
+\x36\x31\x33\x2c\x30\x2c\x38\x2e\x33\x35\x34\x2c\x33\x2e\x37\x34\
+\x2c\x38\x2e\x33\x35\x34\x2c\x38\x2e\x33\x35\x34\x0d\x0a\x09\x43\
+\x31\x38\x2e\x33\x35\x34\x2c\x31\x34\x2e\x36\x31\x34\x2c\x31\x34\
+\x2e\x36\x31\x33\x2c\x31\x38\x2e\x33\x35\x34\x2c\x31\x30\x2c\x31\
+\x38\x2e\x33\x35\x34\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\
+\x3e\x0d\x0a\
+\x00\x00\x00\x6c\
+\x3c\
+\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\
+\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x3e\x3c\x70\x61\x74\x68\
+\x20\x64\x3d\x22\x4d\x31\x38\x20\x31\x32\x76\x31\x48\x38\x76\x35\
+\x6c\x2d\x36\x2d\x36\x20\x36\x2d\x36\x76\x35\x68\x38\x56\x32\x68\
+\x32\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\xb7\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\
+\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\
+\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\
+\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\
+\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\
+\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\
+\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\
+\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\
+\x22\x49\x63\x6f\x6e\x5f\x35\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\
+\x0d\x0a\x09\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\
+\x6e\x74\x73\x3d\x22\x34\x30\x35\x2c\x31\x33\x36\x2e\x37\x39\x38\
+\x20\x33\x37\x35\x2e\x32\x30\x32\x2c\x31\x30\x37\x20\x32\x35\x36\
+\x2c\x32\x32\x36\x2e\x32\x30\x32\x20\x31\x33\x36\x2e\x37\x39\x38\
+\x2c\x31\x30\x37\x20\x31\x30\x37\x2c\x31\x33\x36\x2e\x37\x39\x38\
+\x20\x32\x32\x36\x2e\x32\x30\x32\x2c\x32\x35\x36\x20\x31\x30\x37\
+\x2c\x33\x37\x35\x2e\x32\x30\x32\x20\x31\x33\x36\x2e\x37\x39\x38\
+\x2c\x34\x30\x35\x20\x32\x35\x36\x2c\x32\x38\x35\x2e\x37\x39\x38\
+\x20\x0d\x0a\x09\x09\x09\x33\x37\x35\x2e\x32\x30\x32\x2c\x34\x30\
+\x35\x20\x34\x30\x35\x2c\x33\x37\x35\x2e\x32\x30\x32\x20\x32\x38\
+\x35\x2e\x37\x39\x38\x2c\x32\x35\x36\x20\x09\x09\x22\x2f\x3e\x0d\
+\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x01\xdd\
+\x00\
+\x00\x06\xe4\x78\x9c\xcd\x54\x4d\x6f\x9b\x40\x10\x3d\x13\x29\xff\
+\x61\xba\xb7\x4a\xec\x17\xc4\xd4\xa6\xa6\x51\xfd\x21\xcb\x52\x9a\
+\x58\x6a\xea\xaa\xa7\x0a\xc3\x16\x50\x28\x20\x58\xc0\xce\xaf\xef\
+\xee\x92\x54\x51\x95\xfa\x18\xfb\xb0\x33\xda\x79\x6f\xde\xbc\x65\
+\x24\xa6\xd7\xfb\xdf\x39\x74\xa2\x6e\xb2\xb2\x08\x10\x27\x0c\x81\
+\x28\xa2\x32\xce\x8a\x24\x40\xad\xfc\x85\xc7\xe8\xfa\xd3\xe5\xc5\
+\xf4\x1d\xc6\xb0\x12\x85\xa8\x43\x59\xd6\x3e\x7c\x8e\xcb\x9d\x80\
+\x75\x9e\xb7\x8d\x34\x25\xe0\x1e\x71\x08\xb7\xe1\xeb\x76\x05\xcb\
+\x7d\x55\xd6\x12\x36\x79\x9b\xe0\x75\x01\xc4\x14\xb7\xc3\x10\x1f\
+\x3c\xc2\x18\xcc\xda\x2c\x8f\x81\xbd\x07\xc0\xd8\xe8\x2f\xee\xe6\
+\xf7\x3f\x36\x4b\x68\xba\x04\x36\xdf\x66\x37\xeb\x39\x20\x4c\xe9\
+\x77\x77\x4e\xe9\xe2\x7e\x61\x24\x38\xe1\x94\x2e\x6f\x11\xa0\x54\
+\xca\xca\xa7\xb4\xef\x7b\xd2\xbb\xa4\xac\x13\xba\xaa\xc3\x2a\xcd\
+\xa2\x86\x2a\x22\xd5\x44\xd5\x44\x95\x18\xe7\x24\x96\x31\xd2\x33\
+\xb4\xf4\x8b\xa7\x72\x04\x59\x1c\xa0\x9b\xf0\x20\xea\x9f\xea\xa2\
+\xbe\x44\xd1\x04\xaf\x48\x3b\x8c\x31\x2d\xf5\x44\xf1\xf7\x79\x56\
+\x3c\xbc\x46\xe4\x93\xc9\x84\x1a\x54\x51\x03\xc4\xaa\x3d\x82\xc3\
+\x90\x2f\x2f\x2c\xe8\xb3\x58\xa6\x01\x1a\x71\x47\x03\xa9\xc8\x92\
+\x54\xfe\xbd\x76\x99\xe8\x67\xa5\xee\x02\x06\xaa\xa6\x0f\x82\x46\
+\x1e\x72\x11\x20\x51\x84\xbb\x5c\xe0\x5d\x18\x3d\x24\x75\xd9\x16\
+\xb1\x5f\x88\x1e\x5e\x30\x3f\x1a\x6f\x7e\x53\x85\x91\xa2\x57\xb5\
+\x68\x44\xdd\x09\xf3\xea\x44\x05\x6b\x88\xd6\xb4\x0a\x65\x0a\xea\
+\xd1\x5f\xb8\xc7\x6c\x3e\x72\x89\x1b\x31\xdb\x25\x1f\xb0\x6b\x7b\
+\x2a\xaa\xa3\x73\x8a\x47\x8c\x8c\x22\xac\x00\x9b\xe9\x22\x76\xf1\
+\x13\xdc\x0d\x10\x33\x98\xfb\xdc\xa0\x73\x6a\x00\xd3\xa2\x4b\xb6\
+\x51\xd4\x67\x6b\xe6\x3c\xea\x4f\x60\x59\xf4\x1f\x1f\xce\x78\x7c\
+\x16\x3e\xae\xb8\x77\x3a\x1f\x53\xfa\xff\x25\x39\x63\xfe\x26\xa6\
+\xcc\x9c\x23\x4b\x3a\x07\x1f\x7a\x49\x27\xf3\x71\x6c\x49\x57\x6c\
+\xf2\x26\xa6\xcc\x9c\x23\x4b\x3a\x07\x1f\x7a\x49\x27\xf3\x31\x2c\
+\xe9\x39\xaa\x7f\xb6\xca\x7f\x00\x99\x18\x96\x19\
+\x00\x00\x02\x20\
+\x00\
+\x00\x07\x7f\x78\x9c\xdd\x55\x3b\x6f\xdb\x30\x10\xde\xfb\x2b\xae\
+\xe8\xc0\x76\x20\x45\x52\x24\x45\x06\x51\x02\xd4\x40\xa7\x74\x4b\
+\x96\x6e\x6a\xcc\x48\x6c\x6c\xc9\x90\x54\xcb\xfd\xf7\x3d\xc5\xd6\
+\xc3\x56\xd0\x29\x43\x11\x69\xd0\x3d\x78\x77\xdf\x7d\xc7\x83\xae\
+\x6f\x0f\xdb\x0d\xec\x7d\xdd\x84\xaa\x4c\x89\x60\x9c\x80\x2f\x1f\
+\xab\x75\x28\xf3\x94\x3c\xdc\x7f\xa3\x96\xdc\xde\x7c\xb8\xfe\x48\
+\x29\xdc\x17\xa1\x81\xa7\xb0\xf1\xd0\x65\x0d\xe4\xbe\xf4\x75\xd6\
+\xfa\x35\xfc\xfc\x03\xeb\x7d\x68\xf6\xf9\x16\x24\x53\x40\x29\x9e\
+\x47\x0d\x0a\x1f\xf2\xa2\x4d\x89\x54\xbb\x96\xcc\x6b\x08\xd4\x82\
+\xef\xbe\x56\x87\x94\x68\xc3\x14\x77\x0a\x74\xcc\xac\xb6\x31\x08\
+\xcb\x54\x9c\x68\x90\x8a\x40\x17\xd6\x6d\x81\x01\x47\x53\x9f\x04\
+\xc1\x96\x4d\x4a\x8a\xb6\xdd\x5d\x45\x51\xd7\x75\xac\x8b\x59\x55\
+\xe7\x91\xe4\x9c\x47\x58\xf4\x74\xe4\xea\xb0\x09\xe5\xf3\x6b\x07\
+\x85\x73\x2e\x7a\xf1\x12\x84\x99\x43\x58\xa7\x64\x97\xe5\x5e\x1c\
+\xd5\xb6\xce\xca\xe6\xa9\xaa\xb7\x29\xd9\x66\x6d\x1d\x0e\x9f\x39\
+\x73\xce\x48\xa3\x80\xf7\xef\xa0\x18\xcd\x8c\xb4\x12\x12\xc5\x24\
+\x97\x5f\xfa\xe0\x5d\xd6\x16\x80\xd9\xbe\x03\xb5\x0c\xf1\x72\xa4\
+\x42\x33\x2e\x35\x97\x77\x33\x13\x9f\x2b\x02\x9b\x76\x26\xf6\x54\
+\xe8\xd5\x99\x59\xc6\x2e\xd1\xbd\x79\x66\x35\x4c\x38\x9b\x24\x68\
+\x35\xf3\x7c\xb3\x40\xc1\xb4\x12\x16\xa8\x42\x70\x28\xe1\x38\x12\
+\x27\x8c\x45\xe0\x27\x69\x05\x97\xae\x8b\xd0\x41\x45\x94\xaf\x88\
+\x53\x3f\x13\x54\xce\x38\x62\x9f\x74\x4c\xe4\x30\xd1\x50\x87\x0a\
+\xc9\xac\x12\x09\x62\x18\xc4\xd5\x04\x70\xf4\xd2\x45\x02\x7a\x5e\
+\xe2\x6e\xc9\xea\x0f\xd2\xdf\xc6\x4d\x4a\x3e\x59\xde\xbf\x24\xc2\
+\x29\x44\xf9\xdb\xcd\x71\x8e\x49\x18\x93\xcc\xdb\x44\xfe\xb8\xd5\
+\xb3\x36\x63\xe6\xb4\x55\x2f\x6d\x1e\xc5\xb3\x36\x4f\x5e\xba\x48\
+\x40\x97\x45\x26\x93\xc3\x78\xe5\xe4\x2c\xd1\x38\x94\x51\x9c\x46\
+\x3a\x3a\x17\xf1\x97\x35\x46\xe6\xca\xaa\xf4\x04\x9a\xb6\xae\x9e\
+\x3d\xf2\xc8\x5f\x9e\xc1\x40\x71\x4b\xfc\x63\xb6\x4b\x49\x5d\xfd\
+\x2e\xd7\x67\xe6\x5f\x55\x28\x2f\xed\xdb\xd0\xfa\x7a\x13\xf0\x83\
+\x3b\x8b\x33\xc3\x9a\xa3\x6f\x58\x65\x96\x68\xa3\xcd\x9b\x4f\x6a\
+\xc1\xe2\xbb\xd9\xb8\x53\x3f\xef\x6d\x60\xff\x5a\x2d\x8d\x44\x49\
+\x31\x5b\x2d\x77\x64\x8a\x8f\xe2\xd9\x6a\x9d\xbc\x74\x91\x60\x71\
+\x29\xfe\x13\x12\x8f\x44\xf6\x7f\xab\x9b\xbf\x3f\x45\xd8\x3d\
+\x00\x00\x01\x20\
+\x3c\
+\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\
+\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\
+\x30\x2f\x73\x76\x67\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\
+\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x3e\x3c\x70\x61\x74\x68\
+\x20\x64\x3d\x22\x4d\x34\x2e\x33\x34\x20\x31\x35\x2e\x36\x36\x41\
+\x37\x2e\x39\x37\x20\x37\x2e\x39\x37\x20\x30\x20\x30\x20\x30\x20\
+\x39\x20\x31\x37\x2e\x39\x34\x56\x31\x30\x48\x35\x56\x38\x68\x34\
+\x56\x35\x2e\x38\x33\x61\x33\x20\x33\x20\x30\x20\x31\x20\x31\x20\
+\x32\x20\x30\x56\x38\x68\x34\x76\x32\x68\x2d\x34\x76\x37\x2e\x39\
+\x34\x61\x37\x2e\x39\x37\x20\x37\x2e\x39\x37\x20\x30\x20\x30\x20\
+\x30\x20\x34\x2e\x36\x36\x2d\x32\x2e\x32\x38\x6c\x2d\x31\x2e\x34\
+\x32\x2d\x31\x2e\x34\x32\x68\x35\x2e\x36\x36\x6c\x2d\x32\x2e\x38\
+\x33\x20\x32\x2e\x38\x33\x61\x31\x30\x20\x31\x30\x20\x30\x20\x30\
+\x20\x31\x2d\x31\x34\x2e\x31\x34\x20\x30\x4c\x2e\x31\x20\x31\x34\
+\x2e\x32\x34\x68\x35\x2e\x36\x36\x6c\x2d\x31\x2e\x34\x32\x20\x31\
+\x2e\x34\x32\x7a\x4d\x31\x30\x20\x34\x61\x31\x20\x31\x20\x30\x20\
+\x31\x20\x30\x20\x30\x2d\x32\x20\x31\x20\x31\x20\x30\x20\x30\x20\
+\x30\x20\x30\x20\x32\x7a\x22\x2f\x3e\x3c\x2f\x73\x76\x67\x3e\
+\x00\x00\x02\x6c\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x53\x61\x76\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\
+\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\
+\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\
+\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\
+\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\
+\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\x79\x3d\
+\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\x78\
+\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\x61\
+\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\
+\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x78\
+\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\
+\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\
+\x31\x35\x2e\x31\x37\x33\x2c\x32\x48\x34\x43\x32\x2e\x38\x39\x39\
+\x2c\x32\x2c\x32\x2c\x32\x2e\x39\x2c\x32\x2c\x34\x76\x31\x32\x63\
+\x30\x2c\x31\x2e\x31\x2c\x30\x2e\x38\x39\x39\x2c\x32\x2c\x32\x2c\
+\x32\x68\x31\x32\x63\x31\x2e\x31\x30\x31\x2c\x30\x2c\x32\x2d\x30\
+\x2e\x39\x2c\x32\x2d\x32\x56\x35\x2e\x31\x32\x37\x4c\x31\x35\x2e\
+\x31\x37\x33\x2c\x32\x7a\x20\x4d\x31\x34\x2c\x38\x63\x30\x2c\x30\
+\x2e\x35\x34\x39\x2d\x30\x2e\x34\x35\x2c\x31\x2d\x31\x2c\x31\x48\
+\x37\x0d\x0a\x09\x43\x36\x2e\x34\x35\x2c\x39\x2c\x36\x2c\x38\x2e\
+\x35\x34\x39\x2c\x36\x2c\x38\x56\x33\x68\x38\x56\x38\x7a\x20\x4d\
+\x31\x33\x2c\x34\x68\x2d\x32\x76\x34\x68\x32\x56\x34\x7a\x22\x2f\
+\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x02\xbd\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\
+\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\
+\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\
+\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\
+\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\
+\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\
+\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\
+\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\
+\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\
+\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\
+\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\
+\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\
+\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\
+\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\
+\x3d\x22\x43\x69\x72\x63\x6c\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\
+\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\
+\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\
+\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\
+\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\
+\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\
+\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\
+\x6f\x78\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\
+\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\
+\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\
+\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\
+\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\
+\x22\x4d\x31\x30\x2c\x30\x2e\x34\x43\x34\x2e\x36\x39\x38\x2c\x30\
+\x2e\x34\x2c\x30\x2e\x34\x2c\x34\x2e\x36\x39\x38\x2c\x30\x2e\x34\
+\x2c\x31\x30\x43\x30\x2e\x34\x2c\x31\x35\x2e\x33\x30\x32\x2c\x34\
+\x2e\x36\x39\x38\x2c\x31\x39\x2e\x36\x2c\x31\x30\x2c\x31\x39\x2e\
+\x36\x63\x35\x2e\x33\x30\x31\x2c\x30\x2c\x39\x2e\x36\x2d\x34\x2e\
+\x32\x39\x38\x2c\x39\x2e\x36\x2d\x39\x2e\x36\x30\x31\x0d\x0a\x09\
+\x43\x31\x39\x2e\x36\x2c\x34\x2e\x36\x39\x38\x2c\x31\x35\x2e\x33\
+\x30\x31\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\x34\x7a\x20\x4d\
+\x31\x30\x2c\x31\x37\x2e\x35\x39\x39\x63\x2d\x34\x2e\x31\x39\x37\
+\x2c\x30\x2d\x37\x2e\x36\x2d\x33\x2e\x34\x30\x32\x2d\x37\x2e\x36\
+\x2d\x37\x2e\x36\x53\x35\x2e\x38\x30\x32\x2c\x32\x2e\x34\x2c\x31\
+\x30\x2c\x32\x2e\x34\x63\x34\x2e\x31\x39\x37\x2c\x30\x2c\x37\x2e\
+\x36\x30\x31\x2c\x33\x2e\x34\x30\x32\x2c\x37\x2e\x36\x30\x31\x2c\
+\x37\x2e\x36\x0d\x0a\x09\x53\x31\x34\x2e\x31\x39\x37\x2c\x31\x37\
+\x2e\x35\x39\x39\x2c\x31\x30\x2c\x31\x37\x2e\x35\x39\x39\x7a\x22\
+\x2f\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\
+\x00\x00\x03\x65\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\
+\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\
+\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\
+\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\
+\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\
+\x34\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\x76\x65\x72\x73\
+\x69\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x76\x69\x65\x77\x42\x6f\
+\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\x38\x35\
+\x38\x33\x20\x31\x38\x2e\x37\x35\x20\x31\x38\x2e\x37\x35\x27\x20\
+\x77\x69\x64\x74\x68\x3d\x27\x31\x38\x2e\x37\x35\x70\x74\x27\x20\
+\x78\x6d\x6c\x6e\x73\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\
+\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\
+\x67\x27\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\
+\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\
+\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\x27\x3e\x0a\x3c\
+\x67\x20\x69\x64\x3d\x27\x70\x61\x67\x65\x31\x27\x3e\x0a\x3c\x67\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\
+\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\
+\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\
+\x20\x36\x33\x2e\x32\x33\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\
+\x68\x20\x64\x3d\x27\x4d\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x20\
+\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\x34\
+\x20\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x38\x2e\x36\x35\x37\x33\
+\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\x38\x2e\x36\
+\x35\x37\x33\x34\x20\x2d\x38\x2e\x36\x35\x37\x33\x34\x4c\x20\x2d\
+\x38\x2e\x36\x35\x37\x33\x34\x20\x38\x2e\x36\x35\x37\x33\x34\x5a\
+\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\
+\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\
+\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\
+\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\
+\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3d\x27\x31\x2e\x35\x30\x35\x36\x32\x27\
+\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\
+\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\
+\x36\x34\x20\x36\x35\x2e\x37\x38\x34\x34\x20\x36\x33\x2e\x32\x33\
+\x33\x33\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\
+\x20\x34\x2e\x33\x32\x38\x36\x37\x20\x30\x43\x20\x34\x2e\x33\x32\
+\x38\x36\x37\x20\x2d\x32\x2e\x33\x39\x30\x36\x36\x20\x32\x2e\x33\
+\x39\x30\x36\x36\x20\x2d\x34\x2e\x33\x32\x38\x36\x37\x20\x30\x20\
+\x2d\x34\x2e\x33\x32\x38\x36\x37\x43\x20\x2d\x32\x2e\x33\x39\x30\
+\x36\x36\x20\x2d\x34\x2e\x33\x32\x38\x36\x37\x20\x2d\x34\x2e\x33\
+\x32\x38\x36\x37\x20\x2d\x32\x2e\x33\x39\x30\x36\x36\x20\x2d\x34\
+\x2e\x33\x32\x38\x36\x37\x20\x2d\x30\x43\x20\x2d\x34\x2e\x33\x32\
+\x38\x36\x37\x20\x32\x2e\x33\x39\x30\x36\x36\x20\x2d\x32\x2e\x33\
+\x39\x30\x36\x36\x20\x34\x2e\x33\x32\x38\x36\x37\x20\x30\x20\x34\
+\x2e\x33\x32\x38\x36\x37\x43\x20\x32\x2e\x33\x39\x30\x36\x36\x20\
+\x34\x2e\x33\x32\x38\x36\x37\x20\x34\x2e\x33\x32\x38\x36\x37\x20\
+\x32\x2e\x33\x39\x30\x36\x36\x20\x34\x2e\x33\x32\x38\x36\x37\x20\
+\x30\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\
+\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x3c\x2f\x67\x3e\x0a\x3c\x2f\
+\x73\x76\x67\x3e\
+"
+
+qt_resource_name = b"\
+\x00\x05\
+\x00\x6f\xa6\x53\
+\x00\x69\
+\x00\x63\x00\x6f\x00\x6e\x00\x73\
+\x00\x10\
+\x08\x89\xfa\x47\
+\x00\x63\
+\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x6f\x00\x72\x00\x69\x00\x67\x00\x69\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0e\
+\x05\xed\x38\x67\
+\x00\x61\
+\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x6d\x00\x6f\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x14\
+\x0f\xa5\xe0\xc7\
+\x00\x6d\
+\x00\x61\x00\x67\x00\x6e\x00\x69\x00\x66\x00\x79\x00\x69\x00\x6e\x00\x67\x00\x2d\x00\x67\x00\x6c\x00\x61\x00\x73\x00\x73\x00\x2e\
+\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x09\x76\x60\xc7\
+\x00\x63\
+\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2d\x00\x72\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x0c\xf7\x55\x87\
+\x00\x74\
+\x00\x65\x00\x78\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x0c\x57\x65\x47\
+\x00\x61\
+\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x72\x00\x65\x00\x73\x00\x69\x00\x7a\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x07\x0e\xc4\x87\
+\x00\x6f\
+\x00\x70\x00\x65\x00\x6e\x00\x70\x00\x6f\x00\x6c\x00\x79\x00\x67\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1d\
+\x06\xec\xf4\xc7\
+\x00\x63\
+\x00\x68\x00\x65\x00\x76\x00\x72\x00\x6f\x00\x6e\x00\x2d\x00\x77\x00\x69\x00\x74\x00\x68\x00\x2d\x00\x63\x00\x69\x00\x72\x00\x63\
+\x00\x6c\x00\x65\x00\x2d\x00\x72\x00\x69\x00\x67\x00\x68\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x08\xe4\xaf\x47\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x64\x00\x6f\x00\x6e\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x05\xa8\x57\x87\
+\x00\x63\
+\x00\x6f\x00\x64\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x11\
+\x0c\xa7\xc7\x47\
+\x00\x63\
+\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x70\x00\x6f\x00\x6c\x00\x79\x00\x67\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+\x00\x11\
+\x01\x60\xbc\x47\
+\x00\x73\
+\x00\x6f\x00\x63\x00\x69\x00\x61\x00\x6c\x00\x2d\x00\x70\x00\x79\x00\x74\x00\x68\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+\x00\x19\
+\x0f\xef\x7b\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x63\x00\x6f\x00\x6c\x00\x6f\x00\x72\x00\x2d\x00\x70\x00\x61\x00\x6c\
+\x00\x65\x00\x74\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x12\
+\x08\x55\xef\xc7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x64\x00\x65\x00\x6c\x00\x65\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x12\
+\x08\x79\x97\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x63\x00\x61\x00\x6d\x00\x65\x00\x72\x00\x61\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x19\
+\x0a\x43\x45\xc7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x66\x00\x6f\x00\x72\
+\x00\x77\x00\x61\x00\x72\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x01\xca\x6d\x87\
+\x00\x62\
+\x00\x75\x00\x63\x00\x6b\x00\x65\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x13\
+\x03\x24\x75\x47\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x72\x00\x65\x00\x66\x00\x72\x00\x65\x00\x73\x00\x68\x00\x2e\x00\x73\
+\x00\x76\x00\x67\
+\x00\x09\
+\x0b\x9e\x89\x07\
+\x00\x63\
+\x00\x68\x00\x65\x00\x63\x00\x6b\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1c\
+\x08\x8a\x79\x07\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x72\x00\x61\x00\x64\x00\x69\x00\x6f\x00\x2d\x00\x62\x00\x75\x00\x74\
+\x00\x74\x00\x6f\x00\x6e\x00\x2d\x00\x6f\x00\x66\x00\x66\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1b\
+\x0e\xb5\x68\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x72\x00\x61\x00\x64\x00\x69\x00\x6f\x00\x2d\x00\x62\x00\x75\x00\x74\
+\x00\x74\x00\x6f\x00\x6e\x00\x2d\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x12\
+\x0c\x5e\xd4\xa7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x6c\x00\x6f\x00\x63\x00\x61\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x12\
+\x04\xb2\x21\x47\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x65\x00\x78\x00\x70\x00\x61\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\
+\x00\x67\
+\x00\x0e\
+\x0f\xcb\xd5\xc7\
+\x00\x70\
+\x00\x6c\x00\x75\x00\x73\x00\x2d\x00\x72\x00\x6f\x00\x75\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x17\
+\x07\x87\x48\x27\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x66\x00\x6f\x00\x6c\x00\x64\x00\x65\x00\x72\x00\x2d\x00\x6f\x00\x70\
+\x00\x65\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x06\xe3\xaf\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x68\x00\x61\x00\x6e\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0f\
+\x04\xf2\xa7\x87\
+\x00\x63\
+\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x64\x00\x63\x00\x75\x00\x72\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x17\
+\x06\xc6\x02\xa7\
+\x00\x74\
+\x00\x72\x00\x69\x00\x61\x00\x6e\x00\x67\x00\x6c\x00\x65\x00\x2d\x00\x73\x00\x74\x00\x72\x00\x6f\x00\x6b\x00\x65\x00\x64\x00\x2d\
+\x00\x31\x00\x35\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0d\
+\x05\x20\xce\x87\
+\x00\x6f\
+\x00\x70\x00\x65\x00\x6e\x00\x63\x00\x75\x00\x72\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x07\
+\x0c\xf8\x5a\x07\
+\x00\x65\
+\x00\x79\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x0b\x07\x57\xa7\
+\x00\x65\
+\x00\x64\x00\x69\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x16\
+\x01\xfb\x76\x27\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x62\x00\x61\x00\x63\
+\x00\x6b\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x1c\
+\x04\x66\xe1\x67\
+\x00\x63\
+\x00\x68\x00\x65\x00\x76\x00\x72\x00\x6f\x00\x6e\x00\x2d\x00\x77\x00\x69\x00\x74\x00\x68\x00\x2d\x00\x63\x00\x69\x00\x72\x00\x63\
+\x00\x6c\x00\x65\x00\x2d\x00\x6c\x00\x65\x00\x66\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x15\
+\x0f\xc4\x59\xe7\
+\x00\x73\
+\x00\x75\x00\x62\x00\x64\x00\x69\x00\x72\x00\x65\x00\x63\x00\x74\x00\x6f\x00\x72\x00\x79\x00\x2d\x00\x6c\x00\x65\x00\x66\x00\x74\
+\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x11\
+\x0c\xdb\x38\xe7\
+\x00\x61\
+\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x63\x00\x6c\x00\x6f\x00\x73\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\
+\x00\x08\
+\x08\xf7\x57\x07\
+\x00\x67\
+\x00\x72\x00\x69\x00\x64\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x10\
+\x04\xa9\x22\xc7\
+\x00\x66\
+\x00\x69\x00\x6c\x00\x6c\x00\x65\x00\x64\x00\x62\x00\x75\x00\x63\x00\x6b\x00\x65\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0f\x68\x53\xe7\
+\x00\x61\
+\x00\x6e\x00\x63\x00\x68\x00\x6f\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x08\
+\x08\xc8\x55\xe7\
+\x00\x73\
+\x00\x61\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0a\x2d\x1b\xc7\
+\x00\x63\
+\x00\x69\x00\x72\x00\x63\x00\x6c\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0a\
+\x0a\xc8\x62\x67\
+\x00\x63\
+\x00\x65\x00\x6e\x00\x74\x00\x65\x00\x72\x00\x2e\x00\x73\x00\x76\x00\x67\
+"
+
+qt_resource_struct_v1 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x29\x00\x00\x00\x02\
+\x00\x00\x01\xae\x00\x00\x00\x00\x00\x01\x00\x00\x24\x33\
+\x00\x00\x02\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x39\x2f\
+\x00\x00\x04\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x74\xb4\
+\x00\x00\x02\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x3e\xea\
+\x00\x00\x05\x16\x00\x00\x00\x00\x00\x01\x00\x00\x77\x35\
+\x00\x00\x05\xc2\x00\x01\x00\x00\x00\x01\x00\x00\x80\x09\
+\x00\x00\x03\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x4f\xdc\
+\x00\x00\x04\x42\x00\x00\x00\x00\x00\x01\x00\x00\x5f\x35\
+\x00\x00\x04\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x68\xc4\
+\x00\x00\x01\x70\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x82\
+\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x04\x14\
+\x00\x00\x04\x66\x00\x00\x00\x00\x00\x01\x00\x00\x63\xf6\
+\x00\x00\x04\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x59\x67\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x15\x4c\
+\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x11\x26\
+\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x56\x11\
+\x00\x00\x02\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x30\xe2\
+\x00\x00\x02\x38\x00\x00\x00\x00\x00\x01\x00\x00\x33\x88\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x02\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x45\x24\
+\x00\x00\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x83\x51\
+\x00\x00\x01\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x19\x05\
+\x00\x00\x05\xac\x00\x01\x00\x00\x00\x01\x00\x00\x7e\x28\
+\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x78\
+\x00\x00\x06\x18\x00\x00\x00\x00\x00\x01\x00\x00\x85\xc1\
+\x00\x00\x02\x62\x00\x00\x00\x00\x00\x01\x00\x00\x36\xae\
+\x00\x00\x06\x32\x00\x00\x00\x00\x00\x01\x00\x00\x88\x82\
+\x00\x00\x04\xce\x00\x00\x00\x00\x00\x01\x00\x00\x71\x44\
+\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x42\x14\
+\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xa3\
+\x00\x00\x03\x72\x00\x00\x00\x00\x00\x01\x00\x00\x4b\x74\
+\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xff\
+\x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x00\x7b\x6d\
+\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xc2\
+\x00\x00\x04\xba\x00\x00\x00\x00\x00\x01\x00\x00\x6d\x55\
+\x00\x00\x03\x36\x00\x00\x00\x00\x00\x01\x00\x00\x48\x24\
+\x00\x00\x05\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x82\x2d\
+\x00\x00\x00\x58\x00\x00\x00\x00\x00\x01\x00\x00\x06\xe1\
+\x00\x00\x05\x54\x00\x00\x00\x00\x00\x01\x00\x00\x7a\xfd\
+\x00\x00\x03\xc6\x00\x00\x00\x00\x00\x01\x00\x00\x53\x16\
+\x00\x00\x01\xd6\x00\x00\x00\x00\x00\x01\x00\x00\x2b\xb7\
+"
+
+qt_resource_struct_v2 = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x29\x00\x00\x00\x02\
+\x00\x00\x00\x00\x00\x00\x00\x00\
+\x00\x00\x01\xae\x00\x00\x00\x00\x00\x01\x00\x00\x24\x33\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x39\x2f\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\xe4\x00\x00\x00\x00\x00\x01\x00\x00\x74\xb4\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x02\xb4\x00\x00\x00\x00\x00\x01\x00\x00\x3e\xea\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x05\x16\x00\x00\x00\x00\x00\x01\x00\x00\x77\x35\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x05\xc2\x00\x01\x00\x00\x00\x01\x00\x00\x80\x09\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x4f\xdc\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\x42\x00\x00\x00\x00\x00\x01\x00\x00\x5f\x35\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x04\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x68\xc4\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x01\x70\x00\x00\x00\x00\x00\x01\x00\x00\x1b\x82\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x04\x14\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\x66\x00\x00\x00\x00\x00\x01\x00\x00\x63\xf6\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x04\x1c\x00\x00\x00\x00\x00\x01\x00\x00\x59\x67\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x01\x0a\x00\x00\x00\x00\x00\x01\x00\x00\x15\x4c\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\xe6\x00\x00\x00\x00\x00\x01\x00\x00\x11\x26\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x56\x11\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x02\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x30\xe2\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x02\x38\x00\x00\x00\x00\x00\x01\x00\x00\x33\x88\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\xf8\x00\x00\x00\x00\x00\x01\x00\x00\x45\x24\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x06\x02\x00\x00\x00\x00\x00\x01\x00\x00\x83\x51\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x01\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x19\x05\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x05\xac\x00\x01\x00\x00\x00\x01\x00\x00\x7e\x28\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\x86\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x78\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x06\x18\x00\x00\x00\x00\x00\x01\x00\x00\x85\xc1\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\x62\x00\x00\x00\x00\x00\x01\x00\x00\x36\xae\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x06\x32\x00\x00\x00\x00\x00\x01\x00\x00\x88\x82\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x04\xce\x00\x00\x00\x00\x00\x01\x00\x00\x71\x44\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x02\xe0\x00\x00\x00\x00\x00\x01\x00\x00\x42\x14\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x01\x00\x00\x0e\xa3\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x03\x72\x00\x00\x00\x00\x00\x01\x00\x00\x4b\x74\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x01\x86\x00\x00\x00\x00\x00\x01\x00\x00\x1f\xff\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x05\x84\x00\x00\x00\x00\x00\x01\x00\x00\x7b\x6d\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x00\xaa\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xc2\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x04\xba\x00\x00\x00\x00\x00\x01\x00\x00\x6d\x55\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\x36\x00\x00\x00\x00\x00\x01\x00\x00\x48\x24\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x05\xe8\x00\x00\x00\x00\x00\x01\x00\x00\x82\x2d\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+\x00\x00\x00\x58\x00\x00\x00\x00\x00\x01\x00\x00\x06\xe1\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x05\x54\x00\x00\x00\x00\x00\x01\x00\x00\x7a\xfd\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x03\xc6\x00\x00\x00\x00\x00\x01\x00\x00\x53\x16\
+\x00\x00\x01\x64\xed\x16\x26\xd7\
+\x00\x00\x01\xd6\x00\x00\x00\x00\x00\x01\x00\x00\x2b\xb7\
+\x00\x00\x01\x64\xed\x16\x26\xd6\
+"
+
+qt_version = QtCore.qVersion().split('.')
+if qt_version < ['5', '8', '0']:
+    rcc_version = 1
+    qt_resource_struct = qt_resource_struct_v1
+else:
+    rcc_version = 2
+    qt_resource_struct = qt_resource_struct_v2
+
+def qInitResources():
+    QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+    QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/icons_rc.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/labelEditor.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/labelEditor.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/labelEditor.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,154 @@
+#!/usr/bin/env python3
+
+from pyUIClass.labelTextEditor import Ui_Dialog
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtSvg as Qs
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import xasyArgs as xa
+import xasy2asy as x2a
+import subprocess
+import xasyOptions as xo
+import xasyUtils as xu
+import tempfile
+import uuid
+import os
+import io
+
+
+class labelEditor(Qw.QDialog):
+    def __init__(self, text=''):
+        super().__init__()
+        self.ui = Ui_Dialog()
+        self.ui.setupUi(self)
+
+        self.ui.btnAccept.clicked.connect(self.accept)
+        self.ui.btnCancel.clicked.connect(self.reject)
+        self.ui.chkMathMode.stateChanged.connect(self.chkMathModeChecked)
+        self.ui.btnPreview.clicked.connect(self.btnPreviewOnClick)
+        self.ui.btnGetText.clicked.connect(self.btnGetTextOnClick)
+
+        self.svgPreview = None
+        self.initializeText(text)
+
+    def initializeText(self, text: str):
+        if text[0] == '$' and text[-1] == '$':
+            self.ui.chkMathMode.setChecked(True)
+            text = text.strip('$')
+
+            if text.startswith('\\displaystyle{'):
+                self.ui.cmbMathStyle.setCurrentText('Display Style')
+                text = text.rstrip('}')
+                text = text.replace('\\displaystyle{', '', 1)
+            elif text.startswith('\\scriptstyle{'):
+                self.ui.cmbMathStyle.setCurrentText('Script Style')
+                text = text.rstrip('}')
+                text = text.replace('\\scriptstyle{', '', 1)
+
+        self.ui.txtLabelEdit.setPlainText(text)
+
+    def chkMathModeChecked(self, checked):
+        self.ui.cmbMathStyle.setEnabled(checked)
+
+    def getText(self):
+        rawText = self.ui.txtLabelEdit.toPlainText()
+        rawText.replace('\n', ' ')
+        if self.ui.chkMathMode.isChecked():
+            prefix = ''
+            suffix = ''
+            if self.ui.cmbMathStyle.currentText() == 'Display Style':
+                prefix = '\\displaystyle{'
+                suffix = '}'
+            elif self.ui.cmbMathStyle.currentText() == 'Script Style':
+                prefix = '\\scriptstyle{'
+                suffix = '}'
+            return '${0}{1}{2}$'.format(prefix, rawText, suffix)
+        else:
+            return rawText
+
+    def btnPreviewOnClick(self):
+        path = xa.getArgs().asypath
+        if path is None:
+            opt = xo.xasyOptions().load()
+            path = opt['asyPath']
+
+        asyInput = """
+        frame f;
+        label(f, "{0}");
+        write(min(f), newl);
+        write(max(f), newl);
+        shipout(f);
+        """
+
+        self.svgPreview = Qs.QSvgRenderer()
+        with tempfile.TemporaryDirectory(prefix='xasylbl_') as tmpdir:
+            id = str(uuid.uuid4())
+            tmpFile = os.path.join(tmpdir, 'lbl-{0}.svg'.format(id))
+
+            with subprocess.Popen(args=[path, '-fsvg', '-o', tmpFile, '-'], encoding='utf-8', stdin=subprocess.PIPE,
+                                   stdout=subprocess.PIPE) as asy:
+                asy.stdin.write(asyInput.format(self.getText()))
+                asy.stdin.close()
+                out = asy.stdout.read()
+
+            raw_array = out.splitlines()
+
+            bounds_1, bounds_2 = [val.strip() for val in raw_array]
+
+            min_bounds = xu.listize(bounds_1, (float, float))
+            max_bounds = xu.listize(bounds_2, (float, float))
+
+            new_rect = self.processBounds(min_bounds, max_bounds)
+            self.svgPreview.load(tmpFile)
+
+
+
+        self.drawPreview(new_rect)
+
+    def drawPreview(self, naturalBounds):
+        img = Qg.QPixmap(self.ui.lblLabelPreview.size())
+        img.fill(Qg.QColor.fromRgbF(1, 1, 1, 1))
+        if self.svgPreview is None:
+            pass
+        else:
+            with Qg.QPainter(img) as pnt:
+                scale_ratio = self.getIdealScaleRatio(naturalBounds, self.ui.lblLabelPreview.rect())
+
+                pnt.translate(self.ui.lblLabelPreview.rect().center())
+                pnt.scale(scale_ratio, scale_ratio)
+                self.svgPreview.render(pnt, naturalBounds)
+            self.ui.lblLabelPreview.setPixmap(img)
+
+
+    def getIdealScaleRatio(self, rect, boundsRect):
+        assert isinstance(rect, (Qc.QRect, Qc.QRectF))
+        assert isinstance(rect, (Qc.QRect, Qc.QRectF))
+
+        magic_ratio = 0.50
+        idealRatioHeight = (magic_ratio * boundsRect.height()) / rect.height()
+        magicRatioWidth = 0.50
+
+        if idealRatioHeight * rect.width() > magicRatioWidth * boundsRect.width():
+            idealRatioWidth = (magicRatioWidth * boundsRect.width()) / rect.width()
+            idealRatio = min(idealRatioHeight, idealRatioWidth)
+        else:
+            idealRatio = idealRatioHeight
+        return idealRatio
+
+    def processBounds(self, minPt, maxPt):
+        p1x, p1y = minPt
+        p2x, p2y = maxPt
+
+        minPt = Qc.QPointF(p1x, p1y)
+        maxPt = Qc.QPointF(p2x, p2y)
+
+        newRect = Qc.QRectF(minPt, maxPt)
+        return newRect
+
+
+    def btnGetTextOnClick(self):
+        msgbox = Qw.QMessageBox()
+        msgbox.setText('Text Preview:\n' + self.getText())
+        msgbox.setWindowTitle('Text preview')
+        msgbox.show()
+        return msgbox.exec_()


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/labelEditor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/custMatTransform.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/custMatTransform.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/custMatTransform.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/custMatTransform.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Dialog(object):
+    def setupUi(self, Dialog):
+        Dialog.setObjectName("Dialog")
+        Dialog.resize(500, 320)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
+        Dialog.setSizePolicy(sizePolicy)
+        Dialog.setMinimumSize(QtCore.QSize(500, 320))
+        Dialog.setMaximumSize(QtCore.QSize(500, 320))
+        Dialog.setMouseTracking(False)
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/icons/android-expand.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        Dialog.setWindowIcon(icon)
+        Dialog.setSizeGripEnabled(True)
+        Dialog.setModal(False)
+        self.centralFrame = QtWidgets.QFrame(Dialog)
+        self.centralFrame.setGeometry(QtCore.QRect(20, 20, 461, 271))
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.centralFrame.sizePolicy().hasHeightForWidth())
+        self.centralFrame.setSizePolicy(sizePolicy)
+        self.centralFrame.setBaseSize(QtCore.QSize(0, 0))
+        self.centralFrame.setObjectName("centralFrame")
+        self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.centralFrame)
+        self.verticalLayout_3.setSpacing(4)
+        self.verticalLayout_3.setObjectName("verticalLayout_3")
+        self.horizontalLayout = QtWidgets.QHBoxLayout()
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+        self.verticalLayout = QtWidgets.QVBoxLayout()
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.label = QtWidgets.QLabel(self.centralFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
+        self.label.setSizePolicy(sizePolicy)
+        self.label.setObjectName("label")
+        self.verticalLayout.addWidget(self.label)
+        self.gridFrame = QtWidgets.QFrame(self.centralFrame)
+        self.gridFrame.setFrameShape(QtWidgets.QFrame.Box)
+        self.gridFrame.setObjectName("gridFrame")
+        self.gridLayout = QtWidgets.QGridLayout(self.gridFrame)
+        self.gridLayout.setObjectName("gridLayout")
+        self.lineMat00 = QtWidgets.QLineEdit(self.gridFrame)
+        self.lineMat00.setMaximumSize(QtCore.QSize(70, 16777215))
+        self.lineMat00.setObjectName("lineMat00")
+        self.gridLayout.addWidget(self.lineMat00, 1, 0, 1, 1)
+        self.lineMat11 = QtWidgets.QLineEdit(self.gridFrame)
+        self.lineMat11.setMaximumSize(QtCore.QSize(70, 16777215))
+        self.lineMat11.setObjectName("lineMat11")
+        self.gridLayout.addWidget(self.lineMat11, 2, 1, 1, 1)
+        self.lineMat10 = QtWidgets.QLineEdit(self.gridFrame)
+        self.lineMat10.setMaximumSize(QtCore.QSize(70, 16777215))
+        self.lineMat10.setObjectName("lineMat10")
+        self.gridLayout.addWidget(self.lineMat10, 2, 0, 1, 1)
+        self.lineMat01 = QtWidgets.QLineEdit(self.gridFrame)
+        self.lineMat01.setMaximumSize(QtCore.QSize(70, 16777215))
+        self.lineMat01.setObjectName("lineMat01")
+        self.gridLayout.addWidget(self.lineMat01, 1, 1, 1, 1)
+        self.verticalLayout.addWidget(self.gridFrame)
+        self.horizontalLayout_3.addLayout(self.verticalLayout)
+        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_3.addItem(spacerItem)
+        self.verticalLayout_4 = QtWidgets.QVBoxLayout()
+        self.verticalLayout_4.setObjectName("verticalLayout_4")
+        self.label_3 = QtWidgets.QLabel(self.centralFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth())
+        self.label_3.setSizePolicy(sizePolicy)
+        self.label_3.setObjectName("label_3")
+        self.verticalLayout_4.addWidget(self.label_3)
+        self.gridFrame_2 = QtWidgets.QFrame(self.centralFrame)
+        self.gridFrame_2.setFrameShape(QtWidgets.QFrame.Box)
+        self.gridFrame_2.setObjectName("gridFrame_2")
+        self.gridLayout_2 = QtWidgets.QGridLayout(self.gridFrame_2)
+        self.gridLayout_2.setObjectName("gridLayout_2")
+        self.lineMatTy = QtWidgets.QLineEdit(self.gridFrame_2)
+        self.lineMatTy.setMaximumSize(QtCore.QSize(70, 16777215))
+        self.lineMatTy.setObjectName("lineMatTy")
+        self.gridLayout_2.addWidget(self.lineMatTy, 2, 1, 1, 1)
+        self.lineMatTx = QtWidgets.QLineEdit(self.gridFrame_2)
+        self.lineMatTx.setMaximumSize(QtCore.QSize(70, 16777215))
+        self.lineMatTx.setObjectName("lineMatTx")
+        self.gridLayout_2.addWidget(self.lineMatTx, 1, 1, 1, 1)
+        self.verticalLayout_4.addWidget(self.gridFrame_2)
+        self.horizontalLayout_3.addLayout(self.verticalLayout_4)
+        self.horizontalLayout.addLayout(self.horizontalLayout_3)
+        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem1)
+        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+        self.verticalLayout_2.setObjectName("verticalLayout_2")
+        self.label_2 = QtWidgets.QLabel(self.centralFrame)
+        self.label_2.setObjectName("label_2")
+        self.verticalLayout_2.addWidget(self.label_2)
+        self.imgPreview = QtWidgets.QLabel(self.centralFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.imgPreview.sizePolicy().hasHeightForWidth())
+        self.imgPreview.setSizePolicy(sizePolicy)
+        self.imgPreview.setMinimumSize(QtCore.QSize(150, 150))
+        self.imgPreview.setBaseSize(QtCore.QSize(300, 300))
+        self.imgPreview.setFrameShape(QtWidgets.QFrame.Box)
+        self.imgPreview.setText("")
+        self.imgPreview.setObjectName("imgPreview")
+        self.verticalLayout_2.addWidget(self.imgPreview)
+        self.horizontalLayout.addLayout(self.verticalLayout_2)
+        self.verticalLayout_3.addLayout(self.horizontalLayout)
+        self.lblAnchor = QtWidgets.QLabel(self.centralFrame)
+        self.lblAnchor.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
+        self.lblAnchor.setObjectName("lblAnchor")
+        self.verticalLayout_3.addWidget(self.lblAnchor)
+        self.lblCoordsMode = QtWidgets.QLabel(self.centralFrame)
+        self.lblCoordsMode.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
+        self.lblCoordsMode.setObjectName("lblCoordsMode")
+        self.verticalLayout_3.addWidget(self.lblCoordsMode)
+        spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+        self.verticalLayout_3.addItem(spacerItem2)
+        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout_2.addItem(spacerItem3)
+        self.btnReset = QtWidgets.QPushButton(self.centralFrame)
+        self.btnReset.setObjectName("btnReset")
+        self.horizontalLayout_2.addWidget(self.btnReset)
+        self.btnCancel = QtWidgets.QPushButton(self.centralFrame)
+        self.btnCancel.setObjectName("btnCancel")
+        self.horizontalLayout_2.addWidget(self.btnCancel)
+        self.btnAccept = QtWidgets.QPushButton(self.centralFrame)
+        self.btnAccept.setObjectName("btnAccept")
+        self.horizontalLayout_2.addWidget(self.btnAccept)
+        self.verticalLayout_3.addLayout(self.horizontalLayout_2)
+
+        self.retranslateUi(Dialog)
+        QtCore.QMetaObject.connectSlotsByName(Dialog)
+
+    def retranslateUi(self, Dialog):
+        _translate = QtCore.QCoreApplication.translate
+        Dialog.setWindowTitle(_translate("Dialog", "Set Custom Transformation"))
+        self.label.setText(_translate("Dialog", "Transformation Matrix"))
+        self.lineMat00.setText(_translate("Dialog", "1"))
+        self.lineMat11.setText(_translate("Dialog", "1"))
+        self.lineMat10.setText(_translate("Dialog", "0"))
+        self.lineMat01.setText(_translate("Dialog", "0"))
+        self.label_3.setText(_translate("Dialog", "Translation"))
+        self.lineMatTy.setText(_translate("Dialog", "0"))
+        self.lineMatTx.setText(_translate("Dialog", "0"))
+        self.label_2.setText(_translate("Dialog", "Preview:"))
+        self.imgPreview.setToolTip(_translate("Dialog", "Shows a red square if transformation determinant is negative."))
+        self.lblAnchor.setText(_translate("Dialog", "Anchor: Top Left"))
+        self.lblCoordsMode.setText(_translate("Dialog", "Coordinates: Global"))
+        self.btnReset.setText(_translate("Dialog", "Reset"))
+        self.btnCancel.setText(_translate("Dialog", "Cancel"))
+        self.btnAccept.setText(_translate("Dialog", "Accept"))
+
+import icons_rc


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/custMatTransform.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/labelTextEditor.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/labelTextEditor.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/labelTextEditor.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/labelTextEditor.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Dialog(object):
+    def setupUi(self, Dialog):
+        Dialog.setObjectName("Dialog")
+        Dialog.resize(473, 424)
+        self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.frame = QtWidgets.QFrame(Dialog)
+        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
+        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
+        self.frame.setObjectName("frame")
+        self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.frame)
+        self.verticalLayout_3.setObjectName("verticalLayout_3")
+        self.gridLayout = QtWidgets.QGridLayout()
+        self.gridLayout.setContentsMargins(-1, 0, -1, -1)
+        self.gridLayout.setObjectName("gridLayout")
+        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.gridLayout.addItem(spacerItem, 0, 2, 1, 1)
+        self.chkMathMode = QtWidgets.QCheckBox(self.frame)
+        self.chkMathMode.setObjectName("chkMathMode")
+        self.gridLayout.addWidget(self.chkMathMode, 0, 0, 1, 1)
+        self.cmbMathStyle = QtWidgets.QComboBox(self.frame)
+        self.cmbMathStyle.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.cmbMathStyle.sizePolicy().hasHeightForWidth())
+        self.cmbMathStyle.setSizePolicy(sizePolicy)
+        self.cmbMathStyle.setMinimumSize(QtCore.QSize(100, 0))
+        self.cmbMathStyle.setObjectName("cmbMathStyle")
+        self.cmbMathStyle.addItem("")
+        self.cmbMathStyle.addItem("")
+        self.cmbMathStyle.addItem("")
+        self.gridLayout.addWidget(self.cmbMathStyle, 0, 1, 1, 1)
+        self.verticalLayout_3.addLayout(self.gridLayout)
+        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+        self.verticalLayout_2.setObjectName("verticalLayout_2")
+        self.txtLabelEdit = QtWidgets.QPlainTextEdit(self.frame)
+        self.txtLabelEdit.setObjectName("txtLabelEdit")
+        self.verticalLayout_2.addWidget(self.txtLabelEdit)
+        self.verticalLayout_3.addLayout(self.verticalLayout_2)
+        self.verticalLayout_4 = QtWidgets.QVBoxLayout()
+        self.verticalLayout_4.setContentsMargins(-1, 0, -1, -1)
+        self.verticalLayout_4.setObjectName("verticalLayout_4")
+        self.label = QtWidgets.QLabel(self.frame)
+        self.label.setObjectName("label")
+        self.verticalLayout_4.addWidget(self.label)
+        self.lblLabelPreview = QtWidgets.QLabel(self.frame)
+        self.lblLabelPreview.setMinimumSize(QtCore.QSize(0, 100))
+        self.lblLabelPreview.setFrameShape(QtWidgets.QFrame.Box)
+        self.lblLabelPreview.setText("")
+        self.lblLabelPreview.setObjectName("lblLabelPreview")
+        self.verticalLayout_4.addWidget(self.lblLabelPreview)
+        self.verticalLayout_3.addLayout(self.verticalLayout_4)
+        self.horizontalLayout = QtWidgets.QHBoxLayout()
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem1)
+        self.btnGetText = QtWidgets.QPushButton(self.frame)
+        self.btnGetText.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnGetText.setText("")
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/icons/text.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnGetText.setIcon(icon)
+        self.btnGetText.setFlat(True)
+        self.btnGetText.setObjectName("btnGetText")
+        self.horizontalLayout.addWidget(self.btnGetText)
+        self.btnPreview = QtWidgets.QPushButton(self.frame)
+        self.btnPreview.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnPreview.setText("")
+        icon1 = QtGui.QIcon()
+        icon1.addPixmap(QtGui.QPixmap(":/icons/eye.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnPreview.setIcon(icon1)
+        self.btnPreview.setFlat(True)
+        self.btnPreview.setObjectName("btnPreview")
+        self.horizontalLayout.addWidget(self.btnPreview)
+        self.btnCancel = QtWidgets.QPushButton(self.frame)
+        self.btnCancel.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnCancel.setText("")
+        icon2 = QtGui.QIcon()
+        icon2.addPixmap(QtGui.QPixmap(":/icons/android-close.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnCancel.setIcon(icon2)
+        self.btnCancel.setFlat(True)
+        self.btnCancel.setObjectName("btnCancel")
+        self.horizontalLayout.addWidget(self.btnCancel)
+        self.btnAccept = QtWidgets.QPushButton(self.frame)
+        self.btnAccept.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnAccept.setText("")
+        icon3 = QtGui.QIcon()
+        icon3.addPixmap(QtGui.QPixmap(":/icons/android-done.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnAccept.setIcon(icon3)
+        self.btnAccept.setFlat(True)
+        self.btnAccept.setObjectName("btnAccept")
+        self.horizontalLayout.addWidget(self.btnAccept)
+        self.verticalLayout_3.addLayout(self.horizontalLayout)
+        self.verticalLayout.addWidget(self.frame)
+
+        self.retranslateUi(Dialog)
+        QtCore.QMetaObject.connectSlotsByName(Dialog)
+
+    def retranslateUi(self, Dialog):
+        _translate = QtCore.QCoreApplication.translate
+        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
+        self.chkMathMode.setText(_translate("Dialog", "Math Mode"))
+        self.cmbMathStyle.setItemText(0, _translate("Dialog", "Inline Style"))
+        self.cmbMathStyle.setItemText(1, _translate("Dialog", "Display Style"))
+        self.cmbMathStyle.setItemText(2, _translate("Dialog", "Script Style"))
+        self.label.setText(_translate("Dialog", "Preview"))
+
+import icons_rc


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/labelTextEditor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/setCustomAnchor.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/setCustomAnchor.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/setCustomAnchor.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,55 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/setCustomAnchor.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Dialog(object):
+    def setupUi(self, Dialog):
+        Dialog.setObjectName("Dialog")
+        Dialog.resize(245, 161)
+        self.verticalLayoutWidget = QtWidgets.QWidget(Dialog)
+        self.verticalLayoutWidget.setGeometry(QtCore.QRect(20, 20, 201, 121))
+        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
+        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
+        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.formLayout = QtWidgets.QFormLayout()
+        self.formLayout.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow)
+        self.formLayout.setObjectName("formLayout")
+        self.label = QtWidgets.QLabel(self.verticalLayoutWidget)
+        self.label.setObjectName("label")
+        self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label)
+        self.lineEditX = QtWidgets.QLineEdit(self.verticalLayoutWidget)
+        self.lineEditX.setObjectName("lineEditX")
+        self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.lineEditX)
+        self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget)
+        self.label_2.setObjectName("label_2")
+        self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_2)
+        self.lineEditY = QtWidgets.QLineEdit(self.verticalLayoutWidget)
+        self.lineEditY.setObjectName("lineEditY")
+        self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.lineEditY)
+        self.verticalLayout.addLayout(self.formLayout)
+        self.buttonBox = QtWidgets.QDialogButtonBox(self.verticalLayoutWidget)
+        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
+        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Reset)
+        self.buttonBox.setObjectName("buttonBox")
+        self.verticalLayout.addWidget(self.buttonBox)
+
+        self.retranslateUi(Dialog)
+        self.buttonBox.accepted.connect(Dialog.accept)
+        self.buttonBox.rejected.connect(Dialog.reject)
+        QtCore.QMetaObject.connectSlotsByName(Dialog)
+
+    def retranslateUi(self, Dialog):
+        _translate = QtCore.QCoreApplication.translate
+        Dialog.setWindowTitle(_translate("Dialog", "Set Custom Anchor"))
+        self.label.setText(_translate("Dialog", "X:"))
+        self.lineEditX.setText(_translate("Dialog", "0"))
+        self.label_2.setText(_translate("Dialog", "Y:"))
+        self.lineEditY.setText(_translate("Dialog", "0"))
+


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/setCustomAnchor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addLabel.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addLabel.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addLabel.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_addLabel.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        Form.setObjectName("Form")
+        Form.setWindowModality(QtCore.Qt.NonModal)
+        Form.resize(599, 35)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+        Form.setSizePolicy(sizePolicy)
+        Form.setMinimumSize(QtCore.QSize(0, 35))
+        Form.setMaximumSize(QtCore.QSize(16777215, 35))
+        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
+        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
+        self.horizontalLayout_2.setSpacing(0)
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.horizontalLayout = QtWidgets.QHBoxLayout()
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.txtLabelText = QtWidgets.QLineEdit(Form)
+        self.txtLabelText.setObjectName("txtLabelText")
+        self.horizontalLayout.addWidget(self.txtLabelText)
+        self.btnAdvancedEdit = QtWidgets.QPushButton(Form)
+        self.btnAdvancedEdit.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnAdvancedEdit.setText("")
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnAdvancedEdit.setIcon(icon)
+        self.btnAdvancedEdit.setFlat(True)
+        self.btnAdvancedEdit.setObjectName("btnAdvancedEdit")
+        self.horizontalLayout.addWidget(self.btnAdvancedEdit)
+        self.label = QtWidgets.QLabel(Form)
+        self.label.setObjectName("label")
+        self.horizontalLayout.addWidget(self.label)
+        self.cmbAlign = QtWidgets.QComboBox(Form)
+        self.cmbAlign.setObjectName("cmbAlign")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.cmbAlign.addItem("")
+        self.horizontalLayout.addWidget(self.cmbAlign)
+        self.label_3 = QtWidgets.QLabel(Form)
+        self.label_3.setObjectName("label_3")
+        self.horizontalLayout.addWidget(self.label_3)
+        self.cmbFontSize = QtWidgets.QComboBox(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.cmbFontSize.sizePolicy().hasHeightForWidth())
+        self.cmbFontSize.setSizePolicy(sizePolicy)
+        self.cmbFontSize.setEditable(True)
+        self.cmbFontSize.setObjectName("cmbFontSize")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.cmbFontSize.addItem("")
+        self.horizontalLayout.addWidget(self.cmbFontSize)
+        self.label_2 = QtWidgets.QLabel(Form)
+        self.label_2.setObjectName("label_2")
+        self.horizontalLayout.addWidget(self.label_2)
+        self.txtShiftX = QtWidgets.QLineEdit(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.txtShiftX.sizePolicy().hasHeightForWidth())
+        self.txtShiftX.setSizePolicy(sizePolicy)
+        self.txtShiftX.setMaximumSize(QtCore.QSize(50, 16777215))
+        self.txtShiftX.setObjectName("txtShiftX")
+        self.horizontalLayout.addWidget(self.txtShiftX)
+        self.txtShiftY = QtWidgets.QLineEdit(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.txtShiftY.sizePolicy().hasHeightForWidth())
+        self.txtShiftY.setSizePolicy(sizePolicy)
+        self.txtShiftY.setMaximumSize(QtCore.QSize(50, 16777215))
+        self.txtShiftY.setObjectName("txtShiftY")
+        self.horizontalLayout.addWidget(self.txtShiftY)
+        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem)
+        self.horizontalLayout_2.addLayout(self.horizontalLayout)
+
+        self.retranslateUi(Form)
+        QtCore.QMetaObject.connectSlotsByName(Form)
+
+    def retranslateUi(self, Form):
+        _translate = QtCore.QCoreApplication.translate
+        Form.setWindowTitle(_translate("Form", "Form"))
+        self.txtLabelText.setToolTip(_translate("Form", "Number of Sides"))
+        self.txtLabelText.setPlaceholderText(_translate("Form", "Text"))
+        self.label.setText(_translate("Form", "Align"))
+        self.cmbAlign.setItemText(0, _translate("Form", "Center"))
+        self.cmbAlign.setItemText(1, _translate("Form", "N"))
+        self.cmbAlign.setItemText(2, _translate("Form", "E"))
+        self.cmbAlign.setItemText(3, _translate("Form", "W"))
+        self.cmbAlign.setItemText(4, _translate("Form", "S"))
+        self.cmbAlign.setItemText(5, _translate("Form", "NW"))
+        self.cmbAlign.setItemText(6, _translate("Form", "NE"))
+        self.cmbAlign.setItemText(7, _translate("Form", "SW"))
+        self.cmbAlign.setItemText(8, _translate("Form", "SE"))
+        self.cmbAlign.setItemText(9, _translate("Form", "Custom"))
+        self.label_3.setText(_translate("Form", "Font Size"))
+        self.cmbFontSize.setItemText(0, _translate("Form", "-"))
+        self.cmbFontSize.setItemText(1, _translate("Form", "8"))
+        self.cmbFontSize.setItemText(2, _translate("Form", "9"))
+        self.cmbFontSize.setItemText(3, _translate("Form", "10"))
+        self.cmbFontSize.setItemText(4, _translate("Form", "11"))
+        self.cmbFontSize.setItemText(5, _translate("Form", "12"))
+        self.cmbFontSize.setItemText(6, _translate("Form", "14"))
+        self.cmbFontSize.setItemText(7, _translate("Form", "18"))
+        self.cmbFontSize.setItemText(8, _translate("Form", "24"))
+        self.cmbFontSize.setItemText(9, _translate("Form", "48"))
+        self.cmbFontSize.setItemText(10, _translate("Form", "72"))
+        self.label_2.setText(_translate("Form", "Custom Align"))
+        self.txtShiftX.setPlaceholderText(_translate("Form", "Shift X"))
+        self.txtShiftY.setPlaceholderText(_translate("Form", "Shift Y"))
+
+import icons_rc


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addLabel.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addPolyOpt.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addPolyOpt.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_addPolyOpt.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        Form.setObjectName("Form")
+        Form.setWindowModality(QtCore.Qt.NonModal)
+        Form.resize(326, 35)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+        Form.setSizePolicy(sizePolicy)
+        Form.setMinimumSize(QtCore.QSize(0, 35))
+        Form.setMaximumSize(QtCore.QSize(16777215, 35))
+        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
+        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
+        self.horizontalLayout_2.setSpacing(0)
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.horizontalLayout = QtWidgets.QHBoxLayout()
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.chkInscribed = QtWidgets.QCheckBox(Form)
+        self.chkInscribed.setObjectName("chkInscribed")
+        self.horizontalLayout.addWidget(self.chkInscribed)
+        self.txtSides = QtWidgets.QLineEdit(Form)
+        self.txtSides.setObjectName("txtSides")
+        self.horizontalLayout.addWidget(self.txtSides)
+        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem)
+        self.horizontalLayout_2.addLayout(self.horizontalLayout)
+
+        self.retranslateUi(Form)
+        QtCore.QMetaObject.connectSlotsByName(Form)
+
+    def retranslateUi(self, Form):
+        _translate = QtCore.QCoreApplication.translate
+        Form.setWindowTitle(_translate("Form", "Form"))
+        self.chkInscribed.setText(_translate("Form", "Start at Vertex"))
+        self.txtSides.setToolTip(_translate("Form", "Number of Sides"))
+        self.txtSides.setPlaceholderText(_translate("Form", "Sides"))
+


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_addPolyOpt.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_editBezier.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_editBezier.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_editBezier.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,94 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widg_editBezier.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        Form.setObjectName("Form")
+        Form.setWindowModality(QtCore.Qt.NonModal)
+        Form.resize(692, 35)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(Form.sizePolicy().hasHeightForWidth())
+        Form.setSizePolicy(sizePolicy)
+        Form.setMinimumSize(QtCore.QSize(0, 35))
+        Form.setMaximumSize(QtCore.QSize(16777215, 35))
+        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(Form)
+        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
+        self.horizontalLayout_2.setSpacing(0)
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.horizontalLayout = QtWidgets.QHBoxLayout()
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.cmbLockMode = QtWidgets.QComboBox(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.cmbLockMode.sizePolicy().hasHeightForWidth())
+        self.cmbLockMode.setSizePolicy(sizePolicy)
+        self.cmbLockMode.setObjectName("cmbLockMode")
+        self.cmbLockMode.addItem("")
+        self.cmbLockMode.addItem("")
+        self.cmbLockMode.addItem("")
+        self.horizontalLayout.addWidget(self.cmbLockMode)
+        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem)
+        self.chkRecompute = QtWidgets.QCheckBox(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.chkRecompute.sizePolicy().hasHeightForWidth())
+        self.chkRecompute.setSizePolicy(sizePolicy)
+        self.chkRecompute.setObjectName("chkRecompute")
+        self.horizontalLayout.addWidget(self.chkRecompute)
+        self.btnForceRecompute = QtWidgets.QPushButton(Form)
+        self.btnForceRecompute.setObjectName("btnForceRecompute")
+        self.horizontalLayout.addWidget(self.btnForceRecompute)
+        self.btnOk = QtWidgets.QPushButton(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnOk.sizePolicy().hasHeightForWidth())
+        self.btnOk.setSizePolicy(sizePolicy)
+        self.btnOk.setMaximumSize(QtCore.QSize(25, 25))
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/icons/check.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnOk.setIcon(icon)
+        self.btnOk.setFlat(True)
+        self.btnOk.setObjectName("btnOk")
+        self.horizontalLayout.addWidget(self.btnOk)
+        self.btnCancel = QtWidgets.QPushButton(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnCancel.sizePolicy().hasHeightForWidth())
+        self.btnCancel.setSizePolicy(sizePolicy)
+        self.btnCancel.setMaximumSize(QtCore.QSize(25, 25))
+        icon1 = QtGui.QIcon()
+        icon1.addPixmap(QtGui.QPixmap(":/icons/close-round.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnCancel.setIcon(icon1)
+        self.btnCancel.setFlat(True)
+        self.btnCancel.setObjectName("btnCancel")
+        self.horizontalLayout.addWidget(self.btnCancel)
+        self.horizontalLayout_2.addLayout(self.horizontalLayout)
+
+        self.retranslateUi(Form)
+        self.cmbLockMode.setCurrentIndex(1)
+        QtCore.QMetaObject.connectSlotsByName(Form)
+
+    def retranslateUi(self, Form):
+        _translate = QtCore.QCoreApplication.translate
+        Form.setWindowTitle(_translate("Form", "Form"))
+        self.cmbLockMode.setItemText(0, _translate("Form", "No Lock"))
+        self.cmbLockMode.setItemText(1, _translate("Form", "Lock Angle"))
+        self.cmbLockMode.setItemText(2, _translate("Form", "Lock Angle & Scale"))
+        self.chkRecompute.setText(_translate("Form", "Recompute Path"))
+        self.btnForceRecompute.setText(_translate("Form", "Recompute Once"))
+
+import icons_rc


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widg_editBezier.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widgetPointEditor.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widgetPointEditor.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widgetPointEditor.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/widgetPointEditor.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_Form(object):
+    def setupUi(self, Form):
+        Form.setObjectName("Form")
+        Form.resize(324, 67)
+        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.nameLabel = QtWidgets.QLabel(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.nameLabel.sizePolicy().hasHeightForWidth())
+        self.nameLabel.setSizePolicy(sizePolicy)
+        self.nameLabel.setObjectName("nameLabel")
+        self.verticalLayout.addWidget(self.nameLabel)
+        self.horizontalLayout = QtWidgets.QHBoxLayout()
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.lineXorA = QtWidgets.QLineEdit(Form)
+        self.lineXorA.setEnabled(False)
+        self.lineXorA.setReadOnly(False)
+        self.lineXorA.setObjectName("lineXorA")
+        self.horizontalLayout.addWidget(self.lineXorA)
+        self.lineYorM = QtWidgets.QLineEdit(Form)
+        self.lineYorM.setEnabled(False)
+        self.lineYorM.setAutoFillBackground(False)
+        self.lineYorM.setReadOnly(False)
+        self.lineYorM.setObjectName("lineYorM")
+        self.horizontalLayout.addWidget(self.lineYorM)
+        self.btnRelative = QtWidgets.QPushButton(Form)
+        self.btnRelative.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnRelative.sizePolicy().hasHeightForWidth())
+        self.btnRelative.setSizePolicy(sizePolicy)
+        self.btnRelative.setText("")
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/icons/android-locate.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnRelative.setIcon(icon)
+        self.btnRelative.setCheckable(True)
+        self.btnRelative.setFlat(False)
+        self.btnRelative.setObjectName("btnRelative")
+        self.horizontalLayout.addWidget(self.btnRelative)
+        self.btnPolar = QtWidgets.QPushButton(Form)
+        self.btnPolar.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnPolar.sizePolicy().hasHeightForWidth())
+        self.btnPolar.setSizePolicy(sizePolicy)
+        self.btnPolar.setText("")
+        icon1 = QtGui.QIcon()
+        icon1.addPixmap(QtGui.QPixmap(":/icons/android-radio-button-off.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnPolar.setIcon(icon1)
+        self.btnPolar.setCheckable(True)
+        self.btnPolar.setFlat(False)
+        self.btnPolar.setObjectName("btnPolar")
+        self.horizontalLayout.addWidget(self.btnPolar)
+        self.btnManualAdj = QtWidgets.QPushButton(Form)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnManualAdj.sizePolicy().hasHeightForWidth())
+        self.btnManualAdj.setSizePolicy(sizePolicy)
+        self.btnManualAdj.setText("")
+        icon2 = QtGui.QIcon()
+        icon2.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnManualAdj.setIcon(icon2)
+        self.btnManualAdj.setCheckable(True)
+        self.btnManualAdj.setFlat(False)
+        self.btnManualAdj.setObjectName("btnManualAdj")
+        self.horizontalLayout.addWidget(self.btnManualAdj)
+        self.verticalLayout.addLayout(self.horizontalLayout)
+
+        self.retranslateUi(Form)
+        QtCore.QMetaObject.connectSlotsByName(Form)
+
+    def retranslateUi(self, Form):
+        _translate = QtCore.QCoreApplication.translate
+        Form.setWindowTitle(_translate("Form", "Form"))
+        self.nameLabel.setText(_translate("Form", "Left Control Point"))
+        self.lineXorA.setToolTip(_translate("Form", "X"))
+        self.lineXorA.setPlaceholderText(_translate("Form", "X"))
+        self.lineYorM.setToolTip(_translate("Form", "X"))
+        self.lineYorM.setPlaceholderText(_translate("Form", "Y"))
+
+import icons_rc


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/widgetPointEditor.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/window1.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/window1.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/window1.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,930 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'GUI/windows/window1.ui'
+#
+# Created by: PyQt5 UI code generator 5.10
+#
+# WARNING! All changes made in this file will be lost!
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+class Ui_MainWindow(object):
+    def setupUi(self, MainWindow):
+        MainWindow.setObjectName("MainWindow")
+        MainWindow.resize(1030, 768)
+        self.centralwidget = QtWidgets.QWidget(MainWindow)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.centralwidget.sizePolicy().hasHeightForWidth())
+        self.centralwidget.setSizePolicy(sizePolicy)
+        self.centralwidget.setMouseTracking(True)
+        self.centralwidget.setObjectName("centralwidget")
+        self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.centralwidget)
+        self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
+        self.horizontalLayout_4.setSpacing(0)
+        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
+        self.mainWidget = QtWidgets.QWidget(self.centralwidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.mainWidget.sizePolicy().hasHeightForWidth())
+        self.mainWidget.setSizePolicy(sizePolicy)
+        self.mainWidget.setMouseTracking(True)
+        self.mainWidget.setObjectName("mainWidget")
+        self.verticalLayout = QtWidgets.QVBoxLayout(self.mainWidget)
+        self.verticalLayout.setContentsMargins(2, 2, 2, 2)
+        self.verticalLayout.setSpacing(4)
+        self.verticalLayout.setObjectName("verticalLayout")
+        self.menuFrame = QtWidgets.QFrame(self.mainWidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.menuFrame.sizePolicy().hasHeightForWidth())
+        self.menuFrame.setSizePolicy(sizePolicy)
+        self.menuFrame.setFrameShape(QtWidgets.QFrame.NoFrame)
+        self.menuFrame.setObjectName("menuFrame")
+        self.horizontalLayout = QtWidgets.QHBoxLayout(self.menuFrame)
+        self.horizontalLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize)
+        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
+        self.horizontalLayout.setSpacing(4)
+        self.horizontalLayout.setObjectName("horizontalLayout")
+        self.btnUndo = QtWidgets.QPushButton(self.menuFrame)
+        self.btnUndo.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnUndo.sizePolicy().hasHeightForWidth())
+        self.btnUndo.setSizePolicy(sizePolicy)
+        self.btnUndo.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnUndo.setBaseSize(QtCore.QSize(32, 32))
+        self.btnUndo.setText("")
+        icon = QtGui.QIcon()
+        icon.addPixmap(QtGui.QPixmap(":/icons/android-arrow-back.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnUndo.setIcon(icon)
+        self.btnUndo.setIconSize(QtCore.QSize(16, 16))
+        self.btnUndo.setFlat(True)
+        self.btnUndo.setObjectName("btnUndo")
+        self.horizontalLayout.addWidget(self.btnUndo)
+        self.btnRedo = QtWidgets.QPushButton(self.menuFrame)
+        self.btnRedo.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnRedo.sizePolicy().hasHeightForWidth())
+        self.btnRedo.setSizePolicy(sizePolicy)
+        self.btnRedo.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnRedo.setBaseSize(QtCore.QSize(32, 32))
+        self.btnRedo.setText("")
+        icon1 = QtGui.QIcon()
+        icon1.addPixmap(QtGui.QPixmap(":/icons/android-arrow-forward.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnRedo.setIcon(icon1)
+        self.btnRedo.setFlat(True)
+        self.btnRedo.setObjectName("btnRedo")
+        self.horizontalLayout.addWidget(self.btnRedo)
+        self.btnLoadFile = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnLoadFile.sizePolicy().hasHeightForWidth())
+        self.btnLoadFile.setSizePolicy(sizePolicy)
+        self.btnLoadFile.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnLoadFile.setBaseSize(QtCore.QSize(32, 32))
+        self.btnLoadFile.setText("")
+        icon2 = QtGui.QIcon()
+        icon2.addPixmap(QtGui.QPixmap(":/icons/android-folder-open.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnLoadFile.setIcon(icon2)
+        self.btnLoadFile.setFlat(True)
+        self.btnLoadFile.setObjectName("btnLoadFile")
+        self.horizontalLayout.addWidget(self.btnLoadFile)
+        self.btnSave = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnSave.sizePolicy().hasHeightForWidth())
+        self.btnSave.setSizePolicy(sizePolicy)
+        self.btnSave.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnSave.setBaseSize(QtCore.QSize(32, 32))
+        self.btnSave.setText("")
+        icon3 = QtGui.QIcon()
+        icon3.addPixmap(QtGui.QPixmap(":/icons/save.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnSave.setIcon(icon3)
+        self.btnSave.setFlat(True)
+        self.btnSave.setObjectName("btnSave")
+        self.horizontalLayout.addWidget(self.btnSave)
+        self.btnViewCode = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnViewCode.sizePolicy().hasHeightForWidth())
+        self.btnViewCode.setSizePolicy(sizePolicy)
+        self.btnViewCode.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnViewCode.setBaseSize(QtCore.QSize(32, 32))
+        self.btnViewCode.setText("")
+        icon4 = QtGui.QIcon()
+        icon4.addPixmap(QtGui.QPixmap(":/icons/code.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnViewCode.setIcon(icon4)
+        self.btnViewCode.setFlat(True)
+        self.btnViewCode.setObjectName("btnViewCode")
+        self.horizontalLayout.addWidget(self.btnViewCode)
+        self.btnQuickScreenshot = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnQuickScreenshot.sizePolicy().hasHeightForWidth())
+        self.btnQuickScreenshot.setSizePolicy(sizePolicy)
+        self.btnQuickScreenshot.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnQuickScreenshot.setBaseSize(QtCore.QSize(32, 32))
+        self.btnQuickScreenshot.setText("")
+        icon5 = QtGui.QIcon()
+        icon5.addPixmap(QtGui.QPixmap(":/icons/android-camera.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnQuickScreenshot.setIcon(icon5)
+        self.btnQuickScreenshot.setFlat(True)
+        self.btnQuickScreenshot.setObjectName("btnQuickScreenshot")
+        self.horizontalLayout.addWidget(self.btnQuickScreenshot)
+        spacerItem = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem)
+        self.btnDrawAxes = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnDrawAxes.sizePolicy().hasHeightForWidth())
+        self.btnDrawAxes.setSizePolicy(sizePolicy)
+        self.btnDrawAxes.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnDrawAxes.setBaseSize(QtCore.QSize(32, 32))
+        font = QtGui.QFont()
+        font.setFamily("Roboto")
+        font.setBold(True)
+        font.setWeight(75)
+        self.btnDrawAxes.setFont(font)
+        self.btnDrawAxes.setText("")
+        icon6 = QtGui.QIcon()
+        icon6.addPixmap(QtGui.QPixmap(":/icons/plus-round.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnDrawAxes.setIcon(icon6)
+        self.btnDrawAxes.setCheckable(True)
+        self.btnDrawAxes.setChecked(True)
+        self.btnDrawAxes.setFlat(True)
+        self.btnDrawAxes.setObjectName("btnDrawAxes")
+        self.horizontalLayout.addWidget(self.btnDrawAxes)
+        self.btnDrawGrid = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnDrawGrid.sizePolicy().hasHeightForWidth())
+        self.btnDrawGrid.setSizePolicy(sizePolicy)
+        self.btnDrawGrid.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnDrawGrid.setBaseSize(QtCore.QSize(32, 32))
+        font = QtGui.QFont()
+        font.setFamily("Roboto")
+        font.setBold(True)
+        font.setWeight(75)
+        self.btnDrawGrid.setFont(font)
+        self.btnDrawGrid.setText("")
+        icon7 = QtGui.QIcon()
+        icon7.addPixmap(QtGui.QPixmap(":/icons/grid.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnDrawGrid.setIcon(icon7)
+        self.btnDrawGrid.setCheckable(True)
+        self.btnDrawGrid.setChecked(False)
+        self.btnDrawGrid.setFlat(True)
+        self.btnDrawGrid.setObjectName("btnDrawGrid")
+        self.horizontalLayout.addWidget(self.btnDrawGrid)
+        self.btnSetZoom = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnSetZoom.sizePolicy().hasHeightForWidth())
+        self.btnSetZoom.setSizePolicy(sizePolicy)
+        self.btnSetZoom.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnSetZoom.setBaseSize(QtCore.QSize(32, 32))
+        self.btnSetZoom.setText("")
+        icon8 = QtGui.QIcon()
+        icon8.addPixmap(QtGui.QPixmap(":/icons/magnifying-glass.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnSetZoom.setIcon(icon8)
+        self.btnSetZoom.setFlat(True)
+        self.btnSetZoom.setObjectName("btnSetZoom")
+        self.horizontalLayout.addWidget(self.btnSetZoom)
+        self.btnPanCenter = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnPanCenter.sizePolicy().hasHeightForWidth())
+        self.btnPanCenter.setSizePolicy(sizePolicy)
+        self.btnPanCenter.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnPanCenter.setBaseSize(QtCore.QSize(32, 32))
+        self.btnPanCenter.setText("")
+        icon9 = QtGui.QIcon()
+        icon9.addPixmap(QtGui.QPixmap(":/icons/center.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnPanCenter.setIcon(icon9)
+        self.btnPanCenter.setFlat(True)
+        self.btnPanCenter.setObjectName("btnPanCenter")
+        self.horizontalLayout.addWidget(self.btnPanCenter)
+        self.btnResetPan = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnResetPan.sizePolicy().hasHeightForWidth())
+        self.btnResetPan.setSizePolicy(sizePolicy)
+        self.btnResetPan.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnResetPan.setBaseSize(QtCore.QSize(32, 32))
+        self.btnResetPan.setText("")
+        icon10 = QtGui.QIcon()
+        icon10.addPixmap(QtGui.QPixmap(":/icons/centerorigin.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnResetPan.setIcon(icon10)
+        self.btnResetPan.setFlat(True)
+        self.btnResetPan.setObjectName("btnResetPan")
+        self.horizontalLayout.addWidget(self.btnResetPan)
+        self.btnAlignX = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnAlignX.sizePolicy().hasHeightForWidth())
+        self.btnAlignX.setSizePolicy(sizePolicy)
+        self.btnAlignX.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnAlignX.setBaseSize(QtCore.QSize(32, 32))
+        font = QtGui.QFont()
+        font.setFamily("Roboto")
+        font.setBold(True)
+        font.setWeight(75)
+        self.btnAlignX.setFont(font)
+        self.btnAlignX.setCheckable(True)
+        self.btnAlignX.setFlat(True)
+        self.btnAlignX.setObjectName("btnAlignX")
+        self.horizontalLayout.addWidget(self.btnAlignX)
+        self.btnAlignY = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnAlignY.sizePolicy().hasHeightForWidth())
+        self.btnAlignY.setSizePolicy(sizePolicy)
+        self.btnAlignY.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnAlignY.setBaseSize(QtCore.QSize(32, 32))
+        font = QtGui.QFont()
+        font.setBold(True)
+        font.setWeight(75)
+        self.btnAlignY.setFont(font)
+        self.btnAlignY.setCheckable(True)
+        self.btnAlignY.setFlat(True)
+        self.btnAlignY.setObjectName("btnAlignY")
+        self.horizontalLayout.addWidget(self.btnAlignY)
+        spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem1)
+        self.btnSelectEdit = QtWidgets.QPushButton(self.menuFrame)
+        self.btnSelectEdit.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnSelectEdit.sizePolicy().hasHeightForWidth())
+        self.btnSelectEdit.setSizePolicy(sizePolicy)
+        self.btnSelectEdit.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnSelectEdit.setText("")
+        icon11 = QtGui.QIcon()
+        icon11.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnSelectEdit.setIcon(icon11)
+        self.btnSelectEdit.setFlat(True)
+        self.btnSelectEdit.setObjectName("btnSelectEdit")
+        self.horizontalLayout.addWidget(self.btnSelectEdit)
+        self.btnDeleteMode = QtWidgets.QPushButton(self.menuFrame)
+        self.btnDeleteMode.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnDeleteMode.sizePolicy().hasHeightForWidth())
+        self.btnDeleteMode.setSizePolicy(sizePolicy)
+        self.btnDeleteMode.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnDeleteMode.setBaseSize(QtCore.QSize(32, 32))
+        self.btnDeleteMode.setText("")
+        icon12 = QtGui.QIcon()
+        icon12.addPixmap(QtGui.QPixmap(":/icons/android-delete.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnDeleteMode.setIcon(icon12)
+        self.btnDeleteMode.setCheckable(False)
+        self.btnDeleteMode.setFlat(True)
+        self.btnDeleteMode.setObjectName("btnDeleteMode")
+        self.horizontalLayout.addWidget(self.btnDeleteMode)
+        spacerItem2 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem2)
+        self.btnPan = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnPan.sizePolicy().hasHeightForWidth())
+        self.btnPan.setSizePolicy(sizePolicy)
+        self.btnPan.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnPan.setBaseSize(QtCore.QSize(32, 32))
+        self.btnPan.setText("")
+        icon13 = QtGui.QIcon()
+        icon13.addPixmap(QtGui.QPixmap(":/icons/android-hand.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnPan.setIcon(icon13)
+        self.btnPan.setCheckable(True)
+        self.btnPan.setFlat(True)
+        self.btnPan.setObjectName("btnPan")
+        self.horizontalLayout.addWidget(self.btnPan)
+        self.btnTranslate = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnTranslate.sizePolicy().hasHeightForWidth())
+        self.btnTranslate.setSizePolicy(sizePolicy)
+        self.btnTranslate.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnTranslate.setBaseSize(QtCore.QSize(32, 32))
+        self.btnTranslate.setText("")
+        icon14 = QtGui.QIcon()
+        icon14.addPixmap(QtGui.QPixmap(":/icons/arrow-move.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnTranslate.setIcon(icon14)
+        self.btnTranslate.setCheckable(True)
+        self.btnTranslate.setChecked(True)
+        self.btnTranslate.setFlat(True)
+        self.btnTranslate.setObjectName("btnTranslate")
+        self.horizontalLayout.addWidget(self.btnTranslate)
+        self.btnScale = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnScale.sizePolicy().hasHeightForWidth())
+        self.btnScale.setSizePolicy(sizePolicy)
+        self.btnScale.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnScale.setBaseSize(QtCore.QSize(32, 32))
+        self.btnScale.setText("")
+        icon15 = QtGui.QIcon()
+        icon15.addPixmap(QtGui.QPixmap(":/icons/arrow-resize.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnScale.setIcon(icon15)
+        self.btnScale.setCheckable(True)
+        self.btnScale.setFlat(True)
+        self.btnScale.setObjectName("btnScale")
+        self.horizontalLayout.addWidget(self.btnScale)
+        self.btnRotate = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnRotate.sizePolicy().hasHeightForWidth())
+        self.btnRotate.setSizePolicy(sizePolicy)
+        self.btnRotate.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnRotate.setBaseSize(QtCore.QSize(32, 32))
+        self.btnRotate.setText("")
+        icon16 = QtGui.QIcon()
+        icon16.addPixmap(QtGui.QPixmap(":/icons/android-refresh.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnRotate.setIcon(icon16)
+        self.btnRotate.setCheckable(True)
+        self.btnRotate.setFlat(True)
+        self.btnRotate.setObjectName("btnRotate")
+        self.horizontalLayout.addWidget(self.btnRotate)
+        spacerItem3 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem3)
+        self.btnAnchor = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnAnchor.sizePolicy().hasHeightForWidth())
+        self.btnAnchor.setSizePolicy(sizePolicy)
+        self.btnAnchor.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnAnchor.setBaseSize(QtCore.QSize(32, 32))
+        self.btnAnchor.setText("")
+        icon17 = QtGui.QIcon()
+        icon17.addPixmap(QtGui.QPixmap(":/icons/anchor.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnAnchor.setIcon(icon17)
+        self.btnAnchor.setCheckable(True)
+        self.btnAnchor.setChecked(False)
+        self.btnAnchor.setFlat(True)
+        self.btnAnchor.setObjectName("btnAnchor")
+        self.horizontalLayout.addWidget(self.btnAnchor)
+        self.comboAnchor = QtWidgets.QComboBox(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.comboAnchor.sizePolicy().hasHeightForWidth())
+        self.comboAnchor.setSizePolicy(sizePolicy)
+        self.comboAnchor.setMinimumSize(QtCore.QSize(127, 0))
+        self.comboAnchor.setMaximumSize(QtCore.QSize(127, 25))
+        self.comboAnchor.setLayoutDirection(QtCore.Qt.LeftToRight)
+        self.comboAnchor.setEditable(False)
+        self.comboAnchor.setInsertPolicy(QtWidgets.QComboBox.InsertAtCurrent)
+        self.comboAnchor.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToContentsOnFirstShow)
+        self.comboAnchor.setIconSize(QtCore.QSize(0, 0))
+        self.comboAnchor.setDuplicatesEnabled(False)
+        self.comboAnchor.setFrame(False)
+        self.comboAnchor.setModelColumn(0)
+        self.comboAnchor.setObjectName("comboAnchor")
+        self.comboAnchor.addItem("")
+        self.comboAnchor.addItem("")
+        self.comboAnchor.addItem("")
+        self.comboAnchor.addItem("")
+        self.comboAnchor.addItem("")
+        self.comboAnchor.addItem("")
+        self.comboAnchor.addItem("")
+        self.horizontalLayout.addWidget(self.comboAnchor)
+        self.btnToggleVisible = QtWidgets.QPushButton(self.menuFrame)
+        self.btnToggleVisible.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnToggleVisible.sizePolicy().hasHeightForWidth())
+        self.btnToggleVisible.setSizePolicy(sizePolicy)
+        self.btnToggleVisible.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnToggleVisible.setBaseSize(QtCore.QSize(32, 32))
+        self.btnToggleVisible.setText("")
+        icon18 = QtGui.QIcon()
+        icon18.addPixmap(QtGui.QPixmap(":/icons/eye.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnToggleVisible.setIcon(icon18)
+        self.btnToggleVisible.setCheckable(False)
+        self.btnToggleVisible.setFlat(True)
+        self.btnToggleVisible.setObjectName("btnToggleVisible")
+        self.horizontalLayout.addWidget(self.btnToggleVisible)
+        self.btnCustTransform = QtWidgets.QPushButton(self.menuFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnCustTransform.sizePolicy().hasHeightForWidth())
+        self.btnCustTransform.setSizePolicy(sizePolicy)
+        self.btnCustTransform.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnCustTransform.setBaseSize(QtCore.QSize(32, 32))
+        self.btnCustTransform.setText("")
+        icon19 = QtGui.QIcon()
+        icon19.addPixmap(QtGui.QPixmap(":/icons/android-expand.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnCustTransform.setIcon(icon19)
+        self.btnCustTransform.setFlat(True)
+        self.btnCustTransform.setObjectName("btnCustTransform")
+        self.horizontalLayout.addWidget(self.btnCustTransform)
+        self.btnSendBackwards = QtWidgets.QPushButton(self.menuFrame)
+        self.btnSendBackwards.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnSendBackwards.sizePolicy().hasHeightForWidth())
+        self.btnSendBackwards.setSizePolicy(sizePolicy)
+        self.btnSendBackwards.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnSendBackwards.setBaseSize(QtCore.QSize(32, 32))
+        self.btnSendBackwards.setText("")
+        icon20 = QtGui.QIcon()
+        icon20.addPixmap(QtGui.QPixmap(":/icons/chevron-with-circle-left.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnSendBackwards.setIcon(icon20)
+        self.btnSendBackwards.setFlat(True)
+        self.btnSendBackwards.setObjectName("btnSendBackwards")
+        self.horizontalLayout.addWidget(self.btnSendBackwards)
+        self.btnSendForwards = QtWidgets.QPushButton(self.menuFrame)
+        self.btnSendForwards.setEnabled(False)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnSendForwards.sizePolicy().hasHeightForWidth())
+        self.btnSendForwards.setSizePolicy(sizePolicy)
+        self.btnSendForwards.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnSendForwards.setBaseSize(QtCore.QSize(32, 32))
+        self.btnSendForwards.setText("")
+        icon21 = QtGui.QIcon()
+        icon21.addPixmap(QtGui.QPixmap(":/icons/chevron-with-circle-right.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnSendForwards.setIcon(icon21)
+        self.btnSendForwards.setFlat(True)
+        self.btnSendForwards.setObjectName("btnSendForwards")
+        self.horizontalLayout.addWidget(self.btnSendForwards)
+        spacerItem4 = QtWidgets.QSpacerItem(40, 25, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum)
+        self.horizontalLayout.addItem(spacerItem4)
+        self.btnUndo.raise_()
+        self.btnRedo.raise_()
+        self.btnLoadFile.raise_()
+        self.btnSave.raise_()
+        self.btnViewCode.raise_()
+        self.btnQuickScreenshot.raise_()
+        self.btnDrawAxes.raise_()
+        self.btnDrawGrid.raise_()
+        self.btnSetZoom.raise_()
+        self.btnPanCenter.raise_()
+        self.btnResetPan.raise_()
+        self.btnAlignX.raise_()
+        self.btnAlignY.raise_()
+        self.btnPan.raise_()
+        self.btnTranslate.raise_()
+        self.btnScale.raise_()
+        self.btnCustTransform.raise_()
+        self.btnSendBackwards.raise_()
+        self.btnSendForwards.raise_()
+        self.comboAnchor.raise_()
+        self.btnToggleVisible.raise_()
+        self.btnAnchor.raise_()
+        self.btnRotate.raise_()
+        self.btnSelectEdit.raise_()
+        self.btnDeleteMode.raise_()
+        self.verticalLayout.addWidget(self.menuFrame)
+        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_2.setSpacing(4)
+        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+        self.verticalLayout_2.setSpacing(3)
+        self.verticalLayout_2.setObjectName("verticalLayout_2")
+        self.addOption = QtWidgets.QHBoxLayout()
+        self.addOption.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
+        self.addOption.setContentsMargins(6, -1, -1, 0)
+        self.addOption.setSpacing(6)
+        self.addOption.setObjectName("addOption")
+        self.btnFill = QtWidgets.QPushButton(self.mainWidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnFill.sizePolicy().hasHeightForWidth())
+        self.btnFill.setSizePolicy(sizePolicy)
+        self.btnFill.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnFill.setBaseSize(QtCore.QSize(32, 32))
+        self.btnFill.setAutoFillBackground(False)
+        self.btnFill.setStyleSheet("")
+        self.btnFill.setText("")
+        icon22 = QtGui.QIcon()
+        icon22.addPixmap(QtGui.QPixmap(":/icons/bucket.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        icon22.addPixmap(QtGui.QPixmap(":/icons/filledbucket.svg"), QtGui.QIcon.Normal, QtGui.QIcon.On)
+        self.btnFill.setIcon(icon22)
+        self.btnFill.setCheckable(True)
+        self.btnFill.setDefault(False)
+        self.btnFill.setFlat(True)
+        self.btnFill.setObjectName("btnFill")
+        self.addOption.addWidget(self.btnFill)
+        self.addOptionLayout = QtWidgets.QGridLayout()
+        self.addOptionLayout.setSpacing(6)
+        self.addOptionLayout.setObjectName("addOptionLayout")
+        self.addOption.addLayout(self.addOptionLayout)
+        spacerItem5 = QtWidgets.QSpacerItem(40, 35, QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum)
+        self.addOption.addItem(spacerItem5)
+        self.label = QtWidgets.QLabel(self.mainWidget)
+        self.label.setObjectName("label")
+        self.addOption.addWidget(self.label)
+        self.txtLineWidth = QtWidgets.QLineEdit(self.mainWidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.txtLineWidth.sizePolicy().hasHeightForWidth())
+        self.txtLineWidth.setSizePolicy(sizePolicy)
+        self.txtLineWidth.setMaximumSize(QtCore.QSize(75, 16777215))
+        self.txtLineWidth.setObjectName("txtLineWidth")
+        self.addOption.addWidget(self.txtLineWidth)
+        self.frameCurrColor = QtWidgets.QFrame(self.mainWidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.frameCurrColor.sizePolicy().hasHeightForWidth())
+        self.frameCurrColor.setSizePolicy(sizePolicy)
+        self.frameCurrColor.setMinimumSize(QtCore.QSize(15, 15))
+        self.frameCurrColor.setAutoFillBackground(False)
+        self.frameCurrColor.setStyleSheet("QFrame{ \n"
+"padding: 4.0;\n"
+"border-radius: 3.0; \n"
+"background: rgb(0, 0, 0)\n"
+"}")
+        self.frameCurrColor.setFrameShape(QtWidgets.QFrame.StyledPanel)
+        self.frameCurrColor.setFrameShadow(QtWidgets.QFrame.Sunken)
+        self.frameCurrColor.setObjectName("frameCurrColor")
+        self.addOption.addWidget(self.frameCurrColor)
+        self.btnSelectColor = QtWidgets.QPushButton(self.mainWidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnSelectColor.sizePolicy().hasHeightForWidth())
+        self.btnSelectColor.setSizePolicy(sizePolicy)
+        self.btnSelectColor.setMaximumSize(QtCore.QSize(25, 25))
+        self.btnSelectColor.setBaseSize(QtCore.QSize(32, 32))
+        self.btnSelectColor.setAutoFillBackground(False)
+        self.btnSelectColor.setStyleSheet("")
+        self.btnSelectColor.setText("")
+        icon23 = QtGui.QIcon()
+        icon23.addPixmap(QtGui.QPixmap(":/icons/android-color-palette.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnSelectColor.setIcon(icon23)
+        self.btnSelectColor.setDefault(False)
+        self.btnSelectColor.setFlat(True)
+        self.btnSelectColor.setObjectName("btnSelectColor")
+        self.addOption.addWidget(self.btnSelectColor)
+        self.verticalLayout_2.addLayout(self.addOption)
+        self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_7.setContentsMargins(-1, 6, -1, -1)
+        self.horizontalLayout_7.setSpacing(6)
+        self.horizontalLayout_7.setObjectName("horizontalLayout_7")
+        self.formFrame = QtWidgets.QFrame(self.mainWidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.formFrame.sizePolicy().hasHeightForWidth())
+        self.formFrame.setSizePolicy(sizePolicy)
+        self.formFrame.setFrameShape(QtWidgets.QFrame.NoFrame)
+        self.formFrame.setFrameShadow(QtWidgets.QFrame.Plain)
+        self.formFrame.setLineWidth(0)
+        self.formFrame.setObjectName("formFrame")
+        self.formLayout = QtWidgets.QFormLayout(self.formFrame)
+        self.formLayout.setContentsMargins(0, 0, 0, 0)
+        self.formLayout.setSpacing(0)
+        self.formLayout.setObjectName("formLayout")
+        self.btnOpenPoly = QtWidgets.QPushButton(self.formFrame)
+        self.btnOpenPoly.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnOpenPoly.sizePolicy().hasHeightForWidth())
+        self.btnOpenPoly.setSizePolicy(sizePolicy)
+        self.btnOpenPoly.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnOpenPoly.setText("")
+        icon24 = QtGui.QIcon()
+        icon24.addPixmap(QtGui.QPixmap(":/icons/openpolygon.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnOpenPoly.setIcon(icon24)
+        self.btnOpenPoly.setFlat(True)
+        self.btnOpenPoly.setObjectName("btnOpenPoly")
+        self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.btnOpenPoly)
+        self.btnClosedPoly = QtWidgets.QPushButton(self.formFrame)
+        self.btnClosedPoly.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnClosedPoly.sizePolicy().hasHeightForWidth())
+        self.btnClosedPoly.setSizePolicy(sizePolicy)
+        self.btnClosedPoly.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnClosedPoly.setText("")
+        icon25 = QtGui.QIcon()
+        icon25.addPixmap(QtGui.QPixmap(":/icons/closedpolygon.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnClosedPoly.setIcon(icon25)
+        self.btnClosedPoly.setFlat(True)
+        self.btnClosedPoly.setObjectName("btnClosedPoly")
+        self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.btnClosedPoly)
+        self.btnOpenCurve = QtWidgets.QPushButton(self.formFrame)
+        self.btnOpenCurve.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnOpenCurve.sizePolicy().hasHeightForWidth())
+        self.btnOpenCurve.setSizePolicy(sizePolicy)
+        self.btnOpenCurve.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnOpenCurve.setText("")
+        icon26 = QtGui.QIcon()
+        icon26.addPixmap(QtGui.QPixmap(":/icons/opencurve.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnOpenCurve.setIcon(icon26)
+        self.btnOpenCurve.setFlat(True)
+        self.btnOpenCurve.setObjectName("btnOpenCurve")
+        self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.btnOpenCurve)
+        self.btnClosedCurve = QtWidgets.QPushButton(self.formFrame)
+        self.btnClosedCurve.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnClosedCurve.sizePolicy().hasHeightForWidth())
+        self.btnClosedCurve.setSizePolicy(sizePolicy)
+        self.btnClosedCurve.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnClosedCurve.setText("")
+        icon27 = QtGui.QIcon()
+        icon27.addPixmap(QtGui.QPixmap(":/icons/closedcurve.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnClosedCurve.setIcon(icon27)
+        self.btnClosedCurve.setFlat(True)
+        self.btnClosedCurve.setObjectName("btnClosedCurve")
+        self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.btnClosedCurve)
+        self.btnAddPoly = QtWidgets.QPushButton(self.formFrame)
+        self.btnAddPoly.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnAddPoly.sizePolicy().hasHeightForWidth())
+        self.btnAddPoly.setSizePolicy(sizePolicy)
+        self.btnAddPoly.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnAddPoly.setText("")
+        icon28 = QtGui.QIcon()
+        icon28.addPixmap(QtGui.QPixmap(":/icons/triangle-stroked-15.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnAddPoly.setIcon(icon28)
+        self.btnAddPoly.setFlat(True)
+        self.btnAddPoly.setObjectName("btnAddPoly")
+        self.formLayout.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.btnAddPoly)
+        self.btnAddCircle = QtWidgets.QPushButton(self.formFrame)
+        self.btnAddCircle.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnAddCircle.sizePolicy().hasHeightForWidth())
+        self.btnAddCircle.setSizePolicy(sizePolicy)
+        self.btnAddCircle.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnAddCircle.setText("")
+        icon29 = QtGui.QIcon()
+        icon29.addPixmap(QtGui.QPixmap(":/icons/circle.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnAddCircle.setIcon(icon29)
+        self.btnAddCircle.setFlat(True)
+        self.btnAddCircle.setObjectName("btnAddCircle")
+        self.formLayout.setWidget(10, QtWidgets.QFormLayout.LabelRole, self.btnAddCircle)
+        self.btnAddLabel = QtWidgets.QPushButton(self.formFrame)
+        self.btnAddLabel.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnAddLabel.sizePolicy().hasHeightForWidth())
+        self.btnAddLabel.setSizePolicy(sizePolicy)
+        self.btnAddLabel.setMaximumSize(QtCore.QSize(32, 32))
+        self.btnAddLabel.setText("")
+        icon30 = QtGui.QIcon()
+        icon30.addPixmap(QtGui.QPixmap(":/icons/text.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnAddLabel.setIcon(icon30)
+        self.btnAddLabel.setFlat(True)
+        self.btnAddLabel.setObjectName("btnAddLabel")
+        self.formLayout.setWidget(11, QtWidgets.QFormLayout.LabelRole, self.btnAddLabel)
+        self.horizontalLayout_7.addWidget(self.formFrame)
+        self.imgFrame = QtWidgets.QFrame(self.mainWidget)
+        self.imgFrame.setMinimumSize(QtCore.QSize(0, 6))
+        self.imgFrame.setMouseTracking(True)
+        self.imgFrame.setFrameShape(QtWidgets.QFrame.NoFrame)
+        self.imgFrame.setFrameShadow(QtWidgets.QFrame.Raised)
+        self.imgFrame.setObjectName("imgFrame")
+        self.gridLayout = QtWidgets.QGridLayout(self.imgFrame)
+        self.gridLayout.setContentsMargins(0, 0, 0, 0)
+        self.gridLayout.setSpacing(0)
+        self.gridLayout.setObjectName("gridLayout")
+        self.imgLabel = QtWidgets.QLabel(self.imgFrame)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.imgLabel.sizePolicy().hasHeightForWidth())
+        self.imgLabel.setSizePolicy(sizePolicy)
+        self.imgLabel.setMouseTracking(True)
+        self.imgLabel.setFrameShape(QtWidgets.QFrame.Panel)
+        self.imgLabel.setText("")
+        self.imgLabel.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
+        self.imgLabel.setObjectName("imgLabel")
+        self.gridLayout.addWidget(self.imgLabel, 0, 1, 1, 1)
+        self.horizontalLayout_7.addWidget(self.imgFrame)
+        self.verticalLayout_2.addLayout(self.horizontalLayout_7)
+        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+        self.horizontalLayout_3.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
+        self.horizontalLayout_3.setContentsMargins(-1, 0, -1, -1)
+        self.horizontalLayout_3.setSpacing(0)
+        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+        self.btnTogglePython = QtWidgets.QPushButton(self.mainWidget)
+        self.btnTogglePython.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnTogglePython.sizePolicy().hasHeightForWidth())
+        self.btnTogglePython.setSizePolicy(sizePolicy)
+        self.btnTogglePython.setText("")
+        icon31 = QtGui.QIcon()
+        icon31.addPixmap(QtGui.QPixmap(":/icons/social-python.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnTogglePython.setIcon(icon31)
+        self.btnTogglePython.setIconSize(QtCore.QSize(16, 16))
+        self.btnTogglePython.setCheckable(True)
+        self.btnTogglePython.setFlat(True)
+        self.btnTogglePython.setObjectName("btnTogglePython")
+        self.horizontalLayout_3.addWidget(self.btnTogglePython)
+        self.txtTerminalPrompt = QtWidgets.QLineEdit(self.mainWidget)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.txtTerminalPrompt.sizePolicy().hasHeightForWidth())
+        self.txtTerminalPrompt.setSizePolicy(sizePolicy)
+        self.txtTerminalPrompt.setObjectName("txtTerminalPrompt")
+        self.horizontalLayout_3.addWidget(self.txtTerminalPrompt)
+        self.btnEnterCommand = QtWidgets.QPushButton(self.mainWidget)
+        self.btnEnterCommand.setEnabled(True)
+        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
+        sizePolicy.setHorizontalStretch(0)
+        sizePolicy.setVerticalStretch(0)
+        sizePolicy.setHeightForWidth(self.btnEnterCommand.sizePolicy().hasHeightForWidth())
+        self.btnEnterCommand.setSizePolicy(sizePolicy)
+        self.btnEnterCommand.setText("")
+        icon32 = QtGui.QIcon()
+        icon32.addPixmap(QtGui.QPixmap(":/icons/subdirectory-left.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+        self.btnEnterCommand.setIcon(icon32)
+        self.btnEnterCommand.setFlat(True)
+        self.btnEnterCommand.setObjectName("btnEnterCommand")
+        self.horizontalLayout_3.addWidget(self.btnEnterCommand)
+        self.verticalLayout_2.addLayout(self.horizontalLayout_3)
+        self.horizontalLayout_2.addLayout(self.verticalLayout_2)
+        self.verticalLayout.addLayout(self.horizontalLayout_2)
+        self.horizontalLayout_4.addWidget(self.mainWidget)
+        MainWindow.setCentralWidget(self.centralwidget)
+        self.menubar = QtWidgets.QMenuBar(MainWindow)
+        self.menubar.setGeometry(QtCore.QRect(0, 0, 1030, 28))
+        self.menubar.setObjectName("menubar")
+        self.menuFIle = QtWidgets.QMenu(self.menubar)
+        self.menuFIle.setObjectName("menuFIle")
+        self.menuEdit = QtWidgets.QMenu(self.menubar)
+        self.menuEdit.setObjectName("menuEdit")
+        self.menuOptions = QtWidgets.QMenu(self.menubar)
+        self.menuOptions.setObjectName("menuOptions")
+        self.menuHelp = QtWidgets.QMenu(self.menubar)
+        self.menuHelp.setObjectName("menuHelp")
+        self.menuTools = QtWidgets.QMenu(self.menubar)
+        self.menuTools.setObjectName("menuTools")
+        MainWindow.setMenuBar(self.menubar)
+        self.statusbar = QtWidgets.QStatusBar(MainWindow)
+        self.statusbar.setSizeGripEnabled(False)
+        self.statusbar.setObjectName("statusbar")
+        MainWindow.setStatusBar(self.statusbar)
+        self.actionAbout = QtWidgets.QAction(MainWindow)
+        self.actionAbout.setObjectName("actionAbout")
+        self.actionManual = QtWidgets.QAction(MainWindow)
+        self.actionManual.setObjectName("actionManual")
+        self.actionSettings = QtWidgets.QAction(MainWindow)
+        self.actionSettings.setObjectName("actionSettings")
+        self.actionPause = QtWidgets.QAction(MainWindow)
+        self.actionPause.setObjectName("actionPause")
+        self.actionSaveAs = QtWidgets.QAction(MainWindow)
+        self.actionSaveAs.setObjectName("actionSaveAs")
+        self.actionEnterCommand = QtWidgets.QAction(MainWindow)
+        self.actionEnterCommand.setObjectName("actionEnterCommand")
+        self.actionQuit = QtWidgets.QAction(MainWindow)
+        self.actionQuit.setObjectName("actionQuit")
+        self.actionUndo = QtWidgets.QAction(MainWindow)
+        self.actionUndo.setEnabled(False)
+        self.actionUndo.setObjectName("actionUndo")
+        self.actionRedo = QtWidgets.QAction(MainWindow)
+        self.actionRedo.setEnabled(False)
+        self.actionRedo.setObjectName("actionRedo")
+        self.actionShow_Grid = QtWidgets.QAction(MainWindow)
+        self.actionShow_Grid.setObjectName("actionShow_Grid")
+        self.actionShow_Local_Grid = QtWidgets.QAction(MainWindow)
+        self.actionShow_Local_Grid.setObjectName("actionShow_Local_Grid")
+        self.actionTransform = QtWidgets.QAction(MainWindow)
+        self.actionTransform.setObjectName("actionTransform")
+        self.actionExportAsymptote = QtWidgets.QAction(MainWindow)
+        self.actionExportAsymptote.setObjectName("actionExportAsymptote")
+        self.actionSave = QtWidgets.QAction(MainWindow)
+        self.actionSave.setObjectName("actionSave")
+        self.actionOpen = QtWidgets.QAction(MainWindow)
+        self.actionOpen.setObjectName("actionOpen")
+        self.menuFIle.addAction(self.actionOpen)
+        self.menuFIle.addAction(self.actionSave)
+        self.menuFIle.addAction(self.actionSaveAs)
+        self.menuFIle.addAction(self.actionExportAsymptote)
+        self.menuFIle.addSeparator()
+        self.menuFIle.addAction(self.actionQuit)
+        self.menuEdit.addAction(self.actionUndo)
+        self.menuEdit.addAction(self.actionRedo)
+        self.menuEdit.addSeparator()
+        self.menuOptions.addAction(self.actionSettings)
+        self.menuHelp.addAction(self.actionManual)
+        self.menuHelp.addAction(self.actionAbout)
+        self.menuTools.addAction(self.actionEnterCommand)
+        self.menubar.addAction(self.menuFIle.menuAction())
+        self.menubar.addAction(self.menuEdit.menuAction())
+        self.menubar.addAction(self.menuOptions.menuAction())
+        self.menubar.addAction(self.menuTools.menuAction())
+        self.menubar.addAction(self.menuHelp.menuAction())
+
+        self.retranslateUi(MainWindow)
+        self.comboAnchor.setCurrentIndex(0)
+        QtCore.QMetaObject.connectSlotsByName(MainWindow)
+
+    def retranslateUi(self, MainWindow):
+        _translate = QtCore.QCoreApplication.translate
+        MainWindow.setWindowTitle(_translate("MainWindow", "xasy"))
+        self.btnUndo.setToolTip(_translate("MainWindow", "Undo"))
+        self.btnRedo.setToolTip(_translate("MainWindow", "Redo"))
+        self.btnLoadFile.setToolTip(_translate("MainWindow", "<html><head/><body><p>Open file</p></body></html>"))
+        self.btnSave.setToolTip(_translate("MainWindow", "<html><head/><body><p>Save file</p></body></html>"))
+        self.btnViewCode.setToolTip(_translate("MainWindow", "<html><head/><body><p>Edit code</p></body></html>"))
+        self.btnQuickScreenshot.setToolTip(_translate("MainWindow", "<html><head/><body><p>Screenshot</p></body></html>"))
+        self.btnDrawAxes.setToolTip(_translate("MainWindow", "<html><head/><body><p>Toggle display axes</p></body></html>"))
+        self.btnDrawGrid.setToolTip(_translate("MainWindow", "<html><head/><body><p>Toggle grid</p></body></html>"))
+        self.btnSetZoom.setToolTip(_translate("MainWindow", "Synchronize with Asymptote"))
+        self.btnPanCenter.setToolTip(_translate("MainWindow", "<html><head/><body><p>Center</p></body></html>"))
+        self.btnResetPan.setToolTip(_translate("MainWindow", "<html><head/><body><p>Center about origin</p></body></html>"))
+        self.btnAlignX.setToolTip(_translate("MainWindow", "<html><head/><body><p>Lock transform to X axis</p></body></html>"))
+        self.btnAlignX.setText(_translate("MainWindow", "X"))
+        self.btnAlignY.setToolTip(_translate("MainWindow", "<html><head/><body><p>Lock transform to Y axis</p></body></html>"))
+        self.btnAlignY.setText(_translate("MainWindow", "Y"))
+        self.btnSelectEdit.setToolTip(_translate("MainWindow", "<html><head/><body><p>Bézier editor</p></body></html>"))
+        self.btnDeleteMode.setToolTip(_translate("MainWindow", "<html><head/><body><p>Delete</p></body></html>"))
+        self.btnPan.setToolTip(_translate("MainWindow", "Pan"))
+        self.btnTranslate.setToolTip(_translate("MainWindow", "Translate"))
+        self.btnScale.setToolTip(_translate("MainWindow", "Scale"))
+        self.btnRotate.setToolTip(_translate("MainWindow", "Rotate"))
+        self.btnAnchor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Set custom anchor</p></body></html>"))
+        self.comboAnchor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Anchor</p></body></html>"))
+        self.comboAnchor.setCurrentText(_translate("MainWindow", "Origin"))
+        self.comboAnchor.setItemText(0, _translate("MainWindow", "Origin"))
+        self.comboAnchor.setItemText(1, _translate("MainWindow", "Center"))
+        self.comboAnchor.setItemText(2, _translate("MainWindow", "Top Left"))
+        self.comboAnchor.setItemText(3, _translate("MainWindow", "Top Right"))
+        self.comboAnchor.setItemText(4, _translate("MainWindow", "Bottom Right"))
+        self.comboAnchor.setItemText(5, _translate("MainWindow", "Bottom Left"))
+        self.comboAnchor.setItemText(6, _translate("MainWindow", "Custom"))
+        self.btnCustTransform.setToolTip(_translate("MainWindow", "<html><head/><body><p><br/></p></body></html>"))
+        self.btnSendBackwards.setToolTip(_translate("MainWindow", "<html><head/><body><p><br/></p></body></html>"))
+        self.btnSendForwards.setToolTip(_translate("MainWindow", "Translate"))
+        self.btnFill.setToolTip(_translate("MainWindow", "<html><head/><body><p>Toggle fill/outline</p></body></html>"))
+        self.label.setText(_translate("MainWindow", "Line Width:"))
+        self.txtLineWidth.setToolTip(_translate("MainWindow", "<html><head/><body><p>Current pen width</p></body></html>"))
+        self.frameCurrColor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Current pen color</p></body></html>"))
+        self.btnSelectColor.setToolTip(_translate("MainWindow", "<html><head/><body><p>Set color</p></body></html>"))
+        self.btnOpenPoly.setToolTip(_translate("MainWindow", "<html><head/><body><p>Open polygon</p></body></html>"))
+        self.btnClosedPoly.setToolTip(_translate("MainWindow", "<html><head/><body><p>Closed polygon</p></body></html>"))
+        self.btnOpenCurve.setToolTip(_translate("MainWindow", "<html><head/><body><p>Open Bézier curve</p></body></html>"))
+        self.btnClosedCurve.setToolTip(_translate("MainWindow", "<html><head/><body><p>Closed Bézier curve</p></body></html>"))
+        self.btnAddPoly.setToolTip(_translate("MainWindow", "<html><head/><body><p>Regular polygon</p></body></html>"))
+        self.btnAddCircle.setToolTip(_translate("MainWindow", "<html><head/><body><p>Circle</p></body></html>"))
+        self.btnAddLabel.setToolTip(_translate("MainWindow", "<html><head/><body><p>Text</p></body></html>"))
+        self.menuFIle.setTitle(_translate("MainWindow", "&File"))
+        self.menuEdit.setTitle(_translate("MainWindow", "&Edit"))
+        self.menuOptions.setTitle(_translate("MainWindow", "Optio&ns"))
+        self.menuHelp.setTitle(_translate("MainWindow", "&Help"))
+        self.menuTools.setTitle(_translate("MainWindow", "&Tools"))
+        self.actionAbout.setText(_translate("MainWindow", "&About"))
+        self.actionManual.setText(_translate("MainWindow", "&Manual"))
+        self.actionSettings.setText(_translate("MainWindow", "&Settings"))
+        self.actionPause.setText(_translate("MainWindow", "Pause "))
+        self.actionSaveAs.setText(_translate("MainWindow", "&Save As"))
+        self.actionEnterCommand.setText(_translate("MainWindow", "&Enter Command"))
+        self.actionQuit.setText(_translate("MainWindow", "&Quit"))
+        self.actionUndo.setText(_translate("MainWindow", "&Undo"))
+        self.actionRedo.setText(_translate("MainWindow", "&Redo"))
+        self.actionShow_Grid.setText(_translate("MainWindow", "&Show Grid"))
+        self.actionShow_Local_Grid.setText(_translate("MainWindow", "Show &Local Grid"))
+        self.actionTransform.setText(_translate("MainWindow", "&Transform"))
+        self.actionExportAsymptote.setText(_translate("MainWindow", "Export"))
+        self.actionSave.setText(_translate("MainWindow", "Save"))
+        self.actionOpen.setText(_translate("MainWindow", "Open"))
+
+import icons_rc


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/pyUIClass/window1.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/anchor.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/anchor.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/anchor.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M4.34 15.66A7.97 7.97 0 0 0 9 17.94V10H5V8h4V5.83a3 3 0 1 1 2 0V8h4v2h-4v7.94a7.97 7.97 0 0 0 4.66-2.28l-1.42-1.42h5.66l-2.83 2.83a10 10 0 0 1-14.14 0L.1 14.24h5.66l-1.42 1.42zM10 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-back.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-back.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-back.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_8_">
+	<g>
+		<path d="M427,234.625H167.296l119.702-119.702L256,85L85,256l171,171l29.922-29.924L167.296,277.375H427V234.625z"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-forward.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-forward.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-arrow-forward.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_8_">
+	<g>
+		<path d="M85,277.375h259.704L225.002,397.077L256,427l171-171L256,85l-29.922,29.924l118.626,119.701H85V277.375z"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-camera.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-camera.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-camera.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+	<circle cx="256" cy="280" r="63"/>
+	<path d="M440,96h-88l-32-32H192l-32,32H72c-22.092,0-40,17.908-40,40v272c0,22.092,17.908,40,40,40h368c22.092,0,40-17.908,40-40
+		V136C480,113.908,462.092,96,440,96z M256,392c-61.855,0-112-50.145-112-112s50.145-112,112-112s112,50.145,112,112
+		S317.855,392,256,392z"/>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-close.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-close.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-close.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_5_">
+	<g>
+		<polygon points="405,136.798 375.202,107 256,226.202 136.798,107 107,136.798 226.202,256 107,375.202 136.798,405 256,285.798 
+			375.202,405 405,375.202 285.798,256 		"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-color-palette.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-color-palette.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-color-palette.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_12_">
+	<g>
+		<path d="M256,64C150.401,64,64,150.401,64,256c0,105.604,86.401,192,192,192c18.136,0,32-13.864,32-32
+			c0-8.531-3.198-16-8.531-21.333c-5.333-5.334-8.531-12.803-8.531-21.334c0-18.135,13.864-32,32-32h38.396
+			c58.667,0,106.667-48,106.667-106.666C448,140.802,361.604,64,256,64z M138.667,256c-18.136,0-32-13.864-32-32s13.864-32,32-32
+			c18.135,0,32,13.864,32,32S156.802,256,138.667,256z M202.667,170.667c-18.136,0-32-13.865-32-32c0-18.136,13.864-32,32-32
+			c18.135,0,32,13.864,32,32C234.667,156.802,220.802,170.667,202.667,170.667z M309.333,170.667c-18.135,0-32-13.865-32-32
+			c0-18.136,13.865-32,32-32c18.136,0,32,13.864,32,32C341.333,156.802,327.469,170.667,309.333,170.667z M373.333,256
+			c-18.135,0-32-13.864-32-32s13.865-32,32-32c18.136,0,32,13.864,32,32S391.469,256,373.333,256z"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-delete.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-delete.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-delete.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+	<path d="M128,405.429C128,428.846,147.198,448,170.667,448h170.667C364.802,448,384,428.846,384,405.429V160H128V405.429z M416,96
+		h-80l-26.785-32H202.786L176,96H96v32h320V96z"/>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-done.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-done.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-done.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_1_">
+	<g>
+		<g>
+			<polygon points="186.301,339.893 96,249.461 64,279.968 186.301,402 448,140.506 416,110 			"/>
+		</g>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-expand.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-expand.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-expand.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+	<polygon points="396.795,396.8 320,396.8 320,448 448,448 448,320 396.795,320 	"/>
+	<polygon points="396.8,115.205 396.8,192 448,192 448,64 320,64 320,115.205 	"/>
+	<polygon points="115.205,115.2 192,115.2 192,64 64,64 64,192 115.205,192 	"/>
+	<polygon points="115.2,396.795 115.2,320 64,320 64,448 192,448 192,396.795 	"/>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-folder-open.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-folder-open.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-folder-open.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<path d="M437.334,144H256.006l-42.668-48H74.666C51.197,96,32,115.198,32,138.667v234.666C32,396.802,51.197,416,74.666,416h362.668
+	C460.803,416,480,396.802,480,373.333V186.667C480,163.198,460.803,144,437.334,144z M448,373.333
+	c0,5.782-4.885,10.667-10.666,10.667H74.666C68.884,384,64,379.115,64,373.333V176h373.334c5.781,0,10.666,4.885,10.666,10.667
+	V373.333z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-hand.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-hand.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-hand.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<path d="M450.679,273.5c-14.585-14.577-36.054-15.89-50.639-1.312l-41.687,41.664c-10.852,10.836-23.93,10.859-31.564,1.852
+	c-5.057-5.968-3.061-24.374-1.644-36.049l20.907-171.849c1.867-15.353-9.07-30.185-24.43-32.051
+	c-15.358-1.867-29.322,9.939-31.191,25.289L267.37,236.021c-1.205,3.358-3.79,3.938-4.081-0.582L255.44,60
+	c0-15.465-12.542-28-28.014-28c-15.473,0-28.015,12.535-28.015,28l-0.552,176.752c0.146,2.04-1.604,2.624-1.92,0.294L172.016,99.077
+	c-2.75-15.219-17.323-26.203-32.548-23.453c-15.227,2.748-25.339,18.187-22.591,33.403l22.193,161.455
+	c0.023,2.872-0.941,4.513-2.308,0.831l-33.109-88.517c-5.18-14.572-21.196-23.065-35.776-17.889
+	c-14.579,5.177-22.201,22.061-17.023,36.631l58.042,189.625c0.303,1.046,0.624,2.085,0.953,3.118l0.121,0.39
+	c0.011,0.031,0.025,0.058,0.035,0.088C126.079,444.233,172.57,480,227.427,480c35.116,0,71.591-12.378,99.357-33.672
+	c0.001,0,0.003-0.002,0.003-0.002c29.99-18.051,126.071-121.347,126.071-121.347C467.445,310.402,465.266,288.08,450.679,273.5z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-locate.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-locate.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-locate.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon">
+	<g>
+		<path d="M256,176c-44.004,0-80.001,36-80.001,80c0,44.004,35.997,80,80.001,80c44.005,0,79.999-35.996,79.999-80
+			C335.999,212,300.005,176,256,176z M446.938,234.667c-9.605-88.531-81.074-160-169.605-169.599V32h-42.666v33.067
+			c-88.531,9.599-160,81.068-169.604,169.599H32v42.667h33.062c9.604,88.531,81.072,160,169.604,169.604V480h42.666v-33.062
+			c88.531-9.604,160-81.073,169.605-169.604H480v-42.667H446.938z M256,405.333c-82.137,0-149.334-67.198-149.334-149.333
+			c0-82.136,67.197-149.333,149.334-149.333c82.135,0,149.332,67.198,149.332,149.333C405.332,338.135,338.135,405.333,256,405.333z
+			"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-off.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-off.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-off.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_20_">
+	<g>
+		<path d="M256,48C141.601,48,48,141.601,48,256s93.601,208,208,208s208-93.601,208-208S370.399,48,256,48z M256,422.399
+			c-91.518,0-166.399-74.882-166.399-166.399S164.482,89.6,256,89.6S422.4,164.482,422.4,256S347.518,422.399,256,422.399z"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-on.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-on.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-radio-button-on.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g id="Icon_21_">
+	<g>
+		<path d="M256,152c-57.2,0-104,46.8-104,104s46.8,104,104,104s104-46.8,104-104S313.2,152,256,152z M256,48
+			C141.601,48,48,141.601,48,256s93.601,208,208,208s208-93.601,208-208S370.399,48,256,48z M256,422.4
+			c-91.518,0-166.4-74.883-166.4-166.4S164.482,89.6,256,89.6S422.4,164.482,422.4,256S347.518,422.4,256,422.4z"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-refresh.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-refresh.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/android-refresh.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+	<path d="M256,388c-72.597,0-132-59.405-132-132c0-72.601,59.403-132,132-132c36.3,0,69.299,15.4,92.406,39.601L278,234h154V80
+		l-51.698,51.702C348.406,99.798,304.406,80,256,80c-96.797,0-176,79.203-176,176s78.094,176,176,176
+		c81.045,0,148.287-54.134,169.401-128H378.85C360.105,353.561,311.712,388,256,388z"/>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-move.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-move.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-move.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<polygon points="480,256 384,160 384,236 276,236 276,128 352,128 256,32 160,128 236,128 236,236 128,236 128,160 32,256 128,352 
+	128,276 236,276 236,384 160,384 256,480 352,384 275.8,384 275.4,275.5 384,275.8 384,352 "/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-resize.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-resize.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/arrow-resize.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<polygon points="288,96 337.9,145.9 274,209.7 274,209.7 145.9,337.9 96,288 96,416 224,416 174.1,366.1 357.4,182.9 366.1,174.1 
+	416,224 416,96 "/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/bucket.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/bucket.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/bucket.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 18.4375 24' width='18.4375pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -12.7085 4.62541 -13.9584 0 -13.9584C -4.62541 -13.9584 -8.37504 -12.7085 -8.37504 -11.1667C -8.37504 -9.62492 -4.62541 -8.37504 0 -8.37504C 4.62541 -8.37504 8.37504 -9.62492 8.37504 -11.1667Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M -8.37504 -11.1667L -8.37504 -0L -8.37504 -1.85963e-15C -8.37504 -1.23975e-15 -8.37504 -6.19877e-16 -8.37504 -0C -8.37504 1.5418 -4.62541 2.79168 0 2.79168C 4.62541 2.79168 8.37504 1.5418 8.37504 0L 8.37504 0L 8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -15.7921 4.62541 -19.5418 0 -19.5418C -4.62541 -19.5418 -8.37504 -15.7921 -8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/center.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/center.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/center.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,11 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='18.75pt' version='1.1' viewBox='56.4094 53.8583 18.75 18.75' width='18.75pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M -8.65734 8.65734L 8.65734 8.65734L 8.65734 -8.65734L -8.65734 -8.65734L -8.65734 8.65734Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M 4.32867 0C 4.32867 -2.39066 2.39066 -4.32867 0 -4.32867C -2.39066 -4.32867 -4.32867 -2.39066 -4.32867 -0C -4.32867 2.39066 -2.39066 4.32867 0 4.32867C 2.39066 4.32867 4.32867 2.39066 4.32867 0Z' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/centerorigin.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/centerorigin.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/centerorigin.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='18.75pt' version='1.1' viewBox='56.4094 53.8583 18.75 18.75' width='18.75pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M -8.65734 8.65734L 8.65734 8.65734L 8.65734 -8.65734L -8.65734 -8.65734L -8.65734 8.65734Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M -8.65734 -0L 8.65734 0' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.7844 63.2333)'>
+<path d='M 0 8.65734L 0 -8.65734' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.50562'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/check.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/check.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/check.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Check" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M8.294,16.998c-0.435,0-0.847-0.203-1.111-0.553L3.61,11.724c-0.465-0.613-0.344-1.486,0.27-1.951
+	c0.615-0.467,1.488-0.344,1.953,0.27l2.351,3.104l5.911-9.492c0.407-0.652,1.267-0.852,1.921-0.445
+	c0.653,0.406,0.854,1.266,0.446,1.92L9.478,16.34c-0.242,0.391-0.661,0.635-1.12,0.656C8.336,16.998,8.316,16.998,8.294,16.998z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-left.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-left.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-left.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Chevron_circled_left" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+	 x="0px" y="0px" viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M11.302,6.776c-0.196-0.197-0.515-0.197-0.71,0L7.785,9.641c-0.196,0.199-0.196,0.52,0,0.717l2.807,2.864
+	c0.195,0.199,0.514,0.198,0.71,0c0.196-0.197,0.196-0.518,0-0.717L9,10l2.302-2.506C11.498,7.296,11.498,6.976,11.302,6.776z
+	 M10,0.4c-5.302,0-9.6,4.298-9.6,9.6c0,5.303,4.298,9.6,9.6,9.6s9.6-4.297,9.6-9.6C19.6,4.698,15.302,0.4,10,0.4z M10,18.354
+	c-4.615,0-8.354-3.74-8.354-8.354c0-4.614,3.739-8.354,8.354-8.354c4.613,0,8.354,3.74,8.354,8.354
+	C18.354,14.614,14.613,18.354,10,18.354z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-right.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-right.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/chevron-with-circle-right.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Chevron_circled_right" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+	 x="0px" y="0px" viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M11,10L8.698,7.494c-0.196-0.198-0.196-0.519,0-0.718c0.196-0.197,0.515-0.197,0.71,0l2.807,2.864
+	c0.196,0.199,0.196,0.52,0,0.717l-2.807,2.864c-0.195,0.199-0.514,0.198-0.71,0c-0.196-0.197-0.196-0.518,0-0.717L11,10z M10,0.4
+	c5.302,0,9.6,4.298,9.6,9.6c0,5.303-4.298,9.6-9.6,9.6S0.4,15.303,0.4,10C0.4,4.698,4.698,0.4,10,0.4z M10,18.354
+	c4.613,0,8.354-3.74,8.354-8.354c0-4.614-3.741-8.354-8.354-8.354c-4.615,0-8.354,3.74-8.354,8.354
+	C1.645,14.614,5.385,18.354,10,18.354z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/circle.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/circle.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/circle.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Circle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M10,0.4C4.698,0.4,0.4,4.698,0.4,10C0.4,15.302,4.698,19.6,10,19.6c5.301,0,9.6-4.298,9.6-9.601
+	C19.6,4.698,15.301,0.4,10,0.4z M10,17.599c-4.197,0-7.6-3.402-7.6-7.6S5.802,2.4,10,2.4c4.197,0,7.601,3.402,7.601,7.6
+	S14.197,17.599,10,17.599z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/close-round.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/close-round.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/close-round.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<path d="M437.5,386.6L306.9,256l130.6-130.6c14.1-14.1,14.1-36.8,0-50.9c-14.1-14.1-36.8-14.1-50.9,0L256,205.1L125.4,74.5
+	c-14.1-14.1-36.8-14.1-50.9,0c-14.1,14.1-14.1,36.8,0,50.9L205.1,256L74.5,386.6c-14.1,14.1-14.1,36.8,0,50.9
+	c14.1,14.1,36.8,14.1,50.9,0L256,306.9l130.6,130.6c14.1,14.1,36.8,14.1,50.9,0C451.5,423.4,451.5,400.6,437.5,386.6z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedcurve.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedcurve.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedcurve.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<path d='M -9.39118 -0C -9.96861 -3.83004 -8.55706 -7.51944 -6.64057 -10.2171C -0.491089 -18.8733 8.35676 -15.1906 8.67632 -5.52948C 8.836 -0.702008 6.23968 2.94207 3.32028 5.10857C -1.96891 9.03371 -8.26895 7.4437 -9.39118 -0Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='-6.64057' cy='-10.2171' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='8.67632' cy='-5.52948' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.7688)'>
+<circle cx='3.32028' cy='5.10857' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedpolygon.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedpolygon.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/closedpolygon.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<path d='M -9.39118 -0L -6.64057 -12.045L 8.67632 -6.51871L 3.32028 6.0225L -9.39118 -0Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-6.64057' cy='-12.045' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='8.67632' cy='-6.51871' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='3.32028' cy='6.0225' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/code.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/code.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/code.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Code" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M5.719,14.75c-0.236,0-0.474-0.083-0.664-0.252L-0.005,10l5.341-4.748C5.748,4.887,6.38,4.922,6.747,5.335
+	c0.367,0.413,0.33,1.045-0.083,1.412L3.005,10l3.378,3.002c0.413,0.367,0.45,0.999,0.083,1.412
+	C6.269,14.637,5.994,14.75,5.719,14.75z M14.664,14.748L20.005,10l-5.06-4.498c-0.413-0.367-1.045-0.33-1.411,0.083
+	c-0.367,0.413-0.33,1.045,0.083,1.412L16.995,10l-3.659,3.252c-0.413,0.367-0.45,0.999-0.083,1.412C13.45,14.887,13.725,15,14,15
+	C14.236,15,14.474,14.917,14.664,14.748z M9.986,16.165l2-12c0.091-0.545-0.277-1.06-0.822-1.151
+	c-0.547-0.092-1.061,0.277-1.15,0.822l-2,12c-0.091,0.545,0.277,1.06,0.822,1.151C8.892,16.996,8.946,17,9.001,17
+	C9.481,17,9.905,16.653,9.986,16.165z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/edit.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/edit.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/edit.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+	
+		<rect x="178.846" y="92.087" transform="matrix(-0.7071 -0.7071 0.7071 -0.7071 224.3476 631.1498)" width="128.085" height="354.049"/>
+	<path d="M471.723,88.393l-48.115-48.114c-11.723-11.724-31.558-10.896-44.304,1.85l-45.202,45.203l90.569,90.568l45.202-45.202
+		C482.616,119.952,483.445,100.116,471.723,88.393z"/>
+	<polygon points="64.021,363.252 32,480 148.737,447.979 	"/>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/eye.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/eye.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/eye.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+	<path d="M256,128c-81.9,0-145.7,48.8-224,128c67.4,67.7,124,128,224,128c99.9,0,173.4-76.4,224-126.6
+		C428.2,198.6,354.8,128,256,128z M256,347.3c-49.4,0-89.6-41-89.6-91.3c0-50.4,40.2-91.3,89.6-91.3s89.6,41,89.6,91.3
+		C345.6,306.4,305.4,347.3,256,347.3z"/>
+	<g>
+		<path d="M256,224c0-7.9,2.9-15.1,7.6-20.7c-2.5-0.4-5-0.6-7.6-0.6c-28.8,0-52.3,23.9-52.3,53.3c0,29.4,23.5,53.3,52.3,53.3
+			s52.3-23.9,52.3-53.3c0-2.3-0.2-4.6-0.4-6.9c-5.5,4.3-12.3,6.9-19.8,6.9C270.3,256,256,241.7,256,224z"/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/filledbucket.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/filledbucket.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/filledbucket.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,17 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 18.4375 24' width='18.4375pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M -8.37504 -5.02502L -8.37504 -0L -8.37504 -1.85963e-15C -8.37504 -1.23975e-15 -8.37504 -6.19877e-16 -8.37504 -0C -8.37504 1.5418 -4.62541 2.79168 0 2.79168C 4.62541 2.79168 8.37504 1.5418 8.37504 0L 8.37504 0L 8.37504 -5.02502L 8.37504 -10.05C 8.37504 -11.5918 4.62541 -12.8417 0 -12.8417C -4.62541 -12.8417 -8.37504 -11.5918 -8.37504 -10.05L -8.37504 -5.02502Z' fill='#808080'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -12.7085 4.62541 -13.9584 0 -13.9584C -4.62541 -13.9584 -8.37504 -12.7085 -8.37504 -11.1667C -8.37504 -9.62492 -4.62541 -8.37504 0 -8.37504C 4.62541 -8.37504 8.37504 -9.62492 8.37504 -11.1667Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M -8.37504 -11.1667L -8.37504 -0L -8.37504 -1.85963e-15C -8.37504 -1.23975e-15 -8.37504 -6.19877e-16 -8.37504 -0C -8.37504 1.5418 -4.62541 2.79168 0 2.79168C 4.62541 2.79168 8.37504 1.5418 8.37504 0L 8.37504 0L 8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 65.6282 74.202)'>
+<path d='M 8.37504 -11.1667C 8.37504 -15.7921 4.62541 -19.5418 0 -19.5418C -4.62541 -19.5418 -8.37504 -15.7921 -8.37504 -11.1667' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/grid.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/grid.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/grid.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+	<g>
+		<path d="M160,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
+			/>
+		<path d="M288,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
+			/>
+		<path d="M416,153.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V153.3z"
+			/>
+	</g>
+	<g>
+		<path d="M160,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
+			/>
+		<path d="M288,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
+			/>
+		<path d="M416,281.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V281.3z"
+			/>
+	</g>
+	<g>
+		<path d="M160,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
+			/>
+		<path d="M288,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
+			/>
+		<path d="M416,409.3c0,3.7-3,6.7-6.7,6.7h-50.5c-3.7,0-6.7-3-6.7-6.7v-50.5c0-3.7,3-6.7,6.7-6.7h50.5c3.7,0,6.7,3,6.7,6.7V409.3z"
+			/>
+	</g>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/magnifying-glass.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/magnifying-glass.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/magnifying-glass.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Magnifying_glass" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
+	 y="0px" viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M17.545,15.467l-3.779-3.779c0.57-0.935,0.898-2.035,0.898-3.21c0-3.417-2.961-6.377-6.378-6.377
+	C4.869,2.1,2.1,4.87,2.1,8.287c0,3.416,2.961,6.377,6.377,6.377c1.137,0,2.2-0.309,3.115-0.844l3.799,3.801
+	c0.372,0.371,0.975,0.371,1.346,0l0.943-0.943C18.051,16.307,17.916,15.838,17.545,15.467z M4.004,8.287
+	c0-2.366,1.917-4.283,4.282-4.283c2.366,0,4.474,2.107,4.474,4.474c0,2.365-1.918,4.283-4.283,4.283
+	C6.111,12.76,4.004,10.652,4.004,8.287z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/opencurve.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/opencurve.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/opencurve.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<path d='M -9.39118 -0C -9.32257 -3.77783 -8.34324 -7.38444 -6.64057 -10.1298C -1.26219 -18.8017 7.68971 -15.5351 8.67632 -5.4822C 9.18679 -0.280877 6.74937 4.51887 3.32028 5.06489' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='-6.64057' cy='-10.1298' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='8.67632' cy='-5.4822' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 69.8123)'>
+<circle cx='3.32028' cy='5.06489' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/openpolygon.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/openpolygon.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/openpolygon.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,20 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- This file was generated by dvisvgm 2.4 -->
+<svg height='24pt' version='1.1' viewBox='56.4094 53.8583 24 24' width='24pt' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'>
+<g id='page1'>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<path d='M -9.39118 -0L -6.64057 -12.045L 8.67632 -6.51871L 3.32028 6.0225' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='1.75656'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-9.39118' cy='-0' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='-6.64057' cy='-12.045' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='8.67632' cy='-6.51871' r='3.01125' fill='#000000'/>
+</g>
+<g transform='matrix(0.996264 0 0 0.996264 68.7655 68.8583)'>
+<circle cx='3.32028' cy='6.0225' r='3.01125' fill='#000000'/>
+</g></g>
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/plus-round.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/plus-round.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/plus-round.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<path d="M417.4,224H288V94.6c0-16.9-14.3-30.6-32-30.6c-17.7,0-32,13.7-32,30.6V224H94.6C77.7,224,64,238.3,64,256
+	c0,17.7,13.7,32,30.6,32H224v129.4c0,16.9,14.3,30.6,32,30.6c17.7,0,32-13.7,32-30.6V288h129.4c16.9,0,30.6-14.3,30.6-32
+	C448,238.3,434.3,224,417.4,224z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/save.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/save.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/save.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 18.1.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Save" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 20 20" enable-background="new 0 0 20 20" xml:space="preserve">
+<path d="M15.173,2H4C2.899,2,2,2.9,2,4v12c0,1.1,0.899,2,2,2h12c1.101,0,2-0.9,2-2V5.127L15.173,2z M14,8c0,0.549-0.45,1-1,1H7
+	C6.45,9,6,8.549,6,8V3h8V8z M13,4h-2v4h2V4z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/social-python.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/social-python.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/social-python.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="512px" height="512px" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve">
+<g>
+	<path d="M193.46,249.056c3.723-0.67,7.589-1.041,11.586-1.041L201.924,248h103.823c4.503,0,8.806-0.617,12.908-1.754
+		c19.37-5.363,33.345-22.537,33.345-43.663v-30.822v-56.402c0-24.832-21.15-43.484-46.289-47.606
+		c-15.931-2.624-39.258-3.827-55.089-3.749c-15.829,0.086-30.981,1.404-44.277,3.749C167.143,74.576,160,88.928,160,115.359V144h96
+		v16H128.82c-35.628,0-64.538,42.571-64.813,95.242C64.005,255.495,64,255.747,64,256c0,9.523,0.94,18.72,2.685,27.404
+		C74.648,323.07,99.451,352,128.82,352H144v-2.662v-43.273C144,279.238,164.146,254.332,193.46,249.056z M203.656,127.002
+		c-9.592,0-17.384-7.785-17.384-17.403c0-9.664,7.774-17.52,17.384-17.52c9.574,0,17.399,7.855,17.399,17.52
+		C221.056,119.217,213.246,127.002,203.656,127.002z"/>
+	<path d="M443.951,222.543C434.78,186.021,411.033,160,383.18,160H368v2.626v38.046c0,33.915-22.286,58.474-49.489,62.681
+		c-2.737,0.424-5.483,0.646-8.301,0.646H206.351c-4.518,0-8.904,0.584-13.049,1.672C174.18,270.689,160,286.6,160,307.236v32.922
+		v54.305c0,24.832,24.977,39.426,49.481,46.551c29.327,8.531,61.267,10.068,96.366,0C329.15,434.354,352,420.893,352,394.463V368
+		h-96v-16h127.18c25.24,0,47.107-21.365,57.814-52.549C445.474,286.404,448,271.641,448,256
+		C448,244.232,446.567,232.962,443.951,222.543z M307.867,382.82c9.59,0,17.381,7.785,17.381,17.4
+		c0,9.65-7.791,17.521-17.381,17.521c-9.577,0-17.399-7.871-17.399-17.521C290.468,390.59,298.274,382.82,307.867,382.82z"/>
+</g>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/subdirectory-left.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/subdirectory-left.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/subdirectory-left.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M18 12v1H8v5l-6-6 6-6v5h8V2h2z"/></svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/text.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/text.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/text.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
+  <path d="M0 0v2h.5c0-.55.45-1 1-1h1.5v5.5c0 .28-.22.5-.5.5h-.5v1h4v-1h-.5c-.28 0-.5-.22-.5-.5v-5.5h1.5c.55 0 1 .45 1 1h.5v-2h-8z" />
+</svg>
\ No newline at end of file

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons/triangle-stroked-15.svg
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons/triangle-stroked-15.svg	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons/triangle-stroked-15.svg	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1"
+	 id="svg4619" inkscape:version="0.91+devel+osxmenu r12911" sodipodi:docname="triangle-stroked-15.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
+	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="15px" height="15px"
+	 viewBox="0 0 15 15" style="enable-background:new 0 0 15 15;" xml:space="preserve">
+<path id="rect3338" inkscape:connector-curvature="0" sodipodi:nodetypes="cccccccccccc" d="M7.5243,1.5004
+	C7.2429,1.4913,6.9787,1.6423,6.8336,1.8952l-5.5,9.8692C1.0218,12.3078,1.395,12.9999,2,13h11
+	c0.605-0.0001,0.9782-0.6922,0.6664-1.2355l-5.5-9.8692C8.0302,1.6579,7.7884,1.5092,7.5243,1.5004z M7.5,3.8993l4.1267,7.4704
+	H3.3733L7.5,3.8993z"/>
+</svg>

Added: trunk/Master/texmf-dist/asymptote/GUI/res/icons.qrc
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/res/icons.qrc	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/res/icons.qrc	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,45 @@
+<RCC>
+  <qresource prefix="">
+    <file>icons/android-arrow-back.svg</file>
+    <file>icons/android-arrow-forward.svg</file>
+    <file>icons/android-folder-open.svg</file>
+    <file>icons/save.svg</file>
+    <file>icons/code.svg</file>
+    <file>icons/android-camera.svg</file>
+    <file>icons/plus-round.svg</file>
+    <file>icons/grid.svg</file>
+    <file>icons/magnifying-glass.svg</file>
+    <file>icons/center.svg</file>
+    <file>icons/centerorigin.svg</file>
+    <file>icons/edit.svg</file>
+    <file>icons/android-delete.svg</file>
+    <file>icons/android-hand.svg</file>
+    <file>icons/arrow-move.svg</file>
+    <file>icons/arrow-resize.svg</file>
+    <file>icons/android-refresh.svg</file>
+    <file>icons/anchor.svg</file>
+    <file>icons/eye.svg</file>
+    <file>icons/android-expand.svg</file>
+    <file>icons/chevron-with-circle-left.svg</file>
+    <file>icons/chevron-with-circle-right.svg</file>
+    <file>icons/bucket.svg</file>
+    <file>icons/filledbucket.svg</file>
+    <file>icons/android-color-palette.svg</file>
+    <file>icons/openpolygon.svg</file>
+    <file>icons/closedpolygon.svg</file>
+    <file>icons/opencurve.svg</file>
+    <file>icons/closedcurve.svg</file>
+    <file>icons/triangle-stroked-15.svg</file>
+    <file>icons/circle.svg</file>
+    <file>icons/text.svg</file>
+    <file>icons/social-python.svg</file>
+    <file>icons/subdirectory-left.svg</file>
+    <file>icons/android-done.svg</file>
+    <file>icons/android-close.svg</file>
+    <file>icons/check.svg</file>
+    <file>icons/android-radio-button-on.svg</file>
+    <file>icons/android-radio-button-off.svg</file>
+    <file>icons/android-locate.svg</file>
+    <file>icons/close-round.svg</file>
+  </qresource>
+</RCC>

Added: trunk/Master/texmf-dist/asymptote/GUI/setup.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/setup.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/setup.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+
+import xasyVersion
+from setuptools import setup
+
+setup(
+    name="xasy",
+    version=xasyVersion.xasyVersion,
+    author="Supakorn Rassameemasmuang, Orest Shardt, and John C. Bowman",
+    description="User interface for Asymptote, a vector graphics language", 
+    url="http://asymptote.sourceforge.net",
+    download_url="https://sourceforge.net/projects/asymptote/"
+)


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/setup.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Modified: trunk/Master/texmf-dist/asymptote/GUI/xasy.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasy.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasy.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,38 +1,16 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasy implements a graphical interface for Asymptote.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-############################################################################
+#!/usr/bin/env python3
 
-import getopt,sys,signal
-import xasyMainWin
-if sys.version_info >= (3, 0):
-  from tkinter import *
-else:
-  from Tkinter import *
+import sys
+import PyQt5.QtWidgets as Qw
+from Window1 import MainWindow1
 
-signal.signal(signal.SIGINT,signal.SIG_IGN)
 
-root = Tk()
-mag = 1.0
-try:
-  opts,args = getopt.getopt(sys.argv[1:],"x:")
-  if(len(opts)>=1):
-    mag = float(opts[0][1])
-except:
-  print ("Invalid arguments.")
-  print ("Usage: xasy.py [-x magnification] [filename]")
-  sys.exit(1)
-if(mag <= 0.0):
-  print ("Magnification must be positive.")
-  sys.exit(1)
-if(len(args)>=1):
-  app = xasyMainWin.xasyMainWin(root,args[0],mag)
-else:
-  app = xasyMainWin.xasyMainWin(root,magnification=mag)
-root.mainloop()
+def main(args):
+    qtApp = Qw.QApplication(args)
+    mainWin1 = MainWindow1()
+    mainWin1.show()
+    return qtApp.exec_()
+
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv) or 0)

Modified: trunk/Master/texmf-dist/asymptote/GUI/xasy2asy.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasy2asy.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasy2asy.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,766 +1,1407 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
+
 ###########################################################################
 #
 # xasy2asy provides a Python interface to Asymptote
 #
 #
-# Author: Orest Shardt
-# Created: June 29, 2007
+# Authors: Orest Shardt, Supakorn Rassameemasmuang, and John C. Bowman
 #
 ###########################################################################
-import sys,os,signal,threading
-from subprocess import *
-from string import *
-import xasyOptions
-from tempfile import mkdtemp
 
-if sys.version_info >= (3, 0):
-  from tkinter import *
-  import queue
-else:
-  from Tkinter import *
-  import Queue as queue
+import PyQt5.QtWidgets as Qw
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import PyQt5.QtSvg as Qs
 
-# PIL support is now mandatory due to rotations
-try:
-  from PIL import ImageTk
-  from PIL import Image
-except:
-   pass
+import numpy as np
 
-import CubicBezier
+import sys
+import os
+import signal
+import threading
+import string
+import subprocess
+import tempfile
+import re
+import shutil
+import copy
+import queue
+import io
+import atexit
+import DebugFlags
 
-quickAsyFailed = True
-global AsyTempDir
+import xasyUtils as xu
+import xasyArgs as xa
+import xasyOptions as xo
+import xasySvg as xs
 
-console=None
+class AsymptoteEngine:
+    xasy=chr(4)+"\n"
 
-def startQuickAsy():
-  global quickAsy
-  global quickAsyFailed
-  global AsyTempDir
-  global fout,fin
-  if quickAsyRunning():
-    return
-  try:
-    fout.close()
-    quickAsy.wait()
-  except:
-    pass
-  try:
-    quickAsyFailed = False
-    if os.name == "nt":
-      AsyTempDir=mkdtemp(prefix="asy_", dir="./")
-    else:
-      AsyTempDir=mkdtemp(prefix="asy_")+os.sep
-    if sys.platform[:3] == 'win':
-      quickAsy=Popen([xasyOptions.options['asyPath'],"-noV","-multiline","-q",
-                      "-o"+AsyTempDir,"-inpipe=0","-outpipe=2"],stdin=PIPE,
-                     stderr=PIPE,universal_newlines=True)
-      fout=quickAsy.stdin
-      fin=quickAsy.stderr
-    else:
-      (rx,wx) = os.pipe()
-      (ra,wa) = os.pipe()
-      if sys.version_info >= (3, 4):
-        os.set_inheritable(rx, True)
-        os.set_inheritable(wx, True)
-        os.set_inheritable(ra, True)
-        os.set_inheritable(wa, True)
-      quickAsy=Popen([xasyOptions.options['asyPath'],"-noV","-multiline","-q",
-               "-o"+AsyTempDir,"-inpipe="+str(rx),"-outpipe="+str(wa)],
-                     close_fds=False)
-      fout=os.fdopen(wx,'w')
-      fin=os.fdopen(ra,'r')
-    if quickAsy.returncode != None:
-      quickAsyFailed = True
-  except:
-    quickAsyFailed = True
-  
-def stopQuickAsy():
-  if quickAsyRunning():
-    fout.write("exit;\n");
+    def __init__(self, path=None, keepFiles=DebugFlags.keepFiles, keepDefaultArgs=True):
+        if path is None:
+            path = xa.getArgs().asypath
+            if path is None:
+                opt = xo.BasicConfigs.defaultOpt
+                opt.load()
+                path = opt['asyPath']
 
-def getAsyTempDir():
-  return AsyTempDir
+        if sys.platform[:3] == 'win':
+            rx = 0  # stdin
+            wa = 2  # stderr
+        else:
+            rx, wx = os.pipe()
+            ra, wa = os.pipe()
+            os.set_inheritable(rx, True)
+            os.set_inheritable(wx, True)
+            os.set_inheritable(ra, True)
+            os.set_inheritable(wa, True)
+            self.ostream = os.fdopen(wx, 'w')
+            self.istream = os.fdopen(ra, 'r')
+            
+        self.keepFiles = keepFiles
+        if sys.platform[:3] == 'win':
+            self.tmpdir = tempfile.mkdtemp(prefix='xasyData_',dir='./')+'/'
+        else:
+            self.tmpdir = tempfile.mkdtemp(prefix='xasyData_')+os.sep
 
-def quickAsyRunning():
-  if quickAsyFailed or quickAsy.returncode != None:
-    return False
-  else:
-    return True
+        self.args=['-xasy', '-noV', '-q', '-inpipe=' + str(rx), '-outpipe=' + str(wa), '-o', self.tmpdir]
 
-def asyExecute(command):
-  if not quickAsyRunning():
-    startQuickAsy()
-  fout.write(command)
+        self.asyPath = path
+        self.asyProcess = None
 
-def closeConsole(event):
-  global console
-  console = None
+    def start(self):
+        try:
+            if sys.platform[:3] == 'win':
+                self.asyProcess = subprocess.Popen([self.asyPath] + self.args,
+                                                stdin=subprocess.PIPE, stderr=subprocess.PIPE,
+                                                universal_newlines=True)
+                self.ostream = self.asyProcess.stdin
+                self.istream = self.asyProcess.stderr
+            else:
+                self.asyProcess = subprocess.Popen([self.asyPath] + self.args,close_fds=False)
+        finally:
+            atexit.register(self.cleanup)
 
-def consoleOutput(line):
-  global console
-  global ctl
-  if console == None:
-    ctl=Toplevel()
-    ctl.title("Asymptote Console")
-    ctl.bind("<Destroy>",closeConsole)
-    yscrollbar=Scrollbar(ctl)
-    yscrollbar.pack(side=RIGHT,fill=Y)
-    console=Text(ctl,yscrollcommand=yscrollbar.set)
-    console.pack()
-    yscrollbar.config(command=console.yview)
-  console.insert(END,line)
-  ctl.lift()
+    def wait(self):
+        if self.asyProcess.returncode is not None:
+            return
+        else:
+            return self.asyProcess.wait()
 
-class asyTransform:
-  """A python implementation of an asy transform"""
-  def __init__(self,initTuple,delete=False):
-    """Initialize the transform with a 6 entry tuple"""
-    if type(initTuple) == type((0,)) and len(initTuple) == 6:
-      self.t = initTuple
-      self.x,self.y,self.xx,self.xy,self.yx,self.yy = initTuple
-      self.deleted = delete
-    else:
-      raise Exception("Illegal initializer for asyTransform")
+    def __enter__(self):
+        self.start()
+        return self
 
-  def getCode(self):
-    """Obtain the asy code that represents this transform"""
-    if self.deleted:
-      return str(self.t) + ", false"
-    else:
-      return str(self.t)
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.stop()
+        self.wait()
 
-  def scale(self,s):
-    return asyTransform((0,0,s,0,0,s))*self
+    @property
+    def tempDirName(self):
+        return self.tmpdir
 
-  def __str__(self):
-    """Equivalent functionality to getCode(). It allows the expression str(asyTransform) to be meaningful."""
-    return self.getCode()
+    def startThenStop(self):
+        self.start()
+        self.stop()
+        self.wait()
 
-  def __mul__(self,other):
-    """Define multiplication of transforms as composition."""
-    if type(other)==type((0,)):
-      if len(other) == 6:
-        return self*asyTransform(other)
-      elif len(other) == 2:
-        return ((self.t[0]+self.t[2]*other[0]+self.t[3]*other[1]),(self.t[1]+self.t[4]*other[0]+self.t[5]*other[1]))
-      else:
-        raise Exception("Illegal multiplier of {:s}".format(str(type(other))))
-    elif isinstance(other,asyTransform):
-      result = asyTransform((0,0,0,0,0,0))
-      result.x = self.x+self.xx*other.x+self.xy*other.y
-      result.y = self.y+self.yx*other.x+self.yy*other.y
-      result.xx = self.xx*other.xx+self.xy*other.yx
-      result.xy = self.xx*other.xy+self.xy*other.yy
-      result.yx = self.yx*other.xx+self.yy*other.yx
-      result.yy = self.yx*other.xy+self.yy*other.yy
-      result.t = (result.x,result.y,result.xx,result.xy,result.yx,result.yy)
-      return result
-    else:
-      raise Exception("Illegal multiplier of {:s}".format(str(type(other))))
+    @property
+    def active(self):
+        if self.asyProcess is None:
+            return False
+        return self.asyProcess.returncode is None
 
+    def stop(self):
+        if self.active:
+            self.asyProcess.kill()
+
+    def cleanup(self):
+        self.stop()
+        if self.asyProcess is not None:
+            self.asyProcess.wait()
+        if not self.keepFiles:
+            if os.path.isdir(self.tempDirName + os.sep):
+                shutil.rmtree(self.tempDirName, ignore_errors=True)
+
+class asyTransform(Qc.QObject):
+    """A python implementation of an asy transform"""
+
+    def __init__(self, initTuple, delete=False):
+        """Initialize the transform with a 6 entry tuple"""
+        super().__init__()
+        if isinstance(initTuple, (tuple, list)) and len(initTuple) == 6:
+            self.t = initTuple
+            self.x, self.y, self.xx, self.xy, self.yx, self.yy = initTuple
+            self._deleted = delete
+        else:
+            raise TypeError("Illegal initializer for asyTransform")
+
+    @property
+    def deleted(self):
+        return self._deleted
+
+    @deleted.setter
+    def deleted(self, value):
+        self._deleted = value
+
+    @classmethod
+    def zero(cls):
+        return asyTransform((0, 0, 0, 0, 0, 0))
+
+    @classmethod
+    def fromQTransform(cls, transform: Qg.QTransform):
+        tx, ty = transform.dx(), transform.dy()
+        xx, xy, yx, yy = transform.m11(), transform.m21(), transform.m12(), transform.m22()
+
+        return asyTransform((tx, ty, xx, xy, yx, yy))
+
+    @classmethod
+    def fromNumpyMatrix(cls, transform: np.ndarray):
+        assert transform.shape == (3, 3)
+
+        tx = transform[0, 2]
+        ty = transform[1, 2]
+
+        xx, xy, yx, yy = transform[0:2, 0:2].ravel().tolist()[0]
+
+        return asyTransform((tx, ty, xx, xy, yx, yy))
+
+    def getRawCode(self):
+        return xu.tuple2StrWOspaces(self.t)
+
+    def getCode(self, asy2psmap=None):
+        """Obtain the asy code that represents this transform"""
+        if asy2psmap is None:
+            asy2psmap = asyTransform((0, 0, 1, 0, 0, 1))
+        if self.deleted:
+            return 'zeroTransform'
+        else:
+            return (asy2psmap.inverted() * self * asy2psmap).getRawCode()
+
+    def scale(self, s):
+        return asyTransform((0, 0, s, 0, 0, s)) * self
+
+    def toQTransform(self):
+        return Qg.QTransform(self.xx, self.yx, self.xy, self.yy, self.x, self.y)
+
+    def __str__(self):
+        """Equivalent functionality to getCode(). It allows the expression str(asyTransform) to be meaningful."""
+        return self.getCode()
+
+    def isIdentity(self):
+        return self == identity()
+
+    def inverted(self):
+        return asyTransform.fromQTransform(self.toQTransform().inverted()[0])
+
+    def __eq__(self, other):
+        return list(self.t) == list(other.t)
+
+    def __mul__(self, other):
+        """Define multiplication of transforms as composition."""
+        if isinstance(other, tuple):
+            if len(other) == 6:
+                return self * asyTransform(other)
+            elif len(other) == 2:
+                return ((self.t[0] + self.t[2] * other[0] + self.t[3] * other[1]),
+                        (self.t[1] + self.t[4] * other[0] + self.t[5] * other[1]))
+            else:
+                raise Exception("Illegal multiplier of {:s}".format(str(type(other))))
+        elif isinstance(other, asyTransform):
+            result = asyTransform((0, 0, 0, 0, 0, 0))
+            result.x = self.x + self.xx * other.x + self.xy * other.y
+            result.y = self.y + self.yx * other.x + self.yy * other.y
+            result.xx = self.xx * other.xx + self.xy * other.yx
+            result.xy = self.xx * other.xy + self.xy * other.yy
+            result.yx = self.yx * other.xx + self.yy * other.yx
+            result.yy = self.yx * other.xy + self.yy * other.yy
+            result.t = (result.x, result.y, result.xx, result.xy, result.yx, result.yy)
+            return result
+        elif isinstance(other, str):
+            if other != 'cycle':
+                raise TypeError
+            else:
+                return 'cycle'
+        else:
+            raise TypeError("Illegal multiplier of {:s}".format(str(type(other))))
+
+
 def identity():
-  return asyTransform((0,0,1,0,0,1))
+    return asyTransform((0, 0, 1, 0, 0, 1))
 
-class asyObj:
-  """A base class for asy objects: an item represented by asymptote code."""
-  def __init__(self):
-    """Initialize the object"""
-    self.asyCode = ""
+def yflip():
+    return asyTransform((0, 0, 1, 0, 0, -1))
 
-  def updateCode(self,mag=1.0):
-    """Update the object's code: should be overriden."""
-    pass
+class asyObj(Qc.QObject):
+    """A base class for asy objects: an item represented by asymptote code."""
+    def __init__(self):
+        """Initialize the object"""
+        super().__init__()
+        self.asyCode = ''
 
-  def getCode(self):
-    """Return the code describing the object"""
-    self.updateCode()
-    return self.asyCode
+    def updateCode(self, ps2asymap=identity()):
+        """Update the object's code: should be overriden."""
+        raise NotImplementedError
 
+    def getCode(self, ps2asymap=identity()):
+        """Return the code describing the object"""
+        self.updateCode(ps2asymap)
+        return self.asyCode
+
+
 class asyPen(asyObj):
-  """A python wrapper for an asymptote pen"""
-  def __init__(self,color=(0,0,0),width=0.5,options=""):
-    """Initialize the pen"""
-    asyObj.__init__(self)
-    self.options=options
-    self.width=width
-    self.setColor(color)
-    self.updateCode()
-    if options != "":
-      self.computeColor()
+    """A python wrapper for an asymptote pen"""
+    @staticmethod
+    def getColorFromQColor(color):
+        return color.redF(), color.greenF(), color.blueF()
 
-  def updateCode(self,mag=1.0):
-    """Generate the pen's code"""
-    self.asyCode = "rgb({:g},{:g},{:g})+{:s}".format(self.color[0], self.color[1], self.color[2],str(self.width))
-    if len(self.options) > 0:
-      self.asyCode += "+"+self.options
+    @staticmethod
+    def convertToQColor(color):
+        r, g, b = color
+        return Qg.QColor.fromRgbF(r, g, b)
 
-  def setWidth(self,newWidth):
-    """Set the pen's width"""
-    self.width=newWidth
-    self.updateCode()
+    @classmethod
+    def fromAsyPen(cls, pen):
+        assert isinstance(pen, cls)
+        return cls(asyengine=pen._asyengine, color=pen.color, width=pen.width, pen_options=pen.options)
 
-  def setColor(self,color):
-    """Set the pen's color"""
-    if type(color) == type((1,)) and len(color) == 3:
-      self.color = color
-    else:
-      self.color = "(0,0,0)"
-    self.updateCode()
+    def __init__(self, asyengine=None, color=(0, 0, 0), width=0.5, pen_options=""):
+        """Initialize the pen"""
+        asyObj.__init__(self)
+        self.color = (0, 0, 0)
+        self.options = pen_options
+        self.width = width
+        self._asyengine = asyengine
+        self._deferAsyfy = False
+        if pen_options:
+            self._deferAsyfy = True
+        self.updateCode()
+        self.setColor(color)
 
-  def computeColor(self):
-    """Find out the color of an arbitrary asymptote pen."""
-    fout.write("pen p="+self.getCode()+';\n')
-    fout.write("file fout=output(mode='pipe');\n")
-    fout.write("write(fout,colorspace(p),newl);\n")
-    fout.write("write(fout,colors(p));\n")
-    fout.write("flush(fout);\n")
-    fout.flush()
-    colorspace = fin.readline()
-    if colorspace.find("cmyk") != -1:
-      lines = fin.readline()+fin.readline()+fin.readline()+fin.readline()
-      parts = lines.split()
-      c,m,y,k = eval(parts[0]),eval(parts[1]),eval(parts[2]),eval(parts[3])
-      k = 1-k
-      r,g,b = ((1-c)*k,(1-m)*k,(1-y)*k)
-    elif colorspace.find("rgb") != -1:
-      lines = fin.readline()+fin.readline()+fin.readline()
-      parts = lines.split()
-      r,g,b = eval(parts[0]),eval(parts[1]),eval(parts[2])
-    elif colorspace.find("gray") != -1:
-      lines = fin.readline()
-      parts = lines.split()
-      r = g = b = eval(parts[0])
-    self.color = (r,g,b)
+    @property
+    def asyEngine(self):
+        return self._asyengine
 
-  def tkColor(self):
-    """Return the tk version of the pen's color"""
-    self.computeColor()
-    return '#{}'.format("".join(["{:02x}".format(min(int(256*a),255)) for a in self.color]))
+    @asyEngine.setter
+    def asyEngine(self, value):
+        self._asyengine = value
 
+    def updateCode(self, asy2psmap=identity()):
+        """Generate the pen's code"""
+        if self._deferAsyfy:
+            self.computeColor()
+        self.asyCode = 'rgb({:g},{:g},{:g})+{:s}'.format(self.color[0], self.color[1], self.color[2], str(self.width))
+        if len(self.options) > 0:
+            self.asyCode = self.asyCode + '+' + self.options
+
+    def setWidth(self, newWidth):
+        """Set the pen's width"""
+        self.width = newWidth
+        self.updateCode()
+
+    def setColor(self, color):
+        """Set the pen's color"""
+        if isinstance(color, tuple) and len(color) == 3:
+            self.color = color
+        else:
+            self.color = (0, 0, 0)
+        self.updateCode()
+
+    def setColorFromQColor(self, color):
+        self.setColor(asyPen.getColorFromQColor(color))
+
+    def computeColor(self):
+        """Find out the color of an arbitrary asymptote pen."""
+        assert isinstance(self.asyEngine, AsymptoteEngine)
+        assert self.asyEngine.active
+
+        fout = self.asyEngine.ostream
+        fin = self.asyEngine.istream
+
+        fout.write("pen p=" + self.getCode() + ';\n')
+        fout.write("write(_outpipe,colorspace(p),newl);\n")
+        fout.write("write(_outpipe,colors(p));\n")
+        fout.write("flush(_outpipe);\n")
+        fout.write(self.asyEngine.xasy)
+        fout.flush()
+
+        colorspace = fin.readline()
+        if colorspace.find("cmyk") != -1:
+            lines = fin.readline() + fin.readline() + fin.readline() + fin.readline()
+            parts = lines.split()
+            c, m, y, k = eval(parts[0]), eval(parts[1]), eval(parts[2]), eval(parts[3])
+            k = 1 - k
+            r, g, b = ((1 - c) * k, (1 - m) * k, (1 - y) * k)
+        elif colorspace.find("rgb") != -1:
+            lines = fin.readline() + fin.readline() + fin.readline()
+            parts = lines.split()
+            r, g, b = eval(parts[0]), eval(parts[1]), eval(parts[2])
+        elif colorspace.find("gray") != -1:
+            lines = fin.readline()
+            parts = lines.split()
+            r = g = b = eval(parts[0])
+        else:
+            raise ChildProcessError('Asymptote error.')
+        self.color = (r, g, b)
+        self._deferAsyfy = False
+
+    def tkColor(self):
+        """Return the tk version of the pen's color"""
+        self.computeColor()
+        return '#{}'.format("".join(["{:02x}".format(min(int(256 * a), 255)) for a in self.color]))
+
+    def toQPen(self):
+        if self._deferAsyfy:
+            self.computeColor()
+        newPen = Qg.QPen()
+        newPen.setColor(asyPen.convertToQColor(self.color))
+        newPen.setWidthF(self.width)
+
+        return newPen
+
+
 class asyPath(asyObj):
-  """A python wrapper for an asymptote path"""
-  def __init__(self):
-    """Initialize the path to be an empty path: a path with no nodes, control points, or links."""
-    asyObj.__init__(self)
-    self.nodeSet = []
-    self.linkSet = []
-    self.controlSet = []
-    self.computed = False
+    """A python wrapper for an asymptote path"""
 
-  def initFromNodeList(self,nodeSet,linkSet):
-    """Initialize the path from a set of nodes and link types, "--", "..", or "::" """
-    if len(nodeSet)>0:
-      self.nodeSet = nodeSet[:]
-      self.linkSet = linkSet[:]
-      self.computed = False
+    def __init__(self, asyengine: AsymptoteEngine=None, forceCurve=False):
+        """Initialize the path to be an empty path: a path with no nodes, control points, or links."""
+        super().__init__()
+        self.nodeSet = []
+        self.linkSet = []
+        self.forceCurve = forceCurve
+        self.controlSet = []
+        self.computed = False
+        self.asyengine = asyengine
 
-  def initFromControls(self,nodeSet,controlSet):
-    """Initialize the path from nodes and control points"""
-    self.controlSet = controlSet[:]
-    self.nodeSet = nodeSet[:]
-    self.computed = True
+    @classmethod
+    def fromPath(cls, oldPath):
+        newObj = asyPath(None)
+        newObj.nodeSet = copy.copy(oldPath.nodeSet)
+        newObj.linkSet = copy.copy(oldPath.linkSet)
+        newObj.controlSet = copy.deepcopy(oldPath.controlSet)
+        newObj.computed = oldPath.computed
+        newObj.asyengine = oldPath.asyengine
 
-  def makeNodeStr(self,node):
-    """Represent a node as a string"""
-    if node == 'cycle':
-      return node
-    else:
-      return "("+str(node[0])+","+str(node[1])+")"
+        return newObj
 
-  def updateCode(self,mag=1.0):
-    """Generate the code describing the path"""
-    if not self.computed:
-      count = 0
-      #this string concatenation could be optimised
-      self.asyCode = self.makeNodeStr(self.nodeSet[0])
-      for node in self.nodeSet[1:]:
-        self.asyCode += self.linkSet[count]+self.makeNodeStr(node)
-        count += 1
-    else:
-      count = 0
-      #this string concatenation could be optimised
-      self.asyCode = self.makeNodeStr(self.nodeSet[0])
-      for node in self.nodeSet[1:]:
-        self.asyCode += "..controls"
-        self.asyCode += self.makeNodeStr(self.controlSet[count][0])
-        self.asyCode += "and"
-        self.asyCode += self.makeNodeStr(self.controlSet[count][1])
-        self.asyCode += ".." + self.makeNodeStr(node) + "\n"
-        count += 1
+    @classmethod
+    def fromBezierPoints(cls, pointList: list, engine=None):
+        if not pointList:
+            return None
+        assert isinstance(pointList[0], BezierCurveEditor.BezierPoint)
+        nodeList = []
+        controlList = []
+        for point in pointList:
+            nodeList.append(BezierCurveEditor.QPoint2Tuple(point.point))
+            if point.rCtrlPoint is not None:  # first
+                controlList.append([BezierCurveEditor.QPoint2Tuple(point.rCtrlPoint)])
+            if point.lCtrlPoint is not None:  # last
+                controlList[-1].append(BezierCurveEditor.QPoint2Tuple(point.lCtrlPoint))
+        newPath = asyPath(asyengine=engine)
+        newPath.initFromControls(nodeList, controlList)
+        return newPath
 
-  def getNode(self,index):
-    """Return the requested node"""
-    return self.nodeSet[index]
+    def setInfo(self, path):
+        self.nodeSet = copy.copy(path.nodeSet)
+        self.linkSet = copy.copy(path.linkSet)
+        self.controlSet = copy.deepcopy(path.controlSet)
+        self.computed = path.computed
 
-  def getLink(self,index):
-    """Return the requested link"""
-    return self.linkSet[index]
+    @property
+    def isEmpty(self):
+        return len(self.nodeSet) == 0
 
-  def setNode(self,index,newNode):
-    """Set a node to a new position"""
-    self.nodeSet[index] = newNode
+    @property
+    def isDrawable(self):
+        return len(self.nodeSet) >= 2
 
-  def moveNode(self,index,offset):
-    """Translate a node"""
-    if self.nodeSet[index] != "cycle":
-      self.nodeSet[index] = (self.nodeSet[index][0]+offset[0],self.nodeSet[1]+offset[1])
+    def toQPainterPath(self) -> Qg.QPainterPath:
+        return self.toQPainterPathCurve() if self.containsCurve else self.toQPainterPathLine()
 
-  def setLink(self,index,ltype):
-    """Change the specified link"""
-    self.linkSet[index] = ltype
+    def toQPainterPathLine(self):
+        baseX, baseY = self.nodeSet[0]
+        painterPath = Qg.QPainterPath(Qc.QPointF(baseX, baseY))
 
-  def addNode(self,point,ltype):
-    """Add a node to the end of a path"""
-    self.nodeSet.append(point)
-    if len(self.nodeSet) != 1:
-      self.linkSet.append(ltype)
-    if self.computed:
-      self.computeControls()
+        for pointIndex in range(1, len(self.nodeSet)):
+            node = self.nodeSet[pointIndex]
+            if self.nodeSet[pointIndex] == 'cycle':
+                node = self.nodeSet[0]
 
-  def insertNode(self,index,point,ltype=".."):
-    """Insert a node, and its corresponding link, at the given index"""
-    self.nodeSet.insert(index,point)
-    self.linkSet.insert(index,ltype)
-    if self.computed:
-      self.computeControls()
+            painterPath.lineTo(*node)
 
-  def setControl(self,index,position):
-    """Set a control point to a new position"""
-    self.controlSet[index] = position
+        return painterPath
 
-  def moveControl(self,index,offset):
-    """Translate a control point"""
-    self.controlSet[index] = (self.controlSet[index][0]+offset[0],self.controlSet[index][1]+offset[1])
 
-  def computeControls(self):
-    """Evaluate the code of the path to obtain its control points"""
-    fout.write("file fout=output(mode='pipe');\n")
-    fout.write("path p="+self.getCode()+';\n')
-    fout.write("write(fout,length(p),newl);\n")
-    fout.write("write(fout,unstraighten(p),endl);\n")
-    fout.flush()
-    lengthStr = fin.readline()
-    pathSegments = eval(lengthStr.split()[-1])
-    pathStrLines = []
-    for i in range(pathSegments+1):
-      line=fin.readline()
-      line=line.replace("\n","")
-      pathStrLines.append(line)
-    oneLiner = "".join(pathStrLines).replace(" ", "")
-    splitList = oneLiner.split("..")
-    nodes = [a for a in splitList if a.find("controls")==-1]
-    self.nodeSet = []
-    for a in nodes:
-      if a == 'cycle':
-        self.nodeSet.append(a)
-      else:
-        self.nodeSet.append(eval(a))
-    controls = [a.replace("controls","").split("and") for a in splitList if a.find("controls") != -1]
-    self.controlSet = [[eval(a[0]),eval(a[1])] for a in controls]
-    self.computed = True
+    def toQPainterPathCurve(self):
+        if not self.computed:
+            self.computeControls()
 
+        baseX, baseY = self.nodeSet[0]
+        painterPath = Qg.QPainterPath(Qc.QPointF(baseX, baseY))
+
+        for pointIndex in range(1, len(self.nodeSet)):
+            node = self.nodeSet[pointIndex]
+            if self.nodeSet[pointIndex] == 'cycle':
+                node = self.nodeSet[0]
+            endPoint = Qc.QPointF(node[0], node[1])
+            ctrlPoint1 = Qc.QPointF(self.controlSet[pointIndex-1][0][0], self.controlSet[pointIndex-1][0][1])
+            ctrlPoint2 = Qc.QPointF(self.controlSet[pointIndex-1][1][0], self.controlSet[pointIndex-1][1][1])
+
+            painterPath.cubicTo(ctrlPoint1, ctrlPoint2, endPoint)
+        return painterPath
+
+    def initFromNodeList(self, nodeSet, linkSet):
+        """Initialize the path from a set of nodes and link types, "--", "..", or "::" """
+        if len(nodeSet) > 0:
+            self.nodeSet = nodeSet[:]
+            self.linkSet = linkSet[:]
+            self.computed = False
+
+    def initFromControls(self, nodeSet, controlSet):
+        """Initialize the path from nodes and control points"""
+        self.controlSet = controlSet[:]
+        self.nodeSet = nodeSet[:]
+        self.computed = True
+
+    def makeNodeStr(self, node):
+        """Represent a node as a string"""
+        if node == 'cycle':
+            return node
+        else:
+            # if really want to, disable this rounding
+            # shouldn't be to much of a problem since 10e-6 is quite small... 
+            return '({:.6g},{:.6g})'.format(node[0], node[1])
+
+    def updateCode(self, ps2asymap=identity()):
+        """Generate the code describing the path"""
+        # currently at postscript. Convert to asy
+        asy2psmap =  ps2asymap.inverted()
+        with io.StringIO() as rawAsyCode:
+            count = 0
+            rawAsyCode.write(self.makeNodeStr(asy2psmap * self.nodeSet[0]))
+            for node in self.nodeSet[1:]:
+                if not self.computed or count >= len(self.controlSet):
+                    rawAsyCode.write(self.linkSet[count])
+                    rawAsyCode.write(self.makeNodeStr(asy2psmap * node))
+                else:
+                    rawAsyCode.write('..controls ')
+                    rawAsyCode.write(self.makeNodeStr(asy2psmap *  self.controlSet[count][0]))
+                    rawAsyCode.write(' and ')
+                    rawAsyCode.write(self.makeNodeStr(asy2psmap * self.controlSet[count][1]))
+                    rawAsyCode.write(".." + self.makeNodeStr(asy2psmap * node))
+                count = count + 1
+            self.asyCode = rawAsyCode.getvalue()
+
+    @property
+    def containsCurve(self):
+        return '..' in self.linkSet or self.forceCurve
+
+    def getNode(self, index):
+        """Return the requested node"""
+        return self.nodeSet[index]
+
+    def getLink(self, index):
+        """Return the requested link"""
+        return self.linkSet[index]
+
+    def setNode(self, index, newNode):
+        """Set a node to a new position"""
+        self.nodeSet[index] = newNode
+
+    def moveNode(self, index, offset):
+        """Translate a node"""
+        if self.nodeSet[index] != "cycle":
+            self.nodeSet[index] = (self.nodeSet[index][0] + offset[0], self.nodeSet[index][1] + offset[1])
+
+    def setLink(self, index, ltype):
+        """Change the specified link"""
+        self.linkSet[index] = ltype
+
+    def addNode(self, point, ltype):
+        """Add a node to the end of a path"""
+        self.nodeSet.append(point)
+        if len(self.nodeSet) != 1:
+            self.linkSet.append(ltype)
+        if self.computed:
+            self.computeControls()
+
+    def insertNode(self, index, point, ltype=".."):
+        """Insert a node, and its corresponding link, at the given index"""
+        self.nodeSet.insert(index, point)
+        self.linkSet.insert(index, ltype)
+        if self.computed:
+            self.computeControls()
+
+    def setControl(self, index, position):
+        """Set a control point to a new position"""
+        self.controlSet[index] = position
+
+    def popNode(self):
+        if len(self.controlSet) == len(self.nodeSet):
+            self.controlSet.pop()
+        self.nodeSet.pop()
+        self.linkSet.pop()
+
+    def moveControl(self, index, offset):
+        """Translate a control point"""
+        self.controlSet[index] = (self.controlSet[index][0] + offset[0], self.controlSet[index][1] + offset[1])
+
+    def computeControls(self):
+        """Evaluate the code of the path to obtain its control points"""
+        # For now, if no asymptote process is given spawns a new one.
+        # Only happens if asyengine is None.
+        if self.asyengine is not None:
+            assert isinstance(self.asyengine, AsymptoteEngine)
+            assert self.asyengine.active
+            asy = self.asyengine
+            startUp = False
+        else:
+            startUp = True
+            asy = AsymptoteEngine()
+            asy.start()
+
+        fout = asy.ostream
+        fin = asy.istream
+
+        fout.write("path p=" + self.getCode() + ';\n')
+        fout.write("write(_outpipe,length(p),newl);\n")
+        fout.write("write(_outpipe,unstraighten(p),endl);\n")
+        fout.write(asy.xasy)
+        fout.flush()
+
+        lengthStr = fin.readline()
+        pathSegments = eval(lengthStr.split()[-1])
+        pathStrLines = []
+        for i in range(pathSegments + 1):
+            line = fin.readline()
+            line = line.replace("\n", "")
+            pathStrLines.append(line)
+        oneLiner = "".join(pathStrLines).replace(" ", "")
+        splitList = oneLiner.split("..")
+        nodes = [a for a in splitList if a.find("controls") == -1]
+        self.nodeSet = []
+        for a in nodes:
+            if a == 'cycle':
+                self.nodeSet.append(a)
+            else:
+                self.nodeSet.append(eval(a))
+        controls = [a.replace("controls", "").split("and") for a in splitList if a.find("controls") != -1]
+        self.controlSet = [[eval(a[0]), eval(a[1])] for a in controls]
+        self.computed = True
+
+        if startUp:
+            asy.stop()
+
 class asyLabel(asyObj):
-  """A python wrapper for an asy label"""
-  def __init__(self,text="",location=(0,0),pen=asyPen()):
-    """Initialize the label with the given test, location, and pen"""
-    asyObj.__init__(self)
-    self.text = text
-    self.location = location
-    self.pen = pen
+    """A python wrapper for an asy label"""
 
-  def updateCode(self,mag=1.0):
-    """Generate the code describing the label"""
-    self.asyCode = "Label(\""+self.text+"\","+str((self.location[0],self.location[1]))+","+self.pen.getCode()+",align=SE)"
+    def __init__(self, text="", location=(0, 0), pen=None, align=None, fontSize:int=None):
+        """Initialize the label with the given test, location, and pen"""
+        asyObj.__init__(self)
+        self.align = align
+        self.pen = pen
+        self.fontSize = fontSize
+        if align is None:
+            self.align = 'SE'
+        if pen is None:
+            self.pen = asyPen()
+        self.text = text
+        self.location = location
 
-  def setText(self,text):
-    """Set the label's text"""
-    self.text = text
-    self.updateCode()
+    def updateCode(self, asy2psmap=identity()):
+        """Generate the code describing the label"""
+        newLoc = asy2psmap.inverted() * self.location
+        locStr = xu.tuple2StrWOspaces(newLoc)
+        self.asyCode = 'Label("{0}",{1},p={2}{4},align={3})'.format(self.text, locStr, self.pen.getCode(), self.align,
+        self.getFontSizeText())
 
-  def setPen(self,pen):
-    """Set the label's pen"""
-    self.pen = pen
-    self.updateCode()
+    def getFontSizeText(self):
+        if self.fontSize is not None:
+            return '+fontsize({:.6g})'.format(self.fontSize)
+        else:
+            return ''
 
-  def moveTo(self,newl):
-    """Translate the label's location"""
-    self.location = newl
+    def setText(self, text):
+        """Set the label's text"""
+        self.text = text
+        self.updateCode()
 
+    def setPen(self, pen):
+        """Set the label's pen"""
+        self.pen = pen
+        self.updateCode()
+
+    def moveTo(self, newl):
+        """Translate the label's location"""
+        self.location = newl
+
+
 class asyImage:
-  """A structure containing an image and its format, bbox, and IDTag"""
-  def __init__(self,image,format,bbox):
-    self.image = image
-    self.format = format
-    self.bbox = bbox
-    self.IDTag = None
+    """A structure containing an image and its format, bbox, and IDTag"""
+    def __init__(self, image, format, bbox, transfKey=None, keyIndex=0):
+        self.image = image
+        self.format = format
+        self.bbox = bbox
+        self.IDTag = None
+        self.key = transfKey
+        self.keyIndex = keyIndex
 
-class xasyItem:
-  """A base class for items in the xasy GUI"""
-  def __init__(self,canvas=None):
-    """Initialize the item to an empty item"""
-    self.transform = [identity()]
-    self.asyCode = ""
-    self.imageList = []
-    self.IDTag = None
-    self.asyfied = False
-    self.onCanvas = canvas
+class xasyItem(Qc.QObject):
+    """A base class for items in the xasy GUI"""
+    mapString = 'xmap'
+    setKeyFormatStr = string.Template('$map("{:s}",{:s});').substitute(map=mapString)
+    setKeyAloneFormatStr = string.Template('$map("{:s}");').substitute(map=mapString)
+    resizeComment="// Resize to initial xasy transform"
+    asySize=""
+    def __init__(self, canvas=None, asyengine=None):
+        """Initialize the item to an empty item"""
+        super().__init__()
+        self.transfKeymap = {}              # the new keymap.
+        # should be a dictionary to a list...
+        self.asyCode = ''
+        self.imageList = []
+        self.IDTag = None
+        self.asyfied = False
+        self.onCanvas = canvas
+        self.keyBuffer = None
+        self._asyengine = asyengine
+        self.drawObjects = []
+        self.drawObjectsMap = {}
+        self.setKeyed = True
+        self.unsetKeys = set()
+        self.userKeys = set()
+        self.lineOffset = 0
+        self.imageHandleQueue = queue.Queue()
 
-  def updateCode(self,mag=1.0):
-    """Update the item's code: to be overriden"""
-    pass
+    def updateCode(self, ps2asymap=identity()):
+        """Update the item's code: to be overriden"""
+        with io.StringIO() as rawCode:
+            transfCode = self.getTransformCode()
+            objCode = self.getObjectCode()
 
-  def getCode(self):
-    """Return the code describing the item"""
-    self.updateCode()
-    return self.asyCode
+            rawCode.write(transfCode)
+            rawCode.write(objCode)
+            self.asyCode = rawCode.getvalue() 
 
-  def handleImageReception(self,file,format,bbox,count):
-    """Receive an image from an asy deconstruction. It replaces the default in asyProcess."""
-    image = Image.open(file)
-    self.imageList.append(asyImage(image,format,bbox))
-    if self.onCanvas != None:
-      self.imageList[-1].itk = ImageTk.PhotoImage(image)
-      self.imageList[-1].originalImage = image.copy()
-      self.imageList[-1].originalImage.theta = 0.0
-      self.imageList[-1].originalImage.bbox = bbox
-      if count >= len(self.transform) or self.transform[count].deleted == False:
-        self.imageList[-1].IDTag = self.onCanvas.create_image(bbox[0],-bbox[3],anchor=NW,tags=("image"),image=self.imageList[-1].itk)
-      self.onCanvas.update()
+        return len(transfCode.splitlines()), len(objCode.splitlines())
 
-  def asyfy(self,mag=1.0):
-    self.removeFromCanvas()
-    self.imageList = []
-    self.imageHandleQueue = queue.Queue()
-    worker = threading.Thread(target=self.asyfyThread,args=(mag,))
-    worker.start()
-    item = self.imageHandleQueue.get()
-    if console != None:
-      console.delete(1.0,END)
-    while item != (None,) and item[0] != "ERROR":
-      if(item[0] == "OUTPUT"):
-        consoleOutput(item[1])
-      else:
-        self.handleImageReception(*item)
-        try:
-          os.remove(item[0])
-        except:
-          pass
-      item = self.imageHandleQueue.get()
-    #self.imageHandleQueue.task_done()
-    worker.join()
+    @property
+    def asyengine(self):
+        return self._asyengine
 
-  def asyfyThread(self,mag=1.0):
-    """Convert the item to a list of images by deconstructing this item's code"""
-    fout.write("reset;\n")
-    fout.write("initXasyMode();\n")
-    fout.write("atexit(null);\n")
-    for line in self.getCode().splitlines():
-      fout.write(line+"\n");
-    fout.write("deconstruct({:f});\n".format(mag))
-    fout.flush()
-    maxargs = int(fin.readline().split()[0])
-    boxes=[]
-    batch=0
-    n=0
-    text = fin.readline()
-    # template=AsyTempDir+"%d_%d.%s"
-    fileformat = "png"
-    def render():
-        for i in range(len(boxes)):
-          l,b,r,t = [float(a) for a in boxes[i].split()]
-          name="{:s}{:d}_{:d}.{:s}".format(AsyTempDir,batch,i+1,fileformat)
-          self.imageHandleQueue.put((name,fileformat,(l,b,r,t),i))
-    while text != "Done\n" and text != "Error\n":
-      boxes.append(text)
-      text = fin.readline()
-      n += 1
-      if n >= maxargs:
-        render()
-        boxes=[]
-        batch += 1
-        n=0
-    if text == "Error\n":
-      self.imageHandleQueue.put(("ERROR",fin.readline()))
-    else:
-      render()
-    self.imageHandleQueue.put((None,))
-    self.asyfied = True
+    @asyengine.setter
+    def asyengine(self, value):
+        self._asyengine = value
 
-  def drawOnCanvas(self,canvas,mag,forceAddition=False):
-    pass
-  def removeFromCanvas(self):
-    pass
+    def getCode(self, ps2asymap=identity()):
+        """Return the code describing the item"""
+        self.updateCode(ps2asymap)
+        return self.asyCode
 
+    def getTransformCode(self, asy2psmap=identity()):
+        raise NotImplementedError
+
+    def getObjectCode(self, asy2psmap=identity()):
+        raise NotImplementedError
+
+    def generateDrawObjects(self):
+        raise NotImplementedError
+
+    def handleImageReception(self, file, fileformat, bbox, count, key=None, localCount=0, containsClip=False):
+        """Receive an image from an asy deconstruction. It replaces the default n asyProcess."""
+        # image = Image.open(file).transpose(Image.FLIP_TOP_BOTTOM)
+        if fileformat == 'png':
+            image = Qg.QImage(file)
+        elif fileformat == 'svg':
+            if containsClip:
+                image = xs.SvgObject(file)
+            else:
+                image = Qs.QSvgRenderer(file)
+                assert image.isValid()
+        else:
+            raise Exception('Format not supported!')
+        self.imageList.append(asyImage(image, fileformat, bbox, transfKey=key, keyIndex=localCount))
+        if self.onCanvas is not None:
+            # self.imageList[-1].iqt = ImageTk.PhotoImage(image)
+            currImage = self.imageList[-1]
+            currImage.iqt = image
+            currImage.originalImage = image
+            currImage.originalImage.theta = 0.0
+            currImage.originalImage.bbox = list(bbox)
+            currImage.performCanvasTransform = False
+
+            # handle this case if transform is not in the map yet.
+            # if deleted - set transform to 0, 0, 0, 0, 0
+            transfExists = key in self.transfKeymap.keys()
+            if transfExists:
+                transfExists = localCount <= len(self.transfKeymap[key]) - 1
+                if transfExists:
+                    validKey = not self.transfKeymap[key][localCount].deleted
+            else:
+                validKey = False
+
+            if (not transfExists) or validKey:
+                currImage.IDTag = str(file)
+                newDrawObj = DrawObject(currImage.iqt, self.onCanvas['canvas'], transform=identity(),
+                                        btmRightanchor=Qc.QPointF(bbox[0], bbox[2]), drawOrder=-1, key=key,
+                                        parentObj=self, keyIndex=localCount)
+                newDrawObj.setBoundingBoxPs(bbox)
+                newDrawObj.setParent(self)
+
+                self.drawObjects.append(newDrawObj)
+
+                if key not in self.drawObjectsMap.keys():
+                    self.drawObjectsMap[key] = [newDrawObj]
+                else:
+                    self.drawObjectsMap[key].append(newDrawObj)
+        return containsClip
+    def asyfy(self, force=False):
+        if self.asyengine is None:
+            return 1
+        if self.asyfied and not force:
+            return
+
+        self.drawObjects = []
+        self.drawObjectsMap.clear()
+        assert isinstance(self.asyengine, AsymptoteEngine)
+        self.imageList = []
+
+        self.unsetKeys.clear()
+        self.userKeys.clear()
+
+        self.imageHandleQueue = queue.Queue()
+        worker = threading.Thread(target=self.asyfyThread, args=[])
+        worker.start()
+        item = self.imageHandleQueue.get()
+        while item != (None,) and item[0] != "ERROR":
+            if item[0] == "OUTPUT":
+                print(item[1])
+            else:
+                keepFile = self.handleImageReception(*item)
+                if not DebugFlags.keepFiles and not keepFile:
+                    try:
+                        os.remove(item[0])
+                        pass
+                    except OSError:
+                        pass
+                    finally:
+                        pass
+            item = self.imageHandleQueue.get()
+        # self.imageHandleQueue.task_done()
+        worker.join()
+
+    def asyfyThread(self):
+        """Convert the item to a list of images by deconstructing this item's code"""
+        assert self.asyengine.active
+
+        fout = self.asyengine.ostream
+        fin = self.asyengine.istream
+
+        self.lineOffset = len(self.getTransformCode().splitlines())
+
+        fout.write("reset\n")
+        fout.flush();
+        for line in self.getCode().splitlines():
+            if DebugFlags.printDeconstTranscript:
+                print('fout:', line)
+            fout.write(line+"\n")
+        fout.write(self.asySize)
+        fout.write("deconstruct();\n")
+        fout.write('write(_outpipe,yscale(-1)*currentpicture.calculateTransform(),endl);\n')
+        fout.write(self.asyengine.xasy)
+        fout.flush()
+
+        imageInfos = []                                 # of (box, key)
+        n = 0
+
+        keyCounts = {}
+
+        def render():
+            for i in range(len(imageInfos)):
+                box, key, localCount, useClip = imageInfos[i]
+                l, b, r, t = [float(a) for a in box.split()]
+                name = "{:s}_{:d}.{:s}".format(self.asyengine.tempDirName, i, fileformat)
+
+                self.imageHandleQueue.put((name, fileformat, (l, -t, r, -b), i, key, localCount, useClip))
+
+        # key first, box second.
+        # if key is "Done"
+        raw_text = fin.readline()
+        text = ""
+        if DebugFlags.printDeconstTranscript:
+            print(raw_text.strip())
+
+        # template=AsyTempDir+"%d_%d.%s"
+        fileformat = 'svg'
+
+        while raw_text != "Done\n" and raw_text != "Error\n":
+#            print(raw_text)
+            text = fin.readline()       # the actual bounding box.
+            # print('TESTING:', text)
+            keydata = raw_text.strip().replace('KEY=', '', 1)  # key
+
+            clipflag = keydata[-1] == '1'
+            userkey = keydata[-2] == '1'
+            keydata = keydata[:-3]
+
+            if not userkey:
+                self.unsetKeys.add(keydata)     # the line and column to replace. 
+            else:
+                self.userKeys.add(keydata)
+            
+#                print(line, col)
+
+            if keydata not in keyCounts.keys():
+                keyCounts[keydata] = 0
+
+            imageInfos.append((text, keydata, keyCounts[keydata], clipflag))      # key-data pair
+
+            # for the next item
+            keyCounts[keydata] += 1
+
+            raw_text = fin.readline()
+
+            if DebugFlags.printDeconstTranscript:
+                print(text.rstrip())
+                print(raw_text.rstrip())
+
+            n += 1
+
+        if text == "Error\n":
+            self.imageHandleQueue.put(("ERROR", fin.readline()))
+        else:
+            render()
+
+        self.asy2psmap = asyTransform(xu.listize(fin.readline().rstrip(),float))
+        self.imageHandleQueue.put((None,))
+        self.asyfied = True
+
 class xasyDrawnItem(xasyItem):
-  """A base class for GUI items was drawn by the user. It combines a path, a pen, and a transform."""
-  def __init__(self,path,pen = asyPen(),transform = identity()):
-    """Initialize the item with a path, pen, and transform"""
-    xasyItem.__init__(self)
-    self.path = path
-    self.pen = pen
-    self.transform = [transform]
+    """A base class for GUI items was drawn by the user. It combines a path, a pen, and a transform."""
 
-  def appendPoint(self,point,link=None):
-    """Append a point to the path. If the path is cyclic, add this point before the 'cycle' node."""
-    if self.path.nodeSet[-1] == 'cycle':
-      self.path.nodeSet[-1] = point
-      self.path.nodeSet.append('cycle')
-    else:
-      self.path.nodeSet.append(point)
-    self.path.computed = False
-    if len(self.path.nodeSet) > 1 and link != None:
-      self.path.linkSet.append(link)
+    def __init__(self, path, engine, pen=None, transform=identity(), key=None):
+        """Initialize the item with a path, pen, and transform"""
+        super().__init__(canvas=None, asyengine=engine)
+        if pen is None:
+            pen = asyPen()
+        self.path = path
+        self.path.asyengine = engine
+        self.asyfied = True
+        self.pen = pen
+        self._asyengine = engine
+        self.rawIdentifier = ''
+        self.transfKey = key
+        self.transfKeymap = {self.transfKey: [transform]}
 
-  def clearTransform(self):
-    """Reset the item's transform"""
-    self.transform = [identity()]
+    @property
+    def asyengine(self):
+        return self._asyengine
 
-  def removeLastPoint(self):
-    """Remove the last point in the path. If the path is cyclic, remove the node before the 'cycle' node."""
-    if self.path.nodeSet[-1] == 'cycle':
-      del self.path.nodeSet[-2]
-    else:
-      del self.path.nodeSet[-1]
-    del self.path.linkSet[-1]
-    self.path.computed = False
+    @asyengine.setter
+    def asyengine(self, value: AsymptoteEngine):
+        self._asyengine = value
+        self.path.asyengine = value
 
-  def setLastPoint(self,point):
-    """Modify the last point in the path. If the path is cyclic, modify the node before the 'cycle' node."""
-    if self.path.nodeSet[-1] == 'cycle':
-      self.path.nodeSet[-2] = point
-    else:
-      self.path.nodeSet[-1] = point
-    self.path.computed = False
+    def setKey(self, newKey=None):
+        transform = self.transfKeymap[self.transfKey][0]
 
-class xasyShape(xasyDrawnItem):
-  """An outlined shape drawn on the GUI"""
-  def __init__(self,path,pen=asyPen(),transform=identity()):
-    """Initialize the shape with a path, pen, and transform"""
-    xasyDrawnItem.__init__(self,path,pen,transform)
+        self.transfKey = newKey
+        self.transfKeymap = {self.transfKey: [transform]}
 
-  def updateCode(self,mag=1.0):
-    """Generate the code to describe this shape"""
-    self.asyCode = "xformStack.push("+self.transform[0].getCode()+");\n"
-    self.asyCode += "draw("+self.path.getCode()+","+self.pen.getCode()+");"
+    def generateDrawObjects(self, forceUpdate=False):
+        raise NotImplementedError
 
-  def removeFromCanvas(self,canvas):
-    """Remove the shape's depiction from a tk canvas"""
-    if self.IDTag != None:
-      canvas.delete(self.IDTag)
+    def appendPoint(self, point, link=None):
+        """Append a point to the path. If the path is cyclic, add this point before the 'cycle' node."""
+        if self.path.nodeSet[-1] == 'cycle':
+            self.path.nodeSet[-1] = point
+            self.path.nodeSet.append('cycle')
+        else:
+            self.path.nodeSet.append(point)
+        self.path.computed = False
+        self.asyfied = False
+        if len(self.path.nodeSet) > 1 and link is not None:
+            self.path.linkSet.append(link)
 
-  def drawOnCanvas(self,canvas,mag,asyFy=False,forceAddition=False):
-    """Add this shape to a tk canvas"""
-    if not asyFy:
-      if self.IDTag == None or forceAddition:
-        #add ourselves to the canvas
-        self.path.computeControls()
-        self.IDTag = canvas.create_line(0,0,0,0,tags=("drawn","xasyShape"),fill=self.pen.tkColor(),width=self.pen.width*mag)
-        self.drawOnCanvas(canvas,mag)
-      else:
-        self.path.computeControls()
-        pointSet = []
-        previousNode = self.path.nodeSet[0]
-        nodeCount = 0
-        if len(self.path.nodeSet) == 0:
-          pointSet = [0,0,0,0]
-        elif len(self.path.nodeSet) == 1:
-          if self.path.nodeSet[-1] != 'cycle':
-            p = self.transform[0]*(self.path.nodeSet[0][0],self.path.nodeSet[0][1])
-            pointSet = [p[0],-p[1],p[0],-p[1],p[0],-p[1]]
-          else:
-            pointSet = [0,0,0,0]
+    def clearTransform(self):
+        """Reset the item's transform"""
+        self.transform = [identity()]
+        self.asyfied = False
+
+    def removeLastPoint(self):
+        """Remove the last point in the path. If the path is cyclic, remove the node before the 'cycle' node."""
+        if self.path.nodeSet[-1] == 'cycle':
+            del self.path.nodeSet[-2]
         else:
-          for node in self.path.nodeSet[1:]:
-            if node == 'cycle':
-              node = self.path.nodeSet[0]
-            transform = self.transform[0].scale(mag)
-            points = CubicBezier.makeBezier(transform*previousNode,transform*self.path.controlSet[nodeCount][0],transform*self.path.controlSet[nodeCount][1],transform*node)
-            for point in points:
-              pointSet += [point[0],-point[1]]
-            nodeCount += 1
-            previousNode = node
-        canvas.coords(self.IDTag,*pointSet)
-        canvas.itemconfigure(self.IDTag,fill=self.pen.tkColor(),width=self.pen.width*mag)
-    else:
-      #first asyfy then add an image list
-      pass
+            del self.path.nodeSet[-1]
+        del self.path.linkSet[-1]
+        self.path.computed = False
+        self.asyfied = False
 
-  def __str__(self):
-    """Create a string describing this shape"""
-    return "xasyShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+    def setLastPoint(self, point):
+        """Modify the last point in the path. If the path is cyclic, modify the node before the 'cycle' node."""
+        if self.path.nodeSet[-1] == 'cycle':
+            self.path.nodeSet[-2] = point
+        else:
+            self.path.nodeSet[-1] = point
+        self.path.computed = False
+        self.asyfied = False
 
-class xasyFilledShape(xasyShape):
-  """A filled shape drawn on the GUI"""
-  def __init__(self,path,pen=asyPen(),transform=identity()):
-    """Initialize this shape with a path, pen, and transform"""
-    if path.nodeSet[-1] != 'cycle':
-      raise Exception("Filled paths must be cyclic")
-    xasyShape.__init__(self,path,pen,transform)
 
-  def updateCode(self,mag=1.0):
-    """Generate the code describing this shape"""
-    self.asyCode = "xformStack.push("+self.transform[0].getCode()+");\n"
-    self.asyCode += "fill("+self.path.getCode()+","+self.pen.getCode()+");"
+class xasyShape(xasyDrawnItem):
+    """An outlined shape drawn on the GUI"""
+    def __init__(self, path, asyengine, pen=None, transform=identity()):
+        """Initialize the shape with a path, pen, and transform"""
+        super().__init__(path=path, engine=asyengine, pen=pen, transform=transform)
 
-  def removeFromCanvas(self,canvas):
-    """Remove this shape's depiction from a tk canvas"""
-    if self.IDTag != None:
-      canvas.delete(self.IDTag)
+    def getObjectCode(self, asy2psmap=identity()):
+        return 'draw(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n'
 
-  def drawOnCanvas(self,canvas,mag,asyFy=False,forceAddition=False):
-    """Add this shape to a tk canvas"""
-    if not asyFy:
-      if self.IDTag == None or forceAddition:
-        #add ourselves to the canvas
-        self.path.computeControls()
-        self.IDTag = canvas.create_polygon(0,0,0,0,0,0,tags=("drawn","xasyFilledShape"),fill=self.pen.tkColor(),outline=self.pen.tkColor(),width=1*mag)
-        self.drawOnCanvas(canvas,mag)
-      else:
-        self.path.computeControls()
-        pointSet = []
-        previousNode = self.path.nodeSet[0]
-        nodeCount = 0
-        if len(self.path.nodeSet) == 0:
-          pointSet = [0,0,0,0,0,0]
-        elif len(self.path.nodeSet) == 1:
-          if self.path.nodeSet[-1] != 'cycle':
-            p = self.transform[0]*(self.path.nodeSet[0][0],self.path.nodeSet[0][1])
-            pointSet = [p[0],-p[1],p[0],-p[1],p[0],-p[1]]
-          else:
-            pointSet = [0,0,0,0,0,0]
-        elif len(self.path.nodeSet) == 2:
-          if self.path.nodeSet[-1] != 'cycle':
-            p = self.transform[0].scale(mag)*(self.path.nodeSet[0][0],self.path.nodeSet[0][1])
-            p2 = self.transform[0].scale(mag)*(self.path.nodeSet[1][0],self.path.nodeSet[1][1])
-            pointSet = [p[0],-p[1],p2[0],-p2[1],p[0],-p[1]]
-          else:
-            pointSet = [0,0,0,0,0,0]
+    def getTransformCode(self, asy2psmap=identity()):
+        transf = self.transfKeymap[self.transfKey][0]
+        if transf == identity():
+            return ''
         else:
-          for node in self.path.nodeSet[1:]:
-            if node == 'cycle':
-              node = self.path.nodeSet[0]
-            transform = self.transform[0].scale(mag)
-            points = CubicBezier.makeBezier(transform*previousNode,transform*self.path.controlSet[nodeCount][0],transform*self.path.controlSet[nodeCount][1],transform*node)
-            for point in points:
-              pointSet += [point[0],-point[1]]
-            nodeCount += 1
-            previousNode = node
-        canvas.coords(self.IDTag,*pointSet)
-        canvas.itemconfigure(self.IDTag,fill=self.pen.tkColor(),outline=self.pen.tkColor(),width=1*mag)
-    else:
-      #first asyfy then add an image list
-      pass
+            return xasyItem.setKeyFormatStr.format(self.transfKey, transf.getCode(asy2psmap))+'\n'
 
-  def __str__(self):
-    """Return a string describing this shape"""
-    return "xasyFilledShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+    def generateDrawObjects(self, forceUpdate=False):
+        if self.path.containsCurve:
+            self.path.computeControls()
+        transf = self.transfKeymap[self.transfKey][0]
 
+        newObj = DrawObject(self.path.toQPainterPath(), None, drawOrder=0, transform=transf, pen=self.pen,
+                            key=self.transfKey)
+        newObj.originalObj = self
+        newObj.setParent(self)
+        return [newObj]
+
+    def __str__(self):
+        """Create a string describing this shape"""
+        return "xasyShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+
+
+class xasyFilledShape(xasyShape):
+    """A filled shape drawn on the GUI"""
+
+    def __init__(self, path, asyengine, pen=None, transform=identity()):
+        """Initialize this shape with a path, pen, and transform"""
+        if path.nodeSet[-1] != 'cycle':
+            raise Exception("Filled paths must be cyclic")
+        super().__init__(path, asyengine, pen, transform)
+
+    def getObjectCode(self, asy2psmap=identity()):
+        return 'fill(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n'
+
+    def generateDrawObjects(self, forceUpdate=False):
+        if self.path.containsCurve:
+            self.path.computeControls()
+        newObj = DrawObject(self.path.toQPainterPath(), None, drawOrder=0, transform=self.transfKeymap[self.transfKey][0],
+                            pen=self.pen, key=self.transfKey, fill=True)
+        newObj.originalObj = self
+        newObj.setParent(self)
+        return [newObj]
+
+    def __str__(self):
+        """Return a string describing this shape"""
+        return "xasyFilledShape code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+
+
 class xasyText(xasyItem):
-  """Text created by the GUI"""
-  def __init__(self,text,location,pen=asyPen(),transform=identity()):
-    """Initialize this item with text, a location, pen, and transform"""
-    xasyItem.__init__(self)
-    self.label=asyLabel(text,location,pen)
-    self.transform = [transform]
-    self.onCanvas = None
+    """Text created by the GUI"""
 
-  def updateCode(self,mag=1.0):
-    """Generate the code describing this object"""
-    self.asyCode = "xformStack.push("+self.transform[0].getCode()+");\n"
-    self.asyCode += "label("+self.label.getCode()+");"
+    def __init__(self, text, location, asyengine, pen=None, transform=yflip(), key=None, align=None, fontsize:int=None):
+        """Initialize this item with text, a location, pen, and transform"""
+        super().__init__(asyengine=asyengine)
+        if pen is None:
+            pen = asyPen(asyengine=asyengine)
+        if pen.asyEngine is None:
+            pen.asyEngine = asyengine
+        self.label = asyLabel(text, location, pen, align, fontSize=fontsize)
+        # self.transform = [transform]
+        self.transfKey = key
+        self.transfKeymap = {self.transfKey: [transform]}
+        self.asyfied = False
+        self.onCanvas = None
+    
+    def setKey(self, newKey=None):
+        transform = self.transfKeymap[self.transfKey][0]
 
-  def removeFromCanvas(self):
-    """Removes the label's images from a tk canvas"""
-    if self.onCanvas == None:
-      return
-    for image in self.imageList:
-      if image.IDTag != None:
-        self.onCanvas.delete(image.IDTag)
+        self.transfKey = newKey
+        self.transfKeymap = {self.transfKey: [transform]}
 
-  def drawOnCanvas(self,canvas,mag,asyFy=True,forceAddition=False):
-    """Adds the label's images to a tk canvas"""
-    if self.onCanvas == None:
-      self.onCanvas = canvas
-    elif self.onCanvas != canvas:
-      raise Exception("Error: item cannot be added to more than one canvas")
-    self.asyfy(mag)
+    def getTransformCode(self, asy2psmap=yflip()):
+        transf = self.transfKeymap[self.transfKey][0]
+        if transf == yflip():
+            # return xasyItem.setKeyAloneFormatStr.format(self.transfKey)
+            return ''
+        else:
+            return xasyItem.setKeyFormatStr.format(self.transfKey, transf.getCode(asy2psmap))+"\n"
 
-  def __str__(self):
-    return "xasyText code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+    def getObjectCode(self, asy2psmap=yflip()):
+        return 'label(KEY="{0}",{1});'.format(self.transfKey, self.label.getCode(asy2psmap))+'\n'
 
+    def generateDrawObjects(self, forceUpdate=False):
+        self.asyfy(forceUpdate)
+        return self.drawObjects
+
+    def getBoundingBox(self):
+        self.asyfy()
+        return self.imageList[0].bbox
+
+    def __str__(self):
+        return "xasyText code:{:s}".format("\n\t".join(self.getCode().splitlines()))
+
+
 class xasyScript(xasyItem):
-  """A set of images create from asymptote code. It is always deconstructed."""
-  def __init__(self,canvas,script="",transforms=[]):
-    """Initialize this script item"""
-    xasyItem.__init__(self,canvas)
-    self.transform = transforms[:]
-    self.script = script
+    """A set of images create from asymptote code. It is always deconstructed."""
 
-  def clearTransform(self):
-    """Reset the transforms for each of the deconstructed images""" 
-    self.transform = [identity() for im in self.imageList]
+    def __init__(self, canvas, engine, script="", transforms=None, transfKeyMap=None):
+        """Initialize this script item"""
+        super().__init__(canvas, asyengine=engine)
+        if transfKeyMap is not None:
+            self.transfKeymap = transfKeyMap
+        else:
+            self.transfKeymap = {}
 
-  def updateCode(self,mag=1.0):
-    """Generate the code describing this script"""
-    self.asyCode = "";
-    if len(self.transform) > 0:
-      self.asyCode = "xformStack.add("
-      isFirst = True
-      count = 0
-      for xform in self.transform:
-        if not isFirst:
-          self.asyCode+=",\n"
-        self.asyCode += "indexedTransform({:d},{:s})".format(count,str(xform))
-        isFirst = False
-        count += 1
-      self.asyCode += ");\n"
-    self.asyCode += "startScript(); {\n"
-    self.asyCode += self.script.replace("\t"," ")
-    self.asyCode = self.asyCode.rstrip()
-    self.asyCode += "\n} endScript();\n"
+        self.script = script
+        self.key2imagemap = {}
+        self.namedUnsetKeys = {}
+        self.keyPrefix = ''
+        self.scriptAsyfied = False
+        self.updatedPrefix = True
 
-  def setScript(self,script):
-    """Sets the content of the script item."""
-    self.script = script
-    self.updateCode()
+    def clearTransform(self):
+        """Reset the transforms for each of the deconstructed images"""
+        # self.transform = [identity()] * len(self.imageList)
+        keyCount = {}
 
-  def removeFromCanvas(self):
-    """Removes the script's images from a tk canvas"""
-    if self.onCanvas == None:
-      return
-    for image in self.imageList:
-      if image.IDTag != None:
-        self.onCanvas.delete(image.IDTag)
+        for im in self.imageList:
+            if im.key not in keyCount.keys():
+                keyCount[im.key] = 1
+            else:
+                keyCount[im.key] += 1
 
-  def asyfy(self,mag):
-    """Generate the list of images described by this object and adjust the length of the transform list."""
-    xasyItem.asyfy(self,mag)
-    while len(self.imageList) > len(self.transform):
-      self.transform.append(identity())
-    while len(self.imageList) < len(self.transform):
-      self.transform.pop()
-    self.updateCode()
+        for key in keyCount:
+            self.transfKeymap[key] = [identity()] * keyCount[key]
 
-  def drawOnCanvas(self,canvas,mag,asyFy=True,forceAddition=False):
-    """Adds the script's images to a tk canvas"""
-    if self.onCanvas == None:
-      self.onCanvas = canvas
-    elif self.onCanvas != canvas:
-      raise Exception("Error: item cannot be added to more than one canvas")
-    self.asyfy(mag)
+    def getMaxKeyCounter(self):
+        maxCounter = -1
+        for key in self.transfKeymap:
+            testNum = re.match(r'^x(\d+)$', key)
+            if testNum is not None:
+                maxCounter = max(maxCounter, int(testNum.group(1)))
+        return maxCounter + 1
 
-  def __str__(self):
-    """Return a string describing this script"""
-    retVal = "xasyScript\n\tTransforms:\n"
-    for xform in self.transform:
-      retVal += "\t"+str(xform)+"\n"
-    retVal += "\tCode Ommitted"
-    return retVal
+    def getTransformCode(self, asy2psmap=identity()):
+        with io.StringIO() as rawAsyCode:
+            if self.transfKeymap:
+                for key in self.transfKeymap.keys():
+                    val = self.transfKeymap[key]
 
-if __name__=='__main__':
-  root = Tk()
-  t=xasyText("test",(0,0))
-  t.asyfy()
+                    writeval = list(reversed(val))
+                    # need to map all transforms in a list if there is any non-identity
+                    # unfortunately, have to check all transformations in the list. 
+                    while not all(checktransf == identity() for checktransf in writeval) and writeval:
+                        transf = writeval.pop()
+                        if transf.deleted:
+                            rawAsyCode.write(xasyItem.setKeyFormatStr.format(key, transf.getCode(asy2psmap)) + '\n//')
+                        if transf == identity() and not transf.deleted:
+                            rawAsyCode.write(xasyItem.setKeyAloneFormatStr.format(key))
+                        else:
+                            rawAsyCode.write(xasyItem.setKeyFormatStr.format(key, transf.getCode(asy2psmap)))
+                        rawAsyCode.write('\n')
+            result = rawAsyCode.getvalue()
+        return result
+
+    def findNonIdKeys(self):
+        return {key for key in self.transfKeymap if not all(transf == identity() for transf in self.transfKeymap[key]) }
+
+    def getObjectCode(self, asy2psmap=identity()):
+        numeric=r'([-+]?(?:(?:\d*\.\d+)|(?:\d+\.?)))'
+        rSize=re.compile("size\(\("+numeric+","+numeric+","+numeric+","
+                         +numeric+","+numeric+","+numeric+"\)\); "+
+                         self.resizeComment)
+
+        newScript = self.getReplacedKeysCode(self.findNonIdKeys())
+        with io.StringIO() as rawAsyCode:
+            for line in newScript.splitlines():
+                if(rSize.match(line)):
+                    self.asySize=line.rstrip()+'\n'
+                else:
+                    raw_line = line.rstrip().replace('\t', ' ' * 4)
+                    rawAsyCode.write(raw_line + '\n')
+
+            self.updatedCode = rawAsyCode.getvalue()
+            return self.updatedCode
+
+    def setScript(self, script):
+        """Sets the content of the script item."""
+        self.script = script
+        self.updateCode()
+
+    def setKeyPrefix(self, newPrefix=''):
+        self.keyPrefix = newPrefix
+        self.updatedPrefix = False
+
+    def getReplacedKeysCode(self, key2replace: set=None) -> str:
+        keylist = {}
+        prefix = ''
+        
+        key2replaceSet = self.unsetKeys if key2replace is None else \
+                        self.unsetKeys & key2replace
+
+        linenum2key = {}
+
+        if not self.updatedPrefix:
+            prefix = self.keyPrefix
+
+        for key in key2replaceSet:
+            actualkey = key
+
+            key = key.split(':')[0]
+            raw_parsed = xu.tryParseKey(key)
+            assert raw_parsed is not None
+            line, col = [int(val) for val in raw_parsed.groups()]
+            if line not in keylist:
+                keylist[line] = set()
+            keylist[line].add(col)
+            linenum2key[(line, col)] = actualkey
+            self.unsetKeys.discard(key)
+
+
+        raw_code_lines = self.script.splitlines()
+        with io.StringIO() as raw_str:
+            for i_0 in range(len(raw_code_lines)):
+                i = i_0 + self.lineOffset
+                curr_str = raw_code_lines[i_0]
+                if i + 1 in keylist.keys():
+                    # this case, we have a key.
+                    with io.StringIO() as raw_line:
+                        for j in range(len(curr_str)):
+                            raw_line.write(curr_str[j])
+                            if j + 1 in keylist[i + 1]:
+                                # at this point, replace keys with xkey
+                                raw_line.write('KEY="{0:s}",'.format(linenum2key[(i + 1, j + 1)]))
+                                self.userKeys.add(linenum2key[(i + 1, j + 1)])
+                        curr_str = raw_line.getvalue()
+                # else, skip and just write the line.
+                raw_str.write(curr_str + '\n')
+            return raw_str.getvalue()
+
+    def getUnusedKey(self, oldkey) -> str:
+        baseCounter = 0
+        newKey = oldkey
+        while newKey in self.userKeys:
+            newKey = oldkey + ':' + str(baseCounter)
+            baseCounter += 1
+        return newKey
+
+    def asyfy(self, keyOnly=False):
+        """Generate the list of images described by this object and adjust the length of the transform list."""
+        super().asyfy()
+
+        # Id --> Transf --> asy-fied --> Transf
+        # Transf should keep the original, raw transformation
+        # but for all new drawn objects - assign Id as transform.
+
+        if self.scriptAsyfied:
+            return
+
+        keyCount = {}
+        settedKey = {}
+
+        for im in self.imageList:
+            if im.key in self.unsetKeys and im.key not in settedKey.keys():
+                oldkey = im.key
+                self.unsetKeys.remove(im.key)
+                im.key = self.getUnusedKey(im.key)
+                self.unsetKeys.add(im.key)
+
+                for drawobj in self.drawObjectsMap[oldkey]:
+                    drawobj.key = im.key
+
+                self.drawObjectsMap[im.key] = self.drawObjectsMap[oldkey]
+                self.drawObjectsMap.pop(oldkey)
+
+                settedKey[oldkey] = im.key
+            elif im.key in settedKey.keys():
+                im.key = settedKey[im.key]
+
+            if im.key not in keyCount.keys():
+                keyCount[im.key] = 1
+            else:
+                keyCount[im.key] += 1
+
+            if im.key not in self.key2imagemap.keys():
+                self.key2imagemap[im.key] = [im]
+            else:
+                self.key2imagemap[im.key].append(im)
+
+            
+
+        for key in keyCount:
+            if key not in self.transfKeymap.keys():
+                self.transfKeymap[key] = [identity()] * keyCount[key]
+            else:
+                while len(self.transfKeymap[key]) < keyCount[key]:
+                    self.transfKeymap[key].append(identity())
+
+                # while len(self.transfKeymap[key]) > keyCount[key]:
+                    # self.transfKeymap[key].pop()
+
+        # change of basis 
+        for keylist in self.transfKeymap.values():
+            for i in range(len(keylist)):
+                if keylist[i] != identity():
+                    keylist[i] = self.asy2psmap * keylist[i] * self.asy2psmap.inverted()
+
+        self.updateCode()
+        self.scriptAsyfied = True
+
+    def generateDrawObjects(self, forceUpdate=False):
+        self.asyfy(forceUpdate)
+        return self.drawObjects
+
+    def __str__(self):
+        """Return a string describing this script"""
+        retVal = "xasyScript\n\tTransforms:\n"
+        for xform in self.transform:
+            retVal += "\t" + str(xform) + "\n"
+        retVal += "\tCode Ommitted"
+        return retVal
+
+
+class DrawObject(Qc.QObject):
+    def __init__(self, drawObject, mainCanvas=None, transform=identity(), btmRightanchor=Qc.QPointF(0, 0),
+                 drawOrder=(-1, -1), pen=None, key=None, parentObj=None, fill=False, keyIndex=0):
+        super().__init__()
+        self.drawObject = drawObject
+        self.mainCanvas = mainCanvas
+        self.pTransform = transform
+        self.baseTransform = transform
+        self.drawOrder = drawOrder
+        self.btmRightAnchor = btmRightanchor
+        self.originalObj = parentObj
+        self.explicitBoundingBox = None
+        self.useCanvasTransformation = False
+        self.key = key
+        self.cachedSvgImg = None
+        self.cachedDPI = None
+        self.maxDPI=0
+        self.keyIndex = keyIndex
+        self.pen = pen
+        self.fill = fill
+
+    def getInteriorScrTransform(self, transform):
+        """Generates the transform with Interior transform applied beforehand."""
+        if isinstance(transform, Qg.QTransform):
+            transform = asyTransform.fromQTransform(transform)
+        return self.transform * transform * self.baseTransform.inverted()
+
+    @property
+    def transform(self):
+        return self.pTransform
+
+    @transform.setter
+    def transform(self, value):
+        self.pTransform = value
+
+    def setBoundingBoxPs(self, bbox):
+        l, b, r, t = bbox
+        self.explicitBoundingBox = Qc.QRectF(Qc.QPointF(l, b), Qc.QPointF(r, t))
+        # self.explicitBoundingBox = Qc.QRectF(0, 0, 100, 100)
+
+    @property
+    def boundingBox(self):
+        if self.explicitBoundingBox is not None:
+            testBbox = self.explicitBoundingBox
+        else:
+            if isinstance(self.drawObject, Qg.QImage):
+                testBbox = self.drawObject.rect()
+                testBbox.moveTo(self.btmRightAnchor.toPoint())
+            elif isinstance(self.drawObject, Qg.QPainterPath):
+                testBbox = self.baseTransform.toQTransform().mapRect(self.drawObject.boundingRect())
+            else:
+                raise TypeError('drawObject is not a valid type!')
+        pointList = [self.getScreenTransform().toQTransform().map(point) for point in [
+            testBbox.topLeft(), testBbox.topRight(), testBbox.bottomLeft(), testBbox.bottomRight()
+        ]]
+        return Qg.QPolygonF(pointList).boundingRect()
+
+    @property
+    def localBoundingBox(self):
+        testBbox = self.drawObject.rect()
+        testBbox.moveTo(self.btmRightAnchor.toPoint())
+        return testBbox
+
+    def getScreenTransform(self):
+        scrTransf = self.baseTransform.toQTransform().inverted()[0] * self.pTransform.toQTransform()
+        return asyTransform.fromQTransform(scrTransf)
+
+    def draw(self, additionalTransformation=None, applyReverse=False, canvas: Qg.QPainter=None, dpi=300):
+        if canvas is None:
+            canvas = self.mainCanvas
+        if additionalTransformation is None:
+            additionalTransformation = Qg.QTransform()
+            
+        assert canvas.isActive()
+
+        canvas.save()
+        if self.pen:
+            oldPen = Qg.QPen(canvas.pen())
+            canvas.setPen(self.pen.toQPen())
+        else:
+            oldPen = Qg.QPen()
+
+        if not applyReverse:
+            canvas.setTransform(additionalTransformation, True)
+            canvas.setTransform(self.transform.toQTransform(), True)
+        else:
+            canvas.setTransform(self.transform.toQTransform(), True)
+            canvas.setTransform(additionalTransformation, True)
+
+        canvas.setTransform(self.baseTransform.toQTransform().inverted()[0], True)
+
+        if isinstance(self.drawObject, Qg.QImage):
+            canvas.drawImage(self.explicitBoundingBox, self.drawObject)
+        elif isinstance(self.drawObject, xs.SvgObject):
+            threshold = 1.44
+            
+            if self.cachedDPI is None or self.cachedSvgImg is None \
+               or dpi > self.maxDPI*threshold:
+                self.cachedDPI = dpi
+                self.maxDPI=max(self.maxDPI,dpi)
+                self.cachedSvgImg = self.drawObject.render(dpi)
+
+            canvas.drawImage(self.explicitBoundingBox, self.cachedSvgImg)
+        elif isinstance(self.drawObject, Qs.QSvgRenderer):
+            self.drawObject.render(canvas, self.explicitBoundingBox)
+        elif isinstance(self.drawObject, Qg.QPainterPath):
+            path = self.baseTransform.toQTransform().map(self.drawObject)
+            if self.fill:
+                if self.pen:
+                    brush = self.pen.toQPen().brush()
+                else:
+                    brush = Qg.QBrush()
+                canvas.fillPath(path, brush)
+            else:
+                canvas.drawPath(path)
+
+        if self.pen:
+            canvas.setPen(oldPen)
+        canvas.restore()
+
+    def collide(self, coords, canvasCoordinates=True):
+        # modify these values to grow/shrink the fuzz. 
+        fuzzTolerance = 1
+        marginGrowth = 1
+        leftMargin = marginGrowth if self.boundingBox.width() < fuzzTolerance else 0
+        topMargin = marginGrowth if self.boundingBox.height() < fuzzTolerance else 0
+
+        newMargin = Qc.QMarginsF(leftMargin, topMargin, leftMargin, topMargin)
+        return self.boundingBox.marginsAdded(newMargin).contains(coords)
+
+    def getID(self):
+        return self.originalObj

Deleted: trunk/Master/texmf-dist/asymptote/GUI/xasyActions.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyActions.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyActions.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,391 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyActions implements the possible actions and their inverses
-# for the undo/redo stack in xasy
-#
-# Author: Orest Shardt
-# Created: July 23, 2007
-#
-###########################################################################
-import math
-import sys
-import UndoRedoStack
-import xasy2asy
-if sys.version_info >= (3, 0):
-  from tkinter import *
-else:
-  from Tkinter import *
-
-class translationAction(UndoRedoStack.action):
-  def __init__(self,owner,itemList,indexList,translation):
-    self.translation = translation
-    self.owner = owner
-    self.itemList = itemList
-    self.indexList = indexList
-    UndoRedoStack.action.__init__(self,self.transF,self.unTransF)
-
-  def transF(self):
-    mag = self.owner.magnification
-    for i in range(len(self.itemList)):
-      for index in self.indexList[i]:
-        self.owner.translateSomething(-1,(self.translation[0]/mag,self.translation[1]/mag),self.itemList[i],index)
-        if index==None:
-          index = 0
-        try:
-          self.owner.mainCanvas.move(self.itemList[i].imageList[index].IDTag,self.translation[0]*mag,-self.translation[1]*mag)
-        except:
-          self.owner.mainCanvas.move(self.itemList[i].IDTag,self.translation[0]*mag,-self.translation[1]*mag)
-    self.owner.updateSelection()
-    self.owner.updateCanvasSize()
-
-  def unTransF(self):
-    mag = self.owner.magnification
-    for i in range(len(self.itemList)):
-      for index in self.indexList[i]:
-        self.owner.translateSomething(-1,(-self.translation[0]/mag,-self.translation[1]/mag),self.itemList[i],index)
-        try:
-          self.owner.mainCanvas.move(self.itemList[i].imageList[index].IDTag,-self.translation[0]*mag,self.translation[1]*mag)
-        except:
-          self.owner.mainCanvas.move(self.itemList[i].IDTag,-self.translation[0]*mag,self.translation[1]*mag)
-    self.owner.updateSelection()
-    self.owner.updateCanvasSize()
-
-  def __str__(self):
-    return "Translation of "+str(self.itemList)+str(self.indexList)+" by "+str(self.translation)
-
-class rotationAction(UndoRedoStack.action):
-  def __init__(self,owner,itemList,indexList,angle,origin):
-    self.owner = owner
-    self.itemList = itemList
-    self.indexList = indexList
-    self.angle = angle
-    self.origin = origin
-    UndoRedoStack.action.__init__(self,self.rotF,self.unRotF)
-
-  def rotF(self):
-    for i in range(len(self.itemList)):
-      for index in self.indexList[i]:
-        self.owner.rotateSomething(-1,self.angle,self.origin,self.itemList[i],index)
-    for item in self.itemList:
-      item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-      self.owner.bindItemEvents(item)
-    self.owner.updateSelection()
-    self.owner.updateCanvasSize()
-
-  def unRotF(self):
-    for i in range(len(self.itemList)):
-      for index in self.indexList[i]:
-        self.owner.rotateSomething(-1,-self.angle,self.origin,self.itemList[i],index)
-    for item in self.itemList:
-      item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-      self.owner.bindItemEvents(item)
-    self.owner.updateSelection()
-    self.owner.updateCanvasSize()
-
-  def __str__(self):
-    return "Rotation of "+str(self.itemList)+str(self.indexList)+" by "+"%.3f"%(self.angle*180.0/math.pi)+" about "+str(self.origin)
-
-class addLabelAction(UndoRedoStack.action):
-  def __init__(self,owner,label):
-    self.owner = owner
-    self.label = label
-    UndoRedoStack.action.__init__(self,self.addF,self.unAddF)
-
-  def addF(self):
-    self.owner.addItemToFile(self.label)
-    self.label.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.label)
-
-  def unAddF(self):
-    self.label.removeFromCanvas()
-    del self.owner.fileItems[-1]
-    self.owner.propList.delete(0)
-    self.owner.clearSelection()
-
-  def __str__(self):
-    return "Addition of a label"
-
-class deleteLabelAction(UndoRedoStack.action):
-  def __init__(self,owner,label,index):
-    self.owner = owner
-    self.label = label
-    self.index = index
-    UndoRedoStack.action.__init__(self,self.delF,self.unDelF)
-
-  def delF(self):
-    self.owner.fileItems[self.index].removeFromCanvas()
-    self.owner.propList.delete(len(self.owner.fileItems)-self.index-1)
-    del self.owner.fileItems[self.index]
-
-  def unDelF(self):
-    self.owner.fileItems.insert(self.index,self.label)
-    self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.propList.insert(len(self.owner.fileItems)-self.index-1,self.owner.describeItem(self.label))
-    self.owner.bindItemEvents(self.label)
-
-  def __str__(self):
-    return "Deletion of a label"
-
-class editLabelTextAction(UndoRedoStack.action):
-  def __init__(self,owner,label,newText,oldText):
-    self.owner = owner
-    self.label = label
-    self.newText = newText
-    self.oldText = oldText
-    UndoRedoStack.action.__init__(self,self.modT,self.unModT)
-
-  def modT(self):
-    self.label.label.setText(self.newText)
-    self.label.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.label)
-
-  def unModT(self):
-    self.label.label.setText(self.oldText)
-    self.label.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.label)
-
-  def __str__(self):
-    return "Editing a label's text"
-
-class editLabelPenAction(UndoRedoStack.action):
-  def __init__(self,owner,oldPen,newPen,index):
-    self.owner = owner
-    self.newPen = newPen
-    self.oldPen = oldPen
-    self.index = index
-    UndoRedoStack.action.__init__(self,self.editF,self.unEditF)
-
-  def editF(self):
-    self.owner.fileItems[self.index].removeFromCanvas()
-    self.owner.fileItems[self.index].label.pen = self.newPen
-    self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
-  def unEditF(self):
-    self.owner.fileItems[self.index].removeFromCanvas()
-    self.owner.fileItems[self.index].label.pen = self.oldPen
-    self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
-  def __str__(self):
-    return "Changing a label's pen"
-
-class addScriptAction(UndoRedoStack.action):
-  def __init__(self,owner,script):
-    self.owner = owner
-    self.script = script
-    UndoRedoStack.action.__init__(self,self.addF,self.unAddF)
-
-  def addF(self):
-    self.owner.addItemToFile(self.script)
-    self.script.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.script)
-
-  def unAddF(self):
-    self.script.removeFromCanvas()
-    del self.owner.fileItems[-1]
-    self.owner.propList.delete(0)
-    self.owner.clearSelection()
-
-  def __str__(self):
-    return "Addition of a script"
-
-class deleteScriptAction(UndoRedoStack.action):
-  def __init__(self,owner,script,index):
-    self.owner = owner
-    self.script = script
-    self.index = index
-    UndoRedoStack.action.__init__(self,self.delF,self.unDelF)
-
-  def delF(self):
-    self.owner.fileItems[self.index].removeFromCanvas()
-    self.owner.propList.delete(len(self.owner.fileItems)-self.index-1)
-    del self.owner.fileItems[self.index]
-
-  def unDelF(self):
-    self.owner.fileItems.insert(self.index,self.script)
-    self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.propList.insert(len(self.owner.fileItems)-self.index-1,self.owner.describeItem(self.script))
-    self.owner.bindItemEvents(self.script)
-  
-  def __str__(self):
-    return "Deletion of a script"
-
-class deleteScriptItemAction(UndoRedoStack.action):
-  def __init__(self,owner,script,indices,oldTransforms):
-    self.owner = owner
-    self.script = script
-    self.indices = indices[:]
-    UndoRedoStack.action.__init__(self,self.delI,self.unDelI)
-  def delI(self):
-    for index in self.indices:
-      self.script.transform[index].deleted = True
-      self.owner.mainCanvas.delete(self.script.imageList[index].IDTag)
-
-  def unDelI(self):
-    for i in range(len(self.indices)):
-      index = self.indices[i]
-      self.script.transform[index].deleted = False
-      bbox = self.script.imageList[index].originalImage.bbox
-      self.script.imageList[index].IDTag = self.owner.mainCanvas.create_image(bbox[0],-bbox[3],anchor=NW,tags=("image"),image=self.script.imageList[index].itk)
-      self.owner.bindEvents(self.script.imageList[index].IDTag)
-    self.owner.resetStacking()
-
-  def __str__(self):
-    return "Deletion of item "+str(self.indices)+" in "+str(self.script)
-
-class editScriptAction(UndoRedoStack.action):
-  def __init__(self,owner,script,newText,oldText):
-    self.owner = owner
-    self.script = script
-    self.newText = newText
-    self.oldText = oldText
-    UndoRedoStack.action.__init__(self,self.modS,self.unModS)
-
-  def modS(self):
-    self.script.setScript(self.newText)
-    self.script.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.script)
-
-  def unModS(self):
-    self.script.setScript(self.oldText)
-    self.script.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-    self.owner.bindItemEvents(self.script)
-
-  def __str__(self):
-    return "Modification of a script"
-
-class clearItemTransformsAction(UndoRedoStack.action):
-  def __init__(self,owner,item,oldTransforms):
-    self.owner = owner
-    self.item = item
-    self.oldTransforms = oldTransforms
-    UndoRedoStack.action.__init__(self,self.clearF,self.unClearF)
-
-  def clearF(self):
-    for i in range(len(self.oldTransforms)):
-      self.item.transform[i] = xasy2asy.identity()
-    self.item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-
-  def unClearF(self):
-    for i in range(len(self.oldTransforms)):
-      self.item.transform[i] = self.oldTransforms[i]
-    self.item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification)
-
-  def __str__(self):
-    return "Clear the transforms of "+str(self.item)+" from "+str(self.oldTransforms)
-
-class itemRaiseAction(UndoRedoStack.action):
-  def __init__(self,owner,items,oldPositions):
-    self.owner = owner
-    self.items = items[:]
-    self.oldPositions = oldPositions[:]
-    UndoRedoStack.action.__init__(self,self.raiseI,self.unRaiseI)
-
-  def raiseI(self):
-    for item in self.items:
-      self.owner.raiseSomething(item)
-
-  def unRaiseI(self):
-    length = len(self.owner.fileItems)
-    indices = self.oldPositions[:]
-    indices = [length-i-1 for i in indices]
-    indices.reverse()
-    for index in indices:
-      for i in range(index):
-        self.owner.raiseSomething(self.owner.fileItems[length-index-1])
-
-  def __str__(self):
-    return "Raise items "+str(self.items)+" from positions "+str(self.oldPositions)
-
-class itemLowerAction(UndoRedoStack.action):
-  def __init__(self,owner,items,oldPositions):
-    self.owner = owner
-    self.items = items[:]
-    self.oldPositions = oldPositions[:]
-    UndoRedoStack.action.__init__(self,self.lowerI,self.unLowerI)
-
-  def lowerI(self):
-    for item in self.items:
-      self.owner.lowerSomething(item)
-
-  def unLowerI(self):
-    indices = self.oldPositions[:]
-    indices.reverse()
-    for index in indices:
-      for i in range(index):
-        self.owner.lowerSomething(self.owner.fileItems[index])
-
-  def __str__(self):
-    return "Lower items "+str(self.items)+" from positions "+str(self.oldPositions)
-
-class addDrawnItemAction(UndoRedoStack.action):
-  def __init__(self,owner,item):
-    self.owner = owner
-    self.item = item
-    UndoRedoStack.action.__init__(self,self.drawF,self.unDrawF)
-
-  def drawF(self):
-    self.owner.addItemToFile(self.item)
-    self.item.drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
-    self.owner.bindItemEvents(self.item)
-
-  def unDrawF(self):
-    self.item.removeFromCanvas(self.owner.mainCanvas)
-    del self.owner.fileItems[-1]
-    self.owner.propList.delete(0)
-    self.owner.clearSelection()
-
-  def __str__(self):
-    return "Drawing of an item"
-
-class deleteDrawnItemAction(UndoRedoStack.action):
-  def __init__(self,owner,item,index):
-    self.owner = owner
-    self.item = item
-    self.index = index
-    UndoRedoStack.action.__init__(self,self.delF,self.unDelF)
-
-  def delF(self):
-    self.owner.fileItems[self.index].removeFromCanvas(self.owner.mainCanvas)
-    self.owner.propList.delete(len(self.owner.fileItems)-self.index-1)
-    del self.owner.fileItems[self.index]
-
-  def unDelF(self):
-    self.owner.fileItems.insert(self.index,self.item)
-    self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
-    self.owner.propList.insert(len(self.owner.fileItems)-self.index-1,self.owner.describeItem(self.item))
-    self.owner.bindItemEvents(self.item)
-
-  def __str__(self):
-    return "Deletion of a drawn item"
-
-class editDrawnItemAction(UndoRedoStack.action):
-  def __init__(self,owner,oldItem,newItem,index):
-    self.owner = owner
-    self.oldItem = oldItem
-    self.newItem = newItem
-    self.index = index
-    UndoRedoStack.action.__init__(self,self.editF,self.unEditF)
-
-  def editF(self):
-    self.owner.fileItems[self.index].removeFromCanvas(self.owner.mainCanvas)
-    self.owner.fileItems[self.index].path = self.newItem.path
-    self.owner.fileItems[self.index].pen = self.newItem.pen
-    self.owner.fileItems[self.index].transform = self.newItem.transform
-    self.owner.fileItems[self.index].IDTag = self.newItem.IDTag
-    self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
-    self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
-  def unEditF(self):
-    self.owner.fileItems[self.index].removeFromCanvas(self.owner.mainCanvas)
-    self.owner.fileItems[self.index].path = self.oldItem.path
-    self.owner.fileItems[self.index].pen = self.oldItem.pen
-    self.owner.fileItems[self.index].transform = self.oldItem.transform
-    self.owner.fileItems[self.index].IDTag = self.oldItem.IDTag
-    self.owner.fileItems[self.index].drawOnCanvas(self.owner.mainCanvas,self.owner.magnification,forceAddition=True)
-    self.owner.bindItemEvents(self.owner.fileItems[self.index])
-
-  def __str__(self):
-    return "Modification of a drawn item"

Added: trunk/Master/texmf-dist/asymptote/GUI/xasyArgs.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyArgs.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyArgs.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+import argparse
+import xasyVersion
+import PyQt5.QtCore as Qc
+# Add arguments here.
+
+
+def parseArgs(args):
+    parser = argparse.ArgumentParser(args)
+    parser.add_argument('-p', '--asypath', help='Custom Asymptote asy executable')
+    parser.add_argument('-v', '--version', help='Version number', action='version',
+                        version='xasy v{0}'.format(xasyVersion.xasyVersion))
+    parser.add_argument('-l', '--language', help='language')
+    parser.add_argument('-x', '--mag', help='Magnification. Defaults to 1', default=1, type=float)
+
+    parser.add_argument(
+            'filename', help='Filename to load. If empty, initializes empty xasy canvas.', nargs='?', default=None)
+
+    return parser.parse_args()
+
+
+def getArgs():
+    return parseArgs(Qc.QCoreApplication.arguments())


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/xasyArgs.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Deleted: trunk/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,213 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyBezierEditor implements the ability to graphically edit the location
-# of the nodes and control points of a bezier curve.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-
-import math
-import sys
-from CubicBezier import *
-import xasy2asy
-
-if sys.version_info >= (3, 0):
-  from tkinter import *
-else:
-  from Tkinter import *
-
-class node:
-  def __init__(self,precontrol,node,postcontrol,uid,isTied = True):
-    self.node = node
-    self.precontrol = precontrol
-    self.postcontrol = postcontrol
-    self.isTied = isTied
-    self.uid = uid
-    self.nodeID = self.precontrolID = self.prelineID = self.postcontrolID = self.postlineID = None
-
-  def shiftNode(self,delta):
-    self.node = (self.node[0]+delta[0],self.node[1]+delta[1])
-    if self.precontrol != None:
-      self.precontrol = (self.precontrol[0]+delta[0],self.precontrol[1]+delta[1])
-    if self.postcontrol != None:
-      self.postcontrol = (self.postcontrol[0]+delta[0],self.postcontrol[1]+delta[1])
-
-  def shiftPrecontrol(self,delta):
-    self.precontrol = (self.precontrol[0]+delta[0],self.precontrol[1]+delta[1])
-    if self.isTied and self.postcontrol != None:
-      self.rotatePostControl(self.precontrol)
-
-  def shiftPostcontrol(self,delta):
-    self.postcontrol = (self.postcontrol[0]+delta[0],self.postcontrol[1]+delta[1])
-    if self.isTied and self.precontrol != None:
-      self.rotatePrecontrol(self.postcontrol)
-
-  def rotatePrecontrol(self,after):
-    vx,vy = after[0]-self.node[0],after[1]-self.node[1]
-    l = norm((vx,vy))
-    if l == 0:
-      return
-    m = norm((self.precontrol[0]-self.node[0],self.precontrol[1]-self.node[1]))
-    vx = -m*vx/l
-    vy = -m*vy/l
-    self.precontrol = self.node[0]+vx,self.node[1]+vy
-
-  def rotatePostControl(self,after):
-    vx,vy = after[0]-self.node[0],after[1]-self.node[1]
-    l = norm((vx,vy))
-    if l == 0:
-      return
-    m = norm((self.postcontrol[0]-self.node[0],self.postcontrol[1]-self.node[1]))
-    vx = -m*vx/l
-    vy = -m*vy/l
-    self.postcontrol = self.node[0]+vx,self.node[1]+vy
-
-  def draw(self,canvas):
-    width = 3
-    if self.precontrol != None:
-      if self.prelineID == None:
-        self.prelineID = canvas.create_line(self.precontrol[0],-self.precontrol[1],self.node[0],-self.node[1],tags=("preline",self.uid))
-      else:
-        canvas.coords(self.prelineID,self.precontrol[0],-self.precontrol[1],self.node[0],-self.node[1])
-      if self.precontrolID == None:
-        self.precontrolID = canvas.create_oval(self.precontrol[0]-width,-self.precontrol[1]-width,self.precontrol[0]+width,-self.precontrol[1]+width,
-            fill="red",outline="black",tags=("precontrol",self.uid))
-      else:
-        canvas.coords(self.precontrolID,self.precontrol[0]-width,-self.precontrol[1]-width,self.precontrol[0]+width,-self.precontrol[1]+width)
-    if self.postcontrol != None:
-      if self.postlineID == None:
-        self.postlineID = canvas.create_line(self.postcontrol[0],-self.postcontrol[1],self.node[0],-self.node[1],tags=("postline",self.uid))
-      else:
-        canvas.coords(self.postlineID,self.postcontrol[0],-self.postcontrol[1],self.node[0],-self.node[1])
-      if self.postcontrolID == None:
-        self.postcontrolID = canvas.create_oval(self.postcontrol[0]-width,-self.postcontrol[1]-width,self.postcontrol[0]+width,-self.postcontrol[1]+width,
-            fill="red",outline="black",tags=("postcontrol",self.uid))
-      else:
-        canvas.coords(self.postcontrolID,self.postcontrol[0]-width,-self.postcontrol[1]-width,self.postcontrol[0]+width,-self.postcontrol[1]+width)
-    if self.isTied:
-      color = "blue"
-    else:
-      color = "green"
-    if self.nodeID == None:
-      self.nodeID = canvas.create_oval(self.node[0]-width,-self.node[1]-width,self.node[0]+width,-self.node[1]+width,
-          fill=color,outline="black",tags=("node",self.uid))
-    else:
-      canvas.coords(self.nodeID,self.node[0]-width,-self.node[1]-width,self.node[0]+width,-self.node[1]+width)
-      canvas.itemconfigure(self.nodeID,fill=color)
-
-class xasyBezierEditor:
-  def __init__(self,parent,shape,canvas):
-    self.parent = parent
-    self.shape = shape
-    self.transform = self.shape.transform[0]
-    self.path = self.shape.path
-    self.canvas = canvas
-    self.modified = False
-    self.path.computeControls()
-    isCyclic = self.path.nodeSet[-1] == 'cycle'
-    segments = len(self.path.controlSet)
-    self.nodeList = []
-    for i in range(segments):
-      if i == 0:
-        node0 = self.transform*self.path.nodeSet[i]
-        control = self.transform*self.path.controlSet[i][0]
-        self.nodeList.append(node(None,node0,control,len(self.nodeList)))
-      else:
-        node0 = self.transform*self.path.nodeSet[i]
-        precontrol = self.transform*self.path.controlSet[i-1][1]
-        postcontrol = self.transform*self.path.controlSet[i][0]
-        self.nodeList.append(node(precontrol,node0,postcontrol,len(self.nodeList)))
-    if not isCyclic:
-      node0 = self.transform*self.path.nodeSet[-1]
-      precontrol = self.transform*self.path.controlSet[-1][1]
-      self.nodeList.append(node(precontrol,node0,None,len(self.nodeList)))
-    else:
-      self.nodeList[0].precontrol = self.transform*self.path.controlSet[-1][1]
-    self.showControls()
-    self.bindNodeEvents()
-    self.bindControlEvents()
-
-  def showControls(self):
-    for n in self.nodeList:
-      n.draw(self.canvas)
-    self.bindNodeEvents()
-    self.bindControlEvents()
-    self.parent.updateCanvasSize()
-
-  def bindNodeEvents(self):
-    self.canvas.tag_bind("node","<B1-Motion>",self.nodeDrag)
-    self.canvas.tag_bind("node","<Button-1>",self.buttonDown)
-    self.canvas.tag_bind("node","<Double-Button-1>",self.toggleNode)
-
-  def unbindNodeEvents(self):
-    self.canvas.tag_unbind("node","<B1-Motion>")
-    self.canvas.tag_unbind("node","<Button-1>")
-    self.canvas.tag_unbind("node","<Double-Button-1>")
-
-  def bindControlEvents(self):
-    self.canvas.tag_bind("precontrol || postcontrol","<B1-Motion>",self.controlDrag)
-    self.canvas.tag_bind("precontrol || postcontrol","<Button-1>",self.buttonDown)
-
-  def unbindControlEvents(self):
-    self.canvas.tag_unbind("precontrol || postcontrol","<B1-Motion>")
-    self.canvas.tag_unbind("precontrol || postcontrol","<Button-1>")
-
-  def buttonDown(self,event):
-    self.parent.freeMouseDown = False
-    self.startx,self.starty = event.x,event.y
-
-  def toggleNode(self,event):
-    self.parent.freeMouseDown = False
-    tags = self.canvas.gettags(CURRENT)
-    obj = tags[0]
-    uid = int(tags[1])
-    self.nodeList[uid].isTied = not self.nodeList[uid].isTied
-    self.showControls()
-
-  def nodeDrag(self,event):
-    self.parent.freeMouseDown = False
-    deltax = event.x-self.startx
-    deltay = event.y-self.starty
-    tags = self.canvas.gettags(CURRENT)
-    obj = tags[0]
-    uid = int(tags[1])
-    self.nodeList[uid].shiftNode((deltax,-deltay))
-    self.startx,self.starty = event.x,event.y
-    self.applyChanges()
-    self.showControls()
-    self.shape.drawOnCanvas(self.canvas,self.parent.magnification)
-
-  def controlDrag(self,event):
-    self.parent.freeMouseDown = False
-    deltax = event.x-self.startx
-    deltay = event.y-self.starty
-    tags = self.canvas.gettags(CURRENT)
-    obj = tags[0]
-    uid = int(tags[1])
-    if obj == "precontrol":
-      self.nodeList[uid].shiftPrecontrol((deltax,-deltay))
-    elif obj == "postcontrol":
-      self.nodeList[uid].shiftPostcontrol((deltax,-deltay))
-    self.startx,self.starty = event.x,event.y
-    self.applyChanges()
-    self.showControls()
-    self.shape.drawOnCanvas(self.canvas,self.parent.magnification)
-
-  def applyChanges(self):
-    self.modified = True
-    self.shape.transform[0] = xasy2asy.asyTransform((0,0,1,0,0,1))
-    for i in range(len(self.nodeList)):
-      self.path.nodeSet[i] = self.nodeList[i].node
-      if self.nodeList[i].postcontrol != None:
-        self.path.controlSet[i][0] = self.nodeList[i].postcontrol
-      if self.nodeList[i].precontrol != None:
-        self.path.controlSet[i-1][1] = self.nodeList[i].precontrol
-
-  def endEdit(self):
-    self.unbindNodeEvents()
-    self.unbindControlEvents()
-    self.canvas.delete("node || precontrol || postcontrol || preline || postline")

Added: trunk/Master/texmf-dist/asymptote/GUI/xasyBezierInterface.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyBezierInterface.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyBezierInterface.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,375 @@
+#!/usr/bin/env python3
+
+import xasy2asy as x2a
+import xasyUtils as xu
+
+import PyQt5.QtCore as Qc
+import PyQt5.QtGui as Qg
+import PyQt5.QtWidgets as Qw
+
+import Widg_editBezier as Web
+
+import InplaceAddObj
+
+import math
+
+class CurrentlySelctedType:
+    none = -1
+    node = 0
+    ctrlPoint = 1
+
+class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess):
+    editAccepted = Qc.pyqtSignal()
+    editRejected = Qc.pyqtSignal()
+
+    def __init__(self, parent: Qc.QObject, obj: x2a.xasyDrawnItem, info: dict={}):
+        super().__init__(parent)
+        self.info = info
+        self.asyPathBackup = x2a.asyPath.fromPath(obj.path)
+        self.asyPath = obj.path
+        self.curveMode = self.asyPath.containsCurve
+        assert isinstance(self.asyPath, x2a.asyPath)
+        self.transf = obj.transfKeymap[obj.transfKey][0]
+        self._active = True
+
+        self.currentSelMode = None
+        # (Node index, Node subindex for )
+        self.currentSelIndex = (None, 0)
+
+        self.nodeSelRects = []
+        self.ctrlSelRects = []
+
+        self.setSelectionBoundaries()
+
+        self.lastSelPoint = None
+        self.preCtrlOffset = None
+        self.postCtrlOffset = None
+        self.inTransformMode = False
+
+        self.opt = None
+
+        self.prosectiveNodes = []
+        self.prospectiveCtrlPts = []
+
+    def setSelectionBoundaries(self):
+        self.nodeSelRects = self.handleNodeSelectionBounds()
+
+        if self.curveMode:
+            self.ctrlSelRects = self.handleCtrlSelectionBoundaries()
+
+    def handleNodeSelectionBounds(self):
+        nodeSelectionBoundaries = []
+
+        for node in self.asyPath.nodeSet:
+            if node == 'cycle':
+                nodeSelectionBoundaries.append(None)
+                continue
+
+            selEpsilon = 6/self.info['magnification']
+            newRect = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon)
+            x, y = self.transf * node
+            x = int(round(x))
+            y = int(round(y))
+            newRect.moveCenter(Qc.QPoint(x, y))
+
+            nodeSelectionBoundaries.append(newRect)
+
+        return nodeSelectionBoundaries
+
+    def handleCtrlSelectionBoundaries(self):
+        ctrlPointSelBoundaries = []
+
+        for nodes in self.asyPath.controlSet:
+            nodea, nodeb = nodes
+
+            selEpsilon = 6/self.info['magnification']
+
+            newRect = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon)
+            newRectb = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon)
+
+            x, y = self.transf * nodea
+            x2, y2 = self.transf * nodeb
+
+            x = int(round(x))
+            y = int(round(y))
+
+            x2 = int(round(x2))
+            y2 = int(round(y2))
+
+            newRect.moveCenter(Qc.QPoint(x, y))
+            newRectb.moveCenter(Qc.QPoint(x2, y2))
+
+            ctrlPointSelBoundaries.append((newRect, newRectb))
+
+        return ctrlPointSelBoundaries
+
+    def postDrawPreview(self, canvas: Qg.QPainter):
+        assert canvas.isActive()
+
+        dashedPen = Qg.QPen(Qc.Qt.DashLine)
+        dashedPen.setWidthF(1/self.info['magnification'])
+        # draw the base points
+        canvas.save()
+        canvas.setWorldTransform(self.transf.toQTransform(), True)
+
+        epsilonSize = 6/self.info['magnification']
+
+        if self.info['autoRecompute'] or not self.curveMode:
+            ctrlPtsColor = 'gray'
+        else:
+            ctrlPtsColor = 'red'
+
+        canvas.setPen(dashedPen)
+
+        canvas.drawPath(self.asyPath.toQPainterPath())
+
+        nodePen = Qg.QPen(Qg.QColor('blue'))
+        nodePen.setWidthF(1/self.info['magnification'])
+
+        ctlPtsPen = Qg.QPen(Qg.QColor(ctrlPtsColor))
+        ctlPtsPen.setWidthF(1/self.info['magnification'])
+
+        for index in range(len(self.asyPath.nodeSet)):
+            point = self.asyPath.nodeSet[index]
+            
+            if point != 'cycle':
+                basePoint = Qc.QPointF(point[0], point[1])
+                canvas.setPen(nodePen)
+                canvas.drawEllipse(basePoint, epsilonSize, epsilonSize)
+            else:
+                point = self.asyPath.nodeSet[0]
+                basePoint = Qc.QPointF(point[0], point[1])
+            if self.curveMode:   
+                if index != 0:
+                    canvas.setPen(ctlPtsPen)
+                    postCtrolSet = self.asyPath.controlSet[index - 1][1]
+                    postCtrlPoint = Qc.QPointF(postCtrolSet[0], postCtrolSet[1])
+                    canvas.drawEllipse(postCtrlPoint, epsilonSize, epsilonSize)
+
+                    canvas.setPen(dashedPen)
+                    canvas.drawLine(basePoint, postCtrlPoint)
+
+                if index != len(self.asyPath.nodeSet) - 1:
+                    canvas.setPen(ctlPtsPen)
+                    preCtrlSet = self.asyPath.controlSet[index][0]
+                    preCtrlPoint = Qc.QPointF(preCtrlSet[0], preCtrlSet[1])
+                    canvas.drawEllipse(preCtrlPoint, epsilonSize, epsilonSize)
+
+                    canvas.setPen(dashedPen)
+                    canvas.drawLine(basePoint, preCtrlPoint)
+
+        canvas.restore()
+
+    def getPreAndPostCtrlPts(self, index):
+        isCycle = self.asyPath.nodeSet[-1] == 'cycle'
+
+        if index == 0 and not isCycle:
+            preCtrl = None
+        else:
+            preCtrl = self.asyPath.controlSet[index - 1][1]
+
+        if index == len(self.asyPath.nodeSet) - 1 and not isCycle:
+            postCtrl = None
+        else:
+            postCtrl = self.asyPath.controlSet[index % (len(self.asyPath.nodeSet) - 1)][0]
+
+        return preCtrl, postCtrl
+
+    def findLinkingNode(self, index, subindex):
+        """index and subindex are of the control points list."""
+        if subindex == 0:
+            return index
+        else:
+            if self.asyPath.nodeSet[index + 1] == 'cycle':
+                return 0
+            else:
+                return index + 1
+
+    def resetObj(self):
+        self.asyPath.setInfo(self.asyPathBackup)
+        self.setSelectionBoundaries()
+
+    def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None):
+        self.lastSelPoint = pos
+        if self.inTransformMode:
+            return
+
+        if self.prosectiveNodes and not self.inTransformMode:
+            self.currentSelMode = CurrentlySelctedType.node
+            self.currentSelIndex = (self.prosectiveNodes[0], 0)
+            self.inTransformMode = True
+            self.parentNodeIndex = self.currentSelIndex[0]
+        elif self.prospectiveCtrlPts and not self.inTransformMode:
+            self.currentSelMode = CurrentlySelctedType.ctrlPoint
+            self.currentSelIndex = self.prospectiveCtrlPts[0]
+            self.inTransformMode = True
+            self.parentNodeIndex = self.findLinkingNode(*self.currentSelIndex)
+        
+        if self.inTransformMode:
+            parentNode = self.asyPath.nodeSet[self.parentNodeIndex]
+
+            # find the offset of each control point to the node
+            if not self.curveMode:
+                return 
+
+            preCtrl, postCtrl = self.getPreAndPostCtrlPts(self.parentNodeIndex)
+
+            if parentNode == 'cycle':
+                parentNode = self.asyPath.nodeSet[0]
+                self.parentNodeIndex = 0
+
+            if preCtrl is not None:
+                self.preCtrlOffset = xu.funcOnList(
+                    preCtrl, parentNode, lambda a, b: a - b)
+            else:
+                self.preCtrlOffset = None
+
+            if postCtrl is not None:
+                self.postCtrlOffset = xu.funcOnList(
+                    postCtrl, parentNode, lambda a, b: a - b)
+            else:
+                self.postCtrlOffset = None
+
+    def mouseMove(self, pos, event: Qg.QMouseEvent):
+        if self.currentSelMode is None and not self.inTransformMode:
+            # in this case, search for prosective nodes. 
+            prospectiveNodes = []
+            prospectiveCtrlpts = []
+
+            for i in range(len(self.nodeSelRects)):
+                rect = self.nodeSelRects[i]
+                if rect is None:
+                    continue
+                if rect.contains(pos):
+                    prospectiveNodes.append(i)
+
+            self.prosectiveNodes = prospectiveNodes
+
+            if not self.info['autoRecompute'] and self.curveMode:
+                for i in range(len(self.ctrlSelRects)):
+                    recta, rectb = self.ctrlSelRects[i]
+
+                    if recta.contains(pos):
+                        prospectiveCtrlpts.append((i, 0))
+
+                    if rectb.contains(pos):
+                        prospectiveCtrlpts.append((i, 1))
+
+                self.prospectiveCtrlPts = prospectiveCtrlpts
+            else:
+                self.prospectiveCtrlPts = []
+
+
+        if self.inTransformMode:
+            index, subindex = self.currentSelIndex
+            deltaPos = pos - self.lastSelPoint
+            newNode = (pos.x(), pos.y())
+            if self.currentSelMode == CurrentlySelctedType.node:
+                # static throughout the moving
+                if self.asyPath.nodeSet[index] == 'cycle':
+                    return
+
+                self.asyPath.setNode(index, newNode)
+                # if also move node: 
+
+                if self.curveMode:
+                    checkPre, checkPost = self.getPreAndPostCtrlPts(index)
+
+                    if 1 == 1: # TODO: Replace this with an option to also move control pts. 
+                        if checkPre is not None:
+                            self.asyPath.controlSet[index - 1][1] = xu.funcOnList(
+                                newNode, self.preCtrlOffset, lambda a, b: a + b
+                            )
+                        if checkPost is not None:
+                            self.asyPath.controlSet[index][0] = xu.funcOnList(
+                                newNode, self.postCtrlOffset, lambda a, b: a + b
+                            )
+
+                    if self.info['autoRecompute']:
+                        self.quickRecalculateCtrls()
+                        
+
+            elif self.currentSelMode == CurrentlySelctedType.ctrlPoint and self.curveMode:
+                self.asyPath.controlSet[index][subindex] = newNode
+                parentNode = self.asyPath.nodeSet[self.parentNodeIndex]
+
+                if parentNode == 'cycle':
+                    parentNode = self.asyPath.nodeSet[0]
+                    isCycle = True
+                else:
+                    isCycle = False
+
+                if self.parentNodeIndex == 0 and self.asyPath.nodeSet[-1] == 'cycle':
+                    isCycle = True
+
+                rawNewNode = xu.funcOnList(newNode, parentNode, lambda a, b: a - b)
+                rawAngle = math.atan2(rawNewNode[1], rawNewNode[0])
+                newNorm = xu.twonorm(rawNewNode)
+
+
+                if self.info['editBezierlockMode'] >= Web.LockMode.angleLock:
+                    otherIndex = 1 - subindex       # 1 if 0, 0 otherwise. 
+                    if otherIndex == 0:
+                        if index < (len(self.asyPath.controlSet) - 1) or isCycle:
+                            newIndex = 0 if isCycle else index + 1
+
+                            oldOtherCtrlPnt = xu.funcOnList(
+                                self.asyPath.controlSet[newIndex][0], parentNode, lambda a, b: a - b)
+                        
+                            if self.info['editBezierlockMode'] >= Web.LockMode.angleAndScaleLock:
+                                rawNorm = newNorm
+                            else:
+                                rawNorm = xu.twonorm(oldOtherCtrlPnt)
+
+                            newPnt = (rawNorm * math.cos(rawAngle + math.pi), 
+                                rawNorm * math.sin(rawAngle + math.pi))
+                                
+                            self.asyPath.controlSet[newIndex][0] = xu.funcOnList(
+                                newPnt, parentNode, lambda a, b: a + b)
+                    else:
+                        if index > 0 or isCycle:
+                            newIndex = -1 if isCycle else index - 1
+                            oldOtherCtrlPnt = xu.funcOnList(
+                                self.asyPath.controlSet[newIndex][1], parentNode, lambda a, b: a - b)
+
+                            if self.info['editBezierlockMode'] >= Web.LockMode.angleAndScaleLock:
+                                rawNorm = newNorm
+                            else:
+                                rawNorm = xu.twonorm(oldOtherCtrlPnt)
+
+                            newPnt = (rawNorm * math.cos(rawAngle + math.pi),
+                                      rawNorm * math.sin(rawAngle + math.pi))
+                            self.asyPath.controlSet[newIndex][1] = xu.funcOnList(
+                                newPnt, parentNode, lambda a, b: a + b)
+        
+    def recalculateCtrls(self):
+        self.quickRecalculateCtrls()
+        self.setSelectionBoundaries()
+
+    def quickRecalculateCtrls(self):
+        self.asyPath.controlSet.clear()
+        self.asyPath.computeControls()
+
+    def mouseRelease(self):
+        if self.inTransformMode:
+            self.inTransformMode = False
+            self.currentSelMode = None
+
+            self.setSelectionBoundaries()
+            
+    def forceFinalize(self):
+        self.objectUpdated.emit()
+
+    def createOptWidget(self, info):
+        self.opt = Web.Widg_editBezier(self.info, self.curveMode)
+        self.opt.ui.btnOk.clicked.connect(self.editAccepted)
+        self.opt.ui.btnCancel.clicked.connect(self.editRejected)
+        self.opt.ui.btnForceRecompute.clicked.connect(self.recalculateCtrls)
+
+        return self.opt
+
+    def getObject(self):
+        pass
+
+    def getXasyObject(self):
+        pass


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/xasyBezierInterface.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Deleted: trunk/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,47 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyCodeEditor implements a simple text editor for Asymptote scripts in
-# xasy.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-############################################################################
-
-from subprocess import call
-from tempfile import mkstemp
-from os import remove
-from os import fdopen
-from os import path
-import xasyOptions
-
-def getText(text=""):
-  """Launch the external editor"""
-  temp = mkstemp()
-  tempf = fdopen(temp[0],"w")
-  tempf.write(text)
-  tempf.close()
-  try:
-    cmdpath,cmd = path.split(path.expandvars(xasyOptions.options['externalEditor']))
-    split_cmd = cmd.split()
-    cmdpart = [path.join(cmdpath,split_cmd[0])]
-    argpart = split_cmd[1:]+[temp[1]]
-    arglist = cmdpart+argpart
-    call(arglist)
-  except Exception as e:
-    raise Exception('Error launching external editor.')
-  
-  try:
-    tempf = open(temp[1],"r")
-    text = tempf.read()
-    tempf.close()
-    remove(temp[1])
-  except Exception as e:
-    raise Exception('Error reading from external editor.')
-  return text
-
-if __name__ == '__main__':
-  #run a test
-  print (getText("Here is some text to edit"))

Deleted: trunk/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,240 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyColorPicker implements a dialog that allows a user to choose a color
-# from those already defined in Asymptote or a custom RGB color.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-############################################################################
-
-import sys
-
-if sys.version_info >= (3, 0):
-  from tkinter import *
-  from tkinter import colorchooser
-else:
-  from Tkinter import *
-  import tkColorChooser as colorchooser
-
-asyColors = { "black":(0,0,0),
-  "white":(1,1,1),
-  "gray":(0.5,0.5,0.5),
-  "red":(1,0,0),
-  "green":(0,1,0),
-  "blue":(0,0,1),
-  "cmyk":(1,1,1),
-  "Cyan":(0,1,1),
-  "Magenta":(1,0,1),
-  "Yellow":(1,1,0),
-  "Black":(0,0,0),
-  "cyan":(0,1,1),
-  "magenta":(1,0,1),
-  "yellow":(1,1,0),
-  "palered":(1,0.75,0.75),
-  "palegreen":(0.75,1,0.75),
-  "paleblue":(0.75,0.75,1),
-  "palecyan":(0.75,1,1),
-  "palemagenta":(1,0.75,1),
-  "paleyellow":(1,1,0.75),
-  "palegray":(0.95,0.95,0.95),
-  "lightred":(1,0.5,0.5),
-  "lightgreen":(0.5,1,0.5),
-  "lightblue":(0.5,0.5,1),
-  "lightcyan":(0.5,1,1),
-  "lightmagenta":(1,0.5,1),
-  "lightyellow":(1,1,0.5),
-  "lightgray":(0.9,0.9,0.9),
-  "mediumred":(1,0.25,0.25),
-  "mediumgreen":(0.25,1,0.25),
-  "mediumblue":(0.25,0.25,1),
-  "mediumcyan":(0.25,1,1),
-  "mediummagenta":(1,0.25,1),
-  "mediumyellow":(1,1,0.25),
-  "mediumgray":(0.75,0.75,0.75),
-  "heavyred":(0.75,0,0),
-  "heavygreen":(0,0.75,0),
-  "heavyblue":(0,0,0.75),
-  "heavycyan":(0,0.75,0.75),
-  "heavymagenta":(0.75,0,0.75),
-  "lightolive":(0.75,0.75,0),
-  "heavygray":(0.25,0.25,0.25),
-  "deepred":(0.5,0,0),
-  "deepgreen":(0,0.5,0),
-  "deepblue":(0,0,0.5),
-  "deepcyan":(0,0.5,0.5),
-  "deepmagenta":(0.5,0,0.5),
-  "olive":(0.5,0.5,0),
-  "deepgray":(0.1,0.1,0.1),
-  "darkred":(0.25,0,0),
-  "darkgreen":(0,0.25,0),
-  "darkblue":(0,0,0.25),
-  "darkcyan":(0,0.25,0.25),
-  "darkmagenta":(0.25,0,0.25),
-  "darkolive":(0.25,0.25,0),
-  "darkgray":(0.05,0.05,0.05),
-  "orange":(1,0.5,0),
-  "fuchsia":(1,0,0.5),
-  "chartreuse":(0.5,1,0),
-  "springgreen":(0,1,0.5),
-  "purple":(0.5,0,1),
-  "royalblue":(0,0.5,1)
-  }
-colorLayout = [['palered',
-  'lightred',
-  'mediumred',
-  'red',
-  'heavyred',
-  'deepred',
-  'darkred',
-  'palegreen',
-  'lightgreen',
-  'mediumgreen',
-  'green',
-  'heavygreen',
-  'deepgreen',
-  'darkgreen',
-  'paleblue',
-  'lightblue',
-  'mediumblue',
-  'blue',
-  'heavyblue',
-  'deepblue',
-  'darkblue'],
-  ['palecyan',
-  'lightcyan',
-  'heavycyan',
-  'deepcyan',
-  'darkcyan',
-  'palemagenta',
-  'lightmagenta',
-  'mediummagenta',
-  'magenta',
-  'heavymagenta',
-  'deepmagenta',
-  'darkmagenta',
-  'yellow',
-  'lightyellow',
-  'mediumyellow',
-  'yellow',
-  'lightolive',
-  'olive',
-  'darkolive',
-  'palegray',
-  'lightgray',
-  'mediumgray',
-  'gray',
-  'heavygray',
-  'deepgray',
-  'darkgray'],
-  ['black',
-  'white',
-  'orange',
-  'fuchsia',
-  'chartreuse',
-  'springgreen',
-  'purple',
-  'royalblue',
-  'Cyan',
-  'Magenta',
-  'Yellow',
-  'Black']]
-
-def makeRGBfromTkColor(tkColor):
-  """Convert a Tk color of the form #rrggbb to an asy rgb color"""
-  r = int('0x'+tkColor[1:3],16)
-  g = int('0x'+tkColor[3:5],16)
-  b = int('0x'+tkColor[5:7],16)
-  r /= 255.0
-  g /= 255.0
-  b /= 255.0
-  return (r,g,b)
-
-def RGBreal255(rgb):
-  """Convert an RGB color from 0-1 to 0-255"""
-  return [min(int(256*a),255) for a in rgb]
-
-def RGB255hex(rgb):
-  """Make a color in the form #rrggbb in hex from r,g,b in 0-255"""
-  return "#{}".format("".join(["{:02x}".format(a) for a in rgb]))
-
-class xasyColorDlg(Toplevel):
-  """A dialog for choosing an asymptote color. It displays the usual asy presets and allows custom rgb colors"""
-  def __init__(self,master=None,color=(0,0,0)):
-    Toplevel.__init__(self,master,width=500,height=500)
-    self.resizable(False,False)
-    self.parent = master
-    self.title("Color Picker")
-    self.transient(master)
-    self.focus_set()
-    self.wait_visibility()
-    self.grab_set()
-    self.color = self.oldColor = color
-    cwidth = 120
-    rheight = 20
-    self.pframe=Frame(self,bd=0)
-    self.pframe.rowconfigure(0,weight=1)
-    self.pframe.columnconfigure(0,weight=1)
-    Label(self.pframe,text="Color Presets").grid(row=0,column=0)
-    self.colScroll = Scrollbar(self.pframe,orient=VERTICAL)
-    self.colorList = Canvas(self.pframe, width=cwidth*len(colorLayout), scrollregion=(0,0,20+cwidth*len(colorLayout),20+rheight*max([len(i) for i in colorLayout])),yscrollcommand=self.colScroll.set,relief=FLAT)
-    self.colScroll.config(command=self.colorList.yview)
-    self.colScroll.grid(row=1,column=1,sticky=N+S)
-    self.colorList.grid(row=1,column=0,sticky=W)
-    ccount = 0
-    for column in colorLayout:
-      rcount = 0
-      for name in column:
-        self.colorList.create_rectangle(10+cwidth*ccount,10+rheight*rcount,cwidth*ccount+25,rheight*rcount+25,tags=(name,"preset"),fill=RGB255hex(RGBreal255(asyColors[name])))
-        self.colorList.create_text(cwidth*ccount+30,10+rheight*rcount,text=name,anchor=NW,tags=(name,"preset"),fill="black",activefill=RGB255hex(RGBreal255(asyColors[name])))
-        rcount += 1
-      ccount += 1
-    self.colorList.tag_bind("preset","<Button-1>",self.setColorEvt)
-    Button(self,text="Custom color...",command=self.getCustom).grid(row=2,column=0,sticky=W,padx=5,pady=5)
-    self.colDisp = Canvas(self,width=200,height=20,background=RGB255hex(RGBreal255(self.color)),relief=SUNKEN, bd=3)
-    self.colDisp.grid(row=2,column=1,columnspan=2)
-    self.rowconfigure(3,minsize=10)
-    self.columnconfigure(0,weight=1)
-    self.columnconfigure(1,weight=1)
-    self.columnconfigure(2,weight=1)
-    Button(self,text="OK",default=ACTIVE,command=self.destroy).grid(row=4,column=1,sticky=E+W,padx=5,pady=5)
-    Button(self,text="Cancel",command=self.cancel).grid(row=4,column=2,sticky=E+W,padx=5,pady=5)
-    self.pframe.grid(row=1,column=0,columnspan=3,padx=10,pady=10)
-    self.bind("<Return>",self.closeUp)
-    self.setColor(color)
-  def closeUp(self,event):
-    """Close the dialog forcibly"""
-    self.destroy()
-  def getCustom(self):
-    """Request a custom RGB color using a colorchooser"""
-    result=colorchooser.askcolor(initialcolor=RGB255hex(RGBreal255(self.color)),title="Custom Color",parent=self)
-    if result != (None,None):
-      self.setColor((result[0][0]/255.0,result[0][1]/255.0,result[0][2]/255.0))
-  def cancel(self):
-    """Respond to the user pressing cancel"""
-    self.color = self.oldColor
-    self.destroy()
-  def setColor(self,color):
-    """Save the color and update the color display"""
-    self.color = color
-    self.colDisp.configure(background=RGB255hex(RGBreal255(self.color)))
-  def setColorEvt(self,event):
-    """Respond to the user clicking a color from the palette"""
-    self.setColor(asyColors[self.colorList.gettags(CURRENT)[0]])
-  def getColor(self,initialColor=(0,0,0)):
-    """Use this method to prompt for a color. It returns the new color or the old color if the user cancelled the operation.
-
-      e.g:
-        print (xasyColorDlg(Tk()).getColor((1,1,0)))
-    """
-    self.setColor(initialColor)
-    self.oldColor = initialColor
-    self.wait_window(self)
-    return self.color
-
-if __name__ == '__main__':
-  root = Tk()
-  Button(root,text="Pick Color",command=lambda:xasyColorDlg(root).getColor()).pack()
-  root.mainloop()

Modified: trunk/Master/texmf-dist/asymptote/GUI/xasyFile.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyFile.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyFile.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 ###########################################################################
 #
 # xasyFile implements the loading, parsing, and saving of an xasy file.
@@ -10,306 +10,74 @@
 ############################################################################
 
 from string import *
-from xasy2asy import *
+import xasy2asy as x2a
+import io
 import re
 
+
 class xasyParseError(Exception):
-  """A parsing error"""
-  pass
+    """A parsing error"""
+    pass
 
+
 class xasyFileError(Exception):
-  """An i/o error or other error not related to parsing"""
-  pass
+    """An i/o error or other error not related to parsing"""
+    pass
 
-def parseFile(inFile):
-  """Parse a file returning a list of xasyItems"""
-  lines = inFile.read()
-  lines = lines.splitlines()
-  #lines = [line for line in lines.splitlines() if not line.startswith("//")]
-  result = []
-  if lines[0] != "initXasyMode();":
-    raise xasyFileError("Invalid file format: First line must be \"initXasyMode();\"")
-  lines.pop(0)
-  lineCount = 2
-  lineNum = len(lines)
-  while lineNum > 0:
-    line = lines[0]
-    lines.pop(0)
-    if not line.isspace() and len(line)>0:
-      try:
-        #print ("Line {:d}: {:s}".format(lineCount,line))
-        lineResult = parseLine(line.strip(),lines)
-      except:
-        raise xasyParseError("Parsing error: line {:d} in {:s}\n{:s}".format(lineCount,inFile.name,line))
 
-      if lineResult != None:
-        result.append(lineResult)
-        #print ("\tproduced: {:s}".format(str(lineResult)))
-    lineCount += lineNum-len(lines)
-    lineNum = len(lines)
-  return result
-
-transformPrefix = "xformStack"
-scriptPrefix = "startScript(); {"
-scriptSuffix = "} endScript();"
-def extractScript(lines):
-  """Find the code belonging to a script item"""
-  theScript = ""
-  line = lines.pop(0)
-  level = 1
-  while level > 0:
-    check = line.lstrip()
-    while check.endswith(scriptSuffix):
-      level -= 1
-      line = line[:len(line)-len(scriptSuffix)]
-      check = line.lstrip()
-    if check.startswith(scriptPrefix):
-      level += 1
-    theScript += line + "\n"
-    if level > 0:
-      line = lines.pop(0)
-
-  global pendingTransformsD
-  ts = pendingTransformsD[:]
-  pendingTransformsD = []
-  return xasyScript(None,script=theScript,transforms=ts[:])
-
-pendingTransforms = []
-pendingTransformsD = []
-def addTransform(index,t,active=1):
-  """Place a transform in the list of transforms, expanding the list as needed"""
-  while len(pendingTransformsD) < index+1:
-    pendingTransformsD.append(identity())
-  deleted = int(active==0)
-  pendingTransformsD[index]=asyTransform(t,deleted)
-
-def parseIndexedTransforms(args):
-  """Parse a list of indexedTransforms, adding them to the current list of transforms"""
-  global pendingTransformsD
-  pendingTransformsD = []
-  args = args.replace("indexedTransform","")
-  false = 0
-  tList = [eval(a) for a in ")?(".join(args.split("),(")).split("?")]
-  for a in tList:
-    addTransform(*a)
-
-def parseTransformExpression(line):
-  """Parse statements related to the xformStack
-  
-  Syntax:
-    xformStack.push(transform)
-      e.g.: xformStack.push((0,0,1,0,0,1)); //the identity
-    xformStack.add(indexedTransform(index,transform)[,...])
-      e.g.: xformStack.add(indexedTransform(1,(0,0,1,0,0,1));
-  """
-  global pendingTransforms
-  stackCmd = line[len(transformPrefix)+1:line.find("(")]
-  if line[-2:] != ");":
-    raise xasyParseError("Invalid syntax")
-  args = line[line.find("(")+1:-2]
-  if stackCmd == "push":
-    t = asyTransform(eval(args))
-    pendingTransforms.append(t)
-  elif stackCmd == "add":
-    parseIndexedTransforms(args)
-  else:
-    raise xasyParseError("Invalid transform stack command.")
-  return None
-
-def parseLabel(line):
-  """Parse an asy Label statement, returning an xasyText item"""
-  if not (line.startswith("Label(") and line.endswith(",align=SE)")):
-    raise xasyParseError("Invalid syntax")
-  args = line[6:-1]
-  loc2 = args.rfind(",align=SE")
-  loc1 = args.rfind(",",0,loc2-1)
-  loc = args.rfind(",(",0,loc1-1)
-  if loc < 2:
-    raise xasyParseError("Invalid syntax")
-  text = args[1:loc-1]
-  location = eval(args[loc+1:args.find("),",loc)+1])
-  pen = args[loc:loc2]
-  pen = pen[pen.find(",")+1:]
-  pen = pen[pen.find(",")+1:]
-  pen = pen[pen.find(",")+1:]
-  global pendingTransforms
-  return xasyText(text,location,parsePen(pen),pendingTransforms.pop())
-
-def parseLabelCommand(line):
-  """Parse a label command returning an xasyText object
-  
-  Syntax:
-    label(Label(text,location,pen,align=SE));
-      e.g.: label(Label("Hello world!",(0,0),rgb(0,0,0)+0.5,align=SE));
-  """
-  if line[-2:] != ");":
-    raise xasyParseError("Invalid syntax")
-  arguments = line[6:-2]
-  return parseLabel(arguments)
-
-def parseDrawCommand(line):
-  """Parse a draw command returning an xasyShape object
-  
-  Syntax:
-    draw(path,pen);
-      e.g.: draw((0,0)..controls(0.33,0.33)and(0.66,0.66)..(1,1),rgb(1,0,1)+1.5);
-  """
-  if line[-2:] != ");":
-    raise xasyParseError("Invalid syntax")
-  args = line[5:-2]
-  loc = args.rfind(",rgb")
-  path = args[:loc]
-  pen = args[loc+1:]
-  global pendingTransforms
-  return xasyShape(parsePathExpression(path),parsePen(pen),pendingTransforms.pop())
-
-def parseFillCommand(line):
-  """Parse a fill command returning an xasyFilledShape object
-  
-  Syntax:
-    fill(cyclic path,pen);
-      e.g.: fill((0,0)..controls(0.33,0.33)and(0.66,0.66)..(1,1)..controls(0.66,0)and(0.33,0)..cycle,rgb(1,0,1)+1.5);
-  """
-  if line[-2:] != ");":
-    raise xasyParseError("Invalid syntax")
-  args = line[5:-2]
-  loc = args.rfind(",rgb")
-  path = args[:loc]
-  pen = args[loc+1:]
-  global pendingTransforms
-  return xasyFilledShape(parsePathExpression(path),parsePen(pen),pendingTransforms.pop())
-
-def parsePen(pen):
-  """Parse a pen expression returning an asyPen
-  
-  Syntax:
-    color+width[+options]
-      e.g.: rgb(0,0,0)+1.5+evenodd
-      e.g.: rgb(0,1,0)+1.23
-  """
-  try:
-    tokens = pen.split("+")
-    color = eval(tokens[0][3:])
-    width = float(tokens[1])
-    if len(tokens)>2:
-      options = "+".join(tokens[2:])
+def extractTransform(line):
+    """Returns key and the new transform."""
+    # see https://regex101.com/r/6DqkRJ/4 for info
+    mapString = x2a.xasyItem.mapString
+    testMatch = re.match(
+        r'^{0:s}\s*\(\s*\"([^\"]+)\"\s*,\s*\(([-\d, .]+)\)\s*\)'.format(mapString), line.strip())
+    if testMatch is None:
+        mapOnlyMatch = re.match(r'^{0:s}\s*\(\s *\"([^\"]+)\"\s*\)'.format(mapString), line.strip())
+        if mapOnlyMatch is None:
+            return None
+        else:
+            key = mapOnlyMatch.group(1)
+            return key, x2a.identity()
     else:
-      options = ""
-    return asyPen(color,width,options)
-  except:
-    raise xasyParseError("Invalid pen")
+        key = testMatch.group(1)
+        rawStr = testMatch.group(2)
+        rawStrArray = rawStr.split(',')
 
-def parsePathExpression(expr):
-  """Parse an asy path returning an asyPath()"""
-  result = asyPath()
-  expr = "".join(expr.split())
-  #print (expr)
-  if expr.find("controls") != -1:
-    #parse a path with control points
-    tokens = expr.split("..")
-    nodes = [a for a in tokens if not a.startswith("controls")]
-    for a in range(len(nodes)):
-      if nodes[a] != "cycle":
-        nodes[a] = eval(nodes[a])
-    controls = [[eval(b) for b in a.replace("controls", "").split("and")] for a in tokens if a.startswith("controls")]
-    result.initFromControls(nodes, controls)
-  else:
-    #parse a path without control points
-    tokens = re.split(r"(::|--|\.\.)",expr)
-    linkSet = re.findall("::|--|\.\.",expr)
-    nodeSet = [a for a in tokens if not re.match(r"::|--|\.\.",a)]
-    #print (nodeSet)
-    for a in range(len(nodeSet)):
-      if nodeSet[a] != "cycle":
-        nodeSet[a] = eval(nodeSet[a])
-    #print (nodeSet)
-    result.initFromNodeList(nodeSet, linkSet)
-  return result
+        if len(rawStrArray) != 6:
+            return None
+        transf = [float(val.strip()) for val in rawStrArray]
+        return key, x2a.asyTransform(transf)
 
-def takeUntilSemicolon(line,lines):
-  """Read and concatenate lines until the collected lines end with a semicolon"""
-  data = line
-  while not data.endswith(";"):
-    newline = lines.pop(0)
-    data += newline
-  return data
 
-def parseLine(line,lines):
-  """Parse a line of the file"""
-  if len(line)==0 or line.isspace() or line.startswith("//"):
-    return None
-  elif line.startswith(scriptPrefix):
-    return extractScript(lines)
-  elif line.startswith(transformPrefix):
-    return parseTransformExpression(takeUntilSemicolon(line,lines))
-  elif line.startswith("label("):
-    return parseLabelCommand(takeUntilSemicolon(line,lines))
-  elif line.startswith("draw("):
-    return parseDrawCommand(takeUntilSemicolon(line,lines))
-  elif line.startswith("fill("):
-    return parseFillCommand(takeUntilSemicolon(line,lines))
-  elif line.startswith("exitXasyMode();"):
-    return None
-  raise Exception("Could not parse the line")
+def extractTransformsFromFile(fileStr):
+    transfDict = {}
+    maxItemCount = 0
+    with io.StringIO() as rawCode:
+        for line in fileStr.splitlines():
+            test_transf = extractTransform(line.rstrip())
+            if test_transf is None:
+                rawCode.write(line + '\n')
+            else:
+                key, transf = test_transf
+                if key not in transfDict.keys():
+                    transfDict[key] = []
+                transfDict[key].append(transf)
 
-fileHeader = """initXasyMode();
-// This file was generated by xasy. It may be edited manually, however, a strict
-// syntax must be followed. It is advised that manually scripted items be added
-// in the form of a script either by using xasy or by mimicking the format of an
-// xasy-generated script item.
-// Please consult the documentation or the examples provided for details.
-"""
+                # see https://regex101.com/r/RgeBVc/2 for regex
 
-fileFooter = """// This is the end of the file
-exitXasyMode();
+                testNum = re.match(r'^x(\d+)($|:.*$)', key)
+                if testNum is not None:
+                    maxItemCount = max(maxItemCount, int(testNum.group(1)))
+        final_str = rawCode.getvalue()
+    return final_str, transfDict, maxItemCount
 
-"""
 
-def saveFile(file,xasyItems):
-  """Write a list of xasyItems to a file"""
-  file.write(fileHeader)
-  for item in xasyItems:
-    file.write(item.getCode()+"\n\n")
-  file.write(fileFooter)
+def saveFile(file, xasyItems, asy2psmap):
+    """Write a list of xasyItems to a file"""
+    for item in xasyItems:
+        file.write(item.getTransformCode(asy2psmap))
 
-if __name__ == '__main__':
-  root = Tk()
-  try:
-    name = raw_input("enter file name (\"../../xasyTest.asy\"):")
-    if name == '':
-      name = "../../xasyTest.asy"
-    f = open(name,"rt")
-  except:
-    print ("Could not open file.")
-    asy.quit()
-    sys.exit(1)
+    for item in xasyItems:
+        file.write(item.getObjectCode(asy2psmap))
 
-  fileItems = [] 
-  try:
-    fileItems = parseFile(f)
-    res = [str(a) for a in fileItems]
-    print ("----------------------------------")
-    print ("Objects in {:s}".format(f.name))
-    print ("----------------------------------")
-    for a in res:
-      print (a)
-    print ("----------------------------------")
-    print ("successful parse")
-    f.close()
-  except:
-    f.close()
-    print ("parse failed")
-    raise
-
-  print ("making a file")
-  f = open("testfile.asy","wt")
-  saveFile(f,fileItems)
-  f.close()
-  root.configure(width=500,height=500)
-  root.title("Results")
-  canv = Canvas(root,width=500,height=500)
-  canv.pack()
-  for i in fileItems[1].imageList:
-    canv.create_image(250+i.bbox[0],250-i.bbox[3],anchor = NW, image=i.image)
-    Button(root,image=i.image).pack(side=LEFT)
-  root.mainloop()
+    file.write('size('+str(asy2psmap*x2a.yflip())+'); '+ x2a.xasyItem.resizeComment+'\n')

Deleted: trunk/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,92 +0,0 @@
-#!/usr/bin/env python
-##################################################################
-# This file stores the icons used by the xasy GUI
-#
-# About images and base64
-#
-# Suppose you have image.gif and want to create a base64
-# string. This can be accomplished using:
-#
-# import base64
-# base64.encodestring(open("image.gif","rb").read())
-#
-# The resulting output, including the enclosing single quotes,
-# is the base64 encoding of the image and can be used in the
-# dictionary below.
-#
-#
-# Suppose you have a base64 string, b64str, and want to create
-# an image. This can be accomplished using:
-#
-# import base64
-# open("image.gif","w").write(base64.decodestring(b64str))
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-##################################################################
-import base64
-import os
-#toolbar icon image data in base64 eliminates need to worry about files
-#these are the base64 encodings of the content of the directory xasy3Imgs
-iconB64 = {
-'lower': 'R0lGODlhGAAYAPEBAAAAAP///8zMzAAAACH5BAEAAAIALAAAAAAYABgAAAItlI+py+0Po5yUgosz\nrrybK2giqADed6LHKCZm+p7xx2Zuqsqr95KcJpv9cJUCADs=\n',
-'rotate': 'R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAI7jI8JkO231mux1mkistL1zX0Q\ng2Fi6aGmurKp+8KKrJB0Zt+nzOQw6XPZgqjczuQ7eohKEDKoUYWIgQIAOw==\n',
-'raise': 'R0lGODlhGAAYAPEBAAAAAP///8zMzAAAACH5BAEAAAIALAAAAAAYABgAAAIwlI+pywgND3ixzVvZ\nNDSn3nlKKH7fhaZmObKtk8Yh6dKlLcfC5vZ1jvIJh8SikVUAADs=\n',
-'fillPoly': 'R0lGODlhGAAYAPEAAAAAAIOBgwAAAAAAACH5BAEAAAIALAAAAAAYABgAAAJGlI+py+0PEYgNBDCp\nDPxqY3UcRoViRzrmKWbLyqIMHI9vHbsbfuoHjfOBcrlbT0ATIo+gldKpMD1lL8vUo5oqS9vS5wsp\nAAA7\n',
-'move': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAI4jI+py+0I3gNUNhqtwlVD7m3h\nkoVdUJ4MaKTYysVymbDoYcM4Tmv9eAO2cp6YEKUavY5BpvMZKgAAOw==\n',
-'drawBezi': 'R0lGODlhGAAYAPEBAAAAAP///6usrQAAACH5BAEAAAIALAAAAAAYABgAAAI6lI+py+0AnYRUKhox\nsFvUFDXdM4LWUaKnEaorhqSX1noPmMquWJukzpr0YitRcfE5oobFpPIJjUoZBQA7\n',
-'vertiMove': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAIsjI+py+0I3gNUNhqtwlVD7m3h\nko2QmZRooKKt+Y5xOFtc7dwrtrLd3gsKTQUAOw==\n',
-'horizMove': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAIljI+py+0Po5y02oshAGu/7Skg\n143mSYpgGTYt8mbyTNf2jedWAQA7\n',
-'fillEllip': 'R0lGODlhGAAYAPECAAAAAIOBg////6usrSH5BAEAAAMALAAAAAAYABgAAAJAnI+py+0PowS0gkmD\n3qE6wIXctYDi2SkmepLGyrYHHIcuXW93Lr+86BrgakHfrzjjIRGVFgVjWUqm1Kr1ijUUAAA7\n',
-'text': 'R0lGODlhGAAYAIABAAAAAP///yH5BAEAAAEALAAAAAAYABgAAAI+jI+py+0Po5x0AgSu1SZvHnhS\nBnpio5Ukt2Idm3bysYrnddLwy+czH0rhFDkbTigj6UzKl68CjUqn1Ko1UAAAOw==\n',
-'drawPoly': 'R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAI4jI+py+0PEYhtgkmlzgFL/4DJ\nFULiVi4ns66smrUxrMj1fdqHR+60kfPdgCwLzbWTIU1LE+cJKQAAOw==\n',
-'drawLines': 'R0lGODlhGAAYAPEBAAAAAP///6usrQAAACH5BAEAAAIALAAAAAAYABgAAAI3lI+py+0AnYRAPmoZ\njvlwX3Vh8j2XUIIWNXoZS3ZoO8soSK+4fRuYnQPyFEHhcHecFV+ppDNRAAA7\n',
-'drawShape': 'R0lGODlhGAAYAPAAAAAAAAAAACH5BAEAAAEALAAAAAAYABgAAAI5jI+pywffIjQzIrCwdXnTplmh\nMoKmKIHVeZXp5cFcPH+0HbjbqKN17OoxgrTeKiOkPHjH3fIGjS4KADs=\n',
-'drawEllip': 'R0lGODlhGAAYAPEBAAAAAP///6usrQAAACH5BAEAAAIALAAAAAAYABgAAAIylI+py+0PowS0gklX\ndRd29XmgdIQh+Z1TSSJpyxpqZMLqzOB4sgsbmKFZgrCi8YhMNgoAOw==\n',
-'select': 'R0lGODlhGAAYAPIDAAAAAICAgMDAwP///6usrQAAAAAAAAAAACH5BAEAAAQALAAAAAAYABgAAANH\nSLrc/mvA6YCkGIiLIQhb54Gh2HwkZxKo4KoiSpam7L6rfdNZ4M+C3I+0Ush8wSLKCFIyPsnisyld\nAD7VabR6DWSt37BYmgAAOw==\n',
-'fillShape': 'R0lGODlhGAAYAPEAAAAAAIOBgwAAAAAAACH5BAEAAAIALAAAAAAYABgAAAJHlI+pywff4gsUxgSo\nrhflzXXCB4YXWQIiCqpnubnLw8KyU8Omket77wvcgD4ZUTcMIj3KlOLYejY1N8/R0qChaCIrtgsO\nRwoAOw==\n',
-'asy': 'R0lGODlhGAAYAIABAP8AAAAAACH5BAEKAAEALAIAAwAUABIAAAImjI+py+0AHINy0ZouNjBurmGd\nt40fFT4j2aydGqaBq8jvxH46UwAAOw==\n'
-}
-
-def createGIF(key):
-  """Create a gif file from the data in the iconB64 list of icons"""
-  if key not in iconB64.keys():
-    print ("Error: {:s} not found in icon list.".format(key))
-    print ("Available icons:",iconB64.keys())
-  else:
-    print ("Generating {:s}.gif".format(key))
-    open("{:s}.gif".format(key),"w").write(base64.decodestring(iconB64[key]))
-
-def createGIFs():
-  """Create the files for all the icons in iconB64"""
-  for name in iconB64.keys():
-    createGIF(name)
-
-def createStrFromGif(gifFile):
-  """Create the base64 representation of a file"""
-  return base64.encodestring(gifFile.read())
-
-if __name__=='__main__':
-  print ("Testing the xasyGUIIcons module.")
-  print ("Generating all the GIFs:")
-  createGIFs()
-  print ("Checking consistency of all icons in iconB64")
-  allpassed = True
-  for icon in iconB64.keys():
-    print ("Checking {:s}".format(icon))
-    if createStrFromGif(open("{:s}.gif".format(icon),"rb")) == iconB64[icon]:
-      print ("\tPassed.")
-    else:
-      print ("\tFailed.")
-      allpassed= False
-  if allpassed:
-    print ("All files succeeded.")
-  s = raw_input("Delete generated files? (y/n)")
-  if s == "y":
-    for name in iconB64.keys():
-      print ("Deleting {:s}.gif".format(name))
-      os.unlink(name+".gif")
-      print ("\tdone")
-  print ("Done")

Deleted: trunk/Master/texmf-dist/asymptote/GUI/xasyMainWin.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyMainWin.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyMainWin.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,1748 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyMainWin implements the functionality of the GUI. It depends on
-# xasy2asy for its interaction with Asymptote.
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-
-import os
-import sys
-from string import *
-import subprocess
-import math
-import copy
-
-if sys.version_info >= (3, 0):
-  # python3
-  from tkinter import *
-  from tkinter import filedialog, messagebox, simpledialog
-else:
-  # python2
-  # from Tkinter import *
-  import tkFileDialog   as filedialog
-  import tkMessageBox   as messagebox
-  import tkSimpleDialog as simpledialog
-
-import threading
-import time
-
-from xasyVersion import xasyVersion
-import xasyCodeEditor
-from xasy2asy import *
-import xasyFile
-import xasyOptions
-import xasyOptionsDialog
-import CubicBezier
-from xasyBezierEditor import xasyBezierEditor
-from xasyGUIIcons import iconB64
-from xasyColorPicker import *
-
-from UndoRedoStack import *
-from xasyActions import *
-
-import string
-
-try:
-  from PIL import ImageTk
-  from PIL import Image
-  PILAvailable = True
-except:
-  PILAvailable = False
-
-class xasyMainWin:
-  def __init__(self,master,file=None,magnification=1.0):
-    self.opLock = threading.Lock()
-    self.parent = master
-    self.magnification = magnification
-    self.previousZoom = self.magnification
-    self.magList = [0.1,0.25,1.0/3,0.5,1,2,3,4,5,10]
-    self.bindGlobalEvents()
-    self.createWidgets()
-    self.resetGUI()
-    site=""
-    if not PILAvailable:
-      messagebox.showerror("Failed Dependencies","An error occurred loading the required PIL library. Please install Pillow from http://pypi.python.org/pypi/Pillow")
-      self.parent.destroy()
-      sys.exit(1)
-    if file != None:
-      self.loadFile(file)
-    self.parent.after(100,self.tickHandler)
-
-  def testOrAcquireLock(self):
-    val = self.opLock.acquire(False)
-    if val:
-      self.closeDisplayLock()
-    return val
-
-  def acquireLock(self):
-    self.closeDisplayLock()
-    self.opLock.acquire()
-
-  def releaseLock(self):
-    self.opLock.release()
-    self.openDisplayLock()
-
-  def tickHandler(self):
-    self.tickCount += 1
-    self.mainCanvas.itemconfigure("outlineBox",dashoffset=self.tickCount%9)
-    self.parent.after(100,self.tickHandler)
-
-  def closeDisplayLock(self):
-    self.status.config(text="Busy")
-    self.parent.update_idletasks()
-
-  def openDisplayLock(self):
-    self.status.config(text="Ready")
-
-  def bindGlobalEvents(self):
-    #global bindings
-    self.parent.bind_all("<Control-z>",lambda q:self.editUndoCmd())# z -> no shift
-    self.parent.bind_all("<Control-Z>",lambda q:self.editRedoCmd())# Z -> with shift
-    self.parent.bind_all("<Control-o>",lambda q:self.fileOpenCmd())
-    self.parent.bind_all("<Control-n>",lambda q:self.fileNewCmd())
-    self.parent.bind_all("<Control-s>",lambda q:self.fileSaveCmd())
-    self.parent.bind_all("<Control-q>",lambda q:self.fileExitCmd())
-    self.parent.bind_all("<F1>",lambda q:self.helpHelpCmd())
-
-  def unbindGlobalEvents(self):
-    #global bindings
-    self.parent.unbind("<Control-z>")
-    self.parent.unbind("<Control-Z>")
-    self.parent.unbind("<Control-o>")
-    self.parent.unbind("<Control-n>")
-    self.parent.unbind("<Control-s>")
-    self.parent.unbind("<Control-q>")
-    self.parent.unbind("<F1>")
-
-  def createWidgets(self):
-    #first some configuration
-    self.parent.geometry("800x600")
-    self.parent.title("Xasy")
-    self.parent.resizable(True,True)
-
-    #try to capture the closing of the window
-    #find a better way to do this since the widgets may
-    #already be destroyed when this is called
-    self.parent.protocol("WM_DELETE_WINDOW",self.canQuit)
-
-    #the main menu
-    self.mainMenu = Menu(self.parent)
-    self.parent.config(menu=self.mainMenu)
-
-    #the file menu
-    self.fileMenu = Menu(self.mainMenu,tearoff=0)
-    self.fileMenu.add_command(label="New",command=self.fileNewCmd,accelerator="Ctrl+N",underline=0)
-    self.fileMenu.add_command(label="Open",command=self.fileOpenCmd,accelerator="Ctrl+O",underline=0)
-    self.fileMenu.add_separator()
-    self.fileMenu.add_command(label="Save",command=self.fileSaveCmd,accelerator="Ctrl+S",underline=0)
-    self.fileMenu.add_command(label="Save As",command=self.fileSaveAsCmd,underline=5)
-    self.fileMenu.add_separator()
-
-    #an export menu
-    self.exportMenu = Menu(self.fileMenu,tearoff=0)
-    self.exportMenu.add_command(label="EPS...",command=self.exportEPS,underline=0)
-    self.exportMenu.add_command(label="PDF...",command=self.exportPDF,underline=0)
-    self.exportMenu.add_command(label="GIF...",command=self.exportGIF,underline=0)
-    self.exportMenu.add_command(label="PNG...",command=self.exportPNG,underline=1)
-    self.exportMenu.add_command(label="SVG...",command=self.exportSVG,underline=0)
-    self.fileMenu.add_cascade(label="Export",menu=self.exportMenu,underline=1)
-    self.fileMenu.add_separator()
-
-    self.fileMenu.add_command(label="Quit",command=self.fileExitCmd,accelerator="Ctrl+Q",underline=0)
-
-    self.mainMenu.add_cascade(label="File",menu=self.fileMenu,underline=0)
-
-    #the edit menu
-    self.editMenu = Menu(self.mainMenu,tearoff=0)
-    self.editMenu.add_command(label="Undo",command=self.editUndoCmd,accelerator="Ctrl+Z",underline=0)
-    self.editMenu.add_command(label="Redo",command=self.editRedoCmd,accelerator="Shift+Ctrl+Z",underline=0)
-    self.mainMenu.add_cascade(label="Edit",menu=self.editMenu,underline=0)
-
-    #the tools menu
-    self.toolsMenu = Menu(self.mainMenu,tearoff=0)
-    self.mainMenu.add_cascade(label="Tools",menu=self.toolsMenu,underline=0)
-
-    #the options menu
-    self.optionsMenu = Menu(self.toolsMenu,tearoff=0)
-    self.toolsMenu.add_cascade(label="Options",menu=self.optionsMenu,underline=0)
-    self.optionsMenu.add_command(label="Edit...",command=self.editOptions,underline=0)
-    self.optionsMenu.add_command(label="Reset defaults",command=self.resetOptions,underline=6)
-
-    #the help menu
-    self.helpMenu = Menu(self.mainMenu,tearoff=0)
-    self.helpMenu.add_command(label="Help",command=self.helpHelpCmd,state=DISABLED,accelerator="F1",underline=0)
-    self.helpMenu.add_command(label="Asymptote Documentation",command=self.helpAsyDocCmd,underline=10)
-    self.helpMenu.add_separator()
-    self.helpMenu.add_command(label="About xasy",command=self.helpAboutCmd,underline=0)
-    self.mainMenu.add_cascade(label="Help",menu=self.helpMenu,underline=0)
-
-    #status bar
-    self.statusBar = Frame(self.parent,relief=FLAT)
-
-    self.magVal = DoubleVar()
-    self.magVal.set(round(100*self.magnification,1))
-    self.magVal.trace('w',self.zoomViewCmd)
-    zoomList = self.magList
-    if self.magnification not in zoomList:
-      zoomList.append(self.magnification)
-    zoomList.sort()
-    zoomList = [round(100*i,1) for i in zoomList]
-    self.zoomMenu = OptionMenu(self.statusBar,self.magVal,*zoomList)
-    self.zoomMenu.pack(side=RIGHT)
-    Label(self.statusBar,text="Zoom:",anchor=E,width=7).pack(side=RIGHT)
-
-    self.coords = Label(self.statusBar,text="(0,0)",relief=SUNKEN,anchor=W)
-    self.coords.pack(side=RIGHT,anchor=S)
-    self.status = Label(self.statusBar,text="Ready",relief=SUNKEN,anchor=W)
-    self.status.pack(side=RIGHT,fill=X,expand=1,anchor=SW)
-    self.statusBar.pack(side=BOTTOM,fill=X)
-
-    #toolbar for transformation, drawing, and adjustment commands
-    self.toolBar = Frame(self.parent,relief=FLAT,borderwidth=3)
-
-    #let's load some images
-    self.toolIcons = {}
-    for x in iconB64.keys():
-      self.toolIcons[x] = PhotoImage(data=iconB64[x])
-
-    self.transformLbl = Label(self.toolBar,text="",anchor=W)
-    self.transformLbl.grid(row=0,column=0,columnspan=2,sticky=W)
-    self.toolSelectButton = Button(self.toolBar,command=self.toolSelectCmd,image=self.toolIcons["select"])
-    self.toolSelectButton.grid(row=1,column=0,sticky=N+S+E+W)
-    self.toolMoveButton = Button(self.toolBar,command=self.toolMoveCmd,image=self.toolIcons["move"])
-    self.toolMoveButton.grid(row=2,column=0,sticky=N+S+E+W)
-    self.toolRotateButton = Button(self.toolBar,command=self.toolRotateCmd,image=self.toolIcons["rotate"])
-    self.toolRotateButton.grid(row=2,column=1,sticky=N+S+E+W)
-    self.toolVertiMoveButton = Button(self.toolBar,command=self.toolVertiMoveCmd,image=self.toolIcons["vertiMove"])
-    self.toolVertiMoveButton.grid(row=3,column=0,sticky=N+S+E+W)
-    self.toolHorizMoveButton = Button(self.toolBar,command=self.toolHorizMoveCmd,image=self.toolIcons["horizMove"])
-    self.toolHorizMoveButton.grid(row=3,column=1,sticky=N+S+E+W)
-
-    self.drawLbl = Label(self.toolBar,text="",anchor=W)
-    self.drawLbl.grid(row=4,column=0,columnspan=2,sticky=W)
-    self.toolDrawLinesButton = Button(self.toolBar,command=self.toolDrawLinesCmd,image=self.toolIcons["drawLines"])
-    self.toolDrawLinesButton.grid(row=5,column=0,sticky=N+S+E+W)
-    self.toolDrawBeziButton = Button(self.toolBar,command=self.toolDrawBeziCmd,image=self.toolIcons["drawBezi"])
-    self.toolDrawBeziButton.grid(row=5,column=1,sticky=N+S+E+W)
-    self.toolDrawPolyButton = Button(self.toolBar,command=self.toolDrawPolyCmd,image=self.toolIcons["drawPoly"])
-    self.toolDrawPolyButton.grid(row=6,column=0,sticky=N+S+E+W)
-    self.toolFillPolyButton = Button(self.toolBar,command=self.toolFillPolyCmd,image=self.toolIcons["fillPoly"])
-    self.toolFillPolyButton.grid(row=6,column=1,sticky=N+S+E+W)
-    self.toolDrawEllipButton = Button(self.toolBar,command=self.toolDrawEllipCmd,image=self.toolIcons["drawEllip"],state=DISABLED,relief=FLAT)
-    #self.toolDrawEllipButton.grid(row=7,column=0,sticky=N+S+E+W)
-    self.toolFillEllipButton = Button(self.toolBar,command=self.toolFillEllipCmd,image=self.toolIcons["fillEllip"],state=DISABLED,relief=FLAT)
-    #self.toolFillEllipButton.grid(row=7,column=1,sticky=N+S+E+W)
-    self.toolDrawShapeButton = Button(self.toolBar,command=self.toolDrawShapeCmd,image=self.toolIcons["drawShape"])
-    self.toolDrawShapeButton.grid(row=8,column=0,sticky=N+S+E+W)
-    self.toolFillShapeButton = Button(self.toolBar,command=self.toolFillShapeCmd,image=self.toolIcons["fillShape"])
-    self.toolFillShapeButton.grid(row=8,column=1,sticky=N+S+E+W)
-    self.toolTextButton = Button(self.toolBar,command=self.toolTextCmd,image=self.toolIcons["text"])
-    self.toolTextButton.grid(row=9,column=0,sticky=N+S+E+W)
-    self.toolAsyButton = Button(self.toolBar,command=self.toolAsyCmd,image=self.toolIcons["asy"])
-    self.toolAsyButton.grid(row=9,column=1,sticky=N+S+E+W)
-
-    self.adjLbl = Label(self.toolBar,text="",anchor=W)
-    self.adjLbl.grid(row=10,column=0,columnspan=2,sticky=W)
-    self.toolRaiseButton = Button(self.toolBar,command=self.toolRaiseCmd,image=self.toolIcons["raise"])
-    self.toolRaiseButton.grid(row=11,column=0,sticky=N+S+E+W)
-    self.toolLowerButton = Button(self.toolBar,command=self.toolLowerCmd,image=self.toolIcons["lower"])
-    self.toolLowerButton.grid(row=11,column=1,sticky=N+S+E+W)
-
-    self.toolBar.pack(side=LEFT,anchor=NW)
-
-    #documentation for the tool bar buttons
-    self.toolDocs = {
-      self.toolSelectButton : "Click an item to select it. Control-Click will select/deselect additional items. Use mouse scroller (or Up/Down keys) to raise/lower highlighted items.",
-      self.toolMoveButton : "Drag a selected item.",
-      self.toolHorizMoveButton : "Drag a selected item. Only horizontal translation will be applied.",
-      self.toolVertiMoveButton : "Drag a selected item. Only vertical translation will be applied.",
-      self.toolRotateButton : "Drag a selected item to rotate it.",
-      self.toolDrawLinesButton : "Click to draw line segments. Double click to place last point.",
-      self.toolDrawBeziButton : "Click to place points. Double click to place last point.",
-      self.toolDrawPolyButton : "Click to place vertices. Double click to place last point.",
-      self.toolFillPolyButton : "Click to place vertices. Double click to place last point.",
-      self.toolDrawEllipButton : "(UNIMPLEMENTED)Click to place center. Move mouse to achieve correct shape and double click.",
-      self.toolFillEllipButton : "(UNIMPLEMENTED)Click to place center. Move mouse to achieve correct shape and double click.",
-      self.toolDrawShapeButton : "Click to place points. Double click to place last point.",
-      self.toolFillShapeButton : "Click to place points. Double click to place last point.",
-      self.toolTextButton : "Click location of top left label position and enter text in dialog.",
-      self.toolRaiseButton : "Raise selected items to top.",
-      self.toolLowerButton : "Lower selected items to bottom.",
-      self.toolAsyButton : "Insert/Edit Asymptote code."
-    }
-
-    #Current pen settings
-    self.optionsBar = Frame(self.parent,height=100,relief=FLAT,borderwidth=3)
-    self.penDisp = Canvas(self.optionsBar,width=100,height=25,bg="white",relief=SUNKEN,borderwidth=3)
-    self.penDisp.grid(row=0,column=0,padx=3,pady=3)
-    self.penDisp.create_line(10,25,30,10,60,20,80,10,smooth=True,tags="penDisp")
-    self.penDisp.create_text(100,30,text="x1",tags="penMag",anchor=SE,font=("times","8"))
-    self.penColButton = Button(self.optionsBar,text="Color...",width=5,command=self.setPenColCmd,relief=FLAT)
-    self.penColButton.grid(row=0,column=1,padx=3,pady=3)
-    Label(self.optionsBar,text="Width",anchor=E).grid(row=0,column=2)
-    self.penWidthEntry = Entry(self.optionsBar,width=5)
-    self.penWidthEntry.bind("<KeyRelease>",self.penWidthChanged)
-    self.penWidthEntry.bind("<FocusOut>",self.applyPenWidthEvt)
-    self.penWidthEntry.bind("<Return>",self.applyPenWidthEvt)
-    self.penWidthEntry.grid(row=0,column=3)
-    Label(self.optionsBar,text="Options",anchor=E).grid(row=0,column=4)
-    self.penOptEntry = Entry(self.optionsBar)
-    self.penOptEntry.bind("<FocusOut>",self.applyPenOptEvt)
-    self.penOptEntry.bind("<Return>",self.applyPenOptEvt)
-    self.penOptEntry.grid(row=0,column=5)
-    self.optionsBar.pack(side=BOTTOM,anchor=NW)
-
-    #a paned window for the canvas and propert explorer
-    self.windowPane = PanedWindow(self.parent)
-
-    #a property explorer
-    self.propFrame = Frame(self.parent)
-    self.propFrame.rowconfigure(1,weight=1)
-    self.propFrame.columnconfigure(0,weight=1)
-    Label(self.propFrame,text="Item List").grid(row=0,column=0,columnspan=2)
-    self.itemScroll = Scrollbar(self.propFrame,orient=VERTICAL)
-    self.propList = Listbox(self.propFrame, yscrollcommand=self.itemScroll.set)
-    self.itemScroll.config(command=self.propList.yview)
-    self.itemScroll.grid(row=1,column=1,sticky=N+S)
-    self.propList.grid(row=1,column=0,sticky=N+S+E+W)
-    self.propList.bind("<Double-Button-1>",self.propSelect)
-    self.propList.bind("<Button-3>",self.itemPropMenuPopup)
-
-    #the canvas's frame
-    self.canvFrame = Frame(self.parent,relief=FLAT,borderwidth=0)
-    self.canvFrame.rowconfigure(0,weight=1)
-    self.canvFrame.columnconfigure(0,weight=1)
-    self.canvVScroll = Scrollbar(self.canvFrame,orient=VERTICAL)
-    self.canvHScroll = Scrollbar(self.canvFrame,orient=HORIZONTAL)
-    self.canvHScroll.grid(row=1,column=0,sticky=E+W)
-    self.canvVScroll.grid(row=0,column=1,sticky=N+S)
-
-    #add the frames to the window pane
-    self.windowPane.pack(side=RIGHT,fill=BOTH,expand=True)
-    self.windowPane.add(self.canvFrame)
-    self.windowPane.add(self.propFrame)
-    self.windowPane.paneconfigure(self.propFrame,minsize=50,sticky=N+S+E+W)
-    self.windowPane.bind("<Double-Button-1>",self.togglePaneEvt)
-
-    #the highly important canvas!
-    self.mainCanvas = Canvas(self.canvFrame,relief=SUNKEN,background="white",borderwidth=3,
-                  highlightthickness=0,closeenough=1.0,yscrollcommand=self.canvVScroll.set,
-                  xscrollcommand=self.canvHScroll.set)
-    self.mainCanvas.grid(row=0,column=0,sticky=N+S+E+W)
-
-    self.canvVScroll.config(command=self.mainCanvas.yview)
-    self.canvHScroll.config(command=self.mainCanvas.xview)
-
-    self.mainCanvas.bind("<Motion>",self.canvMotion)
-    self.mainCanvas.bind("<Button-1>",self.canvLeftDown)
-    self.mainCanvas.bind("<Double-Button-1>",self.endDraw)
-    self.mainCanvas.bind("<ButtonRelease-1>",self.canvLeftUp)
-    self.mainCanvas.bind("<B1-Motion>",self.canvDrag)
-
-    self.mainCanvas.bind("<Enter>",self.canvEnter)
-    self.mainCanvas.bind("<Leave>",self.canvLeave)
-    self.mainCanvas.bind("<Delete>",self.itemDelete)
-    #self.mainCanvas.bind("<Button-3>",self.canvRightDown)
-    #self.mainCanvas.bind("<ButtonRelease-3>",self.canvRightUp)
-    self.mainCanvas.bind("<Button-4>",self.itemRaise)
-    self.mainCanvas.bind("<Button-5>",self.itemLower)
-    self.mainCanvas.bind("<Up>",self.itemRaise)
-    self.mainCanvas.bind("<Down>",self.itemLower)
-    self.mainCanvas.bind("<Configure>",self.configEvt)
-
-  def foregroundPenColor(self,hex):
-    hex = hex[1:]
-    rgb = max(hex[0:2], hex[2:4], hex[4:6])
-    if(rgb >= "80"):
-      return "black"
-    else:
-      return "white"
-
-  def resetGUI(self):
-    #set up the main window
-    self.filename = None
-    self.fileToOpen = None
-    self.retitle()
-
-    #set up the paned window
-    self.paneVisible = True
-
-    #setup the pen entries
-    self.pendingPenWidthChange = None
-    self.pendingPenOptChange = None
-
-    #load one-time configs
-    xasyOptions.load()
-    self.tkPenColor = xasyOptions.options['defPenColor']
-    self.penColor = makeRGBfromTkColor(self.tkPenColor)
-    self.penColButton.config(activebackground=self.tkPenColor,
-                             activeforeground=self.foregroundPenColor(self.tkPenColor))
-    self.penWidth = xasyOptions.options['defPenWidth']
-    self.penWidthEntry.select_range(0,END)
-    self.penWidthEntry.delete(0,END)
-    self.penWidthEntry.insert(END,str(self.penWidth))
-    self.penOptions = xasyOptions.options['defPenOptions']
-    self.penOptEntry.select_range(0,END)
-    self.penOptEntry.delete(0,END)
-    self.penOptEntry.insert(END,str(self.penOptions))
-    self.showCurrentPen()
-
-    #load modifiable configs
-    self.applyOptions()
-
-    #set up editing
-    self.editor = None
-
-    #set up drawing
-    self.pathInProgress = asyPath()
-    self.currentIDTag = -1
-    self.inDrawingMode = False
-    self.freeMouseDown = True
-    self.dragSelecting = False
-    self.itemsBeingRotated = []
-    self.inRotatingMode = False
-
-    #set up the toolbar
-    try:
-      self.updateSelectedButton(self.toolSelectButton)
-    except:
-      self.selectedButton = self.toolSelectButton
-      self.updateSelectedButton(self.toolSelectButton)
-
-    #set up the canvas
-    self.mainCanvas.delete(ALL)
-    self.mainCanvas.create_rectangle(0,0,0,0,tags="outlineBox",width=0,outline="#801111",dash=(3,6))
-    self.backColor = "white" #in future, load this from an options file. Or, should this really be an option?
-    self.mainCanvas.configure(background=self.backColor)
-
-    #set up the xasy item list
-    self.fileItems = []
-    self.propList.delete(0,END)
-    self.updateCanvasSize()
-
-    #setup timer
-    self.tickCount = 0
-
-    #setup undo/redo!
-    self.undoRedoStack = actionStack()
-    self.amDragging = False
-
-  def retitle(self):
-    if self.filename == None:
-      self.parent.title("Xasy - New File")
-    else:
-      name = os.path.abspath(self.filename)
-      name = os.path.basename(name)
-      self.parent.title("Xasy - %s"%name)
-
-  def applyOptions(self):
-    self.gridcolor = xasyOptions.options['gridColor']
-    self.tickcolor = xasyOptions.options['tickColor']
-    self.axiscolor = xasyOptions.options['axesColor']
-    self.gridVisible = xasyOptions.options['showGrid']
-    self.gridxspace = xasyOptions.options['gridX']
-    self.gridyspace = xasyOptions.options['gridY']
-    self.axesVisible = xasyOptions.options['showAxes']
-    self.axisxspace = xasyOptions.options['axisX']
-    self.axisyspace = xasyOptions.options['axisY']
-    self.updateCanvasSize()
-    #test the asyProcess
-    startQuickAsy()
-    if not quickAsyRunning():
-      if messagebox.askyesno("Xasy Error","Asymptote could not be executed.\r\nTry to find Asymptote automatically?"):
-        xasyOptions.setAsyPathFromWindowsRegistry()
-        xasyOptions.save()
-        startQuickAsy()
-    while not quickAsyRunning():
-      if messagebox.askyesno("Xasy Error","Asymptote could not be executed.\r\nEdit settings?"):
-        xasyOptionsDialog.xasyOptionsDlg(self.parent)
-        xasyOptions.save()
-        startQuickAsy()
-      else:
-        self.parent.destroy()
-        sys.exit(1)
-
-  def drawGrid(self):
-    self.mainCanvas.delete("grid")
-    if not self.gridVisible:
-      return
-    left,top,right,bottom = [int(float(a)) for a in self.mainCanvas.cget("scrollregion").split()]
-    gridyspace = int(self.magnification*self.gridyspace)
-    gridxspace = int(self.magnification*self.gridxspace)
-    if gridxspace >= 3 and gridyspace >= 3:
-      for i in range(0,right,gridxspace):
-        self.mainCanvas.create_line(i,top,i,bottom,tags=("grid","vertical"),fill=self.gridcolor)
-      for i in range(-gridxspace,left,-gridxspace):
-        self.mainCanvas.create_line(i,top,i,bottom,tags=("grid","vertical"),fill=self.gridcolor)
-      for i in range(-gridyspace,top,-gridyspace):
-        self.mainCanvas.create_line(left,i,right,i,tags=("grid","horizontal"),fill=self.gridcolor)
-      for i in range(0,bottom,gridyspace):
-        self.mainCanvas.create_line(left,i,right,i,tags=("grid","horizontal"),fill=self.gridcolor)
-    self.mainCanvas.tag_lower("grid")
-
-  def drawAxes(self):
-    self.mainCanvas.delete("axes")
-    if not self.axesVisible:
-      return
-    left,top,right,bottom = [int(float(a)) for a in self.mainCanvas.cget("scrollregion").split()]
-    self.mainCanvas.create_line(0,top,0,bottom,tags=("axes","yaxis"),fill=self.axiscolor)
-    self.mainCanvas.create_line(left,0,right,0,tags=("axes","xaxis"),fill=self.axiscolor)
-    axisxspace = int(self.magnification*self.axisxspace)
-    axisyspace = int(self.magnification*self.axisyspace)
-    if axisxspace >= 3 and axisyspace >= 3:
-      for i in range(axisxspace,right,axisxspace):
-        self.mainCanvas.create_line(i,-5,i,5,tags=("axes","xaxis-ticks"),fill=self.tickcolor)
-      for i in range(-axisxspace,left,-axisxspace):
-        self.mainCanvas.create_line(i,-5,i,5,tags=("axes","xaxis-ticks"),fill=self.tickcolor)
-      for i in range(-axisyspace,top,-axisyspace):
-        self.mainCanvas.create_line(-5,i,5,i,tags=("axes","yaxis-ticks"),fill=self.tickcolor)
-      for i in range(axisyspace,bottom,axisyspace):
-        self.mainCanvas.create_line(-5,i,5,i,tags=("axes","yaxis-ticks"),fill=self.tickcolor)
-    self.mainCanvas.tag_lower("axes")
-
-  def updateCanvasSize(self,left=-200,top=-200,right=200,bottom=200):
-    self.parent.update_idletasks()
-    bbox = self.mainCanvas.bbox("drawn || image || node || precontrol || postcontrol")
-    if bbox == None:
-      bbox = (0,0,0,0)
-    #(topleft, bottomright)
-    left = min(bbox[0],left)
-    top = min(bbox[1],top)
-    right = max(bbox[2],right)
-    bottom = max(bbox[3],bottom)
-    w,h = self.mainCanvas.winfo_width(),self.mainCanvas.winfo_height()
-    if right-left < w:
-      extraw = w-(right-left)
-      right += extraw//2
-      left -= extraw//2
-    if bottom-top < h:
-      extrah = h-(bottom-top)
-      bottom += extrah//2
-      top -= extrah//2
-    self.mainCanvas.config(scrollregion=(left,top,right,bottom))
-    #self.mainCanvas.xview(MOVETO,float(split(self.mainCanvas["scrollregion"])[0]))
-    #self.mainCanvas.yview(MOVETO,float(split(self.mainCanvas["scrollregion"])[1]))
-    #self.mainCanvas.xview(MOVETO,(left+right)/2)
-    #self.mainCanvas.yview(MOVETO,(top+bottom)/2)
-    self.drawAxes()
-    self.drawGrid()
-
-  def bindEvents(self,tagorID):
-    if tagorID == None:
-      return
-    self.mainCanvas.tag_bind(tagorID,"<Control-Button-1>",self.itemToggleSelect)
-    self.mainCanvas.tag_bind(tagorID,"<Button-1>",self.itemSelect)
-    self.mainCanvas.tag_bind(tagorID,"<ButtonRelease-1>",self.itemMouseUp)
-    self.mainCanvas.tag_bind(tagorID,"<Double-Button-1>",self.itemEditEvt)
-    self.mainCanvas.tag_bind(tagorID,"<B1-Motion>",self.itemDrag)
-    self.mainCanvas.tag_bind(tagorID,"<Delete>",self.itemDelete)
-    self.mainCanvas.tag_bind(tagorID,"<Enter>",self.itemHighlight)
-    self.mainCanvas.tag_bind(tagorID,"<Button-3>",self.itemCanvasMenuPopup)
-
-  def bindItemEvents(self,item):
-    if item == None:
-      return
-    if isinstance(item,xasyScript) or isinstance(item,xasyText):
-      for image in item.imageList:
-        self.bindEvents(image.IDTag)
-    else:
-      self.bindEvents(item.IDTag)
-
-  def canQuit(self,force=False):
-    #print ("Quitting")
-    if not force and not self.testOrAcquireLock():
-      return
-    try:
-      self.releaseLock()
-    except:
-      pass
-    if self.undoRedoStack.changesMade():
-      result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
-      if str(result) == messagebox.CANCEL:
-        return
-      elif result == messagebox.YES:
-        self.fileSaveCmd()
-    try:
-      os.rmdir(getAsyTempDir())
-    except:
-      pass
-
-    stopQuickAsy()
-    self.parent.destroy()
-
-  def openFile(self,name):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock() #release the lock for loadFile
-    self.resetGUI()
-    self.loadFile(name)
-
-  def loadFile(self,name):
-    self.status.config(text="Loading "+name)
-    self.filename = os.path.abspath(name)
-    startQuickAsy()
-    self.retitle()
-    try:
-      try:
-        f = open(self.filename,'rt')
-      except:
-        if self.filename[-4:] == ".asy":
-          raise
-        else:
-          f = open(self.filename+".asy",'rt')
-          self.filename += ".asy"
-          self.retitle()
-      self.fileItems = xasyFile.parseFile(f)
-      f.close()
-    except IOError:
-      messagebox.showerror("File Opening Failed.","File could not be opened.")
-      self.fileItems = []
-    except:
-      self.fileItems = []
-      self.autoMakeScript = True
-      if self.autoMakeScript or messagebox.askyesno("Error Opening File", "File was not recognized as an xasy file.\nLoad as a script item?"):
-        try:
-          item = xasyScript(self.mainCanvas)
-          f.seek(0)
-          item.setScript(f.read())
-          self.addItemToFile(item)
-        except:
-          messagebox.showerror("File Opening Failed.","Could not load as a script item.")
-          self.fileItems = []
-    self.populateCanvasWithItems()
-    self.populatePropertyList()
-    self.updateCanvasSize()
-
-  def populateCanvasWithItems(self):
-    if(not self.testOrAcquireLock()):
-      return
-    self.mainCanvas.delete("drawn || image")
-    self.itemCount = 0
-    for item in self.fileItems:
-      item.drawOnCanvas(self.mainCanvas,self.magnification,forceAddition=True)
-      self.bindItemEvents(item)
-    self.releaseLock()
-
-  def propListCountItem(self,item):
-    plist = self.propList.get(0,END)
-    count = 1
-    for text in plist:
-      if text.startswith(item):
-        count += 1
-    return count
-
-  def describeItem(self,item):
-    if isinstance(item,xasyScript):
-      return "Code Module "+str(self.propListCountItem("Code Module"))
-    elif isinstance(item,xasyText):
-      return "Text Label "+str(self.propListCountItem("Text Label"))
-    elif isinstance(item,xasyFilledShape):
-      return "Filled Shape "+str(self.propListCountItem("Filled Shape"))
-    elif isinstance(item,xasyShape):
-      return "Outline "+str(self.propListCountItem("Outline"))
-    else:
-      return "If this happened, the program is corrupt!"
-
-  def populatePropertyList(self):
-    self.propList.delete(0,END)
-    for item in self.fileItems:
-      self.propList.insert(0,self.describeItem(item))
-
-  def saveFile(self,name):
-    if(not self.testOrAcquireLock()):
-      return
-    f = open(name,"wt")
-    xasyFile.saveFile(f,self.fileItems)
-    f.close()
-    self.undoRedoStack.setCommitLevel()
-    self.retitle()
-    self.releaseLock()
-
-  #menu commands
-  def fileNewCmd(self):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    #print ("Create New File")
-    if self.undoRedoStack.changesMade():
-      result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
-      if str(result) == messagebox.CANCEL:
-        return
-      elif result == messagebox.YES:
-        self.fileSaveCmd()
-    self.resetGUI()
-
-  def fileOpenCmd(self):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    #print ("Open a file")
-    if self.undoRedoStack.changesMade():
-      result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
-      if str(result) == messagebox.CANCEL:
-        return
-      elif result == messagebox.YES:
-        self.fileSaveCmd()
-    filename=filedialog.askopenfilename(filetypes=[("asy files","*.asy"),("All files","*")],title="Open File",parent=self.parent)
-    if type(filename) != type((0,)) and filename != None and filename != '':
-      self.filename = filename
-      self.openFile(self.filename)
-
-  def fileSaveCmd(self):
-    #print ("Save current file")
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    if self.filename == None:
-      filename=filedialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File")
-      if type(filename) != type((0,)) and filename != None and filename != '':
-        self.filename = filename
-    if self.filename != None:
-      self.saveFile(self.filename)
-
-  def fileSaveAsCmd(self):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    #print ("Save current file as")
-    filename=filedialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File")
-    if type(filename) != type((0,)) and filename != None and filename != '':
-      self.filename = filename
-      self.saveFile(self.filename)
-
-  #export the file
-  def exportEPS(self):
-    self.exportFile(self.filename,"eps")
-
-  def exportPDF(self):
-    self.exportFile(self.filename,"pdf")
-
-  def exportGIF(self):
-    self.exportFile(self.filename,"gif")
-
-  def exportPNG(self):
-    self.exportFile(self.filename,"png")
-
-  def exportSVG(self):
-    self.exportFile(self.filename,"svg")
-
-  def exportFile(self,inFile, outFormat):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    if inFile == None:
-      if messagebox.askyesno("xasy","File has not been saved.\nSave?"):
-        self.fileSaveAsCmd()
-        inFile = self.filename
-      else:
-        return
-    elif self.undoRedoStack.changesMade():
-      choice = messagebox._show("xasy","File has been modified.\nOnly saved changes can be exported.\nDo you want to save changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL)
-      choice = str(choice)
-      if choice != messagebox.YES:
-        return
-      else:
-        self.fileSaveCmd()
-    name = os.path.splitext(os.path.basename(self.filename))[0]+'.'+outFormat
-    outfilename = filedialog.asksaveasfilename(defaultextension = '.'+outFormat,filetypes=[(outFormat+" files","*."+outFormat)],initialfile=name,parent=self.parent,title="Choose output file")
-    if type(outfilename)==type((0,)) or not outfilename or outfilename == '':
-      return
-    fullname = os.path.abspath(outfilename)
-    outName = os.path.basename(outfilename)
-    command=[xasyOptions.options['asyPath'],"-f"+outFormat,"-o"+fullname,inFile]
-    saver = subprocess.Popen(command,stdin=PIPE,stdout=PIPE,stderr=PIPE)
-    saver.wait()
-    if saver.returncode != 0:
-      messagebox.showerror("Export Error","Export Error:\n"+saver.stdout.read()+saver.stderr.read())
-      self.status.config(text="Error exporting file")
-    else:
-      self.status.config(text="File exported successfully")
-
-  def fileExitCmd(self):
-    #print ("Exit xasy")
-    self.canQuit()
-
-  def editUndoCmd(self):
-    if not self.editor == None:
-      return
-    if(not self.testOrAcquireLock()):
-      return
-    self.undoOperation()
-    self.releaseLock()
-
-  def editRedoCmd(self):
-    if not self.editor == None:
-      return
-    if(not self.testOrAcquireLock()):
-      return
-    self.redoOperation()
-    self.releaseLock()
-
-  def helpHelpCmd(self):
-    print ("Get help on xasy")
-
-  def helpAsyDocCmd(self):
-    #print ("Open documentation about Asymptote")
-    asyExecute("help;\n")
-
-  def helpAboutCmd(self):
-    messagebox.showinfo("About xasy","A graphical interface for Asymptote "+xasyVersion)
-
-  def updateSelectedButton(self,newB):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    #disable switching modes during an incomplete drawing operation
-    if self.inDrawingMode:
-      return
-    self.selectedButton.config(relief = RAISED)
-    if newB == self.toolSelectButton or self.selectedButton == self.toolSelectButton:
-      self.mainCanvas.delete("highlightBox")
-    if self.editor != None:
-      self.editor.endEdit()
-      if self.editor.modified:
-        self.undoRedoStack.add(editDrawnItemAction(self,self.itemBeingEdited,copy.deepcopy(self.editor.shape),self.fileItems.index(self.editor.shape)))
-    if newB not in (self.toolSelectButton,self.toolMoveButton,self.toolHorizMoveButton,self.toolVertiMoveButton,self.toolRotateButton):
-      self.clearSelection()
-    self.selectedButton = newB
-    self.selectedButton.config(relief = SUNKEN)
-    self.status.config(text=self.toolDocs[newB])
-
-  #toolbar commands
-  def toolSelectCmd(self):
-    self.updateSelectedButton(self.toolSelectButton)
-  def toolMoveCmd(self):
-    self.updateSelectedButton(self.toolMoveButton)
-  def toolRotateCmd(self):
-    self.updateSelectedButton(self.toolRotateButton)
-  def toolVertiMoveCmd(self):
-    self.updateSelectedButton(self.toolVertiMoveButton)
-  def toolHorizMoveCmd(self):
-    self.updateSelectedButton(self.toolHorizMoveButton)
-  def toolDrawLinesCmd(self):
-    self.updateSelectedButton(self.toolDrawLinesButton)
-  def toolDrawBeziCmd(self):
-    self.updateSelectedButton(self.toolDrawBeziButton)
-  def toolDrawPolyCmd(self):
-    self.updateSelectedButton(self.toolDrawPolyButton)
-  def toolFillPolyCmd(self):
-    self.updateSelectedButton(self.toolFillPolyButton)
-  def toolDrawEllipCmd(self):
-    self.updateSelectedButton(self.toolDrawEllipButton)
-  def toolFillEllipCmd(self):
-    self.updateSelectedButton(self.toolFillEllipButton)
-  def toolDrawShapeCmd(self):
-    self.updateSelectedButton(self.toolDrawShapeButton)
-  def toolFillShapeCmd(self):
-    self.updateSelectedButton(self.toolFillShapeButton)
-  def toolTextCmd(self):
-    self.updateSelectedButton(self.toolTextButton)
-  def toolAsyCmd(self):
-    # ignore the command if we are too busy to process it
-    if not self.testOrAcquireLock():
-      return
-    self.updateSelectedButton(self.toolSelectButton)
-    self.clearSelection()
-    self.clearHighlight()
-    self.unbindGlobalEvents()
-    try:
-      self.getNewText("// enter your code here")
-    except Exception as e:
-      messagebox.showerror('xasy Error',e.message)
-    else:
-      self.addItemToFile(xasyScript(self.mainCanvas))
-      text = self.newText
-      self.undoRedoStack.add(addScriptAction(self,self.fileItems[-1]))
-      self.fileItems[-1].setScript(text)
-      self.fileItems[-1].drawOnCanvas(self.mainCanvas,self.magnification)
-      self.bindItemEvents(self.fileItems[-1])
-    self.bindGlobalEvents()
-    self.releaseLock()
-  def toolRaiseCmd(self):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    if not self.inDrawingMode and self.editor == None:
-      itemList = []
-      indexList = []
-      for ID in self.mainCanvas.find_withtag("selectedItem"):
-        item = self.findItem(ID)
-        if item not in itemList:
-          itemList.append(item)
-          indexList.append(self.fileItems.index(item))
-          self.raiseSomething(item)
-      self.undoRedoStack.add(itemRaiseAction(self,itemList,indexList))
-  def toolLowerCmd(self):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    if not self.inDrawingMode and self.editor == None:
-      itemList = []
-      indexList = []
-      for ID in self.mainCanvas.find_withtag("selectedItem"):
-        item = self.findItem(ID)
-        if item not in itemList:
-          itemList.append(item)
-          indexList.append(self.fileItems.index(item))
-          self.lowerSomething(item)
-      self.undoRedoStack.add(itemLowerAction(self,itemList,indexList))
-  def itemRaise(self,event):
-    self.mainCanvas.tag_raise(CURRENT)
-  def itemLower(self,event):
-    self.mainCanvas.tag_lower(CURRENT)
-
-  #options bar commands
-  def setPenColCmd(self):
-    if not self.testOrAcquireLock():
-      return
-    old = self.penColor
-    self.penColor = xasyColorDlg(self.parent).getColor(self.penColor)
-    if self.penColor != old:
-      self.tkPenColor = RGB255hex(RGBreal255(self.penColor))
-      self.penColButton.config(activebackground=self.tkPenColor,
-                               activeforeground=self.foregroundPenColor(self.tkPenColor))
-      self.showCurrentPen()
-    self.releaseLock()
-
-  def clearSelection(self):
-    self.hideSelectionBox()
-    self.mainCanvas.dtag("selectedItem","selectedItem")
-
-  def hideSelectionBox(self):
-    self.mainCanvas.itemconfigure("outlineBox",width=1,outline=self.backColor)
-    self.mainCanvas.tag_lower("outlineBox")
-    self.mainCanvas.coords("outlineBox",self.mainCanvas.bbox(ALL))
-
-  def showSelectionBox(self):
-    self.mainCanvas.itemconfigure("outlineBox",width=2,outline="#801111")
-    self.mainCanvas.tag_raise("outlineBox")
-
-  def setSelection(self,what):
-    self.mainCanvas.addtag_withtag("selectedItem",what)
-    self.updateSelection()
-    if self.selectedButton == self.toolSelectButton and len(self.mainCanvas.find_withtag("selectedItem")) > 0:
-      self.updateSelectedButton(self.toolMoveButton)
-
-  def unSelect(self,what):
-    self.mainCanvas.dtag(what,"selectedItem")
-    self.updateSelection()
-
-  def updateSelection(self):
-    self.clearHighlight()
-    theBbox = self.mainCanvas.bbox("selectedItem")
-    if theBbox != None:
-      theBbox = (theBbox[0]-2,theBbox[1]-2,theBbox[2]+2,theBbox[3]+2)
-      self.mainCanvas.coords("outlineBox",theBbox)
-      self.showSelectionBox()
-    else:
-      self.clearSelection()
-
-  #event handlers
-  def updateZoom(self):
-    self.zoomMenu.config(state=DISABLED)
-    self.magnification = self.magVal.get()/100.0
-    if self.magnification != self.previousZoom:
-      self.populateCanvasWithItems()
-      self.updateCanvasSize()
-      self.updateSelection()
-      self.drawAxes()
-      self.drawGrid()
-      self.previousZoom = self.magnification
-    self.zoomMenu.config(state=NORMAL)
-
-  def zoomViewCmd(self,*args):
-    magnification = self.magVal.get()/100.0
-    self.updateZoom();
-
-  def selectItem(self,item):
-    self.clearSelection()
-    if isinstance(item,xasyScript) or isinstance(item,xasyText):
-      for image in item.imageList:
-        self.setSelection(image.IDTag)
-    else:
-      self.setSelection(item.IDTag)
-
-  def propSelect(self,event):
-    items = [int(a) for a in self.propList.curselection()]
-    if len(items)>0:
-      try:
-        self.selectItem(self.fileItems[len(self.fileItems)-items[0]-1])
-      except:
-        raise
-
-  def findItem(self,ID):
-    for item in self.fileItems:
-      if isinstance(item,xasyScript) or isinstance(item,xasyText):
-        for image in item.imageList:
-          if image.IDTag == ID:
-            return item
-      else:
-        if item.IDTag == ID:
-          return item
-    raise Exception("Illegal operation: Item with matching ID could not be found.")
-
-  def findItemImageIndex(self,item,ID):
-    count = 0
-    for image in item.imageList:
-      if image.IDTag == ID:
-        return count
-      else:
-        count += 1
-    raise Exception("Illegal operation: Image with matching ID could not be found.")
-    return None
-
-  def raiseSomething(self,item,force=False):
-    if self.fileItems[-1] != item or force:
-      index = len(self.fileItems)-self.fileItems.index(item)-1
-      text = self.propList.get(index)
-      self.propList.delete(index)
-      self.propList.insert(0,text)
-      for i in range(self.fileItems.index(item),len(self.fileItems)-1):
-        self.fileItems[i] = self.fileItems[i+1]
-      self.fileItems[-1] = item
-      if isinstance(item,xasyScript) or isinstance(item,xasyText):
-        for im in item.imageList:
-          if im.IDTag != None:
-            self.mainCanvas.tag_raise(im.IDTag)
-      else:
-        if item.IDTag != None:
-          self.mainCanvas.tag_raise(item.IDTag)
-
-  def lowerSomething(self,item):
-    if self.fileItems[0] != item:
-      index = len(self.fileItems)-self.fileItems.index(item)-1
-      text = self.propList.get(index)
-      self.propList.delete(index)
-      self.propList.insert(END,text)
-      indices = range(self.fileItems.index(item))
-      indices.reverse()
-      for i in indices:
-        self.fileItems[i+1] = self.fileItems[i]
-      self.fileItems[0] = item
-      if isinstance(item,xasyScript) or isinstance(item,xasyText):
-        item.imageList.reverse()
-        for im in item.imageList:
-          if im.IDTag != None:
-            self.mainCanvas.tag_lower(im.IDTag)
-        item.imageList.reverse()
-      else:
-        if item.IDTag != None:
-          self.mainCanvas.tag_lower(item.IDTag)
-      self.mainCanvas.tag_lower("axes || grid")
-
-  def translateSomething(self,ID,translation,specificItem=None,specificIndex=None):
-    transform = asyTransform((translation[0],translation[1],1,0,0,1))
-    if ID == -1:
-      item = specificItem
-    else:
-      item = self.findItem(ID)
-    if isinstance(item,xasyText) or isinstance(item,xasyScript):
-      if ID == -1:
-        index = specificIndex
-      else:
-        index = self.findItemImageIndex(item,ID)
-      try:
-        original = item.transform[index]
-      except:
-        original = identity()
-      item.transform[index] = transform*original
-      bbox = item.imageList[index].originalImage.bbox
-      item.imageList[index].originalImage.bbox = bbox[0]+translation[0],bbox[1]+translation[1],bbox[2]+translation[0],bbox[3]+translation[1]
-    else:
-      item.transform = [transform*item.transform[0]]
-
-  def makeRotationMatrix(self,theta,origin):
-    rotMat = (math.cos(theta),-math.sin(theta),math.sin(theta),math.cos(theta))
-    shift = asyTransform((0,0,1-rotMat[0],-rotMat[1],-rotMat[2],1-rotMat[3]))*origin
-    return asyTransform((shift[0],shift[1],rotMat[0],rotMat[1],rotMat[2],rotMat[3]))
-
-  def rotateSomething(self,ID,theta,origin,specificItem=None,specificIndex=None):
-    #print ("Rotating by {} around {}".format(theta*180.0/math.pi,origin))
-    rotMat = self.makeRotationMatrix(theta,(origin[0]/self.magnification,origin[1]/self.magnification))
-    #print (rotMat)
-    if ID == -1:
-      item = specificItem
-    else:
-      item = self.findItem(ID)
-    if isinstance(item,xasyText) or isinstance(item,xasyScript):
-      #transform the image
-      if ID == -1:
-        index = specificIndex
-      else:
-        index = self.findItemImageIndex(item,ID)
-      try:
-        original = item.transform[index]
-      except:
-        original = identity()
-      oldBbox = item.imageList[index].originalImage.bbox
-      oldBbox = (oldBbox[0],-oldBbox[1],oldBbox[2],-oldBbox[3])
-      item.transform[index] = rotMat*item.transform[index]
-      item.transform[index] = rotMat*original
-      item.imageList[index].originalImage.theta += theta
-      item.imageList[index].image = item.imageList[index].originalImage.rotate(item.imageList[index].originalImage.theta*180.0/math.pi,expand=True,resample=Image.BICUBIC)
-      item.imageList[index].itk = ImageTk.PhotoImage(item.imageList[index].image)
-      self.mainCanvas.itemconfigure(ID,image=item.imageList[index].itk)
-      #the image has been rotated in place
-      #now, compensate for any resizing and shift to the correct location
-      #
-      #  p0 --- p1               p1
-      #  |      |     --->      /  \
-      #  p2 --- p3             p0  p3
-      #                         \ /
-      #                          p2
-      #
-      rotMat2 = self.makeRotationMatrix(item.imageList[index].originalImage.theta,origin)
-      p0 = rotMat2*(oldBbox[0],-oldBbox[3])#switch to usual coordinates
-      p1 = rotMat2*(oldBbox[2],-oldBbox[3])
-      p2 = rotMat2*(oldBbox[0],-oldBbox[1])
-      p3 = rotMat2*(oldBbox[2],-oldBbox[1])
-      newTopLeft = (min(p0[0],p1[0],p2[0],p3[0]),-max(p0[1],p1[1],p2[1],p3[1]))#switch back to screen coords
-      shift = (newTopLeft[0]-oldBbox[0],newTopLeft[1]-oldBbox[3])
-      #print (theta*180.0/math.pi,origin,oldBbox,newTopLeft,shift)
-      #print (item.imageList[index].originalImage.size)
-      #print (item.imageList[index].image.size)
-      #print
-      self.mainCanvas.coords(ID,oldBbox[0]+shift[0],oldBbox[3]+shift[1])
-    else:
-      #transform each point of the object
-      xform = rotMat*item.transform[0]
-      item.transform = [identity()]
-      for i in range(len(item.path.nodeSet)):
-        if item.path.nodeSet[i] != 'cycle':
-          item.path.nodeSet[i] = xform*item.path.nodeSet[i]
-      for i in range(len(item.path.controlSet)):
-        item.path.controlSet[i][0] = xform*item.path.controlSet[i][0]
-        item.path.controlSet[i][1] = xform*item.path.controlSet[i][1]
-      item.drawOnCanvas(self.mainCanvas,self.magnification)
-
-  def deleteItem(self,item):
-    if isinstance(item,xasyScript) or isinstance(item,xasyText):
-      if isinstance(item,xasyScript):
-        self.undoRedoStack.add(deleteScriptAction(self,item,self.fileItems.index(item)))
-      else:
-        self.undoRedoStack.add(deleteLabelAction(self,item,self.fileItems.index(item)))
-      for image in item.imageList:
-        self.mainCanvas.delete(image.IDTag)
-    else:
-      if isinstance(item,xasyDrawnItem):
-        self.undoRedoStack.add(deleteDrawnItemAction(self,item,self.fileItems.index(item)))
-      self.mainCanvas.delete(item.IDTag)
-    self.fileItems.remove(item)
-    self.populatePropertyList()
-    self.clearSelection()
-
-  def deleteSomething(self,ID):
-    self.clearSelection()
-    self.clearHighlight()
-    if self.editor != None:
-      self.editor.endEdit()
-      if self.editor.modified:
-        self.undoRedoStack.add(editDrawnItemAction(self,self.itemBeingEdited,copy.deepcopy(self.editor.shape),self.fileItems.index(self.editor.shape)))
-    item = self.findItem(ID)
-    #save an event on the undoredo stack
-    if isinstance(item,xasyScript):
-      index = self.findItemImageIndex(item,ID)
-      item.transform[index].deleted = True
-    else:
-      if isinstance(item,xasyText):
-        self.undoRedoStack.add(deleteLabelAction(self,item,self.fileItems.index(item)))
-      elif isinstance(item,xasyDrawnItem):
-        self.undoRedoStack.add(deleteDrawnItemAction(self,item,self.fileItems.index(item)))
-      self.fileItems.remove(item)
-    self.mainCanvas.delete(ID)
-    self.populatePropertyList()
-
-  def scriptEditThread(self,oldText):
-    try:
-      self.newText = xasyCodeEditor.getText(oldText)
-    except:
-      self.newText = -1
-
-  def getNewText(self,oldText):
-    editThread = threading.Thread(target=self.scriptEditThread,args=(oldText,))
-    editThread.start()
-    while editThread.isAlive():
-      time.sleep(0.05)
-      self.parent.update()
-    editThread.join()
-    if type(self.newText)==type(-1):
-      self.newText = ''
-      raise Exception('Error launching external editor. Please check xasy options.')
-
-  def itemEdit(self,item):
-    # are we too busy?
-    if not self.testOrAcquireLock():
-      return
-    self.updateSelectedButton(self.toolSelectButton)
-    if isinstance(item,xasyScript):
-      self.unbindGlobalEvents()
-      oldText = item.script
-      try:
-        self.getNewText(oldText)
-      except Exception as e:
-        messagebox.showerror('xasy Error',e.message)
-      else:
-        if self.newText != oldText:
-          self.undoRedoStack.add(editScriptAction(self,item,self.newText,oldText))
-          item.setScript(self.newText)
-          item.drawOnCanvas(self.mainCanvas,self.magnification)
-          self.bindItemEvents(item)
-      self.bindGlobalEvents()
-    elif isinstance(item,xasyText):
-      theText = simpledialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue=item.label.text,parent=self.parent)
-      if theText != None and theText != "":
-        self.undoRedoStack.add(editLabelTextAction(self,item,theText,item.label.text))
-        item.label.text = theText
-        item.drawOnCanvas(self.mainCanvas,self.magnification)
-        self.bindItemEvents(item)
-    elif isinstance(item,xasyShape):
-      self.clearSelection()
-      self.clearHighlight()
-      self.itemBeingEdited = copy.deepcopy(item)
-      self.editor = xasyBezierEditor(self,item,self.mainCanvas)
-    self.updateSelection()
-    self.releaseLock()
-
-  def itemEditEvt(self,event):
-    if not self.inDrawingMode:
-      ID = self.mainCanvas.find_withtag(CURRENT)[0]
-      item = self.findItem(ID)
-      self.itemEdit(item)
-
-  def itemDrag(self,event):
-    x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
-    x = x0/self.magnification
-    y = y0/self.magnification
-    if self.selectedButton not in [self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton]:
-      return
-    if "selectedItem" in self.mainCanvas.gettags(CURRENT):
-      self.amDragging = True
-      for ID in self.mainCanvas.find_withtag("selectedItem"):
-        transform = identity()
-        if self.selectedButton == self.toolMoveButton:
-          translation = (x0-self.dragStartx,-(y0-self.dragStarty))
-        elif self.selectedButton == self.toolVertiMoveButton:
-          translation = (0,-(y0-self.dragStarty))
-        elif self.selectedButton == self.toolHorizMoveButton:
-          translation = (x0-self.dragStartx,0)
-        self.translateSomething(ID,(translation[0]/self.magnification,translation[1]/self.magnification))
-        self.mainCanvas.move(ID,translation[0],-translation[1])
-        self.updateSelection()
-        self.updateCanvasSize()
-      self.distanceDragged = (self.distanceDragged[0]+translation[0],self.distanceDragged[1]-translation[1])
-    self.dragStartx,self.dragStarty = x0,y0
-
-  def itemMouseUp(self,event):
-    self.freeMouseDown = True
-    if self.amDragging:
-      IDList = self.mainCanvas.find_withtag("selectedItem")
-      itemList = []
-      indexList = []
-      for ID in IDList:
-        item = self.findItem(ID)
-        if item not in itemList:
-          itemList.append(item)
-          try:
-            indexList.append([self.findItemImageIndex(item,ID)])
-          except:
-            indexList.append([None])
-        else:
-          indexList[itemList.index(item)].append(self.findItemImageIndex(item,ID))
-      self.undoRedoStack.add(translationAction(self,itemList,indexList,(self.distanceDragged[0],-self.distanceDragged[1])))
-      self.amDragging = False
-
-  def itemSelect(self,event):
-    x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
-    x = x0/self.magnification
-    y = y0/self.magnification
-    self.dragStartx,self.dragStarty = x0,y0
-    self.distanceDragged = (0,0)
-    if self.selectedButton in [self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton]:
-      self.freeMouseDown = False
-    if self.selectedButton == self.toolSelectButton or (len(self.mainCanvas.find_withtag("selectedItem"))<=1 and self.selectedButton in [self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton]):
-      self.clearSelection()
-      self.setSelection(CURRENT)
-
-  def itemToggleSelect(self,event):
-    #print ("control click")
-    x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
-    x = x0/self.magnification
-    y = y0/self.magnification
-    if self.selectedButton in [self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton]:
-      self.freeMouseDown = False
-      self.dragStartx,self.dragStarty = x0,y0
-      if "selectedItem" in self.mainCanvas.gettags(CURRENT):
-        self.unSelect(CURRENT)
-      else:
-        self.setSelection(CURRENT)
-
-  def itemDelete(self,event):
-    if(not self.testOrAcquireLock()):
-      return
-    itemList = []
-    self.undoRedoStack.add(endActionGroup)
-    for ID in self.mainCanvas.find_withtag("selectedItem"):
-      item = self.findItem(ID)
-      if isinstance(item,xasyScript):
-        index = self.findItemImageIndex(item,ID)
-        if item not in itemList:
-          itemList.append([item,[index],[item.transform[index]]])
-        else:
-          x = None
-          for i in itemList:
-            if i[0] == item:
-              x = i
-          x[1].append(index)
-          x[2].append(item.transform[index])
-      self.deleteSomething(ID)
-    for entry in itemList:
-      self.undoRedoStack.add(deleteScriptItemAction(self,entry[0],entry[1],entry[2]))
-    self.undoRedoStack.add(beginActionGroup)
-    self.clearSelection()
-    self.releaseLock()
-
-  def itemMotion(self,event):
-    pass
-
-  def itemHighlight(self,event):
-    if self.selectedButton in [self.toolSelectButton] and self.editor == None:
-      box = self.mainCanvas.bbox(CURRENT)
-      box = (box[0]-2,box[1]-2,box[2]+2,box[3]+2)
-      if len(self.mainCanvas.find_withtag("highlightBox"))==0:
-        self.mainCanvas.create_rectangle(box,tags="highlightBox",width=2,outline="red")
-      else:
-        self.mainCanvas.tag_raise("highlightBox")
-        self.mainCanvas.coords("highlightBox",*box)
-      self.mainCanvas.tag_bind("highlightBox","<Leave>",self.itemUnHighlight)
-
-  def itemUnHighlight(self,event):
-    self.clearHighlight()
-
-  def clearHighlight(self):
-    self.mainCanvas.delete("highlightBox")
-
-  def itemLeftDown(self,event):
-    pass
-
-  def itemLeftUp(self,event):
-    pass
-
-  def itemRightDown(self,event):
-    pass
-
-  def itemRightUp(self,event):
-    pass
-
-  def canvMotion(self,event):
-    self.coords.config(
-    text="(%.3f,%.3f)"%(self.mainCanvas.canvasx(event.x)/self.magnification,-self.mainCanvas.canvasy(event.y)/self.magnification)
-    )
-
-  def addItemToFile(self,item):
-    self.fileItems.append(item)
-    self.propList.insert(0,self.describeItem(item))
-    self.updateCanvasSize()
-
-  def startDraw(self,event):
-    # don't start if we can't finish
-    if not self.testOrAcquireLock() and not self.inDrawingMode:
-      return
-    x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
-    x = x0/self.magnification
-    y = y0/self.magnification
-    #self.mainCanvas.create_oval(x,y,x,y,width=5)
-    if self.selectedButton == self.toolDrawEllipButton:
-      pass
-    elif self.selectedButton == self.toolFillEllipButton:
-      pass
-    elif self.selectedButton == self.toolTextButton:
-      theText = simpledialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue="",parent=self.parent)
-      if theText != None and theText != "":
-        theItem = xasyText(theText,(x,-y),asyPen(self.penColor,self.penWidth,self.penOptions))
-        theItem.drawOnCanvas(self.mainCanvas,self.magnification)
-        self.bindItemEvents(theItem)
-        self.addItemToFile(theItem)
-        self.undoRedoStack.add(addLabelAction(self,theItem))
-      self.releaseLock()
-      self.updateSelectedButton(self.toolSelectButton)
-    elif self.selectedButton in [self.toolDrawLinesButton,self.toolDrawBeziButton,self.toolDrawPolyButton,self.toolDrawShapeButton,self.toolFillPolyButton,self.toolFillShapeButton]:
-      self.inDrawingMode = True
-      try:
-        if len(self.itemBeingDrawn.path.nodeSet) == 0:
-          raise Exception
-        else:
-          if self.selectedButton in [self.toolDrawLinesButton,self.toolDrawPolyButton,self.toolFillPolyButton]:
-            self.itemBeingDrawn.appendPoint((x,-y),'--')
-          else:#drawBezi,drawShape,fillShape
-            self.itemBeingDrawn.appendPoint((x,-y),'..')
-      except:
-        path = asyPath()
-        if self.selectedButton == self.toolDrawLinesButton:
-          path.initFromNodeList([(x,-y),(x,-y)],['--'])
-        elif self.selectedButton == self.toolDrawBeziButton:
-          path.initFromNodeList([(x,-y),(x,-y)],['..'])
-        elif self.selectedButton == self.toolDrawPolyButton or self.selectedButton == self.toolFillPolyButton:
-          path.initFromNodeList([(x,-y),(x,-y),'cycle'],['--','--'])
-        elif self.selectedButton == self.toolDrawShapeButton or self.selectedButton == self.toolFillShapeButton:
-          path.initFromNodeList([(x,-y),(x,-y),'cycle'],['..','..'])
-        if self.selectedButton in [self.toolDrawLinesButton,self.toolDrawBeziButton,self.toolDrawPolyButton,self.toolDrawShapeButton]:
-          self.itemBeingDrawn = xasyShape(path,pen=asyPen(self.penColor,self.penWidth,self.penOptions))
-        else:
-          if self.penOptions.find("fillrule") != -1 or self.penOptions.find("evenodd") != -1 or self.penOptions.find("zerowinding") != -1:
-            options = self.penOptions
-          else:
-            options = "evenodd"
-          self.itemBeingDrawn = xasyFilledShape(path,pen=asyPen(self.penColor,self.penWidth,options))
-        self.itemBeingDrawn.drawOnCanvas(self.mainCanvas,self.magnification)
-        self.bindItemEvents(self.itemBeingDrawn)
-        self.mainCanvas.bind("<Motion>",self.extendDraw)
-
-  def extendDraw(self,event):
-    x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
-    x = x0/self.magnification
-    y = y0/self.magnification
-    tags = self.mainCanvas.gettags("itemBeingDrawn")
-    self.itemBeingDrawn.setLastPoint((x,-y))
-    self.itemBeingDrawn.drawOnCanvas(self.mainCanvas,self.magnification)
-    self.canvMotion(event)
-
-  def endDraw(self,event):
-    if not self.inDrawingMode or self.itemBeingDrawn == None:
-      return
-    x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
-    x = x0/self.magnification
-    y = y0/self.magnification
-    #if self.selectedButton in [self.toolDrawLinesButton,self.toolDrawPolyButton,self.toolFillPolyButton]:
-      #self.itemBeingDrawn.appendPoint((x,-y),'--')
-    #else:
-      #self.itemBeingDrawn.appendPoint((x,-y),'..')
-
-    #only needed for certain key bindings when startDraw is triggered right before an endDraw
-    #e.g.: single click: startDraw, double click: endDraw
-    self.itemBeingDrawn.removeLastPoint()
-    self.itemBeingDrawn.setLastPoint((x,-y))
-    self.itemBeingDrawn.drawOnCanvas(self.mainCanvas,self.magnification)
-    self.addItemToFile(self.itemBeingDrawn)
-    self.undoRedoStack.add(addDrawnItemAction(self,self.itemBeingDrawn))
-    self.itemBeingDrawn = None
-    self.mainCanvas.dtag("itemBeingDrawn","itemBeingDrawn")
-    self.mainCanvas.bind("<Motion>",self.canvMotion)
-    self.inDrawingMode = False
-    self.releaseLock()
-
-  def canvLeftDown(self,event):
-    #print ("Left Mouse Down")
-    self.selectDragStart = (self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y))
-    theBbox = self.mainCanvas.bbox("selectedItem")
-    if theBbox != None:
-      self.selectBboxMidpoint = (theBbox[0]+theBbox[2])/2.0,-(theBbox[1]+theBbox[3])/2.0
-    if self.freeMouseDown and self.editor != None:
-      self.editor.endEdit()
-      if self.editor.modified:
-        self.undoRedoStack.add(editDrawnItemAction(self,self.itemBeingEdited,copy.deepcopy(self.editor.shape),self.fileItems.index(self.editor.shape)))
-      self.editor = None
-    elif self.selectedButton in (self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton):
-      if self.freeMouseDown:
-        self.clearSelection()
-        self.dragSelecting = False
-    else:
-      self.startDraw(event)
-
-  def canvLeftUp(self,event):
-    #print ("Left Mouse Up")
-    # if we're busy, ignore it
-    if not self.testOrAcquireLock():
-      return
-    self.freeMouseDown = True
-    if self.inRotatingMode:
-      for item in self.itemsBeingRotated:
-        item.drawOnCanvas(self.mainCanvas,self.magnification)
-        self.bindItemEvents(item)
-      self.updateSelection()
-      self.itemsBeingRotated = []
-      self.inRotatingMode = False
-    if self.dragSelecting:
-      self.hideSelectionBox()
-      self.dragSelecting = False
-      self.mainCanvas.addtag_enclosed("enclosed",self.selectDragStart[0],self.selectDragStart[1],self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y))
-      for item in self.mainCanvas.find_withtag("enclosed"):
-        tags = self.mainCanvas.gettags(item)
-        if "drawn" not in tags and "image" not in tags:
-          self.mainCanvas.dtag(item,"enclosed")
-      self.mainCanvas.addtag_withtag("selectedItem","enclosed")
-      self.mainCanvas.dtag("enclosed","enclosed")
-      if self.selectedButton == self.toolSelectButton and len(self.mainCanvas.find_withtag("selectedItem")) > 0:
-        self.updateSelectedButton(self.toolMoveButton)
-      self.updateSelection()
-    self.releaseLock()
-
-  def canvDrag(self,event):
-    x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)
-    x = x0/self.magnification
-    y = y0/self.magnification
-    if self.selectedButton == self.toolSelectButton and self.editor == None:
-      self.mainCanvas.coords("outlineBox",self.selectDragStart[0],self.selectDragStart[1],x0,y0)
-      self.showSelectionBox()
-      self.dragSelecting = True
-    elif self.selectedButton == self.toolRotateButton and self.editor == None:
-      bbox = self.mainCanvas.bbox("selectedItem")
-      if bbox != None:
-        p1 = self.selectDragStart[0]-self.selectBboxMidpoint[0],-self.selectDragStart[1]-self.selectBboxMidpoint[1]
-        mp1 = math.sqrt(p1[0]**2+p1[1]**2)
-        p2 = x0-self.selectBboxMidpoint[0],-y0-self.selectBboxMidpoint[1]
-        mp2 = math.sqrt(p2[0]**2+p2[1]**2)
-        if mp1 != 0:
-          t1 = math.acos(p1[0]/mp1)
-          if p1[1] < 0:
-            t1 *= -1
-        else:
-          t1 = 0
-        if mp2 != 0:
-          t2 = math.acos(p2[0]/mp2)
-          if p2[1] < 0:
-            t2 *= -1
-        else:
-          t2 = 0
-        theta = t2-t1
-        self.selectDragStart = x0,y0
-        self.itemsBeingRotated = []
-        for ID in self.mainCanvas.find_withtag("selectedItem"):
-          self.rotateSomething(ID,theta,self.selectBboxMidpoint)
-          item = self.findItem(ID)
-          if not item in self.itemsBeingRotated:
-            self.itemsBeingRotated.append(item)
-        self.updateSelection()
-        self.updateCanvasSize()
-        if not self.inRotatingMode:
-          self.currentRotationAngle = theta
-          IDList = self.mainCanvas.find_withtag("selectedItem")
-          itemList = []
-          indexList = []
-          for ID in IDList:
-            item = self.findItem(ID)
-            if item not in itemList:
-              itemList.append(item)
-              try:
-                indexList.append([self.findItemImageIndex(item,ID)])
-              except:
-                indexList.append([None])
-            else:
-              indexList[itemList.index(item)].append(self.findItemImageIndex(item,ID))
-          self.undoRedoStack.add(rotationAction(self,itemList,indexList,self.currentRotationAngle,self.selectBboxMidpoint))
-          self.inRotatingMode = True
-        else:
-          self.currentRotationAngle += theta
-          self.undoRedoStack.undoStack[-1].angle = self.currentRotationAngle
-
-  def canvEnter(self,event):
-    self.freeMouseDown = True
-    event.widget.focus_set()
-
-  def canvLeave(self,event):
-    self.freeMouseDown = False
-
-  def canvRightDown(self,event):
-    pass
-    #print ("Right Mouse Down")
-
-  def canvRightUp(self,event):
-    pass
-    #print ("Right Mouse Up")
-
-  def configEvt(self,event):
-    self.updateCanvasSize()
-    self.sizePane()
-
-  def sizePane(self):
-    width = self.windowPane.winfo_width()-10
-    cwidth = min(int(0.87*self.windowPane.winfo_width()),width-75)
-    if self.paneVisible:
-      self.windowPane.paneconfigure(self.canvFrame,minsize=cwidth)
-    else:
-      self.windowPane.paneconfigure(self.canvFrame,minsize=width)
-    self.windowPane.paneconfigure(self.propFrame,minsize=75)
-
-  def togglePaneEvt(self,event):
-    self.paneVisible = not self.paneVisible
-    self.sizePane()
-
-  def popupDelete(self):
-    self.deleteItem(self.itemPopupMenu.item)
-
-  def popupEdit(self):
-    self.itemEdit(self.itemPopupMenu.item)
-
-  def popupViewCode(self):
-    messagebox.showinfo("Item Code",self.itemPopupMenu.item.getCode())
-
-  def popupClearTransform(self):
-    self.undoRedoStack.add(clearItemTransformsAction(self,self.itemPopupMenu.item,copy.deepcopy(self.itemPopupMenu.item.transform)))
-    if isinstance(self.itemPopupMenu.item,xasyScript) or isinstance(self.itemPopupMenu.item,xasyText):
-      for i in range(len(self.itemPopupMenu.item.transform)):
-        self.itemPopupMenu.item.transform[i] = identity()
-    else:
-      self.itemPopupMenu.item.transform = [identity()]
-    self.popupRedrawItem()
-
-  def popupRedrawItem(self):
-    if not self.testOrAcquireLock():
-      return
-    self.clearSelection()
-    self.clearHighlight()
-    self.itemPopupMenu.item.drawOnCanvas(self.mainCanvas,self.magnification)
-    self.bindItemEvents(self.itemPopupMenu.item)
-    self.updateCanvasSize()
-    self.releaseLock()
-
-  def hidePopupMenu(self):
-    try:
-      self.itemPopupMenu.unpost()
-    except:
-      pass
-
-  def itemMenuPopup(self,parent,item,x,y):
-    self.hidePopupMenu()
-    self.itemPopupMenu = Menu(parent,tearoff=False)
-    self.itemPopupMenu.add_command(label="Edit",command=self.popupEdit)
-    self.itemPopupMenu.add_command(label="Clear Transforms",command=self.popupClearTransform)
-    self.itemPopupMenu.add_command(label="Redraw",command=self.popupRedrawItem)
-    self.itemPopupMenu.add_command(label="View code",command=self.popupViewCode)
-    self.itemPopupMenu.add_separator()
-    self.itemPopupMenu.add_command(label="Delete",command=self.popupDelete)
-    self.itemPopupMenu.item = item
-    #self.itemPopupMenu.bind("<Leave>",lambda a:self.itemPopupMenu.unpost())
-    #self.itemPopupMenu.bind("<FocusOut>",lambda a:self.itemPopupMenu.unpost())
-    self.itemPopupMenu.post(x,y)
-
-  def itemPropMenuPopup(self,event):
-    try:
-      item = self.fileItems[len(self.fileItems)-int(self.propList.curselection()[0])-1]
-      self.itemMenuPopup(self.propList,item,event.x_root,event.y_root)
-    except:
-      pass
-
-  def itemCanvasMenuPopup(self,event):
-    if self.selectedButton in (self.toolSelectButton,self.toolMoveButton,self.toolVertiMoveButton,self.toolHorizMoveButton,self.toolRotateButton):
-      try:
-        item = self.findItem(self.mainCanvas.find_withtag(CURRENT)[0])
-      except:
-        item = None
-      if item != None:
-        self.itemMenuPopup(self.mainCanvas,item,event.x_root,event.y_root)
-
-  def editOptions(self):
-    if(not self.testOrAcquireLock()):
-      return
-    self.releaseLock()
-    xasyOptionsDialog.xasyOptionsDlg(self.parent)
-    self.applyOptions()
-
-  def resetOptions(self):
-    xasyOptions.setDefaults()
-    self.applyOptions()
-
-  def applyPenWidth(self):
-    self.pendingPenWidthChange = None
-    if self.validatePenWidth():
-      old = self.penWidth
-      self.penWidth = float(self.penWidthEntry.get())
-      if old != self.penWidth:
-        self.showCurrentPen()
-
-  def validatePenWidth(self):
-    text = self.penWidthEntry.get()
-    try:
-      width = float(text)
-      if width <= 0:
-        return False
-      else:
-        return True
-    except:
-      return False
-
-  def showCurrentPen(self):
-    mag = 1
-    width = self.penWidth
-    while width > 10:
-      width /= 2
-      mag *= 2
-    self.penDisp.itemconfigure("penDisp",width=width,fill=self.tkPenColor)
-    self.penDisp.itemconfigure("penMag",text="x%d"%mag)
-    #apply the new pen to any selected items
-    IDs = self.mainCanvas.find_withtag("selectedItem")
-    madeAChange = False
-    for ID in IDs:
-      item = self.findItem(ID)
-      if not isinstance(item,xasyScript):
-        if not madeAChange:
-          self.undoRedoStack.add(endActionGroup)
-          madeAChange = True
-        if isinstance(item,xasyText):
-          temp = item.label.pen
-          item.label.pen = asyPen(self.penColor,self.penWidth,self.penOptions)
-          item.drawOnCanvas(self.mainCanvas,self.magnification)
-          self.bindItemEvents(item)
-          self.setSelection(item.imageList[0].IDTag)
-          self.undoRedoStack.add(editLabelPenAction(self,temp,asyPen(self.penColor,self.penWidth,self.penOptions),self.fileItems.index(item)))
-        else:
-          temp = copy.deepcopy(item)
-          item.pen = asyPen(self.penColor,self.penWidth,self.penOptions)
-          item.drawOnCanvas(self.mainCanvas,self.magnification)
-          self.undoRedoStack.add(editDrawnItemAction(self,temp,copy.deepcopy(item),self.fileItems.index(item)))
-    if madeAChange:
-      self.undoRedoStack.add(beginActionGroup)
-
-  def applyPenWidthEvt(self,event):
-    if not self.testOrAcquireLock():
-      return
-    self.applyPenWidth()
-    self.releaseLock()
-
-  def penWidthChanged(self,event):
-    if self.pendingPenWidthChange is not None:
-      self.penWidthEntry.after_cancel(self.pendingPenWidthChange)
-    self.pendingPenWidthChange = self.penWidthEntry.after(1000,self.applyPenWidth)
-
-  def applyPenOptEvt(self,event):
-    if not self.testOrAcquireLock():
-      return
-    self.applyPenOpt()
-    self.releaseLock()
-
-  def validatePenOpt(self):
-    try:
-      penTest = asyPen(self.penColor,self.penWidth,self.penOptEntry.get())
-      return True
-    except:
-      self.penOptEntry.select_range(0,END)
-      self.penOptEntry.delete(0,END)
-      self.penOptEntry.insert(END,"Invalid Pen Options")
-      self.penOptEntry.after(5000,self.clearInvalidOptEntry)
-      self.penOptions = ""
-      return False
-
-  def clearInvalidOptEntry(self):
-    self.penOptEntry.select_range(0,END)
-    self.penOptEntry.delete(0,END)
-
-  def applyPenOpt(self):
-    if self.validatePenOpt():
-      old = self.penOptions
-      self.penOptions = self.penOptEntry.get()
-      if old != self.penOptions:
-        self.showCurrentPen()
-
-  def undoOperation(self):
-    self.undoRedoStack.undo()
-
-  def redoOperation(self):
-    self.undoRedoStack.redo()
-
-  def resetStacking(self):
-    for item in self.fileItems:
-      self.raiseSomething(item,force=True)

Modified: trunk/Master/texmf-dist/asymptote/GUI/xasyOptions.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyOptions.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyOptions.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 ###########################################################################
 #
 # xasyOptions provides a mechanism for storing and restoring a user's
@@ -10,117 +10,149 @@
 #
 ###########################################################################
 
-import pickle
-import sys,os
-import errno
+import json
+import sys
+import io
+import os
+import platform
+import shutil
 
-defaultOptions = {
-    'asyPath':'asy',
-    'showDebug':False,
-    'showGrid':False,
-    'gridX':10,
-    'gridY':10,
-    'gridColor':'#eeeeee',
-    'showAxes':True,
-    'axisX':10,
-    'axisY':10,
-    'axesColor':'#cccccc',
-    'tickColor':'#eeeeee',
-    'defPenOptions':'',
-    'defPenColor':'#000000',
-    'defPenWidth':1.0,
-    'externalEditor':''
-  }
+import configs
 
-if sys.platform[:3] == "win":
-  defaultOptions['externalEditor'] = "%PROGRAMFILES%\Windows NT\Accessories\wordpad.exe"
-else:
-  defaultOptions['externalEditor'] = "emacs"
+try:
+    import cson
+except ModuleNotFoundError:
+    cson = None
 
+try:
+    pass
+#     import yaml
+except ModuleNotFoundError:
+    yaml = None
 
-options = defaultOptions.copy()
+class xasyOptions:
+    def defaultOptions(self):
+        if self._defaultOptions is None:
+            f = io.open(self._defualtOptLocation)
+            try:
+                opt = cson.loads(f.read())
+            finally:
+                f.close()
+            self._defaultOptions = opt
+        return self._defaultOptions
 
-def settingsFileLocation():
-  folder = ""
-  try:
-    folder = os.path.expanduser("~/.asy/")
-  except:
-    pass
-  return os.path.normcase(os.path.join(folder,"xasy.conf"))
+    def overrideSettings(self):
+        settingsName = platform.system()
 
-def setAsyPathFromWindowsRegistry():
-  try:
-    import _winreg as registry
-    #test both registry locations
-    try:
-      key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Asymptote")
-      options['asyPath'] = registry.QueryValueEx(key,"Path")[0]+"\\asy.exe"
-      registry.CloseKey(key)
-    except:
-      key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Asymptote")
-      options['asyPath'] = registry.QueryValueEx(key,"InstallLocation")[0]+"\\asy.exe"
-      registry.CloseKey(key)
-  except:
-    #looks like asy is not installed or this isn't Windows
-    pass
+        if settingsName not in self.options:
+            return
 
-def setDefaults():
-  global options
-  options = defaultOptions.copy()
-  if sys.platform[:3] == 'win': #for windows, wince, win32, etc
-    setAsyPathFromWindowsRegistry()
-  save()
+        for key in self.options[settingsName]:
+            self.options[key] = self.options[settingsName][key]
+    
+    
+    def settingsFileLocation(self):
+        folder = os.path.expanduser("~/.asy/")
 
-def load():
-  global options
-  fileName = settingsFileLocation()
-  if not os.path.exists(fileName):
-    #make folder
-    thedir = os.path.dirname(fileName)
-    if not os.path.exists(thedir):
-      try:
-        os.makedirs(thedir)
-      except:
-        raise Exception("Could not create configuration folder")
-    if not os.path.isdir(thedir):
-      raise Exception("Configuration folder path does not point to a folder")
-    setDefaults()
-  try:
-    f = open(fileName,"rb")
-    newOptions = pickle.load(f)
-    for key in options.keys():
-      if type(newOptions[key]) != type(options[key]):
-        raise Exception("Bad type for entry in xasy settings")
-    options = newOptions
-  except:
-    setDefaults()
+        searchOrder = ['.cson', '.yaml', '.json', '']
 
-def save():
-  global options
-  fileName = settingsFileLocation()
-  try:
-    f = open(fileName,"wb")
-    pickle.dump(options,f)
-    f.close()
-  except:
-    raise Exception("Error saving preferences")
+        searchIndex = 0
+        found = False
+        currentFile = ''
+        while searchIndex < len(searchOrder) and not found:
+            currentFile = os.path.join(folder, self.configName + searchOrder[searchIndex])
+            if os.path.isfile(currentFile):
+                found = True
+            searchIndex += 1
+        
+        if found:
+            return os.path.normcase(currentFile)
+        else:
+            return os.path.normcase(os.path.join(folder, self.configName + '.cson'))
 
-load()
+    def __init__(self, configName, defaultConfigLocation):
+        self.configName = configName
+        self.defaultConfigName = defaultConfigLocation
 
-if __name__=='__main__':
-  print (settingsFileLocation())
-  print ("Current content")
-  load()
-  print ("Setting defaults")
-  setDefaults()
-  save()
-  load()
-  options['showAxes'] = options['showGrid'] = False
-  save()
-  print ("Set to False")
-  load()
-  options['showAxes'] = options['showGrid'] = True
-  save()
-  print ("Set to True")
-  load()
-  print (options)
+        self._defaultOptions = None
+        self._defualtOptLocation = os.path.join(defaultConfigLocation)
+
+        self.options = self.defaultOptions()
+        self.load()
+
+    def __getitem__(self, item):
+        return self.options[item]
+
+    def __setitem__(self, key, value):
+        self.options[key] = value
+
+    def load(self):
+        fileName = self.settingsFileLocation()
+        if not os.path.exists(fileName):
+            # make folder
+            thedir = os.path.dirname(fileName)
+            if not os.path.exists(thedir):
+                os.makedirs(thedir)
+            if not os.path.isdir(thedir):
+                raise Exception("Configuration folder path does not point to a folder")
+            self.setDefaults()
+        f = io.open(fileName, 'r')
+        try:
+            ext = os.path.splitext(fileName)[1]
+            if ext == '.cson':
+                if cson is None:
+                    raise ModuleNotFoundError
+                newOptions = cson.loads(f.read())
+            elif ext in {'.yml', '.yaml'}:
+                if yaml is None:
+                    raise ModuleNotFoundError
+                newOptions = yaml.load(f)
+            else:
+                newOptions = json.loads(f.read())
+        except (IOError, ModuleNotFoundError):
+            self.setDefaults()
+        else:
+            for key in self.options.keys():
+                if key in newOptions:
+                    assert isinstance(newOptions[key], type(self.options[key]))
+                else:
+                    newOptions[key] = self.options[key]
+            self.options = newOptions
+        finally:
+            f.close()
+
+    def setDefaults(self):
+        self.options = self.defaultOptions()
+        if sys.platform[:3] == 'win':  # for windows, wince, win32, etc
+            # setAsyPathFromWindowsRegistry()
+            pass
+        folder = os.path.expanduser("~/.asy/")
+        defaultPath = os.path.join(folder, self.configName + '.cson')
+        shutil.copy2(self._defualtOptLocation, defaultPath)
+        
+
+# TODO: Figure out how to merge this back.
+"""
+def setAsyPathFromWindowsRegistry():
+    if os.name == 'nt':
+        import _winreg as registry
+        # test both registry locations
+        try:
+            key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,
+                                   "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Asymptote")
+            options['asyPath'] = registry.QueryValueEx(key, "Path")[0] + "\\asy.exe"
+            registry.CloseKey(key)
+        except:
+            key = registry.OpenKey(registry.HKEY_LOCAL_MACHINE,
+                                   "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Asymptote")
+            options['asyPath'] = registry.QueryValueEx(key, "InstallLocation")[0] + "\\asy.exe"
+            registry.CloseKey(key)
+"""
+
+
+class BasicConfigs:
+    _configPath = list(configs.__path__)[0]
+    defaultOpt = xasyOptions(
+        'xasyconfig', os.path.join(_configPath, 'xasyconfig.cson'))
+    keymaps = xasyOptions('xasykeymap', os.path.join(
+        _configPath, 'xasykeymap.cson'))

Deleted: trunk/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,234 +0,0 @@
-#!/usr/bin/env python
-###########################################################################
-#
-# xasyOptionsDialog implements a dialog window to allow users to edit
-# their preferences and specify program options
-#
-#
-# Author: Orest Shardt
-# Created: June 29, 2007
-#
-###########################################################################
-
-import os
-import sys
-import xasyOptions
-import xasyColorPicker
-
-if sys.version_info >= (3, 0):
-  from tkinter import *
-  from tkinter import simpledialog, messagebox, filedialog
-else:
-  # python2
-  from Tkinter import *
-  import tkSimpleDialog as simpledialog
-  import tkMessageBox   as messagebox
-  import tkFileDialog   as filedialog
-  # import tkColorChooser as colorchooser
-
-class xasyOptionsDlg(simpledialog.Dialog):
-  """A dialog to interact with users about their preferred settings"""
-  def __init__(self,master=None):
-    simpledialog.Dialog.__init__(self,master,"xasy Options")
-
-  def body(self,master):
-    optFrame = Frame(master)
-    optFrame.grid(row=0,column=0,sticky=N+S+E+W)
-
-    asyGrp = LabelFrame(optFrame,text="Asymptote",padx=5,pady=5)
-    asyGrp.grid(row=0,column=0,sticky=E+W)
-    asyGrp.rowconfigure(0,weight=1)
-    asyGrp.rowconfigure(1,weight=1)
-    asyGrp.columnconfigure(0,weight=1)
-    asyGrp.columnconfigure(0,weight=2)
-    Label(asyGrp,text="Command").grid(row=0,column=0,sticky=W)
-    self.ap = Entry(asyGrp)
-    self.ap.insert(END,xasyOptions.options['asyPath'])
-    self.ap.grid(row=0,column=1,sticky=E+W)
-    Button(asyGrp,text="...",command=self.findAsyPath).grid(row=0,column=2,sticky=E+W)
-    self.showDebug = BooleanVar()
-    self.showDebug.set(xasyOptions.options['showDebug'])
-    self.sd = Checkbutton(asyGrp,text="Show debugging info in console",var=self.showDebug)
-    self.sd.grid(row=1,column=0,columnspan=2,sticky=W)
-
-    editGrp = LabelFrame(optFrame,text="External Editor",padx=5,pady=5)
-    editGrp.grid(row=1,column=0,sticky=E+W)
-    editGrp.rowconfigure(0,weight=1)
-    editGrp.rowconfigure(1,weight=1)
-    editGrp.columnconfigure(0,weight=1)
-    editGrp.columnconfigure(0,weight=2)
-    Label(editGrp,text="Program").grid(row=0,column=0,sticky=W)
-    self.ee = Entry(editGrp)
-    self.ee.insert(END,xasyOptions.options['externalEditor'])
-    self.ee.grid(row=0,column=1,sticky=E+W)
-    Button(editGrp,text="...",command=self.findEEPath).grid(row=0,column=2,sticky=E+W)
-
-    penGrp = LabelFrame(optFrame,text="Default Pen",padx=5,pady=5)
-    penGrp.grid(row=2,column=0,sticky=E+W)
-    penGrp.rowconfigure(0,weight=1)
-    penGrp.rowconfigure(1,weight=1)
-    penGrp.rowconfigure(2,weight=1)
-    penGrp.columnconfigure(1,weight=1)
-    Label(penGrp,text="Color").grid(row=0,column=0,sticky=E)
-    self.pc = xasyOptions.options['defPenColor']
-    Button(penGrp,text="Change",command=self.changePenColor).grid(row=0,column=1,sticky=W)
-    Label(penGrp,text="Width").grid(row=1,column=0,sticky=E)
-    self.pw = Entry(penGrp)
-    self.pw.insert(END,str(xasyOptions.options['defPenWidth']))
-    self.pw.grid(row=1,column=1,sticky=E+W)
-    Label(penGrp,text="Options").grid(row=2,column=0,sticky=E)
-    self.po = Entry(penGrp)
-    self.po.insert(END,xasyOptions.options['defPenOptions'])
-    self.po.grid(row=2,column=1,sticky=E+W)
-
-    dispGrp = LabelFrame(optFrame,text="Display Options",padx=5,pady=5)
-    dispGrp.grid(row=3,column=0,sticky=E+W)
-    dispGrp.rowconfigure(0,weight=1)
-    dispGrp.rowconfigure(1,weight=1)
-    dispGrp.rowconfigure(2,weight=1)
-    dispGrp.rowconfigure(3,weight=1)
-    dispGrp.columnconfigure(0,weight=1)
-    dispGrp.columnconfigure(1,weight=1)
-    dispGrp.columnconfigure(2,weight=1)
-    self.showAxes = BooleanVar()
-    self.showAxes.set(xasyOptions.options['showAxes'])
-    self.sa = Checkbutton(dispGrp,text="Show Axes",var=self.showAxes)
-    self.sa.grid(row=0,column=0,sticky=W)
-    self.ac = xasyOptions.options['axesColor']
-    Button(dispGrp,text="Color...",command=self.changeAxesColor).grid(row=1,column=0)
-    Label(dispGrp,text="x").grid(row=0,column=1,padx=5,sticky=E)
-    self.axs = Entry(dispGrp,width=6)
-    self.axs.insert(END,xasyOptions.options['axisX'])
-    self.axs.grid(row=0,column=2,sticky=W+E)
-    Label(dispGrp,text="y").grid(row=1,column=1,padx=5,sticky=E)
-    self.ays = Entry(dispGrp,width=6)
-    self.ays.insert(END,xasyOptions.options['axisY'])
-    self.ays.grid(row=1,column=2,sticky=W+E)
-
-    self.showGrid = BooleanVar()
-    self.showGrid.set(xasyOptions.options['showGrid'])
-    self.sg = Checkbutton(dispGrp,text="Show Grid",var=self.showGrid)
-    self.sg.grid(row=4,column=0,sticky=W)
-    self.gc = xasyOptions.options['gridColor']
-    Button(dispGrp,text="Color...",command=self.changeGridColor).grid(row=3,column=0)
-    Label(dispGrp,text="x").grid(row=2,column=1,padx=5,sticky=E)
-    self.gxs = Entry(dispGrp,width=6)
-    self.gxs.insert(END,xasyOptions.options['gridX'])
-    self.gxs.grid(row=2,column=2,sticky=W+E)
-    Label(dispGrp,text="y").grid(row=3,column=1,padx=5,sticky=E)
-    self.gys = Entry(dispGrp,width=6)
-    self.gys.insert(END,xasyOptions.options['gridY'])
-    self.gys.grid(row=3,column=2,sticky=W+E)
-
-  def findEEPath(self):
-    if sys.platform[:3] == 'win': #for windows, wince, win32, etc
-      file=filedialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Choose External Editor",parent=self)
-    else:
-      file=filedialog.askopenfile(filetypes=[("All files","*")],title="Choose External Editor",parent=self)
-    if file != None:
-      name = os.path.abspath(file.name)
-      file.close()
-      self.ee.delete(0,END)
-      self.ee.insert(END,name)
-      self.validate()
-
-  def findAsyPath(self):
-    if sys.platform[:3] == 'win': #for windows, wince, win32, etc
-      file=filedialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Find Asymptote Executable",parent=self)
-    else:
-      file=filedialog.askopenfile(filetypes=[("All files","*")],title="Find Asymptote Executable",parent=self)
-    if file != None:
-      name = os.path.abspath(file.name)
-      file.close()
-      self.ap.delete(0,END)
-      self.ap.insert(END,name)
-      self.validate()
-
-  def getAColor(self,color):
-    result = xasyColorPicker.xasyColorDlg(self).getColor(xasyColorPicker.makeRGBfromTkColor(color))
-    return xasyColorPicker.RGB255hex(xasyColorPicker.RGBreal255(result))
-
-  def changeAxesColor(self):
-    self.ac = self.getAColor(self.ac)
-
-  def changeGridColor(self):
-    self.gc = self.getAColor(self.gc)
-
-  def changePenColor(self):
-    self.pc = self.getAColor(self.pc)
-
-  def apply(self):
-    xasyOptions.options['externalEditor'] = self.ee.get()
-    xasyOptions.options['asyPath'] = self.ap.get()
-    xasyOptions.options['showDebug'] = bool(self.showDebug.get())
-
-    xasyOptions.options['defPenColor'] = self.pc
-    xasyOptions.options['defPenWidth'] = float(self.pw.get())
-    xasyOptions.options['defPenOptions'] = self.po.get()
-
-    xasyOptions.options['showAxes'] = bool(self.showAxes.get())
-    xasyOptions.options['axesColor'] = self.ac
-    xasyOptions.options['tickColor'] = self.ac
-    xasyOptions.options['axisX'] = int(self.axs.get())
-    xasyOptions.options['axisY'] = int(self.ays.get())
-    xasyOptions.options['showGrid'] = bool(self.showGrid.get())
-    xasyOptions.options['gridColor'] = self.gc
-    xasyOptions.options['gridX'] = int(self.gxs.get())
-    xasyOptions.options['gridY'] = int(self.gys.get())
-    xasyOptions.save()
-
-  def validateAColor(self,color):
-    hexdigits = '0123456789abcdef'
-    if len(self.pc) != 7 or self.pc[0] != '#' or sum([1 for a in self.pc[1:] if a in hexdigits]) != 6:
-      return False
-    else:
-      return True
-
-  def validate(self):
-    """Validate the data entered into the dialog"""
-    #validate the color
-    hexdigits = '0123456789abcdef'
-    if not self.validateAColor(self.pc):
-      messagebox.showerror("xasy Options","Invalid pen color.\r\n"+self.pc,parent=self)
-      return False
-    #validate the width
-    try:
-      test = float(self.pw.get())
-    except:
-      messagebox.showerror("xasy Options","Pen width must be a number.",parent=self)
-      return False
-
-    #validate the options
-    #nothing to do
-
-    #validate the axis spacing
-    try:
-      test = int(self.axs.get())
-      test = int(self.ays.get())
-    except:
-      messagebox.showerror("xasy Options","Axes' x- and y-spacing must be numbers.",parent=self)
-      return False
-
-    #validate the grid spacing
-    try:
-      test = int(self.gxs.get())
-      test = int(self.gys.get())
-    except:
-      messagebox.showerror("xasy Options","Grid's x- and y-spacing  must be numbers.",parent=self)
-      return False
-
-    if not self.validateAColor(self.ac):
-      messagebox.showerror("xasy Options","Invalid axis color.\r\n"+self.ac,parent=self)
-      return False
-
-    if not self.validateAColor(self.gc):
-      messagebox.showerror("xasy Options","Invalid grid color.\r\n"+self.gc,parent=self)
-      return False
-
-    return True
-
-if __name__ == '__main__':
-  root = Tk()
-  xasyOptions.load()
-  d = xasyOptionsDlg(root)
-  print (d.result)

Added: trunk/Master/texmf-dist/asymptote/GUI/xasyStrings.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyStrings.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyStrings.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,23 @@
+#!/usr/bin/env python3
+
+import gettext
+
+p = property
+
+class xasyString:
+    def __init__(self, lang=None):
+        s = self
+        if lang is None:
+            _ = lambda x:  x 
+        else:
+            lng = gettext.translation('base', localedir='GUI/locale', languages=[lang])
+            lng.install()
+            _ = lng.gettext
+            
+        s.rotate = _('Rotate')
+        s.scale = _('Scale')
+        s.translate = _('Translate')
+
+        s.fileOpenFailed = _('File Opening Failed.')
+        s.fileOpenFailedText = _('File could not be opened.')
+        s.asyfyComplete = _('Ready.')


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/xasyStrings.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/xasySvg.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasySvg.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasySvg.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+
+import PyQt5.QtGui as Qg
+import PyQt5.QtWidgets as Qw
+import io
+import subprocess
+import sys
+
+class SvgObject():
+    def __init__(self, file: str):
+        self.file=file
+
+    def render(self, dpi:int) -> Qg.QImage:
+        try:
+            rawDataProc = subprocess.Popen(['rsvg-convert', '--dpi-x', str(dpi),
+                                            '--dpi-y', str(dpi), self.file],
+                                           stdout=subprocess.PIPE)
+        except:
+            Qw.QMessageBox.about(None,'rsvg-convert missing','Please install rsvg-convert version >= 2.40 in your path.')
+            sys.exit(-1)
+
+        return Qg.QImage.fromData(rawDataProc.stdout.read(), 'PNG')


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/xasySvg.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/xasyTransform.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyTransform.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyTransform.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,24 @@
+#!/usr/bin/env python3
+import xasy2asy as x2a
+import PyQt5.QtGui as Qg
+import PyQt5.QtCore as Qc
+import numpy as np
+import math
+
+
+class xasyTransform:
+    @classmethod
+    def makeRotTransform(cls, theta, origin):
+        if isinstance(origin, Qc.QPointF) or isinstance(origin, Qc.QPoint):
+            origin = (origin.x(), origin.y())
+        rotMat = (math.cos(theta), -math.sin(theta), math.sin(theta), math.cos(theta))
+        shift = x2a.asyTransform((0, 0, 1 - rotMat[0], -rotMat[1], -rotMat[2], 1 - rotMat[3])) * origin
+        return x2a.asyTransform((shift[0], shift[1], rotMat[0], rotMat[1], rotMat[2], rotMat[3]))
+
+    @classmethod
+    def makeScaleTransform(cls, sx, sy, origin):
+        if isinstance(origin, Qc.QPointF) or isinstance(origin, Qc.QPoint):
+            origin = (origin.x(), origin.y())
+        shiftMat = x2a.asyTransform((0, 0, 1 - sx, 0, 0, 1 - sy)) * origin
+        return x2a.asyTransform((shiftMat[0], shiftMat[1], sx, 0, 0, sy))
+


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/xasyTransform.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/xasyUtils.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyUtils.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyUtils.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+
+import re
+import typing as ty
+import math
+import itertools
+
+def tuple2StrWOspaces(val: tuple) -> str:
+    newStr = ','.join(['{:.6g}'.format(value) for value in val])
+    return '({0})'.format(newStr)
+
+def tryParse(val, typ=float):
+    try:
+        return typ(val)
+    except ValueError:
+        return None
+
+def funcOnList(list1: ty.Union[ty.List, ty.Tuple], list2: ty.Union[ty.List, ty.Tuple], func: ty.Callable) -> tuple:
+    """Returns [f(x[i], y[i]) : i in 1, ..., n - 1] in order with f as func 
+    and x and y as list1 and 2. """
+
+    assert len(list1) == len(list2)
+    return tuple([func(list1[i], list2[i]) for i in range(len(list1))]) 
+
+
+def listize(str, typ, delim='()') -> list:
+    str = str.strip(delim)
+    raw_elem = str.split(',')
+    final_list = []
+    if isinstance(typ, (list, tuple)):
+        for i in range(len(raw_elem)):
+            if i < len(typ):
+                curr_typ = typ[i]
+            else:
+                curr_typ = typ[-1]
+            final_list.append(curr_typ(raw_elem[i].strip()))
+    else:
+        for elem in raw_elem:
+            final_list.append(typ(elem.strip()))
+    return final_list
+
+def twonorm(vec: ty.Iterable[ty.Union[float, int]]) -> float:
+    rawSquared = sum(map(lambda x: x*x, vec))
+    return math.sqrt(rawSquared)
+
+def tryParseKey(raw_key):
+    """Returns None if raw key is not in #.# format"""
+    # See https://regex101.com/r/6G9MZD/1/
+    # for the regex data
+    return re.fullmatch(r'^(\d+)\.(\d+)$', raw_key)


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/xasyUtils.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/asymptote/GUI/xasyValidator.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyValidator.py	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyValidator.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,13 @@
+#!/usr/bin/env python3
+
+def validateFloat(text):
+    try:
+        float(text)
+        return True
+    except ValueError:
+        return False
+
+
+if __name__ == '__main__':
+    assert validateFloat('0.5')
+    assert not validateFloat('.-')


Property changes on: trunk/Master/texmf-dist/asymptote/GUI/xasyValidator.py
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Modified: trunk/Master/texmf-dist/asymptote/GUI/xasyVersion.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/GUI/xasyVersion.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/GUI/xasyVersion.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,2 +1,2 @@
-#!/usr/bin/env python
-xasyVersion = "2.44"
+#!/usr/bin/env python3
+xasyVersion = "2.47"

Modified: trunk/Master/texmf-dist/asymptote/animation.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/animation.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/animation.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -56,7 +56,6 @@
     string format=nativeformat();
     plain.shipout(name,f,format=format,view=false);
     files.push(name+"."+format);
-    shipped=false;
   }
   
   void add(picture pic=currentpicture, enclosure enclosure=NoBox) {
@@ -119,7 +118,6 @@
       plain.shipout(prefix,multi,view=view);
       settings.inlinetex=inlinetex;
     }
-    shipped=true;
   }
 
   string load(int frames, real delay=animationdelay, string options="",
@@ -152,8 +150,6 @@
     if(global)
       export(filename,enclosure,multipage=multipage);
     
-    shipped=false;
-
     if(!keep) {
       exitfcn currentexitfunction=atexit();
       void exitfunction() {

Modified: trunk/Master/texmf-dist/asymptote/asy-keywords.el
===================================================================
--- trunk/Master/texmf-dist/asymptote/asy-keywords.el	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/asy-keywords.el	2019-02-28 18:48:48 UTC (rev 50168)
@@ -2,16 +2,16 @@
 ;; This file is automatically generated by asy-list.pl.
 ;; Changes will be overwritten.
 ;;
-(defvar asy-keywords-version "2.44")
+(defvar asy-keywords-version "2.47")
 
 (defvar asy-keyword-name '(
 and controls tension atleast curl if else while for do return break continue struct typedef new access import unravel from include quote static public private restricted this explicit true false null cycle newframe operator ))
 
 (defvar asy-type-name '(
-Braid FitResult Label Legend Solution TreeNode abscissa arc arrowhead binarytree binarytreeNode block bool bool3 bounds bqe circle conic coord coordsys cputime ellipse evaluatedpoint file filltype frame grid3 guide horner hsv hyperbola indexedTransform int inversion key light line linefit marginT marker mass object pair parabola patch path path3 pen picture point position positionedvector projection rational real revolution scaleT scientific segment side slice solution splitface string surface tensionSpecifier ticklocate ticksgridT tickvalues transform transformation tree triangle trilinear triple vector vertex void ))
+Braid FitResult Label Legend Solution TreeNode abscissa arc arrowhead binarytree binarytreeNode block bool bool3 bounds bqe circle conic coord coordsys cputime ellipse evaluatedpoint file filltype frame grid3 guide horner hsv hyperbola int inversion key light line linefit marginT marker mass node object pair parabola patch path path3 pen picture point position positionedvector projection rational real revolution scaleT scientific segment side simplex slice solution splitface string surface tensionSpecifier ticklocate ticksgridT tickvalues transform transformation tree triangle trilinear triple vector vertex void ))
 
 (defvar asy-function-name '(
-AND Arc ArcArrow ArcArrows Arrow Arrows AtA Automatic AvantGarde B03 B13 B23 B33 BBox BWRainbow BWRainbow2 Bar Bars BeginArcArrow BeginArrow BeginBar BeginDotMargin BeginMargin BeginPenMargin Blank Bookman Bottom BottomTop Bounds Break Broken BrokenLog CLZ CTZ Ceil Circle CircleBarIntervalMarker Cos Courier CrossIntervalMarker DOSendl DOSnewl DefaultFormat DefaultLogFormat Degrees Dir DotMargin DotMargins Dotted Draw Drawline Embed EndArcArrow EndArrow EndBar EndDotMargin EndMargin EndPenMargin Fill FillDraw Floor Format Full Gaussian Gaussrand Gaussrandpair Gradient Grayscale Helvetica Hermite HookHead InOutTicks InTicks Jn Label Landscape Left LeftRight LeftTicks Legend Linear Log LogFormat Margin Margins Mark MidArcArrow MidArrow NOT NewCenturySchoolBook NoBox NoMargin NoModifier NoTicks NoTicks3 NoZero NoZeroFormat None OR OmitFormat OmitTick OmitTickInterval OmitTickIntervals OutTicks Ox Oy Palatino PaletteTicks Pen PenMargin PenMargins Pentype Portrait RadialShade RadialShadeDraw Rainbow Range Relative Right RightTicks Rotate Round SQR Scale ScaleX ScaleY ScaleZ Seascape Shift Sin Slant Spline StickIntervalMarker Straight Symbol Tan TeXify Ticks Ticks3 TildeIntervalMarker TimesRoman Top TrueMargin UnFill UpsideDown Wheel X XEquals XOR XY XYEquals XYZero XYgrid XZEquals XZZero XZero XZgrid Y YEquals YXgrid YZ YZEquals YZZero YZero YZgrid Yn Z ZX ZXgrid ZYgrid ZapfChancery ZapfDingbats _begingroup3 _cputime _draw _eval _findroot _image _labelpath _projection _strokepath _texpath aCos aSin aTan abort abs accel acos acosh acot acsc activatequote add addArrow addMargins addSaveFunction addpenarc addpenline addseg adjust alias align all altitude angabscissa angle angledegrees angpoint animate annotate anticomplementary antipedal apply approximate arc arcarrowsize arccircle arcdir arcfromcenter arcfromfocus arclength arcnodesnumber arcpoint arcsubtended arcsubtendedcenter arctime arctopath array arrow arrow2 arrowbase arrowbasepoints arrowsize ascii asec asin asinh ask assert asy asycode asydir asyfigure!
  asyfilecode asyinclude asywrite atan atan2 atanh atbreakpoint atexit attach attract atupdate autoformat autoscale autoscale3 axes axes3 axialshade axis axiscoverage azimuth babel background bangles bar barmarksize barsize basealign baseline bbox beep begin beginclip begingroup beginpoint between bevel bezier bezierP bezierPP bezierPPP bezulate bibliography bibliographystyle binarytree binarytreeNode binomial bins bisector bisectorpoint bispline bitreverse blend blockconnector box bqe brace breakpoint breakpoints brick buildRestoreDefaults buildRestoreThunk buildcycle bulletcolor byte calculateScaling canonical canonicalcartesiansystem cartesiansystem case1 case2 case3 cbrt cd ceil center centerToFocus centroid cevian change2 changecoordsys checkSegment check_fpt_zero checkconditionlength checker checkincreasing checklengths checkposition checkpt checkptincube checktriangle choose circle circlebarframe circlemarkradius circlenodesnumber circumcenter circumcircle clamped clear clip clipdraw close cmyk code colatitude collect collinear color colorless colors colorspace comma compassmark complement complementary concat concurrent cone conic conicnodesnumber conictype conj connect containmentTree contains contour contour3 controlSpecifier convert coordinates coordsys copy copyPairOrTriple cos cosh cot countIntersections cputime crop cropcode cross crossframe crosshatch crossmarksize csc cubicroots curabscissa curlSpecifier curpoint currentarrow currentexitfunction currentmomarrow currentpolarconicroutine curve cut cutafter cutbefore cyclic cylinder deactivatequote debugger deconstruct defaultdir defaultformat defaultpen defined degenerate degrees delete deletepreamble determinant diagonal diamond diffdiv dir dirSpecifier dirtime display distance divisors do_overpaint dot dotframe dotsize downcase draw drawAll drawDoubleLine drawFermion drawGhost drawGluon drawMomArrow drawPRCcylinder drawPRCdisk drawPRCsphere drawPRCtube drawPhoton drawScalar drawVertex drawVertexBox drawVertexBoxO drawVertexBoxX drawVertexO drawVer!
 texOX drawVertexTriangle drawVertexTriangleO drawVertexX drawarrow drawarrow2 drawbeziertriangle drawline drawpixel drawstrokepath drawtick duplicate elle ellipse ellipsenodesnumber embed embed3 embedplayer empty enclose end endScript endclip endgroup endgroup3 endl endpoint endpoints eof eol equation equations erase erasestep erf erfc error errorbar errorbars eval excenter excircle exit exitXasyMode exitfunction exp expfactors expi expm1 exradius extend extension extouch fabs factorial fermat fft fhorner figure file filecode fill filldraw filloutside fillrule filltype find findall findroot finite finiteDifferenceJacobian firstcut firstframe fit fit2 fixedscaling floor flush fmdefaults fmod focusToCenter font fontcommand fontsize foot format frac frequency fromCenter fromFocus fspline functionshade gamma gcd generate_random_backtrace generateticks gergonne getc getint getpair getreal getstring gettriple gluon gouraudshade graph graphic graphicscale gray grestore grid grid3 gsave halfbox hatch hdiffdiv hermite hex histogram history hline hprojection hsv hyperbola hyperbolanodesnumber hyperlink hypot identity image implicitsurface incenter incentral incircle increasing incrementposition indexedTransform indexedfigure initXasyMode initdefaults initialized input inradius insert inside insphere integrate interactive interior interp interpolate intersect intersection intersectionpoint intersectionpoints intersections intouch inverse inversion invisible is3D isDuplicate isnan isogonal isogonalconjugate isotomic isotomicconjugate isparabola italic item jobname key kurtosis kurtosisexcess label labelaxis labelmargin labelpath labels labeltick labelx labelx3 labely labely3 labelz labelz3 lastcut latex latitude latticeshade layer layout lcm ldexp leastsquares legend legenditem length lexorder lift light limits line linear linecap lineinversion linejoin linemargin lineskip linetype linewidth link list lm_enorm lm_evaluate_default lm_lmdif lm_lmpar lm_minimize lm_print_default lm_print_quiet lm_qrfac lm_qrsolv locale locate !
 locatefile location log log10 log1p logaxiscoverage longitude lookup make3dgrid makeNode makecircle makedraw makepen maketriangle map margin markangle markangleradius markanglespace markarc marker markinterval marknodes markrightangle markthin markuniform mass masscenter massformat math max max3 maxAfterTransform maxbezier maxbound maxcoords maxlength maxratio maxtimes mean medial median midpoint min min3 minAfterTransform minbezier minbound minipage minratio mintimes miterlimit mktemp momArrowPath momarrowsize monotonic multifigure nGrad nativeformat natural needshipout newl newpage newslide newton newtree nextframe nextnormal nextpage nib nodabscissa none norm normalout normalvideo nosetpagesize notaknot nowarn numberpage nurb object offset onpath opacity opposite orient orientation origin orthic orthocentercenter outformat outline outname outprefix output overloadedMessage overwrite pack pad pairs palette parabola parabolanodesnumber parallel parallelogram partialsum patchwithnormals path path3 pathbetween pathinface pattern pause pdf pedal periodic perp perpendicular perpendicularmark phantom phi1 phi2 phi3 photon piecewisestraight point polar polarconicroutine polargraph polygon popcount postcontrol postscript pow10 ppoint prc prc0 prconly precision precontrol prepend printBytecode print_random_addresses progress project projection projecttospan projecttospan_findcoeffs purge pwhermite quadpatches quadrant quadraticroots quantize quarticroots quotient radialshade radians radicalcenter radicalline radius rand randompath rd readline realmult realquarticroots rectangle rectangular rectify reflect relabscissa relative relativedistance reldir relpoint reltime remainder remark removeDuplicates rename replace report resetdefaultpen restore restoredefaults reverse reversevideo rf rfind rgb rgba rgbint rms rotate rotateO rotation round roundbox roundedpath roundrectangle samecoordsys sameside sample save savedefaults saveline scale scale3 scaleO scaleT scaleless scientific search searchtree sec secondaryX secondaryY!
  seconds section sector seek seekeof segment segmentlimits sequence setpens sgn sgnd sharpangle sharpdegrees shift shiftless shipout shipout3 show simeq simpson sin sinh size size3 skewness skip slant sleep slice slope slopefield solve solveBVP sort sourceline sphere split sqrt square srand standardizecoordsys startScript stdev step stickframe stickmarksize stickmarkspace stop straight straightness string stripdirectory stripextension stripfile stripsuffix strokepath subdivide subitem subpath substr sum surface symmedial symmedian system tab tableau tan tangent tangential tangents tanh tell tensionSpecifier tensorshade tex texcolor texify texpath texpreamble texreset texshipout texsize textpath thick thin tick tickMax tickMax3 tickMin tickMin3 ticklabelshift ticklocate tildeframe tildemarksize tile tiling time times title titlepage topbox transform transformation transpose trembleFuzz triangle triangleAbc triangleabc triangletoquads trianglewithnormals triangulate tricoef tridiagonal trilinear trim truepoint tube uncycle unfill uniform unique unit unitrand unitsize unityroot unstraighten upcase updatefunction uperiodic upscale uptodate usepackage usersetting usetypescript usleep value variance variancebiased vbox vector vectorfield verbatim view vline vperiodic vprojection warn warning windingnumber write xaxis xaxis3 xaxis3At xaxisAt xequals xlimits xpart xscale xscaleO xtick xtick3 xtrans yaxis yaxis3 yaxis3At yaxisAt yequals ylimits ypart yscale yscaleO ytick ytick3 ytrans zaxis3 zaxis3At zero zlimits zpart ztick ztick3 ztrans ))
+AND Arc ArcArrow ArcArrows Arrow Arrows AtA Automatic AvantGarde B03 B13 B23 B33 BBox BWRainbow BWRainbow2 Bar Bars BeginArcArrow BeginArrow BeginBar BeginDotMargin BeginMargin BeginPenMargin Blank Bookman Bottom BottomTop Bounds Break Broken BrokenLog CLZ CTZ Ceil Circle CircleBarIntervalMarker Cos Courier CrossIntervalMarker DOSendl DOSnewl DefaultFormat DefaultLogFormat Degrees Dir DotMargin DotMargins Dotted Draw Drawline Embed EndArcArrow EndArrow EndBar EndDotMargin EndMargin EndPenMargin Fill FillDraw Floor Format Full Gaussian Gaussrand Gaussrandpair Gradient Grayscale Helvetica Hermite HookHead InOutTicks InTicks Jn Label Landscape Left LeftRight LeftTicks Legend Linear Log LogFormat Margin Margins Mark MidArcArrow MidArrow NOT NewCenturySchoolBook NoBox NoMargin NoModifier NoTicks NoTicks3 NoZero NoZeroFormat None OR OmitFormat OmitTick OmitTickInterval OmitTickIntervals OutTicks Ox Oy Palatino PaletteTicks Pen PenMargin PenMargins Pentype Portrait RGB RadialShade RadialShadeDraw Rainbow Range Relative Right RightTicks Rotate Round SQR Scale ScaleX ScaleY ScaleZ Seascape Shift Sin Slant Spline StickIntervalMarker Straight Symbol Tan TeXify Ticks Ticks3 TildeIntervalMarker TimesRoman Top TrueMargin UnFill UpsideDown Wheel X XEquals XOR XY XYEquals XYZero XYgrid XZEquals XZZero XZero XZgrid Y YEquals YXgrid YZ YZEquals YZZero YZero YZgrid Yn Z ZX ZXgrid ZYgrid ZapfChancery ZapfDingbats _begingroup3 _cputime _draw _eval _findroot _image _labelpath _projection _shipout _strokepath _texpath aCos aSin aTan abort abs accel acos acosh acot acsc activatequote add addArrow addMargins addSaveFunction addpenarc addpenline addseg adjust alias align all altitude angabscissa angle angledegrees angpoint animate annotate anticomplementary antipedal apply approximate arc arcarrowsize arccircle arcdir arcfromcenter arcfromfocus arclength arcnodesnumber arcpoint arcsubtended arcsubtendedcenter arctime arctopath array arrow arrow2 arrowbase arrowbasepoints arrowsize ascii asec asin asinh ask assert asy asycode asy!
 dir asyfigure asyfilecode asyinclude asywrite atan atan2 atanh atbreakpoint atexit attach attract atupdate autoformat autoscale autoscale3 axes axes3 axialshade axis axiscoverage azimuth babel background bangles bar barmarksize barsize basealign baseline bbox beep begin beginclip begingroup beginpoint between bevel bezier bezierP bezierPP bezierPPP bezulate bibliography bibliographystyle binarytree binarytreeNode binomial bins bisector bisectorpoint bispline bitreverse blend blockconnector box bqe brace breakpoint breakpoints brick buildRestoreDefaults buildRestoreThunk buildcycle bulletcolor byte calculateScaling canonical canonicalcartesiansystem cartesiansystem case1 case2 case3 cbrt cd ceil center centerToFocus centroid cevian change2 changecoordsys checkSegment check_fpt_zero checkconditionlength checker checkincreasing checklengths checkposition checkpt checkptincube checktriangle choose circle circlebarframe circlemarkradius circlenodesnumber circumcenter circumcircle clamped clear clip clipdraw close cmyk code colatitude collect collinear color colorless colors colorspace comma compassmark complement complementary concat concurrent cone conic conicnodesnumber conictype conj connect containmentTree contains contour contour3 controlSpecifier convert coordinates coordsys copy copyPairOrTriple cos cosh cot countIntersections cputime crop cropcode cross crossframe crosshatch crossmarksize csc cubicroots curabscissa curlSpecifier curpoint currentarrow currentexitfunction currentmomarrow currentpolarconicroutine curve cut cutafter cutbefore cyclic cylinder deactivatequote debugger deconstruct defaultdir defaultformat defaultpen defined degenerate degrees delete deletepreamble determinant diagonal diamond diffdiv dir dirSpecifier dirtime display distance divisors do_overpaint dot dotframe dotsize downcase draw drawAll drawDoubleLine drawFermion drawGhost drawGluon drawMomArrow drawPRCcylinder drawPRCdisk drawPRCsphere drawPRCtube drawPhoton drawScalar drawVertex drawVertexBox drawVertexBoxO drawVertexBoxX drawVe!
 rtexO drawVertexOX drawVertexTriangle drawVertexTriangleO drawVertexX drawarrow drawarrow2 drawbeziertriangle drawline drawpixel drawstrokepath drawtick duplicate elle ellipse ellipsenodesnumber embed embed3 embedplayer empty enclose end endclip endgroup endgroup3 endl endpoint endpoints eof eol equation equations erase erasestep erf erfc error errorbar errorbars eval excenter excircle exit exitfunction exp expfactors expi expm1 exradius extend extension extouch fabs factorial fermat fft fhorner figure file filecode fill filldraw filloutside fillrule filltype find findall findroot finite finiteDifferenceJacobian firstcut firstframe fit fit2 fixedscaling floor flush fmdefaults fmod focusToCenter font fontcommand fontsize foot format frac frequency fromCenter fromFocus fspline functionshade gamma gcd generate_random_backtrace generateticks gergonne getc getint getpair getreal getstring gettriple gluon gouraudshade graph graphic graphicscale gray grestore grid grid3 gsave halfbox hatch hdiffdiv hermite hex histogram history hline hprojection hsv hyperbola hyperbolanodesnumber hyperlink hypot identity image implicitsurface incenter incentral incircle increasing incrementposition indexedfigure initdefaults initialized input inradius insert inside insphere integrate interactive interior interp interpolate intersect intersection intersectionpoint intersectionpoints intersections intouch inverse inversion invisible is3D isDuplicate isnan isogonal isogonalconjugate isotomic isotomicconjugate isparabola italic item jobname key kurtosis kurtosisexcess label labelaxis labelmargin labelpath labels labeltick labelx labelx3 labely labely3 labelz labelz3 lastcut latex latitude latticeshade layer layout lcm ldexp leastsquares legend legenditem length lexorder lift light limits line linear linecap lineinversion linejoin linemargin lineskip linetype linewidth link list lm_enorm lm_evaluate_default lm_lmdif lm_lmpar lm_minimize lm_print_default lm_print_quiet lm_qrfac lm_qrsolv locale locate locatefile location log log10 log1p loga!
 xiscoverage longitude lookup make3dgrid makeNode makecircle makedraw makepen maketriangle map margin markangle markangleradius markanglespace markarc marker markinterval marknodes markrightangle markthin markuniform mass masscenter massformat math max max3 maxAfterTransform maxbezier maxbound maxcoords maxlength maxratio maxtimes mean medial median midpoint min min3 minAfterTransform minbezier minbound minipage minratio mintimes miterlimit mktemp momArrowPath momarrowsize monotonic multifigure nGrad nativeformat natural newl newpage newslide newton newtree nextframe nextnormal nextpage nib nodabscissa node none norm normalout normalvideo nosetpagesize notaknot nowarn numberpage nurb object offset onpath opacity opposite orient orientation origin orthic orthocentercenter outformat outline outname outprefix output overloadedMessage overwrite pack pad pairs palette parabola parabolanodesnumber parallel parallelogram partialsum patchwithnormals path path3 pathbetween pathinface pattern pause pdf pedal periodic perp perpendicular perpendicularmark phantom phi1 phi2 phi3 photon piecewisestraight point polar polarconicroutine polargraph polygon popcount postcontrol postscript pow10 ppoint prc prc0 prconly precision precontrol prepend printBytecode print_random_addresses progress project projection projecttospan projecttospan_findcoeffs purge pwhermite quadpatches quadrant quadraticroots quantize quarticroots quotient radialshade radians radicalcenter radicalline radius rand randompath rd readline realmult realquarticroots rectangle rectangular rectify reflect relabscissa relative relativedistance reldir relpoint reltime remainder remark removeDuplicates rename replace report resetdefaultpen restore restoredefaults reverse reversevideo rf rfind rgb rgba rgbint rms rotate rotateO rotation round roundbox roundedpath roundrectangle samecoordsys sameside sample save savedefaults saveline scale scale3 scaleO scaleT scaleless scientific search searchtree sec secondaryX secondaryY seconds section sector seek seekeof segment se!
 gmentlimits sequence setpens sgn sgnd sharpangle sharpdegrees shift shiftless shipout shipout3 show simeq simplex simpson sin sinh size size3 skewness skip slant sleep slice slope slopefield solve solveBVP sort sourceline sphere split sqrt square srand standardizecoordsys stdev step stickframe stickmarksize stickmarkspace stop straight straightness string stripdirectory stripextension stripfile stripsuffix strokepath subdivide subitem subpath substr sum surface symmedial symmedian system tab tableau tan tangent tangential tangents tanh tell tensionSpecifier tensorshade tex texcolor texify texpath texpreamble texreset texshipout texsize textpath thick thin tick tickMax tickMax3 tickMin tickMin3 ticklabelshift ticklocate tildeframe tildemarksize tile tiling time times title titlepage topbox toplocation transform transformation transpose trembleFuzz triangle triangleAbc triangleabc triangletoquads trianglewithnormals triangulate tricoef tridiagonal trilinear trim truepoint tube uncycle unfill uniform unique unit unitrand unitsize unityroot unstraighten upcase updatefunction uperiodic upscale uptodate usepackage usersetting usetypescript usleep value variance variancebiased vbox vector vectorfield verbatim view vline vperiodic vprojection warn warning windingnumber write xasyKEY xaxis xaxis3 xaxis3At xaxisAt xequals xlimits xmap xpart xscale xscaleO xtick xtick3 xtrans yaxis yaxis3 yaxis3At yaxisAt yequals ylimits ypart yscale yscaleO ytick ytick3 ytrans zaxis3 zaxis3At zero zlimits zpart ztick ztick3 ztrans ))
 
 (defvar asy-variable-name '(
-AliceBlue Align Allow AntiqueWhite Apricot Aqua Aquamarine Aspect Azure BeginPoint Beige Bisque Bittersweet Black BlanchedAlmond Blue BlueGreen BlueViolet Both Break BrickRed Brown BurlyWood BurntOrange CCW CW CadetBlue CarnationPink Center Centered Cerulean Chartreuse Chocolate Coeff Coral CornflowerBlue Cornsilk Crimson Crop Cyan Dandelion DarkBlue DarkCyan DarkGoldenrod DarkGray DarkGreen DarkKhaki DarkMagenta DarkOliveGreen DarkOrange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DefaultHead DimGray DodgerBlue Dotted Down Draw E ENE EPS ESE E_Euler E_PC E_RK2 E_RK3BS Emerald EndPoint Euler Fill FillDraw FireBrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold Goldenrod Gray Green GreenYellow Honeydew HookHead Horizontal HotPink I IgnoreAspect IndianRed Indigo Ivory JOIN_IN JOIN_OUT JungleGreen Khaki LM_DWARF LM_MACHEP LM_SQRT_DWARF LM_SQRT_GIANT LM_USERTOL Label Lavender LavenderBlush LawnGreen Left LeftJustified LeftSide LemonChiffon LightBlue LightCoral LightCyan LightGoldenrodYellow LightGreen LightGrey LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateGray LightSteelBlue LightYellow Lime LimeGreen Linear Linen Log Logarithmic Magenta Mahogany Mark MarkFill MarkPath Maroon Max MediumAquamarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue MediumSpringGreen MediumTurquoise MediumVioletRed Melon MidPoint MidnightBlue Min MintCream MistyRose Moccasin Move MoveQuiet Mulberry N NE NNE NNW NULL_VERTEX NW NavajoWhite Navy NavyBlue NoAlign NoCrop NoFill NoSide OldLace Olive OliveDrab OliveGreen Orange OrangeRed Orchid Ox Oy PC PaleGoldenrod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip Peach PeachPuff Periwinkle Peru PineGreen Pink Plum PowderBlue ProcessBlue Purple RK2 RK3 RK3BS RK4 RK5 RK5DP RK5F RawSienna Red RedOrange RedViolet Rhodamine Right RightJustified RightSide RosyBrown RoyalBlue RoyalPurple RubineRed S SE SSE SSW SW SaddleBrown Salmon SandyBrown SeaGreen Seashell Sepia Sienna S!
 ilver SimpleHead SkyBlue SlateBlue SlateGray Snow SpringGreen SteelBlue Suppress SuppressQuiet Tan TeXHead Teal TealBlue Thistle Ticksize Tomato Turquoise UnFill Up VERSION Value Vertical Violet VioletRed W WNW WSW Wheat White WhiteSmoke WildStrawberry XHIGH XLOW XYAlign YAlign YHIGH YLOW Yellow YellowGreen YellowOrange ZHIGH ZLOW aboveequationskip addpenarc addpenline align allowstepping angularsystem animationdelay appendsuffix arcarrowangle arcarrowfactor arrow2sizelimit arrowangle arrowbarb arrowdir arrowfactor arrowhookfactor arrowlength arrowsizelimit arrowtexfactor authorpen axis axiscoverage axislabelfactor background backgroundcolor backgroundpen barfactor barmarksizefactor basealign baselinetemplate bernstein beveljoin bigvertexpen bigvertexsize black blue bm bottom bp bracedefaultratio braceinnerangle bracemidangle braceouterangle brown bullet byfoci byvertices camerafactor chartreuse circlemarkradiusfactor circlenodesnumberfactor circleprecision circlescale cm codefile codepen codeskip colorPen coloredNodes coloredSegments conditionlength conicnodesfactor count cputimeformat crossmarksizefactor currentcoordsys currentlight currentpatterns currentpen currentpicture currentposition currentprojection curvilinearsystem cuttings cyan darkblue darkbrown darkcyan darkgray darkgreen darkgrey darkmagenta darkolive darkred dashdotted dashed datepen dateskip debuggerlines debugging deepblue deepcyan deepgray deepgreen deepgrey deepmagenta deepred deepyellow default defaultControl defaultS defaultbackpen defaultcoordsys defaultexcursion defaultfilename defaultformat defaultmassformat defaultpen defaultseparator diagnostics differentlengths dot dotfactor dotframe dotted doublelinepen doublelinespacing down duplicateFuzz ellipsenodesnumberfactor eps epsgeo epsilon evenodd expansionfactor extendcap fermionpen figureborder figuremattpen file3 firstnode firststep foregroundcolor fuchsia fuzz gapfactor ghostpen gluonamplitude gluonpen gluonratio gray green grey hatchepsilon havepagenumber heavyblue heavycyan heavygray!
  heavygreen heavygrey heavymagenta heavyred hline hwratio hyperbolanodesnumberfactor identity4 ignore inXasyMode inch inches includegraphicscommand inf infinity institutionpen intMax intMin invert invisible itempen itemskip itemstep labelmargin landscape lastnode left legendhskip legendlinelength legendmargin legendmarkersize legendmaxrelativewidth legendvskip lightblue lightcyan lightgray lightgreen lightgrey lightmagenta lightolive lightred lightyellow linemargin lm_infmsg lm_shortmsg longdashdotted longdashed magenta magneticRadius mantissaBits markangleradius markangleradiusfactor markanglespace markanglespacefactor maxrefinements mediumblue mediumcyan mediumgray mediumgreen mediumgrey mediummagenta mediumred mediumyellow middle minDistDefault minblockheight minblockwidth mincirclediameter minipagemargin minipagewidth minvertexangle miterjoin mm momarrowfactor momarrowlength momarrowmargin momarrowoffset momarrowpen monoPen morepoints nCircle nan newbulletcolor ngraph nil nmesh nobasealign nodeMarginDefault nodesystem nomarker nopoint noprimary nullpath nullpen numarray ocgindex oldbulletcolor olive orange origin overpaint page pageheight pagemargin pagenumberalign pagenumberpen pagenumberposition pagewidth paleblue palecyan palegray palegreen palegrey palemagenta palered paleyellow parabolanodesnumberfactor perpfactor phi photonamplitude photonpen photonratio pi pink plain plain_bounds plain_scaling plus preamblenodes pt purple r3 r4a r4b randMax realDigits realEpsilon realMax realMin red relativesystem reverse right roundcap roundjoin royalblue salmon saveFunctions scalarpen sequencereal settings shipped signedtrailingzero solid spinner springgreen sqrtEpsilon squarecap squarepen startposition stdin stdout stepfactor stepfraction steppagenumberpen stepping stickframe stickmarksizefactor stickmarkspacefactor swap textpen ticksize tildeframe tildemarksizefactor tinv titlealign titlepagepen titlepageposition titlepen titleskip top trailingzero treeLevelStep treeMinNodeWidth treeNodeStep trembleAngle trembleFr!
 equency trembleRandom undefined unitcircle unitsquare up urlpen urlskip version vertexpen vertexsize viewportmargin viewportsize vline white wye xformStack yellow ylabelwidth zerotickfuzz zerowinding ))
+AliceBlue Align Allow AntiqueWhite Apricot Aqua Aquamarine Aspect Azure BeginPoint Beige Bisque Bittersweet Black BlanchedAlmond Blue BlueGreen BlueViolet Both Break BrickRed Brown BurlyWood BurntOrange CCW CW CadetBlue CarnationPink Center Centered Cerulean Chartreuse Chocolate Coeff Coral CornflowerBlue Cornsilk Crimson Crop Cyan Dandelion DarkBlue DarkCyan DarkGoldenrod DarkGray DarkGreen DarkKhaki DarkMagenta DarkOliveGreen DarkOrange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DefaultHead DimGray DodgerBlue Dotted Down Draw E ENE EPS ESE E_Euler E_PC E_RK2 E_RK3BS Emerald EndPoint Euler Fill FillDraw FireBrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold Goldenrod Gray Green GreenYellow Honeydew HookHead Horizontal HotPink I IgnoreAspect IndianRed Indigo Ivory JOIN_IN JOIN_OUT JungleGreen Khaki LM_DWARF LM_MACHEP LM_SQRT_DWARF LM_SQRT_GIANT LM_USERTOL Label Lavender LavenderBlush LawnGreen Left LeftJustified LeftSide LemonChiffon LightBlue LightCoral LightCyan LightGoldenrodYellow LightGreen LightGrey LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateGray LightSteelBlue LightYellow Lime LimeGreen Linear Linen Log Logarithmic Magenta Mahogany Mark MarkFill MarkPath Maroon Max MediumAquamarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue MediumSpringGreen MediumTurquoise MediumVioletRed Melon MidPoint MidnightBlue Min MintCream MistyRose Moccasin Move MoveQuiet Mulberry N NE NNE NNW NULL_VERTEX NW NavajoWhite Navy NavyBlue NoAlign NoCrop NoFill NoSide OldLace Olive OliveDrab OliveGreen Orange OrangeRed Orchid Ox Oy PC PaleGoldenrod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip Peach PeachPuff Periwinkle Peru PineGreen Pink Plum PowderBlue ProcessBlue Purple RK2 RK3 RK3BS RK4 RK5 RK5DP RK5F RawSienna Red RedOrange RedViolet Rhodamine Right RightJustified RightSide RosyBrown RoyalBlue RoyalPurple RubineRed S SE SSE SSW SW SaddleBrown Salmon SandyBrown SeaGreen Seashell Sepia Sienna S!
 ilver SimpleHead SkyBlue SlateBlue SlateGray Snow SpringGreen SteelBlue Suppress SuppressQuiet Tan TeXHead Teal TealBlue Thistle Ticksize Tomato Turquoise UnFill Up VERSION Value Vertical Violet VioletRed W WNW WSW Wheat White WhiteSmoke WildStrawberry XHIGH XLOW XYAlign YAlign YHIGH YLOW Yellow YellowGreen YellowOrange ZHIGH ZLOW _outpipe aboveequationskip addpenarc addpenline align allowstepping angularsystem animationdelay appendsuffix arcarrowangle arcarrowfactor arrow2sizelimit arrowangle arrowbarb arrowdir arrowfactor arrowhookfactor arrowlength arrowsizelimit arrowtexfactor authorpen axis axiscoverage axislabelfactor background backgroundcolor backgroundpen barfactor barmarksizefactor basealign baselinetemplate bernstein beveljoin bigvertexpen bigvertexsize black blue bm bottom bp bracedefaultratio braceinnerangle bracemidangle braceouterangle brown bullet byfoci byvertices camerafactor chartreuse circlemarkradiusfactor circlenodesnumberfactor circleprecision circlescale cm codefile codepen codeskip colorPen coloredNodes coloredSegments conditionlength conicnodesfactor count cputimeformat crossmarksizefactor currentcoordsys currentlight currentpatterns currentpen currentpicture currentposition currentprojection curvilinearsystem cuttings cyan darkblue darkbrown darkcyan darkgray darkgreen darkgrey darkmagenta darkolive darkred dashdotted dashed datepen dateskip debuggerlines debugging deepblue deepcyan deepgray deepgreen deepgrey deepmagenta deepred deepyellow default defaultControl defaultS defaultbackpen defaultcoordsys defaultexcursion defaultfilename defaultformat defaultmassformat defaultpen defaultseparator differentlengths dot dotfactor dotframe dotted doublelinepen doublelinespacing down duplicateFuzz ellipsenodesnumberfactor eps epsgeo epsilon evenodd expansionfactor extendcap fermionpen figureborder figuremattpen file3 firstnode firststep foregroundcolor fuchsia fuzz gapfactor ghostpen gluonamplitude gluonpen gluonratio gray green grey hatchepsilon havepagenumber heavyblue heavycyan heavygray he!
 avygreen heavygrey heavymagenta heavyred hline hwratio hyperbolanodesnumberfactor identity identity4 ignore implicitshipout inch inches includegraphicscommand inf infinity institutionpen intMax intMin invert invisible itempen itemskip itemstep labelmargin landscape lastnode left legendhskip legendlinelength legendmargin legendmarkersize legendmaxrelativewidth legendvskip lightblue lightcyan lightgray lightgreen lightgrey lightmagenta lightolive lightred lightyellow linemargin lm_infmsg lm_shortmsg longdashdotted longdashed magenta magneticRadius mantissaBits markangleradius markangleradiusfactor markanglespace markanglespacefactor maxrefinements mediumblue mediumcyan mediumgray mediumgreen mediumgrey mediummagenta mediumred mediumyellow middle minDistDefault minblockheight minblockwidth mincirclediameter minipagemargin minipagewidth minvertexangle miterjoin mm momarrowfactor momarrowlength momarrowmargin momarrowoffset momarrowpen monoPen morepoints nCircle nan newbulletcolor ngraph nil nmesh nobasealign nodeMarginDefault nodesystem nomarker nopoint noprimary nullpath nullpen numarray ocgindex oldbulletcolor olive orange origin overpaint page pageheight pagemargin pagenumberalign pagenumberpen pagenumberposition pagewidth paleblue palecyan palegray palegreen palegrey palemagenta palered paleyellow parabolanodesnumberfactor perpfactor phi photonamplitude photonpen photonratio pi pink plain plain_bounds plain_scaling plus preamblenodes pt purple r3 r4a r4b randMax realDigits realEpsilon realMax realMin red relativesystem reverse right roundcap roundjoin royalblue salmon saveFunctions scalarpen sequencereal settings signedtrailingzero simplex solid spinner springgreen sqrtEpsilon squarecap squarepen startposition stdin stdout stepfactor stepfraction steppagenumberpen stepping stickframe stickmarksizefactor stickmarkspacefactor swap textpen ticksize tildeframe tildemarksizefactor tinv titlealign titlepagepen titlepageposition titlepen titleskip top trailingzero treeLevelStep treeMinNodeWidth treeNodeStep trembleAngl!
 e trembleFrequency trembleRandom undefined unitcircle unitsquare up urlpen urlskip version vertexpen vertexsize viewportmargin viewportsize vline white wye yellow ylabelwidth zeroTransform zerotickfuzz zerowinding ))

Modified: trunk/Master/texmf-dist/asymptote/asymptote.py
===================================================================
--- trunk/Master/texmf-dist/asymptote/asymptote.py	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/asymptote.py	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+
 # Python module to feed Asymptote with commands
 # (modified from gnuplot.py)
 from subprocess import *
@@ -6,7 +8,7 @@
 		self.session = Popen(['asy','-quiet','-inpipe=0','-outpipe=2'],stdin=PIPE)
 		self.help()
 	def send(self, cmd):
-		self.session.stdin.write(cmd+'\n')
+		self.session.stdin.write(bytes(cmd+'\n','utf-8'))
 		self.session.stdin.flush()
 	def size(self, size):
 		self.send("size(%d);" % size)
@@ -23,10 +25,10 @@
 	def erase(self):
 		self.send("erase();")
 	def help(self):
-		print "Asymptote session is open.  Available methods are:"
-		print "    help(), size(int), draw(str), fill(str), clip(str), label(str), shipout(str), send(str), erase()"
+		print("Asymptote session is open.  Available methods are:")
+		print("    help(), size(int), draw(str), fill(str), clip(str), label(str), shipout(str), send(str), erase()")
 	def __del__(self):
-		print "closing Asymptote session..."
+		print("closing Asymptote session...")
 		self.send('quit');
 		self.session.stdin.close();
 		self.session.wait()

Modified: trunk/Master/texmf-dist/asymptote/bsp.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/bsp.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/bsp.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -184,20 +184,20 @@
   for(int i=0; i < n; ++i)
     Faces[i]=faces[i].copy();
   
-  pic.nodes.push(new void (frame f, transform t, transform T,
-                           pair m, pair M) {
-                   // Fit all of the pictures so we know their exact sizes.
-                   face[] faces=new face[n];
-                   for(int i=0; i < n; ++i) {
-                     faces[i]=Faces[i].copy();
-                     face F=faces[i];
-                     F.t=t*T*F.pic.T;
-                     F.fit=F.pic.fit(t,T*F.pic.T,m,M);
-                   }
+  pic.add(new void (frame f, transform t, transform T,
+                                pair m, pair M) {
+                        // Fit all of the pictures so we know their exact sizes.
+                        face[] faces=new face[n];
+                        for(int i=0; i < n; ++i) {
+                          faces[i]=Faces[i].copy();
+                          face F=faces[i];
+                          F.t=t*T*F.pic.T;
+                          F.fit=F.pic.fit(t,T*F.pic.T,m,M);
+                        }
     
-                   bsp bsp=bsp(faces,P);
-                   if(bsp != null) bsp.add(f);
-                 });
+                        bsp bsp=bsp(faces,P);
+                        if(bsp != null) bsp.add(f);
+          });
     
   for(int i=0; i < n; ++i) {
     picture F=Faces[i].pic;

Modified: trunk/Master/texmf-dist/asymptote/plain.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -41,18 +41,19 @@
 
 typedef void exitfcn();
 
-bool needshipout() {
-  return !shipped && !currentpicture.empty();
-}
-
 void updatefunction()
 {
+  implicitshipout=true;
   if(!currentpicture.uptodate) shipout();
+  implicitshipout=false;
 }
 
 void exitfunction()
 {
-  if(needshipout()) shipout();
+  implicitshipout=true;
+  if(!currentpicture.empty())
+    shipout();
+  implicitshipout=false;
 }
 
 atupdate(updatefunction);
@@ -273,7 +274,6 @@
   string s=settings.autoimport;
   settings.autoimport="";
   eval("import \""+s+"\" as dummy",true);
-  shipped=false;
   atupdate(updatefunction);
   atexit(exitfunction);
   settings.autoimport=s;

Modified: trunk/Master/texmf-dist/asymptote/plain_Label.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_Label.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_Label.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -339,8 +339,8 @@
     }
 
     pic.add(new void (frame f, transform t) {
-        out(f,t,point(g,position),
-            alignrelative ? -Align*dir(t*g,position)*I : Align);
+        out(f,t,point(g,position),alignrelative ?
+            inverse(rotation(t))*-Align*dir(t*g,position)*I : Align);
       },!alignrelative);
 
     frame f;
@@ -485,6 +485,15 @@
 {
   label(pic,L,L.position,align,p,filltype);
 }
+
+// Label, but with postscript coords instead of asy
+void label(pair origin, picture pic=currentpicture, Label L, align align=NoAlign,
+           pen p=currentpen, filltype filltype=NoFill)
+{
+  picture opic;
+  label(opic,L,L.position,align,p,filltype);
+  add(pic,opic,origin);
+}
   
 void label(picture pic=currentpicture, Label L, explicit path g,
            align align=NoAlign, pen p=currentpen, filltype filltype=NoFill)

Modified: trunk/Master/texmf-dist/asymptote/plain_boxes.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_boxes.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_boxes.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -131,7 +131,9 @@
            real xmargin=0, real ymargin=xmargin,
            pen p=currentpen, filltype filltype=NoFill)
 {
-  frame f=pic.fit(max(pic.xsize-2*xmargin,0),max(pic.ysize-2*ymargin,0));
+  real penwidth=linewidth(p);
+  frame f=pic.fit(max(pic.xsize-2*(xmargin+penwidth),0),
+                  max(pic.ysize-2*(ymargin+penwidth),0));
   box(f,xmargin,ymargin,p,filltype,above=false);
   return f;
 }

Modified: trunk/Master/texmf-dist/asymptote/plain_constants.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_constants.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_constants.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -36,6 +36,9 @@
 restricted pair Align=sqrtEpsilon*NE; 
 restricted int mantissaBits=ceil(-log(realEpsilon)/log(2))+1;
 
+restricted transform identity;
+restricted transform zeroTransform=(0,0,0,0,0,0);
+
 int min(... int[] a) {return min(a);}
 int max(... int[] a) {return max(a);}
 

Modified: trunk/Master/texmf-dist/asymptote/plain_pens.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_pens.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_pens.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -324,10 +324,16 @@
 // Return a pen corresponding to a given 6-character RGB hexidecimal string.
 pen rgb(string s) 
 {
-  real value(string s, int i) {return hex(substr(s,2i,2))/255;}
+  int offset=substr(s,0,1) == '#' ? 1 : 0;
+  real value(string s, int i) {return hex(substr(s,2i+offset,2))/255;}
   return rgb(value(s,0),value(s,1),value(s,2));
 }
 
+pen RGB(int r, int g, int b)
+{
+  return rgb(r/255,g/255,b/255);
+}
+
 pen[] operator +(pen[] a, pen b)
 {
   return sequence(new pen(int i) {return a[i]+b;},a.length);

Modified: trunk/Master/texmf-dist/asymptote/plain_picture.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_picture.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_picture.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -169,6 +169,15 @@
 // TODO: Add documentation as to what T is.
 typedef void drawerBound(frame f, transform t, transform T, pair lb, pair rt);
 
+struct node {
+  drawerBound d;
+  string key;
+  void operator init(drawerBound d, string key=xasyKEY()) {
+    this.d=d;
+    this.key=key;
+  }
+}
+
 // PairOrTriple <<<1
 // This struct is used to represent a userMin/userMax which serves as both a
 // pair and a triple depending on the context.
@@ -199,9 +208,18 @@
   typedef void drawerBound3(frame f, transform3 t, transform3 T,
                             picture pic, projection P, triple lb, triple rt);
 
+  struct node3 {
+    drawerBound3 d;
+    string key;
+    void operator init(drawerBound3 d, string key=xasyKEY()) {
+      this.d=d;
+      this.key=key;
+    }
+  }
+
   // The functions to do the deferred drawing.
-  drawerBound[] nodes;
-  drawerBound3[] nodes3;
+  node[] nodes;
+  node3[] nodes3;
 
   bool uptodate=true;
 
@@ -266,15 +284,20 @@
   }
   init();
   
+  // Erase the current picture, retaining bounds.
+  void clear() {
+    nodes.delete();
+    nodes3.delete();
+    legend.delete();
+  }
+
   // Erase the current picture, retaining any size specification.
   void erase() {
-    nodes.delete();
-    nodes3.delete();
+    clear();
     bounds.erase();
     bounds3.erase();
     T=identity();
     scale=new ScaleT;
-    legend.delete();
     init();
   }
   
@@ -445,15 +468,15 @@
     uptodate=false;
     if(!exact) bounds.exact=false;
     if(above)
-      nodes.push(d);
+      nodes.push(node(d));
     else
-      nodes.insert(0,d);
+      nodes.insert(0,node(d));
   }
   
   // Faster implementation of most common case.
   void addExactAbove(drawerBound d) {
     uptodate=false;
-    nodes.push(d);
+    nodes.push(node(d));
   }
 
   void add(drawer d, bool exact=false, bool above=true) {
@@ -466,9 +489,9 @@
     uptodate=false;
     if(!exact) bounds.exact=false;
     if(above)
-      nodes3.push(d);
+      nodes3.push(node3(d));
     else
-      nodes3.insert(0,d);
+      nodes3.insert(0,node3(d));
   }
 
   void add(drawer3 d, bool exact=false, bool above=true) {
@@ -675,9 +698,10 @@
 
   frame fit(transform t, transform T0=T, pair m, pair M) {
     frame f;
-    int n = nodes.length;
-    for(int i=0; i < n; ++i)
-      nodes[i](f,t,T0,m,M);
+    for(node n : nodes) {
+      xasyKEY(n.key);
+      n.d(f,t,T0,m,M);
+    }
     return f;
   }
 
@@ -684,8 +708,10 @@
   frame fit3(transform3 t, transform3 T0=T3, picture pic, projection P,
              triple m, triple M) {
     frame f;
-    for(int i=0; i < nodes3.length; ++i)
-      nodes3[i](f,t,T0,pic,P,m,M);
+    for(node3 n : nodes3) {
+      xasyKEY(n.key);
+      n.d(f,t,T0,pic,P,m,M);
+    }
     return f;
   }
 
@@ -905,7 +931,7 @@
   // picture. Fitting this picture will not scale as the original picture would.
   picture drawcopy() {
     picture dest=new picture;
-    dest.nodes = copy(nodes);
+    dest.nodes=copy(nodes);
     dest.nodes3=copy(nodes3);
     dest.T=T;
     dest.T3=T3;
@@ -945,13 +971,15 @@
     picture dest=drawcopy();
 
     // Replace nodes with a single drawer that realizes the transform.
-    drawerBound[] oldnodes = dest.nodes;
+    node[] oldnodes = dest.nodes;
     void drawAll(frame f, transform tt, transform T, pair lb, pair rt) {
       transform Tt = T*t;
-      for (var node : oldnodes)
-        node(f, tt, Tt, lb, rt);
+      for (node n : oldnodes) {
+        xasyKEY(n.key);
+        n.d(f,tt,Tt,lb,rt);
+      }
     }
-    dest.nodes = new drawerBound[] { drawAll };
+    dest.nodes = new node[] {node(drawAll)};
 
     dest.uptodate=uptodate;
     dest.bounds=bounds.transformed(t);
@@ -984,16 +1012,19 @@
 
     picture srcCopy=src.drawcopy();
     // Draw by drawing the copied picture.
-    if(srcCopy.nodes.length > 0)
-      nodes.push(new void(frame f, transform t, transform T, pair m, pair M) {
+    if(srcCopy.nodes.length > 0) {
+      nodes.push(node(new void(frame f, transform t, transform T,
+                               pair m, pair M) {
           add(f,srcCopy.fit(t,T*srcCopy.T,m,M),group,filltype,above);
-        });
+          }));
+    }
     
     if(srcCopy.nodes3.length > 0) {
-      nodes3.push(new void(frame f, transform3 t, transform3 T3, picture pic,
-                           projection P, triple m, triple M) {
+      nodes3.push(node3(new void(frame f, transform3 t, transform3 T3,
+                                 picture pic, projection P, triple m, triple M)
+                        {
                     add(f,srcCopy.fit3(t,T3*srcCopy.T3,pic,P,m,M),group,above);
-                  });
+                        }));
     }
     
     legend.append(src.legend);
@@ -1042,6 +1073,14 @@
   pic.size(x,y,keepAspect);
 }
 
+void size(picture pic=currentpicture, transform t)
+{
+  if(pic.empty3()) {
+    pair z=size(pic.fit(t));
+    pic.size(z.x,z.y);
+  }
+}
+
 void size3(picture pic=currentpicture, real x, real y=x, real z=y,
            bool keepAspect=pic.keepAspect)
 {
@@ -1408,7 +1447,6 @@
 {
   if(copy)
     g=copy(g);
-  //pic.userClip(min(g),max(g));
   pic.clip(min(g), max(g),
            new void(frame f, transform t) {
              clip(f,t*g,stroke,fillrule,false);

Modified: trunk/Master/texmf-dist/asymptote/plain_scaling.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_scaling.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_scaling.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -192,19 +192,30 @@
   return M;
 }
 
-// Calculate the sizing constants for the given array and maximum size.
+import simplex;
+
+/*
+ Calculate the sizing constants for the given array and maximum size.
+ Solve the two-variable linear programming problem using the simplex method.
+ This problem is specialized in that the second variable, "b", does not have
+ a non-negativity condition, and the first variable, "a", is the quantity
+ being maximized.
+*/
 real calculateScaling(string dir, coord[] m, coord[] M, real size,
                       bool warn=true) {
-  access simplex;
-  simplex.problem p=new simplex.problem;
- 
+  real[][] A;
+  real[] b;
+  real[] c=new real[] {-1,0,0};
+
   void addMinCoord(coord c) {
     // (a*user + b) + truesize >= 0:
-    p.addRestriction(c.user,1,c.truesize);
-  }
+    A.push(new real[] {c.user,1,-1});
+    b.push(-c.truesize);
+  }     
   void addMaxCoord(coord c) {
     // (a*user + b) + truesize <= size:
-    p.addRestriction(-c.user,-1,size-c.truesize);
+    A.push(new real[] {-c.user,-1,1});
+    b.push(c.truesize-size);
   }
 
   for (int i=0; i < m.length; ++i)
@@ -212,11 +223,12 @@
   for (int i=0; i < M.length; ++i)
     addMaxCoord(M[i]);
 
-  int status=p.optimize();
-  if(status == simplex.problem.OPTIMAL) {
-    // TODO: Could just be return a;
-    return scaling.build(p.a(),p.b()).a;
-  } else if(status == simplex.problem.UNBOUNDED) {
+  int[] s=array(A.length,1);
+  simplex S=simplex(c,A,s,b);
+
+  if(S.case == S.OPTIMAL) {
+    return S.x[0];
+  } else if(S.case == S.UNBOUNDED) {
     if(warn) warning("unbounded",dir+" scaling in picture unbounded");
     return 0;
   } else {

Modified: trunk/Master/texmf-dist/asymptote/plain_shipout.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_shipout.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_shipout.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,6 +1,10 @@
 // Default file prefix used for inline LaTeX mode
 string defaultfilename;
 
+file _outpipe;
+if(settings.xasy)
+  _outpipe=output(mode="pipe");
+
 string[] file3;
 
 string outprefix(string prefix=defaultfilename) {
@@ -14,8 +18,6 @@
   return format;
 }
 
-bool shipped; // Was a picture or frame already shipped out?
-
 frame currentpatterns;
 
 frame Portrait(frame f) {return f;};
@@ -58,24 +60,37 @@
   } return F.f;
 }
 
-include plain_xasy;
+void deconstruct(picture pic=currentpicture)
+{
+  frame f;
+  transform t=pic.calculateTransform();
+  if(currentpicture.fitter == null)
+    f=pic.fit(t);
+  else
+    f=pic.fit();
+  deconstruct(f,currentpatterns,t);
+}
 
+bool implicitshipout=false;
+
 void shipout(string prefix=defaultfilename, frame f,
              string format="", bool wait=false, bool view=true,
 	     string options="", string script="",
-	     light light=currentlight, projection P=currentprojection)
+	     light light=currentlight, projection P=currentprojection,
+             transform t=identity)
 {
   if(is3D(f)) {
     f=enclose(prefix,embed3(prefix,f,format,options,script,light,P));
     if(settings.render != 0 && !prc(format)) {
-      shipped=true;
       return;
     }
   }
 
-  if(inXasyMode) {
-    erase();
-    add(f,group=false);
+  if(settings.xasy || (!implicitshipout && prefix == defaultfilename)) {
+    if(prefix == defaultfilename) {
+      currentpicture.clear();
+      add(f,group=false);
+    }
     return;
   }
   
@@ -84,9 +99,7 @@
   int limit=2000;
   if(abs(m.x) > limit || abs(m.y) > limit) f=shift(-m)*f;
 
-  shipout(prefix,f,currentpatterns,format,wait,view,
-          xformStack.empty() ? null : xformStack.pop0);
-  shipped=true;
+  _shipout(prefix,f,currentpatterns,format,wait,view,t);
 }
 
 void shipout(string prefix=defaultfilename, picture pic=currentpicture,
@@ -95,6 +108,7 @@
 	     string options="", string script="",
 	     light light=currentlight, projection P=currentprojection)
 {
+  pic.uptodate=true;
   if(!uptodate()) {
     bool inlinetex=settings.inlinetex;
     bool prc=prc(format);
@@ -110,14 +124,17 @@
       }
       settings.inlinetex=settings.inlineimage;
     }
-    frame f=pic.fit(prefix,format,view=view,options,script,light,P);
+    frame f;
+    transform t=pic.calculateTransform();
+    if(currentpicture.fitter == null)
+      f=pic.fit(t);
+    else
+      f=pic.fit(prefix,format,view=view,options,script,light,P);
+
     if(!prconly() && (!pic.empty2() || settings.render == 0 || prc || empty3))
-      shipout(prefix,orientation(f),format,wait,view);
+      shipout(prefix,orientation(f),format,wait,view,t);
     settings.inlinetex=inlinetex;
   }
-  
-  pic.uptodate=true;
-  shipped=true;
 }
 
 void newpage(picture pic=currentpicture)

Deleted: trunk/Master/texmf-dist/asymptote/plain_xasy.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/plain_xasy.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/plain_xasy.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,132 +0,0 @@
-restricted bool inXasyMode=false;
-bool diagnostics=false;
-void report(string text)
-{
- if(diagnostics)
-  write(text);
-}
-void report(transform t)
-{
- if(diagnostics)
-  write(t);
-}
-void report(int i)
-{
- if(diagnostics)
-  write(i);
-}
-void initXasyMode()
-{
-  size(0,0);
-  inXasyMode=true;
-}
-
-void exitXasyMode()
-{
-  inXasyMode=false;
-}
-private picture[] tempStore;
-private picture newPic;
-void startScript()
-{
-  tempStore.push(currentpicture.copy());
-  newPic=new picture;
-  currentpicture=newPic;
-}
-
-void endScript()
-{
-  if(tempStore.length < 1) {
-    abort("endScript() without matching beginScript()");
-  } else {
-    currentpicture=tempStore.pop();
-    add(currentpicture,newPic.fit(),group=false);
-  }
-  shipped=false;
-}
-
-struct indexedTransform {
-  int index;
-  transform t;
-  bool active;
-  void operator init(int index, transform t, bool active=true) {
-    this.index=index;
-    this.t=t;
-    this.active=active;
-  }
-}
-
-struct framedTransformStack {
-  struct transact {
-    transform t;
-    bool active;
-    void operator init(transform t, bool active=true) {
-      this.t=t;
-      this.active=active;
-    }
-    void operator init(indexedTransform i){
-      this.t=i.t;
-      this.active=i.active;
-    }
-    void operator init() {
-      this.t=identity();
-      this.active=true;
-    }
-  }
-  private transact[] stack;
-  private int[] frames;
-  private int stackBase=0;
-  transform pop() {
-    if(stack.length == 0)
-      return identity();
-    else {
-      transform popped=stack[0].t;
-      stack.delete(0);
-      report("Popped");
-      report(popped);
-      return popped;
-    }
-  }
-
-  transform pop0() {
-    if(stack.length == 0)
-      return identity();
-    else {
-      static transform zerotransform=(0,0,0,0,0,0);
-      transform popped=stack[0].active ? stack[0].t : zerotransform;
-      stack.delete(0);
-      report("Popped");
-      report(popped);
-      return popped;
-    }
-  }
-
-  void push(transform t, bool Active=true) {
-    report("Pushed");
-    report(t);
-    stack.push(transact(t,Active));
-  }
-
-  void add(... indexedTransform[] tList) {
-    transact[] toPush;
-    for(int a=0; a < tList.length; ++a)
-      toPush[tList[a].index]=transact(tList[a]);
-    for(int a=0; a < toPush.length; ++a)
-      if(!toPush.initialized(a))
-        toPush[a]=transact();
-    report("Added");
-    report(toPush.length);
-    stack.append(toPush);
-  }
-
-  bool empty() {
-    return stack.length == 0;
-  }
-}
-
-framedTransformStack xformStack;
-
-void deconstruct(picture pic=currentpicture, real magnification=1)
-{
-  deconstruct(pic.fit(),currentpatterns,magnification,xformStack.pop);
-}

Modified: trunk/Master/texmf-dist/asymptote/rational.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/rational.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/rational.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -87,6 +87,11 @@
   return r.p == s.p && r.q == s.q;
 }
 
+bool operator !=(rational r, rational s)
+{
+  return r.p != s.p || r.q != s.q;
+}
+
 bool operator <(rational r, rational s)
 {
   return r.p*s.q-s.p*r.q < 0;

Added: trunk/Master/texmf-dist/asymptote/rationalSimplex.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/rationalSimplex.asy	                        (rev 0)
+++ trunk/Master/texmf-dist/asymptote/rationalSimplex.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,280 @@
+// Rational simplex solver written by John C. Bowman and Pouria Ramazi, 2018.
+import rational;
+
+struct simplex {
+  static int OPTIMAL=0;
+  static int UNBOUNDED=1;
+  static int INFEASIBLE=2;
+
+  int case;
+  rational[] x;
+  rational cost;
+
+  int m,n;
+  int J;
+
+  // Row reduce based on pivot E[I][J]
+  void rowreduce(rational[][] E, int N, int I, int J) {
+    rational[] EI=E[I];
+    rational v=EI[J];
+    for(int j=0; j < J; ++j) EI[j] /= v;
+    EI[J]=1;
+    for(int j=J+1; j <= N; ++j) EI[j] /= v;
+
+    for(int i=0; i < I; ++i) {
+      rational[] Ei=E[i];
+      rational EiJ=Ei[J];
+      for(int j=0; j < J; ++j)
+        Ei[j] -= EI[j]*EiJ;
+      Ei[J]=0;
+      for(int j=J+1; j <= N; ++j)
+        Ei[j] -= EI[j]*EiJ;
+    }
+    for(int i=I+1; i <= m; ++i) {
+      rational[] Ei=E[i];
+      rational EiJ=Ei[J];
+      for(int j=0; j < J; ++j)
+        Ei[j] -= EI[j]*EiJ;
+      Ei[J]=0;
+      for(int j=J+1; j <= N; ++j)
+        Ei[j] -= EI[j]*EiJ;
+    }
+  }
+
+  int iterate(rational[][] E, int N, int[] Bindices) {
+    while(true) {
+      // Find first negative entry in bottom (reduced cost) row
+      rational[] Em=E[m];
+      for(J=0; J < N; ++J)
+        if(Em[J] < 0) break;
+
+      if(J == N)
+        return 0;
+
+      int I=-1;
+      rational M;
+      for(int i=0; i < m; ++i) {
+        rational e=E[i][J];
+        if(e > 0) {
+          M=E[i][N]/e;
+          I=i;
+          break;
+        }
+      }
+      for(int i=I+1; i < m; ++i) {
+        rational e=E[i][J];
+        if(e > 0) {
+          rational v=E[i][N]/e;
+          if(v <= M) {M=v; I=i;}
+        }
+      }
+      if(I == -1)
+        return UNBOUNDED; // Can only happen in Phase 2.
+
+      Bindices[I]=J;
+
+      // Generate new tableau
+      rowreduce(E,N,I,J);
+    }
+    return 0;
+  }
+
+  // Try to find a solution x to Ax=b that minimizes the cost c^T x,
+  // where A is an m x n matrix, x is a vector of length n, b is a
+  // vector of length m, and c is a vector of length n.
+  void operator init(rational[] c, rational[][] A, rational[] b,
+                     bool phase1=true) {
+    // Phase 1    
+    m=A.length;
+    n=A[0].length;
+
+    int N=phase1 ? n+m : n;
+    rational[][] E=new rational[m+1][N+1];
+    rational[] Em=E[m];
+
+    for(int j=0; j < n; ++j)
+      Em[j]=0;
+
+    for(int i=0; i < m; ++i) {
+      rational[] Ai=A[i];
+      rational[] Ei=E[i];
+      if(b[i] >= 0) {
+        for(int j=0; j < n; ++j) {
+          rational Aij=Ai[j];
+          Ei[j]=Aij;
+          Em[j] -= Aij;
+        }
+      } else {
+        for(int j=0; j < n; ++j) {
+          rational Aij=-Ai[j];
+          Ei[j]=Aij;
+          Em[j] -= Aij;
+        }
+      }
+    }
+
+    if(phase1) {
+      for(int i=0; i < m; ++i) { 
+        rational[] Ei=E[i];
+        for(int j=0; j < i; ++j)
+          Ei[n+j]=0;
+        Ei[n+i]=1;
+        for(int j=i+1; j < m; ++j)
+          Ei[n+j]=0;
+      }
+    }
+
+    rational sum=0;
+    for(int i=0; i < m; ++i) {
+      rational B=abs(b[i]);
+      E[i][N]=B;
+      sum -= B;
+    }
+    Em[N]=sum;
+
+    if(phase1)
+      for(int j=0; j < m; ++j)
+        Em[n+j]=0;
+   
+    int[] Bindices=sequence(new int(int x){return x;},m)+n;
+
+    if(phase1) {
+      iterate(E,N,Bindices);
+  
+      if(Em[J] != 0) {
+      case=INFEASIBLE;
+      return;
+      }
+    }
+    
+    rational[][] D=phase1 ? new rational[m+1][n+1] : E;
+    rational[] Dm=D[m];
+    rational[] cb=phase1 ? new rational[m] : c[n-m:n];
+    if(phase1) {
+      int ip=0; // reduced i
+      for(int i=0; i < m; ++i) {
+        int k=Bindices[i];
+        if(k >= n) continue;
+        Bindices[ip]=k; 
+        cb[ip]=c[k];
+        rational[] Dip=D[ip];
+        rational[] Ei=E[i];
+        for(int j=0; j < n; ++j)
+          Dip[j]=Ei[j];
+        Dip[n]=Ei[N];
+        ++ip;
+      }
+
+      rational[] Dip=D[ip];
+      rational[] Em=E[m];
+      for(int j=0; j < n; ++j)
+        Dip[j]=Em[j];
+      Dip[n]=Em[N];
+
+      m=ip;
+
+      for(int j=0; j < n; ++j) {
+        rational sum=0;
+        for(int k=0; k < m; ++k)
+          sum += cb[k]*D[k][j];
+        Dm[j]=c[j]-sum;
+      }
+
+      // Done with Phase 1
+    }
+   
+    rational sum=0;
+    for(int k=0; k < m; ++k)
+      sum += cb[k]*D[k][n];
+    Dm[n]=-sum;
+
+    if(iterate(D,n,Bindices) == UNBOUNDED) {
+    case=UNBOUNDED;
+    return;
+    }
+
+    for(int j=0; j < n; ++j)
+      x[j]=0;
+
+    for(int k=0; k < m; ++k)
+      x[Bindices[k]]=D[k][n];
+
+    cost=-Dm[n];
+    case=OPTIMAL;
+  }
+
+  // Try to find a solution x to sgn(Ax-b)=sgn(s) that minimizes the cost
+  // c^T x, where A is an m x n matrix, x is a vector of length n, b is a
+  // vector of length m, and c is a vector of length n.
+  void operator init(rational[] c, rational[][] A, int[] s, rational[] b) {
+    int m=A.length;
+    int n=A[0].length;
+
+    int count=0;
+    for(int i=0; i < m; ++i)
+      if(s[i] != 0) ++count;
+
+    rational[][] a=new rational[m][n+count];
+
+    for(int i=0; i < m; ++i) {
+      rational[] ai=a[i];
+      rational[] Ai=A[i];
+      for(int j=0; j < n; ++j) {
+        ai[j]=Ai[j];
+      }
+    }
+  
+    int k=0;
+
+    for(int i=0; i < m; ++i) {
+      rational[] ai=a[i];
+      for(int j=0; j < k; ++j)
+        ai[n+j]=0;
+      if(k < count)
+        ai[n+k]=-s[i];
+      for(int j=k+1; j < count; ++j)
+        ai[n+j]=0;
+      if(s[i] != 0) ++k;
+    }
+
+    bool phase1=!all(s == -1);
+    operator init(concat(c,array(count,rational(0))),a,b,phase1);
+
+    if(case == OPTIMAL)
+      x.delete(n,n+count-1);
+  }
+}
+
+/*
+simplex S=simplex(new rational[] {4,1,1},
+                  new rational[][] {{2,1,2},{3,3,1}},
+                  new rational[] {4,3});
+
+simplex S=simplex(new rational[] {2,6,1,1},
+                  new rational[][] {{1,2,0,1},{1,2,1,1},{1,3,-1,2},{1,1,1,0}},
+                  new rational[] {6,7,7,5});
+simplex S=simplex(new rational[] {-10,-12,-12,0,0,0},
+                  new rational[][] {{1,2,2,1,0,0},
+                                    {2,1,2,0,1,0},
+                                    {2,2,1,0,0,1}},
+                  new rational[] {20,20,20});
+
+simplex S=simplex(new rational[] {-10,-12,-12},
+                  new rational[][] {{1,2,2},
+                                    {2,1,2},
+                                    {2,2,1}},
+                  new int[] {0,0,-1},
+                  new rational[] {20,20,20});
+
+simplex S=simplex(new rational[] {1,1,1,0},
+                  new rational[][] {{1,2,3,0},
+                                    {-1,2,6,0},
+                                    {0,4,9,0},
+                                    {0,0,3,1}},
+                  new rational[] {3,2,5,1});
+
+write();
+write("case:",S.case);
+write("x:",S.x);
+write("Cost=",S.cost);
+*/

Modified: trunk/Master/texmf-dist/asymptote/simplex.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/simplex.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/simplex.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,274 +1,253 @@
-/*****
- * simplex.asy
- * Andy Hammerlindl 2004/07/27
- *
- * Solves the two-variable linear programming problem using the simplex method.
- * This problem is specialized in that the second variable, "b", does not have
- * a non-negativity condition, and the first variable, "a", is the quantity
- * being maximized.
- * Correct execution of the algorithm also assumes that the coefficient of "b"
- * will be +1 or -1 in every added restriction, and that the problem can be
- * initialized to a valid state by pivoting b with one of the slack
- * variables.  This assumption may in fact be incorrect.
- *****/
+// General simplex solver written by John C. Bowman and Pouria Ramazi, 2018.
 
-private real infinity=sqrt(0.25*realMax);
+struct simplex {
+  static int OPTIMAL=0;
+  static int UNBOUNDED=1;
+  static int INFEASIBLE=2;
 
-struct problem {
-  typedef int var;
-  static var VAR_A = 0;
-  static var VAR_B = 1;
+  int case;
+  real[] x;
+  real cost;
 
-  static int OPTIMAL = -1;
-  static var UNBOUNDED = -2;
-  static int INVALID = -3;
+  int m,n;
+  int J;
+  real epsilonA;
 
-  struct row {
-    real c, t[];
+  // Row reduce based on pivot E[I][J]
+  void rowreduce(real[][] E, int N, int I, int J) {
+    real[] EI=E[I];
+    real v=EI[J];
+    for(int j=0; j < J; ++j) EI[j] /= v;
+    EI[J]=1.0;
+    for(int j=J+1; j <= N; ++j) EI[j] /= v;
+
+    for(int i=0; i < I; ++i) {
+      real[] Ei=E[i];
+      real EiJ=Ei[J];
+      for(int j=0; j < J; ++j)
+        Ei[j] -= EI[j]*EiJ;
+      Ei[J]=0.0;
+      for(int j=J+1; j <= N; ++j)
+        Ei[j] -= EI[j]*EiJ;
+    }
+    for(int i=I+1; i <= m; ++i) {
+      real[] Ei=E[i];
+      real EiJ=Ei[J];
+      for(int j=0; j < J; ++j)
+        Ei[j] -= EI[j]*EiJ;
+      Ei[J]=0.0;
+      for(int j=J+1; j <= N; ++j)
+        Ei[j] -= EI[j]*EiJ;
+    }
   }
 
-  // The variables of the rows.
-  // Initialized for the two variable problem.
-  var[] v = {VAR_A, VAR_B};
+  int iterate(real[][] E, int N, int[] Bindices) {
+    while(true) {
+      // Find first negative entry in bottom (reduced cost) row
+      real[] Em=E[m];
+      for(J=0; J < N; ++J)
+        if(Em[J] < 0) break;
 
-  // The rows of equalities.
-  row rowA() {
-    row r = new row;
-    r.c = 0;
-    r.t = new real[] {1, 0};
-    return r;
-  }
-  row rowB() {
-    row r = new row;
-    r.c = 0;
-    r.t = new real[] {0, 1};
-    return r;
-  }
-  row[] rows = {rowA(), rowB()};
+      if(J == N)
+        return 0;
 
-  // The number of original variables.
-  int n = rows.length;
+      int I=-1;
+      real M;
+      for(int i=0; i < m; ++i) {
+        real e=E[i][J];
+        if(e > epsilonA) {
+          M=E[i][N]/e;
+          I=i;
+          break;
+        }
+      }
+      for(int i=I+1; i < m; ++i) {
+        real e=E[i][J];
+        if(e > epsilonA) {
+          real v=E[i][N]/e;
+          if(v <= M) {M=v; I=i;}
+        }
+      }
+      if(I == -1)
+        return UNBOUNDED; // Can only happen in Phase 2.
 
-  // Pivot the variable v[col] with vp.
-  void pivot(int col, var vp)
-  {
-    var vc=v[col];
+      Bindices[I]=J;
 
-    // Recalculate rows v[col] and vp for the pivot-swap.
-    row rvc = rows[vc], rvp = rows[vp];
-    real factor=1/rvp.t[col]; // NOTE: Handle rvp.t[col] == 0 case.
-    rvc.c=-rvp.c*factor;
-    rvp.c=0;
-    rvc.t=-rvp.t*factor;
-    rvp.t *= 0;
-    rvc.t[col]=factor;
-    rvp.t[col]=1;
-    
-    var a=min(vc,vp);
-    var b=max(vc,vp);
-    
-    // Recalculate the rows other than the two used for the above pivot.
-    for (var i = 0; i < a; ++i) {
-      row r=rows[i];
-      real m = r.t[col];
-      r.c += m*rvc.c;
-      r.t += m*rvc.t;
-      r.t[col]=m*factor;
+      // Generate new tableau
+      rowreduce(E,N,I,J);
     }
-    for (var i = a+1; i < b; ++i) {
-      row r=rows[i];
-      real m = r.t[col];
-      r.c += m*rvc.c;
-      r.t += m*rvc.t;
-      r.t[col]=m*factor;
-    }
-    for (var i = b+1; i < rows.length; ++i) {
-      row r=rows[i];
-      real m = r.t[col];
-      r.c += m*rvc.c;
-      r.t += m*rvc.t;
-      r.t[col]=m*factor;
-    }
-
-    // Relabel the vars.
-    v[col] = vp;
+    return 0;
   }
 
-  // As b does not have a non-negativity condition, it must initially be
-  // pivoted out for a variable that does.  This selects the initial
-  // variable to pivot with b.  It also assumes that there is a valid
-  // solution with a == 0 to the linear programming problem, and if so, it
-  // picks a pivot to get to that state.  In our case, a == 0 corresponds to
-  // a picture with the user coordinates shrunk down to zero, and if that
-  // doesn't fit, nothing will.
-  var initVar()
-  {
-    real min=infinity, max=-infinity;
-    var argmin=0, argmax=0;
+  // Try to find a solution x to Ax=b that minimizes the cost c^T x,
+  // where A is an m x n matrix, x is a vector of n non-negative numbers,
+  // b is a vector of length m, and c is a vector of length n.
+  void operator init(real[] c, real[][] A, real[] b, bool phase1=true) {
+    static real epsilon=sqrt(realEpsilon);
+    epsilonA=epsilon*norm(A);
 
-    for (var i = 2; i < rows.length; ++i) {
-      row r=rows[i];
-      if (r.t[VAR_B] > 0) {
-        real val=r.c/r.t[VAR_B];
-        if (val < min) {
-          min=val;
-          argmin=i;
+    // Phase 1    
+    m=A.length;
+    if(m == 0) {case=INFEASIBLE; return;}
+    n=A[0].length;
+    if(n == 0) {case=INFEASIBLE; return;}
+
+    int N=phase1 ? n+m : n;
+    real[][] E=new real[m+1][N+1];
+    real[] Em=E[m];
+
+    for(int j=0; j < n; ++j)
+      Em[j]=0;
+
+    for(int i=0; i < m; ++i) {
+      real[] Ai=A[i];
+      real[] Ei=E[i];
+      if(b[i] >= 0) {
+        for(int j=0; j < n; ++j) {
+          real Aij=Ai[j];
+          Ei[j]=Aij;
+          Em[j] -= Aij;
         }
-      } else if (r.t[VAR_B] < 0) {
-        real val=r.c/r.t[VAR_B];
-        if (val > max) {
-          max=val;
-          argmax=i;
+      } else {
+        for(int j=0; j < n; ++j) {
+          real Aij=-Ai[j];
+          Ei[j]=Aij;
+          Em[j] -= Aij;
         }
       }
     }
 
-    // If b has a minimal value, choose a pivot that will give b its minimal
-    // value.  Otherwise, if b has maximal value, choose a pivot to give b its
-    // maximal value.
-    return argmin != 0 ? argmin :
-      argmax != 0 ? argmax :
-      UNBOUNDED;
-  }
+    if(phase1) {
+      for(int i=0; i < m; ++i) { 
+        real[] Ei=E[i];
+        for(int j=0; j < i; ++j)
+          Ei[n+j]=0.0;
+        Ei[n+i]=1.0;
+        for(int j=i+1; j < m; ++j)
+          Ei[n+j]=0.0;
+      }
+    }
 
-  // Initialize the linear program problem by moving into an acceptable state
-  // this assumes that b is unrestrained and is the second variable.
-  // NOTE: Works in limited cases, may be bug-ridden.
-  void init()
-  {
-    // Find the lowest constant term in the equations.
-    var lowest = 0;
-    for (var i = 2; i < rows.length; ++i) {
-      if (rows[i].c < rows[lowest].c)
-        lowest = i;
+    real sum=0;
+    for(int i=0; i < m; ++i) {
+      real B=abs(b[i]);
+      E[i][N]=B;
+      sum -= B;
     }
+    Em[N]=sum;
 
-    // Pivot if necessary.
-    if (lowest != 0)
-      pivot(VAR_B, lowest);
-  }
+    if(phase1)
+      for(int j=0; j < m; ++j)
+        Em[n+j]=0.0;
+   
+    int[] Bindices=sequence(new int(int x){return x;},m)+n;
 
-  // Selects a column to pivot on.  Returns OPTIMAL if the current state is
-  // optimal.  Assumes we are optimizing the first row.
-  int selectColumn()
-  {
-    int i=find(rows[0].t > 0,1);
-    return (i >= 0) ? i : OPTIMAL;
-  }
-
-  // Select the new variable associated with a pivot on the column given.
-  // Returns UNBOUNDED if the space is unbounded.
-  var selectVar(int col)
-  {
-    // We assume that the first two vars (a and b) once swapped out, won't be
-    // swapped back in.  This finds the variable which gives the tightest
-    // non-negativity condition restricting our optimization.  This turns
-    // out to be the max of c/t[col].  Note that as c is positive, and
-    // t[col] is negative, all c/t[col] will be negative, so we are finding
-    // the smallest in magnitude.
-    var vp=UNBOUNDED;
-    real max=-infinity;
-    for (int i = 2; i < rows.length; ++i) {
-      row r=rows[i];
-      if(r.c < max*r.t[col]) {
-        max=r.c/r.t[col]; vp=i;
+    if(phase1) {
+      iterate(E,N,Bindices);
+  
+      if(abs(Em[J]) > epsilonA) {
+      case=INFEASIBLE;
+      return;
       }
     }
     
-    return vp;
-  }
+    real[][] D=phase1 ? new real[m+1][n+1] : E;
+    real[] Dm=D[m];
+    real[] cb=phase1 ? new real[m] : c[n-m:n];
+    if(phase1) {
+      int ip=0; // reduced i
+      for(int i=0; i < m; ++i) {
+        int k=Bindices[i];
+        if(k >= n) continue;
+        Bindices[ip]=k; 
+        cb[ip]=c[k];
+        real[] Dip=D[ip];
+        real[] Ei=E[i];
+        for(int j=0; j < n; ++j)
+          Dip[j]=Ei[j];
+        Dip[n]=Ei[N];
+        ++ip;
+      }
 
-  // Checks that the rows are in a valid state.
-  bool valid()
-  {
-    // Checks that constants are valid.
-    bool validConstants() {
-      for (int i = 0; i < rows.length; ++i)
-        // Do not test the row for b, as it does not have a non-negativity
-        // condition.
-        if (i != VAR_B && rows[i].c < 0)
-           return false;
-      return true;
-    }
+      real[] Dip=D[ip];
+      real[] Em=E[m];
+      for(int j=0; j < n; ++j)
+        Dip[j]=Em[j];
+      Dip[n]=Em[N];
 
-    // Check a variable to see if its row is simple.
-    // NOTE: Simple rows could be optimized out, since they are not really
-    // used. 
-    bool validVar(int col) {
+      m=ip;
 
-      var vc = v[col];
-      row rvc = rows[vc];
+      for(int j=0; j < n; ++j) {
+        real sum=0;
+        for(int k=0; k < m; ++k)
+          sum += cb[k]*D[k][j];
+        Dm[j]=c[j]-sum;
+      }
 
-      if (rvc.c != 0)
-        return false;
-      for (int i = 0; i < n; ++i)
-        if (rvc.t[i] != (i == col ? 1 : 0))
-          return false;
-      
-      return true;
+      // Done with Phase 1
     }
+   
+    real sum=0;
+    for(int k=0; k < m; ++k)
+      sum += cb[k]*D[k][n];
+    Dm[n]=-sum;
 
-    if (!validConstants()) {
-      return false;
+    if(iterate(D,n,Bindices) == UNBOUNDED) {
+    case=UNBOUNDED;
+    return;
     }
-    for (int i = 0; i < n; ++i)
-      if (!validVar(i)) {
-        return false;
-      }
 
-    return true;
+    for(int j=0; j < n; ++j)
+      x[j]=0;
+
+    for(int k=0; k < m; ++k)
+      x[Bindices[k]]=D[k][n];
+
+    cost=-Dm[n];
+    case=OPTIMAL;
   }
 
+  // Try to find a solution x to sgn(Ax-b)=sgn(s) that minimizes the cost
+  // c^T x, where A is an m x n matrix, x is a vector of n non-negative
+  // numbers, b is a vector of length m, and c is a vector of length n.
+  void operator init(real[] c, real[][] A, int[] s, real[] b) {
+    int m=A.length;
+    if(m == 0) {case=INFEASIBLE; return;}
+    int n=A[0].length;
+    if(n == 0) {case=INFEASIBLE; return;}
 
-  // Perform the algorithm to find the optimal solution.  Returns OPTIMAL,
-  // UNBOUNDED, or INVALID (if no solution is possible).
-  int optimize()
-  {
-    // Put into a valid state to begin and pivot b out.
-    var iv=initVar();
-    if (iv == UNBOUNDED)
-      return iv;
-    pivot(VAR_B, iv);
+    int count=0;
+    for(int i=0; i < m; ++i)
+      if(s[i] != 0) ++count;
 
-    if (!valid())
-      return INVALID;
+    real[][] a=new real[m][n+count];
 
-    while(true) {
-      int col = selectColumn();
-      
-      if (col == OPTIMAL)
-        return col;
-      var vp = selectVar(col);
-      
-      if (vp == UNBOUNDED)
-        return vp;
+    for(int i=0; i < m; ++i) {
+      real[] ai=a[i];
+      real[] Ai=A[i];
+      for(int j=0; j < n; ++j) {
+        ai[j]=Ai[j];
+      }
+    }
+  
+    int k=0;
 
-      pivot(col, vp);
+    for(int i=0; i < m; ++i) {
+      real[] ai=a[i];
+      for(int j=0; j < k; ++j)
+        ai[n+j]=0;
+      if(k < count)
+        ai[n+k]=-s[i];
+      for(int j=k+1; j < count; ++j)
+        ai[n+j]=0;
+      if(s[i] != 0) ++k;
     }
 
-    // Shouldn't reach here.
-    return INVALID;
-  }
+    //    bool phase1=!all(s == -1); // TODO: Check
+    bool phase1=true;
+    operator init(concat(c,array(count,0.0)),a,b,phase1);
 
-  // Add a restriction to the problem:
-  // t1*a + t2*b + c >= 0
-  void addRestriction(real t1, real t2, real c)
-  {
-    row r = new row;
-    r.c = c;
-    r.t = new real[] {t1, t2};
-    rows.push(r);
+    if(case == OPTIMAL)
+      x.delete(n,n+count-1);
   }
-
-  // Return the value of a computed.
-  real a()
-  {
-    return rows[VAR_A].c;
-  }
-
-  // Return the value of b computed.
-  real b()
-  {
-    return rows[VAR_B].c;
-  }
 }

Modified: trunk/Master/texmf-dist/asymptote/slide.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/slide.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/slide.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -225,7 +225,7 @@
   for(int i=0; i < firstnode.length; ++i) {
     for(int j=firstnode[i]; j <= lastnode[i]; ++j) {
       tex(bulletcolor(oldbulletcolor));
-      currentpicture.add(currentpicture.nodes[j]);
+      currentpicture.add(currentpicture.nodes[j].d);
     }
   }
   firstnode.push(currentpicture.nodes.length-1);

Modified: trunk/Master/texmf-dist/asymptote/three.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/three.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/three.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,6 +1,7 @@
 private import math;
 
-if(inXasyMode) settings.render=0;
+if(settings.xasy)
+  settings.render=0;
 
 if(prc0()) {
   if(!latex()) settings.prc=false;
@@ -2916,9 +2917,9 @@
   if((preview || (prc && settings.render == 0)) && settings.embed) {
     image=prefix;
     if(settings.inlinetex) image += "_0";
-    if(!preview && !shipped && !S.pic2.empty2()) {
+    if(!preview && !S.pic2.empty2()) {
       transform T=S.pic2.scaling(S.width,S.height);
-      shipout(image,S.pic2.fit(T),newframe,nativeformat(),false,false,null);
+      _shipout(image,S.pic2.fit(T),newframe,nativeformat(),false,false);
     }
     
     image += "."+nativeformat();

Modified: trunk/Master/texmf-dist/asymptote/version.asy
===================================================================
--- trunk/Master/texmf-dist/asymptote/version.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/asymptote/version.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1 +1 @@
-string VERSION="2.44";
+string VERSION="2.47";

Modified: trunk/Master/texmf-dist/doc/asymptote/CAD.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/asymptote/TeXShopAndAsymptote.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/asymptote/asy-latex.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/asymptote/asyRefCard.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/asymptote/asymptote.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/asymptote/examples/p-orbital.asy
===================================================================
--- trunk/Master/texmf-dist/doc/asymptote/examples/p-orbital.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/doc/asymptote/examples/p-orbital.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -12,7 +12,7 @@
   real r=t.x;
   real phi=t.y;
   real f=f(r);
-  real s=max(min(c0/f,1),-1);
+  real s=max(min(f != 0 ? c0/f : 1,1),-1);
   real R=r*sqrt(1-s^2);
   return (R*cos(phi),R*sin(phi),r*s);
 }

Modified: trunk/Master/texmf-dist/doc/asymptote/examples/planes.asy
===================================================================
--- trunk/Master/texmf-dist/doc/asymptote/examples/planes.asy	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/doc/asymptote/examples/planes.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -16,4 +16,3 @@
 filldraw(faces.push(g),project(g),green);
 
 add(faces);
-

Added: trunk/Master/texmf-dist/doc/asymptote/examples/slope.asy
===================================================================
--- trunk/Master/texmf-dist/doc/asymptote/examples/slope.asy	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/asymptote/examples/slope.asy	2019-02-28 18:48:48 UTC (rev 50168)
@@ -0,0 +1,83 @@
+import ode;
+import graph;
+import math;
+size(200,200,IgnoreAspect);
+
+real f(real t, real y) {return cos(y);}
+//real f(real t, real y) {return 1/(1+y);}
+typedef real function(real,real);
+
+real a=0;
+real b=1;
+real y0=0;
+
+real L[]={1,2};
+
+int M=L.length; // Number of modes.
+
+//real Y0[]=array(M,y0);
+real Y0[]=new real[] {-1,2};
+
+real[] F(real t, real[] y) {
+  return sequence(new real(int m) {return f(t,y[M-m-1]);},M);
+    //  return new real[] {exp((L[1]-1)*t)*y[1],
+    //      -exp(-(L[1]-1)*t)*y[0]};
+  //  return new real[]{-y[0]^2};
+}
+
+real[] G(real t, real[] y) {
+  return F(t,y)-sequence(new real(int m) {return L[m]*y[m];},M);
+}
+
+real lambda=sqrt(0.5);
+real[] tau,error,error2;
+int n=25;
+
+real order=3;
+
+for(int i=0; i < n-1; ++i) {
+  real dt=(b-a)*lambda^(n-i);
+  Solution S=integrate(Y0,L,F,a,b,dt,dynamic=false,0.0002,0.0004,ERK3BS,verbose=false);
+  real maxnorm=0;
+
+  Solution E=integrate(Y0,G,a,b,1e-2*dt,dynamic=false,0.0002,0.0004,RK5);
+  real[] exact=E.y[E.y.length-1];
+
+  //  real[] exact=new real[] {exp(-b)*sin(b),exp(-L[1]*b)*cos(b)};
+  for(int m=0; m < M; ++m)
+    maxnorm=max(maxnorm,abs(S.y[S.y.length-1][m]-exact[m]));
+    if(maxnorm != 0) {
+      tau.push(dt);
+      //      error.push(dt^-(order+1)*maxnorm);
+            error.push(maxnorm);
+    }
+}
+
+/*
+for(int i=0; i < n-1; ++i) {
+  real dt=(b-a)*lambda^(n-i);
+  real maxnorm=0;
+  for(int m=0; m < M; ++m) {
+    solution S=integrate(Y0[m],L[m],f,a,b,dt,dynamic=false,0.000,1000,RK4_375,verbose=false);
+    maxnorm=max(maxnorm,abs(S.y[S.y.length-1]-exact[m]));
+  }
+  error2.push(dt^-order*maxnorm);
+}
+*/
+
+//scale(Log,Log);
+scale(Log,Linear);
+
+//draw(graph(tau,error),marker(scale(0.8mm)*unitcircle,red));
+//draw(graph(tau,error2),marker(scale(0.8mm)*unitcircle,blue));
+
+int[] index=sequence(error.length-1);
+real[] slope=log(error[index+1]/error[index])/log(tau[index+1]/tau[index]);
+real[] t=sqrt(tau[index]*tau[index+1]);
+//write(t,slope);
+draw(graph(t,slope),red);
+
+
+
+xaxis("$\tau$",BottomTop,LeftTicks);
+yaxis("$e/\tau^"+string(order)+"$",LeftRight,RightTicks);

Modified: trunk/Master/texmf-dist/doc/info/asy-faq.info
===================================================================
--- trunk/Master/texmf-dist/doc/info/asy-faq.info	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/doc/info/asy-faq.info	2019-02-28 18:48:48 UTC (rev 50168)
@@ -10,7 +10,7 @@
 File: asy-faq.info, Node: Top, Next: Question 1.1, Up: (dir)
 
             ASYMPTOTE FREQUENTLY ASKED QUESTIONS
-                            07 Apr 2018
+                            30 Jul 2018
                           
 This is the list of Frequently Asked Questions about Asymptote (asy).
 

Modified: trunk/Master/texmf-dist/doc/info/asymptote.info
===================================================================
--- trunk/Master/texmf-dist/doc/info/asymptote.info	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/doc/info/asymptote.info	2019-02-28 18:48:48 UTC (rev 50168)
@@ -1,7 +1,7 @@
-This is asymptote.info, produced by makeinfo version 6.4 from
+This is asymptote.info, produced by makeinfo version 6.5 from
 asymptote.texi.
 
-This file documents 'Asymptote', version 2.44.
+This file documents 'Asymptote', version 2.47.
 
    <http://asymptote.sourceforge.net>
 
@@ -22,7 +22,7 @@
 Asymptote
 *********
 
-This file documents 'Asymptote', version 2.44.
+This file documents 'Asymptote', version 2.47.
 
    <http://asymptote.sourceforge.net>
 
@@ -339,7 +339,7 @@
 <http://www.imagemagick.org/script/binary-releases.php>
 
 is required to support output formats other than EPS, PDF, SVG, and PNG
-(*note convert::).  The 'Python 2' interpreter from
+(*note convert::).  The 'Python 3' interpreter from
 <http://www.python.org> is only required if you wish to try out the
 graphical user interface (*note GUI::).
 
@@ -778,8 +778,8 @@
 draw((1,0){up}..{left}(0,1),Arrow);
 
                             [quartercircle]
-Here the directions 'up' and 'left' in braces specify the incoming and
-outgoing directions at the points '(1,0)' and '(0,1)', respectively.
+Here the directions 'up' and 'left' in braces specify the outgoing and
+incoming directions at the points '(1,0)' and '(0,1)', respectively.
 
    In general, a path is specified as a list of points (or other paths)
 interconnected with '--', which denotes a straight line segment, or
@@ -2248,6 +2248,10 @@
           This produces an RGB color, where each of the red, green, and
           blue intensities 'r', 'g', 'b', lies in the interval [0,1].
 
+     'pen RGB(int r, int g, int b);'
+          This produces an RGB color, where each of the red, green, and
+          blue intensities 'r', 'g', 'b', lies in the interval [0,255].
+
      'pen cmyk(real c, real m, real y, real k);'
           This produces a CMYK color, where each of the cyan, magenta,
           yellow, and black intensities 'c', 'm', 'y', 'k', lies in the
@@ -2609,7 +2613,7 @@
 
    The built-in transforms are:
 
-'transform identity();'
+'transform identity;'
      the identity transform;
 'transform shift(pair z);'
      translates by the pair 'z';
@@ -2629,6 +2633,8 @@
      rotates by 'angle' in degrees about 'z';
 'transform reflect(pair a, pair b);'
      reflects about the line 'a--b'.
+'transform zeroTransform;'
+     the zero transform;
 
    The implicit initializer for transforms is 'identity()'.  The
 routines 'shift(transform t)' and 'shiftless(transform t)' return the
@@ -4148,9 +4154,12 @@
      bob     9
      pete    7
 
-'T[] sort(T[] a, bool less(T i, T j))'
-     returns a copy of 'a' stably sorted in ascending order such that
-     element 'i' precedes element 'j' if 'less(i,j)' is true.
+'T[] sort(T[] a, bool less(T i, T j), bool stable=true)'
+     returns a copy of 'a' sorted in ascending order such that element
+     'i' precedes element 'j' if 'less(i,j)' is true, subject to (if
+     'stable' is 'true') the stability constraint that the original
+     order of elements 'i' and 'j' is preserved if 'less(i,j)' and
+     'less(j,i)' are both 'false'.
 
 'T[][] transpose(T[][] a)'
      returns the transpose of 'a'.
@@ -7228,6 +7237,9 @@
 |b.x b.y b.z 1|
 |c.x c.y c.z 1|
 |d.x d.y d.z 1|
+   The result is negative (positive) if 'a', 'b', 'c' appear in
+counterclockwise (clockwise) order when viewed from 'd' or zero if all
+four points are coplanar.
 
    The routine
 real insphere(triple a, triple b, triple c, triple d, triple e);
@@ -7343,7 +7355,6 @@
 
 add(faces);
 
-
                                [planes]
 
 
@@ -8125,6 +8136,7 @@
 -wait                  Wait for child processes to finish before exiting [false]
 -warn string           Enable warning; command-line only
 -where                 Show where listed variables are declared [false]
+-xasy                  Special interactive mode for xasy [false]
 -zoomfactor factor     Zoom step factor [1.05]
 -zoomstep step         Mouse motion zoom step [0.1]
 
@@ -8324,7 +8336,7 @@
    The file 'asymptote.py' in the 'Asymptote' system directory provides
 an alternative way of entering 'Asymptote' commands interactively,
 coupled with the full power of 'Python'.  Copy this file to your 'Python
-path' and then execute from within 'Python' the commands
+path' and then execute from within 'Python 3' the commands
 from asymptote import *
 g=asy()
 g.size(200)
@@ -8356,22 +8368,19 @@
 11.1 GUI installation
 =====================
 
-As 'xasy' is written in the interactive scripting language 'Python/TK',
-it requires 'Python' (<http://www.python.org>), the 'Pillow' fork of the
-'Python Imaging Library',and the 'tkinter' package (included with
-'Python' under 'Microsoft Windows').  'Fedora Linux' users can either
-install 'tkinter' and 'Pillow' with the commands
-dnf install tkinter
-dnf install tk-devel
-dnf install python-pillow-tk
-or manually install the 'tkinter', 'tix', 'tk', and 'tk-devel' packages.
+As 'xasy' is written in the interactive scripting language 'Python/Qt',
+it requires 'Python' (<http://www.python.org>), along with the 'Python'
+packages 'pyqt5', 'cson', and 'numpy':
 
-   Pictures are deconstructed into the PNG image format, which supports
-full alpha channel transparency.  Under 'Microsoft Windows', this
-requires 'Python 2.7.4' or later and version '3.1.0' of the 'Pillow'
-fork of the 'Python Imaging Library', available from
-     <http://pypi.python.org/pypi/Pillow>
+pip3 install pyqt5 cson numpy
 
+   Pictures are deconstructed into the SVG image format.  Since 'Qt5'
+does not suport 'SVG' clipping, you will need the 'rsvg-convert'
+utility, which is part of the 'librsvg2-tools' package on 'UNIX'
+systems; under 'Microsoft Windows', it is available as
+
+   <https://sourceforge.net/projects/tumagcc/files/rsvg-convert-2.40.20.7z>
+
 
 File: asymptote.info,  Node: GUI usage,  Prev: GUI installation,  Up: GUI
 
@@ -8378,11 +8387,11 @@
 11.2 GUI usage
 ==============
 
-A wheel mouse is convenient for raising and lowering objects within
-'xasy', to expose the object to be moved.  If a wheel mouse is not
-available, mouse 'Button-2' can be used to repeatedly lower an object
-instead.  When run from the command line, 'xasy' accepts a command line
-option '-x n', which sets the initial magnification to 'n'.
+The arrow keys (or mouse wheel) are convenient for temporarily raising
+and lowering objects within 'xasy', allowing an object to be selected.
+Pressing the arrow keys will pan while the shift key is held and zoom
+while the control key is held.  The mouse wheel will pan while the alt
+or shift keys is held and zoom while the control key is held.
 
    Deconstruction of compound objects (such as arrows) can be prevented
 by enclosing them within the commands
@@ -8583,9 +8592,9 @@
 * ---:                                   Bezier curves.      (line   84)
 * -=:                                    Self & prefix operators.
                                                              (line    6)
-* -c:                                    Options.            (line  183)
-* -l:                                    Options.            (line  202)
-* -u:                                    Options.            (line  193)
+* -c:                                    Options.            (line  184)
+* -l:                                    Options.            (line  203)
+* -u:                                    Options.            (line  194)
 * -V:                                    Configuring.        (line    6)
 * -V <1>:                                Drawing in batch mode.
                                                              (line   16)
@@ -8598,7 +8607,7 @@
 * 2D graphs:                             graph.              (line    6)
 * 3D graphs:                             graph3.             (line    6)
 * 3D grids:                              grid3.              (line    6)
-* 3D PostScript:                         three.              (line  580)
+* 3D PostScript:                         three.              (line  583)
 * ::                                     Arithmetic & logical.
                                                              (line   61)
 * :::                                    Bezier curves.      (line   70)
@@ -8648,7 +8657,7 @@
                                                              (line  228)
 * add <2>:                               three.              (line  256)
 * addViews:                              three.              (line  377)
-* adjust:                                Pens.               (line  119)
+* adjust:                                Pens.               (line  123)
 * Ai:                                    Mathematical functions.
                                                              (line   48)
 * Airy:                                  Mathematical functions.
@@ -8658,9 +8667,9 @@
 * alias:                                 Structures.         (line   62)
 * alias <1>:                             Arrays.             (line  174)
 * Align:                                 label.              (line   12)
-* aligndir:                              Options.            (line  175)
-* all:                                   Arrays.             (line  322)
-* Allow:                                 Pens.               (line  343)
+* aligndir:                              Options.            (line  176)
+* all:                                   Arrays.             (line  325)
+* Allow:                                 Pens.               (line  347)
 * and:                                   Bezier curves.      (line   56)
 * AND:                                   Arithmetic & logical.
                                                              (line   68)
@@ -8672,7 +8681,7 @@
 * animation <1>:                         animation.          (line    6)
 * annotate:                              annotate.           (line    6)
 * antialias:                             three.              (line  195)
-* antialias <1>:                         Options.            (line  146)
+* antialias <1>:                         Options.            (line  147)
 * append:                                Files.              (line   36)
 * append <1>:                            Arrays.             (line   39)
 * arc:                                   Paths and guides.   (line   24)
@@ -8679,9 +8688,9 @@
 * Arc:                                   Paths and guides.   (line   37)
 * arc <1>:                               three.              (line  267)
 * ArcArrow:                              draw.               (line   26)
-* ArcArrow3:                             three.              (line  547)
+* ArcArrow3:                             three.              (line  550)
 * ArcArrows:                             draw.               (line   26)
-* ArcArrows3:                            three.              (line  547)
+* ArcArrows3:                            three.              (line  550)
 * arclength:                             Paths and guides.   (line  153)
 * arclength <1>:                         three.              (line  484)
 * arcpoint:                              Paths and guides.   (line  163)
@@ -8699,10 +8708,11 @@
 * arrow <1>:                             label.              (line   70)
 * arrow keys:                            Drawing in interactive mode.
                                                              (line   11)
-* Arrow3:                                three.              (line  547)
+* arrow keys <1>:                        GUI usage.          (line    6)
+* Arrow3:                                three.              (line  550)
 * arrows:                                draw.               (line   26)
 * Arrows:                                draw.               (line   26)
-* Arrows3:                               three.              (line  547)
+* Arrows3:                               three.              (line  550)
 * as:                                    Import.             (line   67)
 * ascii:                                 Data types.         (line  308)
 * ascii <1>:                             Data types.         (line  308)
@@ -8723,7 +8733,7 @@
 * asyinclude:                            LaTeX usage.        (line   45)
 * asymptote.sty:                         LaTeX usage.        (line    6)
 * asymptote.xml:                         Editing modes.      (line   48)
-* ASYMPTOTE_CONFIG:                      Options.            (line  117)
+* ASYMPTOTE_CONFIG:                      Options.            (line  118)
 * atan:                                  Mathematical functions.
                                                              (line    6)
 * aTan:                                  Mathematical functions.
@@ -8738,7 +8748,7 @@
 * attach <1>:                            LaTeX usage.        (line   50)
 * attach <2>:                            graph.              (line  407)
 * autoadjust:                            three.              (line  342)
-* autoimport:                            Options.            (line  113)
+* autoimport:                            Options.            (line  114)
 * automatic scaling:                     graph.              (line  691)
 * automatic scaling <1>:                 graph.              (line  691)
 * axialshade:                            fill.               (line   43)
@@ -8752,34 +8762,34 @@
                                                              (line  180)
 * BackView:                              three.              (line  370)
 * Bar:                                   draw.               (line   19)
-* Bar3:                                  three.              (line  547)
+* Bar3:                                  three.              (line  550)
 * Bars:                                  draw.               (line   19)
-* Bars3:                                 three.              (line  547)
+* Bars3:                                 three.              (line  550)
 * barsize:                               draw.               (line   19)
 * base modules:                          Base modules.       (line    6)
-* basealign:                             Pens.               (line  177)
+* basealign:                             Pens.               (line  181)
 * baseline:                              label.              (line   90)
 * batch mode:                            Drawing in batch mode.
                                                              (line    6)
 * beep:                                  Data types.         (line  381)
 * BeginArcArrow:                         draw.               (line   26)
-* BeginArcArrow3:                        three.              (line  547)
+* BeginArcArrow3:                        three.              (line  550)
 * BeginArrow:                            draw.               (line   26)
-* BeginArrow3:                           three.              (line  547)
+* BeginArrow3:                           three.              (line  550)
 * BeginBar:                              draw.               (line   19)
-* BeginBar3:                             three.              (line  547)
+* BeginBar3:                             three.              (line  550)
 * BeginDotMargin:                        draw.               (line   42)
-* BeginDotMargin3:                       three.              (line  563)
+* BeginDotMargin3:                       three.              (line  566)
 * BeginMargin:                           draw.               (line   42)
-* BeginMargin3:                          three.              (line  563)
+* BeginMargin3:                          three.              (line  566)
 * BeginPenMargin:                        draw.               (line   42)
-* BeginPenMargin2:                       three.              (line  563)
-* BeginPenMargin3:                       three.              (line  563)
+* BeginPenMargin2:                       three.              (line  566)
+* BeginPenMargin3:                       three.              (line  566)
 * BeginPoint:                            label.              (line   55)
 * Bessel:                                Mathematical functions.
                                                              (line   48)
 * bevel:                                 flowchart.          (line   72)
-* beveljoin:                             Pens.               (line  145)
+* beveljoin:                             Pens.               (line  149)
 * Bezier curves:                         Bezier curves.      (line    6)
 * Bezier patch:                          three.              (line   88)
 * Bezier triangle:                       three.              (line   88)
@@ -8828,7 +8838,7 @@
 * brace:                                 Paths and guides.   (line   51)
 * break:                                 Programming.        (line   48)
 * breakpoints:                           Debugger.           (line   21)
-* brick:                                 Pens.               (line  265)
+* brick:                                 Pens.               (line  269)
 * broken axis:                           graph.              (line  802)
 * bug reports:                           Help.               (line   19)
 * buildcycle:                            Paths and guides.   (line  270)
@@ -8849,7 +8859,7 @@
                                                              (line   26)
 * Center:                                label.              (line   60)
 * center:                                three.              (line  319)
-* checker:                               Pens.               (line  265)
+* checker:                               Pens.               (line  269)
 * Chinese:                               unicode.            (line   12)
 * choose:                                Mathematical functions.
                                                              (line   39)
@@ -8869,16 +8879,16 @@
                                                              (line   68)
 * cm:                                    Figure size.        (line   18)
 * cmd:                                   Configuring.        (line   31)
-* cmyk:                                  Pens.               (line   34)
+* cmyk:                                  Pens.               (line   38)
 * colatitude:                            Data types.         (line  158)
 * color:                                 Pens.               (line   23)
 * coloredNodes:                          tube.               (line   25)
 * coloredpath:                           tube.               (line   18)
 * coloredSegments:                       tube.               (line   25)
-* colorless:                             Pens.               (line   53)
-* colors:                                Pens.               (line   50)
+* colorless:                             Pens.               (line   57)
+* colors:                                Pens.               (line   54)
 * comma:                                 Files.              (line   61)
-* comma-separated-value mode:            Arrays.             (line  354)
+* comma-separated-value mode:            Arrays.             (line  357)
 * command-line options:                  Configuring.        (line   83)
 * command-line options <1>:              Options.            (line    6)
 * comment character:                     Files.              (line   16)
@@ -8891,13 +8901,13 @@
 * conditional <1>:                       Arithmetic & logical.
                                                              (line   61)
 * config:                                Configuring.        (line   64)
-* config <1>:                            Options.            (line  117)
+* config <1>:                            Options.            (line  118)
 * configuration file:                    Configuring.        (line   21)
-* configuration file <1>:                Options.            (line  117)
+* configuration file <1>:                Options.            (line  118)
 * configuring:                           Configuring.        (line    6)
 * conj:                                  Data types.         (line   62)
 * constructors:                          Structures.         (line   91)
-* context:                               Options.            (line  146)
+* context:                               Options.            (line  147)
 * continue:                              Programming.        (line   48)
 * continue <1>:                          Debugger.           (line   31)
 * contour:                               contour.            (line    6)
@@ -8908,8 +8918,8 @@
 * convert:                               Configuring.        (line   64)
 * convert <1>:                           Files.              (line  155)
 * convert <2>:                           animation.          (line    6)
-* convert <3>:                           Options.            (line  146)
-* convertOptions:                        Options.            (line  132)
+* convert <3>:                           Options.            (line  147)
+* convertOptions:                        Options.            (line  133)
 * Coons shading:                         fill.               (line   77)
 * copy:                                  Arrays.             (line  167)
 * cos:                                   Mathematical functions.
@@ -8925,11 +8935,11 @@
 * cross <1>:                             Data types.         (line  196)
 * cross <2>:                             graph.              (line  481)
 * crossframe:                            markers.            (line   22)
-* crosshatch:                            Pens.               (line  282)
-* csv:                                   Arrays.             (line  354)
+* crosshatch:                            Pens.               (line  286)
+* csv:                                   Arrays.             (line  357)
 * CTZ:                                   Arithmetic & logical.
                                                              (line   68)
-* cubicroots:                            Arrays.             (line  311)
+* cubicroots:                            Arrays.             (line  314)
 * curl:                                  Bezier curves.      (line   66)
 * curl <1>:                              three.              (line    6)
 * curlSpecifier:                         Paths and guides.   (line  408)
@@ -8948,8 +8958,8 @@
 * cyclic <2>:                            Arrays.             (line   39)
 * cyclic <3>:                            three.              (line  484)
 * Cyrillic:                              unicode.            (line    7)
-* dashdotted:                            Pens.               (line   98)
-* dashed:                                Pens.               (line   98)
+* dashdotted:                            Pens.               (line  102)
+* dashed:                                Pens.               (line  102)
 * data types:                            Data types.         (line    6)
 * date:                                  Data types.         (line  320)
 * Debian:                                UNIX binary distributions.
@@ -8960,14 +8970,14 @@
 * default arguments:                     Default arguments.  (line    6)
 * defaultformat:                         graph.              (line  175)
 * DefaultHead:                           draw.               (line   26)
-* DefaultHead3:                          three.              (line  547)
-* defaultpen:                            Pens.               (line   45)
-* defaultpen <1>:                        Pens.               (line  118)
-* defaultpen <2>:                        Pens.               (line  123)
-* defaultpen <3>:                        Pens.               (line  135)
-* defaultpen <4>:                        Pens.               (line  188)
-* defaultpen <5>:                        Pens.               (line  343)
-* defaultpen <6>:                        Pens.               (line  367)
+* DefaultHead3:                          three.              (line  550)
+* defaultpen:                            Pens.               (line   49)
+* defaultpen <1>:                        Pens.               (line  122)
+* defaultpen <2>:                        Pens.               (line  127)
+* defaultpen <3>:                        Pens.               (line  139)
+* defaultpen <4>:                        Pens.               (line  192)
+* defaultpen <5>:                        Pens.               (line  347)
+* defaultpen <6>:                        Pens.               (line  371)
 * defaultrender:                         three.              (line   46)
 * deferred drawing:                      simplex.            (line    6)
 * degrees:                               Data types.         (line   78)
@@ -8978,9 +8988,9 @@
 * delete:                                Files.              (line  150)
 * delete <1>:                            Arrays.             (line   39)
 * description:                           Description.        (line    6)
-* diagonal:                              Arrays.             (line  296)
+* diagonal:                              Arrays.             (line  299)
 * diamond:                               flowchart.          (line   54)
-* dimension:                             Arrays.             (line  359)
+* dimension:                             Arrays.             (line  362)
 * dir:                                   Search paths.       (line    9)
 * dir <1>:                               Data types.         (line   90)
 * dir <2>:                               Data types.         (line  180)
@@ -8997,13 +9007,13 @@
 * dot:                                   draw.               (line   82)
 * dot <1>:                               Data types.         (line  103)
 * dot <2>:                               Data types.         (line  193)
-* dot <3>:                               Arrays.             (line  251)
-* dot <4>:                               Arrays.             (line  254)
+* dot <3>:                               Arrays.             (line  254)
+* dot <4>:                               Arrays.             (line  257)
 * DotMargin:                             draw.               (line   42)
-* DotMargin3:                            three.              (line  563)
+* DotMargin3:                            three.              (line  566)
 * DotMargins:                            draw.               (line   42)
-* DotMargins3:                           three.              (line  563)
-* dotted:                                Pens.               (line   98)
+* DotMargins3:                           three.              (line  566)
+* dotted:                                Pens.               (line  102)
 * double deferred drawing:               three.              (line  241)
 * double precision:                      Files.              (line   76)
 * draw:                                  Drawing commands.   (line   31)
@@ -9017,10 +9027,10 @@
 * drawline:                              math.               (line    9)
 * drawtree:                              drawtree.           (line    6)
 * dvips:                                 Configuring.        (line   64)
-* dvipsOptions:                          Options.            (line  132)
+* dvipsOptions:                          Options.            (line  133)
 * dvisvgm:                               Configuring.        (line   64)
-* dvisvgm <1>:                           Options.            (line  151)
-* dvisvgmOptions:                        Options.            (line  132)
+* dvisvgm <1>:                           Options.            (line  152)
+* dvisvgmOptions:                        Options.            (line  133)
 * E:                                     Labels.             (line   18)
 * E <1>:                                 Mathematical functions.
                                                              (line   48)
@@ -9039,29 +9049,29 @@
 * empty:                                 Frames and pictures.
                                                              (line    7)
 * EndArcArrow:                           draw.               (line   26)
-* EndArcArrow3:                          three.              (line  547)
+* EndArcArrow3:                          three.              (line  550)
 * EndArrow:                              draw.               (line   26)
-* EndArrow3:                             three.              (line  547)
+* EndArrow3:                             three.              (line  550)
 * EndBar:                                draw.               (line   19)
-* EndBar3:                               three.              (line  547)
+* EndBar3:                               three.              (line  550)
 * EndDotMargin:                          draw.               (line   42)
-* EndDotMargin3:                         three.              (line  563)
+* EndDotMargin3:                         three.              (line  566)
 * endl:                                  Files.              (line   61)
 * EndMargin:                             draw.               (line   42)
-* EndMargin3:                            three.              (line  563)
+* EndMargin3:                            three.              (line  566)
 * EndPenMargin:                          draw.               (line   42)
-* EndPenMargin2:                         three.              (line  563)
-* EndPenMargin3:                         three.              (line  563)
+* EndPenMargin2:                         three.              (line  566)
+* EndPenMargin3:                         three.              (line  566)
 * EndPoint:                              label.              (line   55)
 * envelope:                              Frames and pictures.
                                                              (line   25)
 * environment variables:                 Configuring.        (line   87)
 * eof:                                   Files.              (line   93)
-* eof <1>:                               Arrays.             (line  336)
+* eof <1>:                               Arrays.             (line  339)
 * eol:                                   Files.              (line   93)
-* eol <1>:                               Arrays.             (line  336)
+* eol <1>:                               Arrays.             (line  339)
 * EPS:                                   label.              (line   78)
-* EPS <1>:                               Options.            (line  146)
+* EPS <1>:                               Options.            (line  147)
 * erase:                                 Drawing in interactive mode.
                                                              (line   11)
 * erase <1>:                             Data types.         (line  256)
@@ -9080,7 +9090,7 @@
 * eval:                                  Import.             (line   97)
 * eval <1>:                              Import.             (line  107)
 * evenodd:                               Paths.              (line   37)
-* evenodd <1>:                           Pens.               (line  160)
+* evenodd <1>:                           Pens.               (line  164)
 * exit:                                  Data types.         (line  372)
 * exit <1>:                              Interactive mode.   (line   54)
 * exit <2>:                              Debugger.           (line   56)
@@ -9094,7 +9104,7 @@
                                                              (line    6)
 * exponential integral:                  Mathematical functions.
                                                              (line   48)
-* extendcap:                             Pens.               (line  135)
+* extendcap:                             Pens.               (line  139)
 * extension:                             Paths and guides.   (line  246)
 * extension <1>:                         MetaPost.           (line   10)
 * external:                              embed.              (line   11)
@@ -9103,13 +9113,13 @@
                                                              (line   48)
 * fabs:                                  Mathematical functions.
                                                              (line    6)
-* face:                                  three.              (line  588)
+* face:                                  three.              (line  591)
 * factorial:                             Mathematical functions.
                                                              (line   39)
 * Fedora:                                UNIX binary distributions.
                                                              (line   15)
 * feynman:                               feynman.            (line    6)
-* fft:                                   Arrays.             (line  237)
+* fft:                                   Arrays.             (line  240)
 * fft <1>:                               math.               (line   26)
 * FFTW:                                  Compiling from UNIX source.
                                                              (line   63)
@@ -9126,7 +9136,7 @@
 * FillDraw <1>:                          Frames and pictures.
                                                              (line  136)
 * filloutside:                           fill.               (line   27)
-* fillrule:                              Pens.               (line  160)
+* fillrule:                              Pens.               (line  164)
 * find:                                  Data types.         (line  241)
 * find <1>:                              Arrays.             (line  149)
 * findall:                               Arrays.             (line  154)
@@ -9143,13 +9153,13 @@
 * flush <1>:                             Files.              (line   93)
 * fmod:                                  Mathematical functions.
                                                              (line    6)
-* font:                                  Pens.               (line  202)
-* font command:                          Pens.               (line  202)
-* fontcommand:                           Pens.               (line  217)
-* fontsize:                              Pens.               (line  188)
+* font:                                  Pens.               (line  206)
+* font command:                          Pens.               (line  206)
+* fontcommand:                           Pens.               (line  221)
+* fontsize:                              Pens.               (line  192)
 * for:                                   Programming.        (line   26)
 * format:                                Data types.         (line  289)
-* format <1>:                            Options.            (line  146)
+* format <1>:                            Options.            (line  147)
 * forum:                                 Help.               (line    6)
 * frame:                                 Frames and pictures.
                                                              (line    7)
@@ -9174,7 +9184,7 @@
 * gettriple:                             Files.              (line  118)
 * git:                                   Git.                (line    6)
 * glOptions:                             three.              (line  195)
-* glOptions <1>:                         Options.            (line  132)
+* glOptions <1>:                         Options.            (line  133)
 * GNU Scientific Library:                Mathematical functions.
                                                              (line   48)
 * gouraudshade:                          fill.               (line   62)
@@ -9187,7 +9197,7 @@
 * gray:                                  Pens.               (line   25)
 * grayscale:                             Pens.               (line   25)
 * Grayscale:                             palette.            (line    9)
-* grid:                                  Pens.               (line  265)
+* grid:                                  Pens.               (line  269)
 * grid <1>:                              graph.              (line  747)
 * grid3:                                 grid3.              (line    6)
 * gs:                                    Configuring.        (line    6)
@@ -9195,13 +9205,13 @@
                                                              (line   63)
 * gsl:                                   Mathematical functions.
                                                              (line   48)
-* gsOptions:                             Options.            (line  132)
+* gsOptions:                             Options.            (line  133)
 * GUI:                                   GUI.                (line    6)
 * GUI installation:                      GUI installation.   (line    6)
 * GUI usage:                             GUI usage.          (line    6)
 * guide:                                 Paths and guides.   (line  314)
 * guide3:                                three.              (line    6)
-* hatch:                                 Pens.               (line  282)
+* hatch:                                 Pens.               (line  286)
 * height:                                LaTeX usage.        (line   50)
 * help:                                  Interactive mode.   (line   42)
 * help <1>:                              Help.               (line    6)
@@ -9209,10 +9219,10 @@
 * Hermite:                               graph.              (line   36)
 * Hermite(splinetype splinetype:         graph.              (line   36)
 * hex:                                   Data types.         (line  305)
-* hex <1>:                               Pens.               (line   60)
+* hex <1>:                               Pens.               (line   64)
 * hexidecimal:                           Data types.         (line  305)
-* hexidecimal <1>:                       Pens.               (line   58)
-* hidden surface removal:                three.              (line  588)
+* hexidecimal <1>:                       Pens.               (line   62)
+* hidden surface removal:                three.              (line  591)
 * histogram:                             Mathematical functions.
                                                              (line   39)
 * history:                               Files.              (line  143)
@@ -9219,9 +9229,9 @@
 * history <1>:                           Interactive mode.   (line   54)
 * historylines:                          Interactive mode.   (line   57)
 * HookHead:                              draw.               (line   26)
-* HookHead3:                             three.              (line  547)
+* HookHead3:                             three.              (line  550)
 * Horizontal:                            flowchart.          (line   77)
-* hyperrefOptions:                       Options.            (line  132)
+* hyperrefOptions:                       Options.            (line  133)
 * hypot:                                 Mathematical functions.
                                                              (line    6)
 * I:                                     Mathematical functions.
@@ -9230,7 +9240,7 @@
 * identity:                              Transforms.         (line   24)
 * identity <1>:                          Mathematical functions.
                                                              (line    6)
-* identity <2>:                          Arrays.             (line  293)
+* identity <2>:                          Arrays.             (line  296)
 * identity4:                             three.              (line  422)
 * if:                                    Programming.        (line   26)
 * IgnoreAspect:                          Frames and pictures.
@@ -9239,7 +9249,7 @@
 * image <1>:                             palette.            (line   58)
 * ImageMagick:                           Configuring.        (line   64)
 * ImageMagick <1>:                       animation.          (line    6)
-* ImageMagick <2>:                       Options.            (line  146)
+* ImageMagick <2>:                       Options.            (line  147)
 * images:                                palette.            (line    6)
 * implicit casts:                        Casts.              (line    6)
 * implicit linear solver:                MetaPost.           (line   10)
@@ -9267,12 +9277,16 @@
 * inside:                                Paths and guides.   (line  294)
 * inside <1>:                            Paths and guides.   (line  299)
 * inside <2>:                            Paths and guides.   (line  305)
-* insphere:                              three.              (line  510)
+* insphere:                              three.              (line  513)
 * inst:                                  Debugger.           (line   35)
 * installation:                          Installation.       (line    6)
 * int:                                   Data types.         (line   30)
 * integer division:                      Arithmetic & logical.
                                                              (line   20)
+* integral:                              Mathematical functions.
+                                                             (line   82)
+* integrate:                             Mathematical functions.
+                                                             (line   82)
 * interactive mode:                      Drawing in interactive mode.
                                                              (line    6)
 * interactive mode <1>:                  Interactive mode.   (line    6)
@@ -9298,9 +9312,9 @@
 * intMax:                                Data types.         (line   30)
 * intMin:                                Data types.         (line   30)
 * inverse:                               Transforms.         (line   16)
-* inverse <1>:                           Arrays.             (line  299)
+* inverse <1>:                           Arrays.             (line  302)
 * invert:                                three.              (line  412)
-* invisible:                             Pens.               (line   39)
+* invisible:                             Pens.               (line   43)
 * isnan:                                 Data types.         (line   35)
 * i_scaled:                              Mathematical functions.
                                                              (line   48)
@@ -9340,8 +9354,8 @@
                                                              (line  104)
 * lastcut:                               Paths and guides.   (line  266)
 * lasy-mode:                             Editing modes.      (line    6)
-* latex:                                 Options.            (line  146)
-* LaTeX fonts:                           Pens.               (line  202)
+* latex:                                 Options.            (line  147)
+* LaTeX fonts:                           Pens.               (line  206)
 * LaTeX usage:                           LaTeX usage.        (line    6)
 * latexmk:                               LaTeX usage.        (line   30)
 * latin1:                                latin1.             (line    6)
@@ -9372,21 +9386,21 @@
 * lexorder:                              math.               (line   67)
 * lexorder <1>:                          math.               (line   70)
 * libgs:                                 Configuring.        (line   64)
-* libgs <1>:                             Options.            (line  151)
+* libgs <1>:                             Options.            (line  152)
 * libm routines:                         Mathematical functions.
                                                              (line    6)
 * libsigsegv:                            Functions.          (line  100)
 * libsigsegv <1>:                        Help.               (line   27)
 * limits:                                graph.              (line  640)
-* line:                                  Arrays.             (line  336)
-* line <1>:                              Arrays.             (line  340)
-* line mode:                             Arrays.             (line  336)
+* line:                                  Arrays.             (line  339)
+* line <1>:                              Arrays.             (line  343)
+* line mode:                             Arrays.             (line  339)
 * Linear:                                graph.              (line  691)
-* linecap:                               Pens.               (line  135)
-* linejoin:                              Pens.               (line  145)
-* lineskip:                              Pens.               (line  188)
-* linetype:                              Pens.               (line  119)
-* linewidth:                             Pens.               (line  123)
+* linecap:                               Pens.               (line  139)
+* linejoin:                              Pens.               (line  149)
+* lineskip:                              Pens.               (line  192)
+* linetype:                              Pens.               (line  123)
+* linewidth:                             Pens.               (line  127)
 * locale:                                Data types.         (line  315)
 * log:                                   Mathematical functions.
                                                              (line    6)
@@ -9400,23 +9414,23 @@
 * logarithmic graph:                     graph.              (line  725)
 * logical operators:                     Arithmetic & logical.
                                                              (line    6)
-* longdashdotted:                        Pens.               (line   98)
-* longdashed:                            Pens.               (line   98)
+* longdashdotted:                        Pens.               (line  102)
+* longdashed:                            Pens.               (line  102)
 * longitude:                             Data types.         (line  168)
 * loop:                                  Programming.        (line   26)
-* lualatex:                              Options.            (line  146)
-* luatex:                                Options.            (line  146)
+* lualatex:                              Options.            (line  147)
+* luatex:                                Options.            (line  147)
 * MacOS X binary distributions:          MacOS X binary distributions.
                                                              (line    6)
-* makepen:                               Pens.               (line  318)
+* makepen:                               Pens.               (line  322)
 * map:                                   Arrays.             (line  131)
 * Margin:                                draw.               (line   42)
 * Margin <1>:                            draw.               (line   42)
-* Margin3:                               three.              (line  563)
-* Margin3 <1>:                           three.              (line  563)
+* Margin3:                               three.              (line  566)
+* Margin3 <1>:                           three.              (line  566)
 * Margins:                               draw.               (line   42)
 * margins:                               three.              (line  247)
-* Margins3:                              three.              (line  563)
+* Margins3:                              three.              (line  566)
 * mark:                                  graph.              (line  481)
 * markangle:                             markers.            (line   35)
 * marker:                                graph.              (line  481)
@@ -9430,8 +9444,8 @@
 * max:                                   Paths and guides.   (line  279)
 * max <1>:                               Frames and pictures.
                                                              (line    7)
-* max <2>:                               Arrays.             (line  218)
-* max <3>:                               Arrays.             (line  228)
+* max <2>:                               Arrays.             (line  221)
+* max <3>:                               Arrays.             (line  231)
 * max <4>:                               three.              (line  484)
 * maxbound:                              Data types.         (line  134)
 * maxbound <1>:                          Data types.         (line  204)
@@ -9446,23 +9460,23 @@
 * MetaPost whatever:                     MetaPost.           (line   10)
 * Microsoft Windows:                     Microsoft Windows.  (line    6)
 * MidArcArrow:                           draw.               (line   26)
-* MidArcArrow3:                          three.              (line  547)
+* MidArcArrow3:                          three.              (line  550)
 * MidArrow:                              draw.               (line   26)
-* MidArrow3:                             three.              (line  547)
+* MidArrow3:                             three.              (line  550)
 * MidPoint:                              label.              (line   55)
 * midpoint:                              Paths and guides.   (line  180)
 * min:                                   Paths and guides.   (line  275)
 * min <1>:                               Frames and pictures.
                                                              (line    7)
-* min <2>:                               Arrays.             (line  213)
-* min <3>:                               Arrays.             (line  223)
+* min <2>:                               Arrays.             (line  216)
+* min <3>:                               Arrays.             (line  226)
 * min <4>:                               three.              (line  484)
 * minbound:                              Data types.         (line  131)
 * minbound <1>:                          Data types.         (line  201)
 * minipage:                              label.              (line  116)
 * mintimes:                              Paths and guides.   (line  228)
-* miterjoin:                             Pens.               (line  145)
-* miterlimit:                            Pens.               (line  155)
+* miterjoin:                             Pens.               (line  149)
+* miterlimit:                            Pens.               (line  159)
 * mktemp:                                Files.              (line   44)
 * mm:                                    Figure size.        (line   18)
 * mode:                                  Files.              (line   76)
@@ -9470,8 +9484,9 @@
 * monotonic:                             graph.              (line   36)
 * mouse:                                 GUI.                (line    6)
 * mouse bindings:                        three.              (line  151)
-* Move:                                  Pens.               (line  355)
-* MoveQuiet:                             Pens.               (line  361)
+* mouse wheel:                           GUI usage.          (line    6)
+* Move:                                  Pens.               (line  359)
+* MoveQuiet:                             Pens.               (line  365)
 * multisample:                           three.              (line  142)
 * N:                                     Labels.             (line   18)
 * name:                                  Files.              (line   89)
@@ -9489,18 +9504,18 @@
 * newton <1>:                            Mathematical functions.
                                                              (line   73)
 * next:                                  Debugger.           (line   41)
-* NFSS:                                  Pens.               (line  202)
-* nobasealign:                           Pens.               (line  177)
+* NFSS:                                  Pens.               (line  206)
+* nobasealign:                           Pens.               (line  181)
 * NoFill:                                draw.               (line   26)
 * NoFill <1>:                            Frames and pictures.
                                                              (line  154)
 * NoMargin:                              draw.               (line   42)
-* NoMargin3:                             three.              (line  563)
+* NoMargin3:                             three.              (line  566)
 * None:                                  draw.               (line   19)
 * None <1>:                              draw.               (line   26)
 * none:                                  Files.              (line   61)
 * normal:                                three.              (line  470)
-* nosafe:                                Options.            (line  170)
+* nosafe:                                Options.            (line  171)
 * NOT:                                   Arithmetic & logical.
                                                              (line   68)
 * notaknot:                              graph.              (line   36)
@@ -9520,12 +9535,12 @@
 * obliqueY:                              three.              (line  315)
 * obliqueZ:                              three.              (line  302)
 * ode:                                   ode.                (line    6)
-* offset:                                Pens.               (line  119)
-* offset <1>:                            Options.            (line  175)
+* offset:                                Pens.               (line  123)
+* offset <1>:                            Options.            (line  176)
 * OmitTick:                              graph.              (line  223)
 * OmitTickInterval:                      graph.              (line  223)
 * OmitTickIntervals:                     graph.              (line  223)
-* opacity:                               Pens.               (line  233)
+* opacity:                               Pens.               (line  237)
 * open:                                  Files.              (line   12)
 * OpenGL:                                three.              (line  142)
 * operator:                              User-defined operators.
@@ -9552,10 +9567,10 @@
 * outprefix:                             Frames and pictures.
                                                              (line   91)
 * output:                                Files.              (line   36)
-* output <1>:                            Options.            (line  146)
+* output <1>:                            Options.            (line  147)
 * OutTicks:                              graph3.             (line   35)
 * overloading functions:                 Functions.          (line   55)
-* overwrite:                             Pens.               (line  340)
+* overwrite:                             Pens.               (line  344)
 * P:                                     Mathematical functions.
                                                              (line   48)
 * pack:                                  label.              (line  100)
@@ -9562,7 +9577,7 @@
 * packing:                               Rest arguments.     (line   30)
 * pair:                                  Figure size.        (line    6)
 * pair <1>:                              Data types.         (line   46)
-* pairs:                                 Arrays.             (line  233)
+* pairs:                                 Arrays.             (line  236)
 * paperheight:                           Configuring.        (line   58)
 * papertype:                             Configuring.        (line   58)
 * paperwidth:                            Configuring.        (line   58)
@@ -9580,20 +9595,20 @@
 * path3:                                 three.              (line    6)
 * path3 <1>:                             three.              (line   42)
 * path[]:                                Paths.              (line   23)
-* patterns:                              Pens.               (line  251)
+* patterns:                              Pens.               (line  255)
 * patterns <1>:                          patterns.           (line    6)
-* PDF:                                   Options.            (line  146)
-* pdflatex:                              Options.            (line  146)
-* pdfreloadOptions:                      Options.            (line  132)
+* PDF:                                   Options.            (line  147)
+* pdflatex:                              Options.            (line  147)
+* pdfreloadOptions:                      Options.            (line  133)
 * pdfviewer:                             Configuring.        (line    6)
-* pdfviewerOptions:                      Options.            (line  132)
+* pdfviewerOptions:                      Options.            (line  133)
 * pen:                                   Pens.               (line    6)
 * PenMargin:                             draw.               (line   42)
-* PenMargin2:                            three.              (line  563)
-* PenMargin3:                            three.              (line  563)
+* PenMargin2:                            three.              (line  566)
+* PenMargin3:                            three.              (line  566)
 * PenMargins:                            draw.               (line   42)
-* PenMargins2:                           three.              (line  563)
-* PenMargins3:                           three.              (line  563)
+* PenMargins2:                           three.              (line  566)
+* PenMargins3:                           three.              (line  566)
 * periodic:                              graph.              (line   36)
 * perl:                                  LaTeX usage.        (line   30)
 * perpendicular:                         geometry.           (line    6)
@@ -9603,7 +9618,7 @@
 * picture alignment:                     Frames and pictures.
                                                              (line  228)
 * piecewisestraight:                     Paths and guides.   (line   92)
-* pixel:                                 three.              (line  570)
+* pixel:                                 three.              (line  573)
 * Pl:                                    Mathematical functions.
                                                              (line   48)
 * plain:                                 plain.              (line    6)
@@ -9625,7 +9640,7 @@
                                                              (line   19)
 * postscript:                            Frames and pictures.
                                                              (line  294)
-* PostScript fonts:                      Pens.               (line  220)
+* PostScript fonts:                      Pens.               (line  224)
 * PostScript subpath:                    Paths.              (line   23)
 * pow10:                                 Mathematical functions.
                                                              (line    6)
@@ -9640,13 +9655,13 @@
 * pstoedit:                              PostScript to Asymptote.
                                                              (line    6)
 * psviewer:                              Configuring.        (line    6)
-* psviewerOptions:                       Options.            (line  132)
+* psviewerOptions:                       Options.            (line  133)
 * pt:                                    Figure size.        (line   18)
 * public:                                Structures.         (line    6)
 * push:                                  Arrays.             (line   39)
 * Python usage:                          Interactive mode.   (line   72)
-* quadraticroots:                        Arrays.             (line  302)
-* quadraticroots <1>:                    Arrays.             (line  307)
+* quadraticroots:                        Arrays.             (line  305)
+* quadraticroots <1>:                    Arrays.             (line  310)
 * quarticroots:                          math.               (line   22)
 * quick reference:                       Description.        (line   81)
 * quit:                                  Drawing in interactive mode.
@@ -9670,9 +9685,9 @@
                                                              (line   39)
 * randMax:                               Mathematical functions.
                                                              (line   39)
-* read:                                  Arrays.             (line  376)
+* read:                                  Arrays.             (line  379)
 * reading:                               Files.              (line   12)
-* reading string arrays:                 Arrays.             (line  346)
+* reading string arrays:                 Arrays.             (line  349)
 * readline:                              Files.              (line  135)
 * real:                                  Data types.         (line   35)
 * realDigits:                            Data types.         (line   35)
@@ -9693,9 +9708,9 @@
 * rename:                                Files.              (line  152)
 * render:                                three.              (line   46)
 * render <1>:                            three.              (line  142)
-* render <2>:                            Options.            (line  146)
+* render <2>:                            Options.            (line  147)
 * replace:                               Data types.         (line  269)
-* resetdefaultpen:                       Pens.               (line  367)
+* resetdefaultpen:                       Pens.               (line  371)
 * rest arguments:                        Rest arguments.     (line    6)
 * restore:                               Frames and pictures.
                                                              (line  288)
@@ -9709,7 +9724,8 @@
 * rewind:                                Files.              (line   93)
 * rfind:                                 Data types.         (line  246)
 * rgb:                                   Pens.               (line   30)
-* rgb <1>:                               Pens.               (line   58)
+* rgb <1>:                               Pens.               (line   34)
+* rgb <2>:                               Pens.               (line   62)
 * Riemann zeta function:                 Mathematical functions.
                                                              (line   48)
 * Right:                                 graph.              (line  272)
@@ -9722,9 +9738,9 @@
 * Rotate(pair z):                        label.              (line   39)
 * round:                                 Mathematical functions.
                                                              (line   26)
-* roundcap:                              Pens.               (line  135)
+* roundcap:                              Pens.               (line  139)
 * roundedpath:                           roundedpath.        (line    6)
-* roundjoin:                             Pens.               (line  145)
+* roundjoin:                             Pens.               (line  149)
 * roundrectangle:                        flowchart.          (line   66)
 * RPM:                                   UNIX binary distributions.
                                                              (line    6)
@@ -9731,12 +9747,12 @@
 * runtime imports:                       Import.             (line   97)
 * Russian:                               unicode.            (line    7)
 * S:                                     Labels.             (line   18)
-* safe:                                  Options.            (line  170)
+* safe:                                  Options.            (line  171)
 * save:                                  Frames and pictures.
                                                              (line  285)
 * saveline:                              Files.              (line  135)
 * Scale:                                 label.              (line   45)
-* scale:                                 Pens.               (line  119)
+* scale:                                 Pens.               (line  123)
 * scale <1>:                             Transforms.         (line   34)
 * scale <2>:                             Transforms.         (line   36)
 * scale <3>:                             graph.              (line  691)
@@ -9763,7 +9779,7 @@
                                                              (line    6)
 * sequence:                              Arrays.             (line  118)
 * settings:                              Configuring.        (line   21)
-* settings <1>:                          Options.            (line  117)
+* settings <1>:                          Options.            (line  118)
 * sgn:                                   Mathematical functions.
                                                              (line   26)
 * shading:                               fill.               (line   32)
@@ -9770,9 +9786,9 @@
 * Shift:                                 label.              (line   33)
 * shift:                                 Transforms.         (line   26)
 * shift <1>:                             Transforms.         (line   28)
-* shift <2>:                             Transforms.         (line   44)
+* shift <2>:                             Transforms.         (line   46)
 * shift <3>:                             three.              (line  427)
-* shiftless:                             Transforms.         (line   44)
+* shiftless:                             Transforms.         (line   46)
 * shipout:                               Frames and pictures.
                                                              (line   91)
 * showtarget:                            three.              (line  319)
@@ -9806,7 +9822,7 @@
 * size <4>:                              Frames and pictures.
                                                              (line   74)
 * size <5>:                              three.              (line  484)
-* size <6>:                              Options.            (line  146)
+* size <6>:                              Options.            (line  147)
 * size3:                                 three.              (line  244)
 * Slant:                                 label.              (line   42)
 * slant:                                 Transforms.         (line   38)
@@ -9821,10 +9837,10 @@
 * smoothcontour3:                        smoothcontour3.     (line    6)
 * sncndn:                                Mathematical functions.
                                                              (line   48)
-* solid:                                 Pens.               (line   98)
+* solid:                                 Pens.               (line  102)
 * solids:                                solids.             (line    6)
-* solve:                                 Arrays.             (line  271)
-* solve <1>:                             Arrays.             (line  287)
+* solve:                                 Arrays.             (line  274)
+* solve <1>:                             Arrays.             (line  290)
 * sort:                                  Arrays.             (line  177)
 * sort <1>:                              Arrays.             (line  181)
 * sort <2>:                              Arrays.             (line  196)
@@ -9833,7 +9849,7 @@
 * split:                                 Data types.         (line  278)
 * sqrt:                                  Mathematical functions.
                                                              (line    6)
-* squarecap:                             Pens.               (line  135)
+* squarecap:                             Pens.               (line  139)
 * srand:                                 Mathematical functions.
                                                              (line   39)
 * stack overflow:                        Functions.          (line  100)
@@ -9864,17 +9880,17 @@
 * subpictures:                           Frames and pictures.
                                                              (line  113)
 * substr:                                Data types.         (line  261)
-* sum:                                   Arrays.             (line  208)
+* sum:                                   Arrays.             (line  211)
 * superpath:                             Paths.              (line   23)
-* Suppress:                              Pens.               (line  347)
-* SuppressQuiet:                         Pens.               (line  351)
+* Suppress:                              Pens.               (line  351)
+* SuppressQuiet:                         Pens.               (line  355)
 * surface:                               three.              (line   46)
 * surface <1>:                           three.              (line   88)
 * surface <2>:                           three.              (line  102)
 * surface <3>:                           graph3.             (line   99)
-* SVG:                                   Options.            (line  151)
+* SVG:                                   Options.            (line  152)
 * system:                                Data types.         (line  353)
-* system <1>:                            Options.            (line  170)
+* system <1>:                            Options.            (line  171)
 * syzygy:                                syzygy.             (line    6)
 * tab:                                   Files.              (line   61)
 * tab completion:                        Drawing in interactive mode.
@@ -9895,12 +9911,12 @@
 * tessellation:                          three.              (line  114)
 * tex:                                   Frames and pictures.
                                                              (line  302)
-* tex <1>:                               Options.            (line  146)
-* TeX fonts:                             Pens.               (line  211)
+* tex <1>:                               Options.            (line  147)
+* TeX fonts:                             Pens.               (line  215)
 * TeX string:                            Data types.         (line  207)
 * texcommand:                            Configuring.        (line   64)
 * TeXHead:                               draw.               (line   26)
-* TeXHead3:                              three.              (line  547)
+* TeXHead3:                              three.              (line  550)
 * texpath:                               Configuring.        (line   64)
 * texpath <1>:                           label.              (line  113)
 * texpreamble:                           Frames and pictures.
@@ -9922,8 +9938,8 @@
 * Ticks:                                 graph.              (line  160)
 * Ticks <1>:                             graph.              (line  233)
 * tildeframe:                            markers.            (line   24)
-* tile:                                  Pens.               (line  265)
-* tilings:                               Pens.               (line  251)
+* tile:                                  Pens.               (line  269)
+* tilings:                               Pens.               (line  255)
 * time:                                  Data types.         (line  320)
 * time <1>:                              Data types.         (line  345)
 * time <2>:                              math.               (line   30)
@@ -9937,24 +9953,24 @@
 * transform:                             Transforms.         (line    6)
 * transform <1>:                         three.              (line  459)
 * transform3:                            three.              (line  422)
-* transparency:                          Pens.               (line  233)
-* transpose:                             Arrays.             (line  200)
-* transpose <1>:                         Arrays.             (line  203)
+* transparency:                          Pens.               (line  237)
+* transpose:                             Arrays.             (line  203)
+* transpose <1>:                         Arrays.             (line  206)
 * tree:                                  tree.               (line    6)
 * trembling:                             trembling.          (line    6)
 * triangle:                              geometry.           (line    6)
 * triangles:                             three.              (line  114)
 * triangulate:                           contour.            (line  149)
-* tridiagonal:                           Arrays.             (line  258)
+* tridiagonal:                           Arrays.             (line  261)
 * trigonometric integrals:               Mathematical functions.
                                                              (line   48)
 * triple:                                Data types.         (line  137)
 * TrueMargin:                            draw.               (line   42)
-* TrueMargin3:                           three.              (line  563)
+* TrueMargin3:                           three.              (line  566)
 * tube:                                  three.              (line  125)
 * tube <1>:                              tube.               (line    6)
 * tutorial:                              Tutorial.           (line    6)
-* type1cm:                               Pens.               (line  188)
+* type1cm:                               Pens.               (line  192)
 * typedef:                               Data types.         (line  384)
 * typedef <1>:                           Functions.          (line   46)
 * U3D:                                   embed.              (line   22)
@@ -10006,7 +10022,7 @@
 * vectorfield:                           graph.              (line 1005)
 * vectorfield <1>:                       graph.              (line 1044)
 * vectorfield3:                          graph3.             (line  157)
-* vectorization:                         Arrays.             (line  315)
+* vectorization:                         Arrays.             (line  318)
 * verbatim:                              Frames and pictures.
                                                              (line  294)
 * vertex-dependent colors:               three.              (line   79)
@@ -10024,17 +10040,17 @@
 * Wheel:                                 palette.            (line   22)
 * wheel mouse:                           GUI.                (line    6)
 * while:                                 Programming.        (line   48)
-* white-space string delimiter mode:     Arrays.             (line  346)
+* white-space string delimiter mode:     Arrays.             (line  349)
 * width:                                 LaTeX usage.        (line   50)
 * windingnumber:                         Paths and guides.   (line  283)
-* word:                                  Arrays.             (line  346)
+* word:                                  Arrays.             (line  349)
 * write:                                 Files.              (line   53)
-* write <1>:                             Arrays.             (line  385)
+* write <1>:                             Arrays.             (line  388)
 * X:                                     three.              (line  259)
 * xasy:                                  GUI.                (line    6)
 * xaxis3:                                graph3.             (line    7)
 * xdr:                                   Files.              (line   76)
-* xelatex:                               Options.            (line  146)
+* xelatex:                               Options.            (line  147)
 * XEquals:                               graph.              (line  265)
 * xequals:                               graph.              (line  278)
 * xlimits:                               graph.              (line  640)
@@ -10073,7 +10089,8 @@
 * YZZero:                                graph3.             (line   21)
 * Z:                                     three.              (line  259)
 * zaxis3:                                graph3.             (line    7)
-* zerowinding:                           Pens.               (line  160)
+* zeroTransform:                         Transforms.         (line   44)
+* zerowinding:                           Pens.               (line  164)
 * zero_Ai:                               Mathematical functions.
                                                              (line   48)
 * zero_Ai_deriv:                         Mathematical functions.
@@ -10131,115 +10148,115 @@
 Ref: circle75874
 Ref: extension85581
 Node: Pens92390
-Ref: fillrule99897
-Ref: basealign100801
-Ref: transparency103635
-Ref: makepen107215
-Ref: overwrite108098
-Node: Transforms109312
-Node: Frames and pictures111094
-Ref: envelope112252
-Ref: size113345
-Ref: unitsize114332
-Ref: shipout115405
-Ref: filltype117756
-Ref: add120928
-Ref: add about121934
-Ref: tex124963
-Node: Files125859
-Ref: cd126846
-Ref: scroll131531
-Node: Variable initializers134449
-Node: Structures137166
-Node: Operators144668
-Node: Arithmetic & logical144982
-Node: Self & prefix operators147353
-Node: User-defined operators148147
-Node: Implicit scaling149060
-Node: Functions149623
-Ref: stack overflow152766
-Node: Default arguments153048
-Node: Named arguments153804
-Node: Rest arguments156374
-Node: Mathematical functions159496
-Node: Arrays164159
-Ref: sort171267
-Ref: tridiagonal173696
-Ref: solve174927
-Node: Slices179066
-Node: Casts182974
-Node: Import185241
-Node: Static190499
-Node: LaTeX usage193392
-Node: Base modules199909
-Node: plain202466
-Node: simplex203140
-Node: math203414
-Node: interpolate206123
-Node: geometry206402
-Node: trembling206996
-Node: stats207265
-Node: patterns207525
-Node: markers207761
-Node: tree209621
-Node: binarytree209806
-Node: drawtree210472
-Node: syzygy210673
-Node: feynman210947
-Node: roundedpath211222
-Node: animation211505
-Ref: animate211926
-Node: embed213043
-Node: slide213998
-Node: MetaPost214339
-Node: unicode215058
-Node: latin1215932
-Node: babel216301
-Node: labelpath216531
-Node: labelpath3217352
-Node: annotate217663
-Node: CAD218133
-Node: graph218444
-Ref: ticks225605
-Ref: pathmarkers239397
-Ref: marker239868
-Ref: markuniform240222
-Ref: errorbars242030
-Ref: automatic scaling246504
-Node: palette258251
-Ref: images258369
-Ref: image262543
-Ref: logimage263063
-Ref: penimage264168
-Ref: penfunctionimage264430
-Node: three265201
-Ref: PostScript3D292212
-Node: obj293951
-Node: graph3294200
-Ref: GaussianSurface299480
-Node: grid3300629
-Node: solids301413
-Node: tube302405
-Node: flowchart304639
-Node: contour309247
-Node: contour3314562
-Node: smoothcontour3314875
-Node: slopefield316596
-Node: ode318085
-Node: Options318342
-Ref: configuration file324506
-Ref: settings324506
-Ref: texengines325749
-Ref: convert325749
-Node: Interactive mode329073
-Ref: history331223
-Node: GUI332527
-Node: GUI installation333078
-Node: GUI usage333989
-Node: PostScript to Asymptote334897
-Node: Help335655
-Node: Debugger337309
-Node: Credits339065
-Node: Index340047
+Ref: fillrule100079
+Ref: basealign100983
+Ref: transparency103817
+Ref: makepen107397
+Ref: overwrite108280
+Node: Transforms109494
+Node: Frames and pictures111326
+Ref: envelope112484
+Ref: size113577
+Ref: unitsize114564
+Ref: shipout115637
+Ref: filltype117988
+Ref: add121160
+Ref: add about122166
+Ref: tex125195
+Node: Files126091
+Ref: cd127078
+Ref: scroll131763
+Node: Variable initializers134681
+Node: Structures137398
+Node: Operators144900
+Node: Arithmetic & logical145214
+Node: Self & prefix operators147585
+Node: User-defined operators148379
+Node: Implicit scaling149292
+Node: Functions149855
+Ref: stack overflow152998
+Node: Default arguments153280
+Node: Named arguments154036
+Node: Rest arguments156606
+Node: Mathematical functions159728
+Node: Arrays164391
+Ref: sort171499
+Ref: tridiagonal174124
+Ref: solve175355
+Node: Slices179494
+Node: Casts183402
+Node: Import185669
+Node: Static190927
+Node: LaTeX usage193820
+Node: Base modules200337
+Node: plain202894
+Node: simplex203568
+Node: math203842
+Node: interpolate206551
+Node: geometry206830
+Node: trembling207424
+Node: stats207693
+Node: patterns207953
+Node: markers208189
+Node: tree210049
+Node: binarytree210234
+Node: drawtree210900
+Node: syzygy211101
+Node: feynman211375
+Node: roundedpath211650
+Node: animation211933
+Ref: animate212354
+Node: embed213471
+Node: slide214426
+Node: MetaPost214767
+Node: unicode215486
+Node: latin1216360
+Node: babel216729
+Node: labelpath216959
+Node: labelpath3217780
+Node: annotate218091
+Node: CAD218561
+Node: graph218872
+Ref: ticks226033
+Ref: pathmarkers239825
+Ref: marker240296
+Ref: markuniform240650
+Ref: errorbars242458
+Ref: automatic scaling246932
+Node: palette258679
+Ref: images258797
+Ref: image262971
+Ref: logimage263491
+Ref: penimage264596
+Ref: penfunctionimage264858
+Node: three265629
+Ref: PostScript3D292801
+Node: obj294539
+Node: graph3294788
+Ref: GaussianSurface300068
+Node: grid3301217
+Node: solids302001
+Node: tube302993
+Node: flowchart305227
+Node: contour309835
+Node: contour3315150
+Node: smoothcontour3315463
+Node: slopefield317184
+Node: ode318673
+Node: Options318930
+Ref: configuration file325159
+Ref: settings325159
+Ref: texengines326402
+Ref: convert326402
+Node: Interactive mode329726
+Ref: history331876
+Node: GUI333182
+Node: GUI installation333733
+Node: GUI usage334415
+Node: PostScript to Asymptote335331
+Node: Help336089
+Node: Debugger337743
+Node: Credits339499
+Node: Index340481
 
 End Tag Table

Modified: trunk/Master/texmf-dist/doc/man/man1/asy.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/asy.1	2019-02-28 18:45:38 UTC (rev 50167)
+++ trunk/Master/texmf-dist/doc/man/man1/asy.1	2019-02-28 18:48:48 UTC (rev 50168)
@@ -283,6 +283,9 @@
 .B \-where               
 Show where listed variables are declared [false].
 .TP
+.B \-xasy                
+Special interactive mode for xasy [false].
+.TP
 .B \-zoomfactor factor   
 Zoom step factor [1.05].
 .TP

Modified: trunk/Master/texmf-dist/doc/man/man1/asy.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/man/man1/xasy.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/tlpkg/asymptote/asy.exe
===================================================================
(Binary files differ)

Modified: trunk/Master/tlpkg/asymptote64/asy.exe
===================================================================
(Binary files differ)



More information about the tex-live-commits mailing list