diff options
Diffstat (limited to 'Build/source/utils/asymptote/GUI')
52 files changed, 2196 insertions, 3493 deletions
diff --git a/Build/source/utils/asymptote/GUI/CustMatTransform.py b/Build/source/utils/asymptote/GUI/CustMatTransform.py index 563907fc502..0a66807d359 100644 --- a/Build/source/utils/asymptote/GUI/CustMatTransform.py +++ b/Build/source/utils/asymptote/GUI/CustMatTransform.py @@ -1,14 +1,14 @@ #!/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 +import PyQt5.QtWidgets as QtWidgets +import PyQt5.QtGui as QtGui +import PyQt5.QtCore as QtCore +import numpy as numpy +import xasy2asy as xasy2asy from pyUIClass.custMatTransform import Ui_Dialog -class CustMatTransform(Qw.QDialog): +class CustMatTransform(QtWidgets.QDialog): def __init__(self): super().__init__() self.ui = Ui_Dialog() @@ -18,14 +18,14 @@ class CustMatTransform(Qw.QDialog): self.ui.btnCancel.clicked.connect(self.reject) self.ui.btnReset.clicked.connect(self.resetDialog) - self.mainTransformation = Qg.QTransform() + self.mainTransformation = QtGui.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() + validator = QtGui.QDoubleValidator() for lineInput in self.matrixLineInputs: lineInput.setValidator(validator) lineInput.textChanged.connect(self.handleUpdateText) @@ -37,7 +37,7 @@ class CustMatTransform(Qw.QDialog): def createCanvas(self): self.canvSize = self.ui.imgPreview.size() - self.previewPixmap = Qg.QPixmap(self.canvSize) + self.previewPixmap = QtGui.QPixmap(self.canvSize) tx, ty = self.canvSize.width() / 2, self.canvSize.height() / 2 self.mainTransformation.translate(tx, -ty) @@ -52,27 +52,27 @@ class CustMatTransform(Qw.QDialog): def updatePreview(self): self.previewPixmap.fill() - canvas = Qg.QPainter(self.previewPixmap) + canvas = QtGui.QPainter(self.previewPixmap) if not canvas.isActive(): return canvas.setTransform(self.mainTransformation) canvas.save() - canvas.setPen(Qc.Qt.lightGray) + canvas.setPen(QtCore.Qt.lightGray) self.drawBasicGrid(canvas) - transform = x2a.asyTransform.fromNumpyMatrix(self.getTransformationMatrix()) + transform = xasy2asy.asyTransform.fromNumpyMatrix(self.getTransformationMatrix()) canvTransform = transform.toQTransform() canvas.setTransform(canvTransform, True) - canvas.setPen(Qc.Qt.black) + canvas.setPen(QtCore.Qt.black) if canvTransform.isInvertible(): self.drawBasicGrid(canvas, False) if canvTransform.determinant() <= 0: - canvas.setPen(Qc.Qt.red) + canvas.setPen(QtCore.Qt.red) - canvas.drawRect(Qc.QRect(Qc.QPoint(0, 0), Qc.QSize(20, 20))) + canvas.drawRect(QtCore.QRect(QtCore.QPoint(0, 0), QtCore.QSize(20, 20))) self.ui.imgPreview.setPixmap(self.previewPixmap) @@ -86,17 +86,17 @@ class CustMatTransform(Qw.QDialog): 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)) + canvas.drawLine(QtCore.QLine(-9999, 0, 9999, 0)) + canvas.drawLine(QtCore.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)) + canvas.drawLine(QtCore.QLine(-9999, iterIndex * gridSize, 9999, iterIndex * gridSize)) + canvas.drawLine(QtCore.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)) + return numpy.matrix(rawMatrixNum).reshape((3, 3)) diff --git a/Build/source/utils/asymptote/GUI/DebugFlags.py b/Build/source/utils/asymptote/GUI/DebugFlags.py index 8a7eb4b282e..c8f8af897a4 100644 --- a/Build/source/utils/asymptote/GUI/DebugFlags.py +++ b/Build/source/utils/asymptote/GUI/DebugFlags.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 keepFiles = False -printFoutTranscript = False +printAsyTranscript = False printDeconstTranscript = False -forceRasterizationSVG = False diff --git a/Build/source/utils/asymptote/GUI/GuidesManager.py b/Build/source/utils/asymptote/GUI/GuidesManager.py index 5467843377a..fd317439d47 100644 --- a/Build/source/utils/asymptote/GUI/GuidesManager.py +++ b/Build/source/utils/asymptote/GUI/GuidesManager.py @@ -1,18 +1,17 @@ #!/usr/bin/env python3 -import PyQt5.QtWidgets as Qw -import PyQt5.QtGui as Qg -import PyQt5.QtCore as Qc -import numpy as np +import PyQt5.QtGui as QtGui +import PyQt5.QtCore as QtCore +import numpy as numpy class Guide: def __init__(self, pen=None): if pen is None: - pen = Qg.QPen() - assert isinstance(pen, Qg.QPen) + pen = QtGui.QPen() + assert isinstance(pen, QtGui.QPen) self.pen = pen def drawShape(self, pen): - assert isinstance(pen, Qg.QPainter) + assert isinstance(pen, QtGui.QPainter) pen.save() pen.setPen(self.pen) @@ -24,19 +23,19 @@ class LineGuide(Guide): 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)) + p1 = self.origin + (9999 * QtCore.QPointF(numpy.cos(self.direction), numpy.sin(self.direction))) + p2 = self.origin - (9999 * QtCore.QPointF(numpy.cos(self.direction), numpy.sin(self.direction))) + pen.drawLine(QtCore.QLineF(p1, p2)) pen.restore() class ArcGuide(Guide): @classmethod def radTo16Deg(cls, radians): - return int(round(np.rad2deg(radians) * 16)) + return int(round(numpy.rad2deg(radians) * 16)) - def __init__(self, center=None, radius=1, startAng=0, endAng=(2*np.pi), pen=None): + def __init__(self, center=None, radius=1, startAng=0, endAng=(2*numpy.pi), pen=None): if center is None: - center = Qc.QPointF(0, 0) + center = QtCore.QPointF(0, 0) super().__init__(pen) self.center = center self.radius = int(radius) @@ -45,7 +44,7 @@ class ArcGuide(Guide): def drawShape(self, pen): super().drawShape(pen) - assert isinstance(pen, Qg.QPainter) + assert isinstance(pen, QtGui.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)) diff --git a/Build/source/utils/asymptote/GUI/InplaceAddObj.py b/Build/source/utils/asymptote/GUI/InplaceAddObj.py index 132969dad19..9bacd5f51fe 100644 --- a/Build/source/utils/asymptote/GUI/InplaceAddObj.py +++ b/Build/source/utils/asymptote/GUI/InplaceAddObj.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -import PyQt5.QtCore as Qc -import PyQt5.QtGui as Qg -import xasy2asy as x2a +import PyQt5.QtCore as QtCore +import PyQt5.QtGui as QtGui +import xasy2asy as xasy2asy import PrimitiveShape import math @@ -11,9 +11,9 @@ import Widg_addPolyOpt import Widg_addLabel -class InplaceObjProcess(Qc.QObject): - objectCreated = Qc.pyqtSignal(Qc.QObject) - objectUpdated = Qc.pyqtSignal() +class InplaceObjProcess(QtCore.QObject): + objectCreated = QtCore.pyqtSignal(QtCore.QObject) + objectUpdated = QtCore.pyqtSignal() def __init__(self, parent=None): super().__init__(parent) @@ -24,10 +24,10 @@ class InplaceObjProcess(Qc.QObject): def active(self): return self._active - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): raise NotImplementedError - def mouseMove(self, pos, event: Qg.QMouseEvent): + def mouseMove(self, pos, event: QtGui.QMouseEvent): raise NotImplementedError def mouseRelease(self): @@ -45,7 +45,7 @@ class InplaceObjProcess(Qc.QObject): def getXasyObject(self): raise NotImplementedError - def postDrawPreview(self, canvas: Qg.QPainter): + def postDrawPreview(self, canvas: QtGui.QPainter): pass def createOptWidget(self, info): @@ -55,10 +55,10 @@ class InplaceObjProcess(Qc.QObject): class AddCircle(InplaceObjProcess): def __init__(self, parent=None): super().__init__(parent) - self.center = Qc.QPointF(0, 0) + self.center = QtCore.QPointF(0, 0) self.radius = 0 - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) self.radius = 0 self.center.setX(x) @@ -75,9 +75,9 @@ class AddCircle(InplaceObjProcess): 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) + boundRect = QtCore.QRectF(x - self.radius, y - self.radius, 2 * self.radius, 2 * self.radius) # because the internal image is flipped... - newPath = Qg.QPainterPath() + newPath = QtGui.QPainterPath() newPath.addEllipse(boundRect) # newPath.addRect(boundRect) return newPath @@ -87,9 +87,9 @@ class AddCircle(InplaceObjProcess): def getXasyObject(self): if self.fill: - newObj = x2a.xasyFilledShape(self.getObject(), None) + newObj = xasy2asy.xasyFilledShape(self.getObject(), None) else: - newObj = x2a.xasyShape(self.getObject(), None) + newObj = xasy2asy.xasyShape(self.getObject(), None) return newObj def forceFinalize(self): @@ -102,8 +102,9 @@ class AddLabel(InplaceObjProcess): self.alignMode = None self.opt = None self.text = None - self.anchor = Qc.QPointF(0, 0) + self.anchor = QtCore.QPointF(0, 0) self._active = False + self.fontSize = 12 def createOptWidget(self, info): self.opt = Widg_addLabel.Widg_addLabel(info) @@ -121,7 +122,7 @@ class AddLabel(InplaceObjProcess): self.anchor.setX(x) self.anchor.setY(y) - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): if self.opt is not None: self.text = self.opt.labelText x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) @@ -140,7 +141,7 @@ class AddLabel(InplaceObjProcess): text = self.text align = str(self.alignMode) anchor = PrimitiveShape.PrimitiveShape.pos_to_tuple(self.anchor) - newLabel = x2a.xasyText(text=text, location=anchor, pen=None, + newLabel = xasy2asy.xasyText(text=text, location=anchor, pen=None, align=align, asyengine=None, fontsize=self.fontSize) newLabel.asyfied = False return newLabel @@ -164,11 +165,11 @@ class AddBezierShape(InplaceObjProcess): # 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.currentPoint = QtCore.QPointF(0, 0) self.pendingPoint = None self.useLegacy = False - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) self.currentPoint.setX(x) self.currentPoint.setY(y) @@ -222,7 +223,7 @@ class AddBezierShape(InplaceObjProcess): # self.updateBasePath() def updateBasePath(self): - self.basePath = x2a.asyPath(asyengine=self.asyengine, forceCurve=self.useBezierBase) + self.basePath = xasy2asy.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: @@ -237,7 +238,7 @@ class AddBezierShape(InplaceObjProcess): self.basePath.computeControls() def updateBasePathPreview(self): - self.basePathPreview = x2a.asyPath( + self.basePathPreview = xasy2asy.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()] @@ -271,16 +272,16 @@ class AddBezierShape(InplaceObjProcess): def getXasyObject(self): if self.fill: - return x2a.xasyFilledShape(self.getObject(), None) + return xasy2asy.xasyFilledShape(self.getObject(), None) else: - return x2a.xasyShape(self.getObject(), None) + return xasy2asy.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.center = QtCore.QPointF(0, 0) + self.currPos = QtCore.QPointF(0, 0) self.sides = None self.inscribed = None self.centermode = None @@ -288,18 +289,18 @@ class AddPoly(InplaceObjProcess): self.fill = None self.opt = None - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.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) + self.currPos = QtCore.QPointF(self.center) def mouseMove(self, pos, event): x, y = PrimitiveShape.PrimitiveShape.pos_to_tuple(pos) @@ -329,7 +330,7 @@ class AddPoly(InplaceObjProcess): else: poly = PrimitiveShape.PrimitiveShape.exscribedRegPolygon(self.sides, self.center, self._rad(), self._angle(), qpoly=True) - newPath = Qg.QPainterPath() + newPath = QtGui.QPainterPath() newPath.addPolygon(poly) return newPath @@ -350,7 +351,121 @@ class AddPoly(InplaceObjProcess): def getXasyObject(self): if self.fill: - newObj = x2a.xasyFilledShape(self.getObject(), None) + newObj = xasy2asy.xasyFilledShape(self.getObject(), None) else: - newObj = x2a.xasyShape(self.getObject(), None) + newObj = xasy2asy.xasyShape(self.getObject(), None) return newObj + +class AddFreehand(InplaceObjProcess): + # TODO: At the moment this is just a copy-paste of the AddBezierObj. + # Must find a better algorithm for constructing the obj rather than + # a node for every pixel the mouse moves. + 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 = QtCore.QPointF(0, 0) + self.pendingPoint = None + self.useLegacy = False + + def mouseDown(self, pos, info, mouseEvent: QtGui.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) + self.pointsList.append((x, y, self._getLinkType())) + + + def createOptWidget(self, info): + return None + + def mouseRelease(self): + self.updateBasePath() + self._active = False + self.pointsList.clear() + self.objectCreated.emit(self.getXasyObject()) + self.basePath = None + + def updateBasePath(self): + self.basePath = xasy2asy.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 = xasy2asy.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 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): + self.fill = False + return xasy2asy.xasyShape(self.getObject(), None) diff --git a/Build/source/utils/asymptote/GUI/PrimitiveShape.py b/Build/source/utils/asymptote/GUI/PrimitiveShape.py index c75e014079f..bbb2414866c 100644 --- a/Build/source/utils/asymptote/GUI/PrimitiveShape.py +++ b/Build/source/utils/asymptote/GUI/PrimitiveShape.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 -import xasy2asy as x2a -import numpy as np +import xasy2asy as xasy2asy +import numpy as numpy import math -import PyQt5.QtCore as Qc -import PyQt5.QtGui as Qg +import PyQt5.QtCore as QtCore +import PyQt5.QtGui as QtGui class PrimitiveShape: @@ -14,9 +14,9 @@ class PrimitiveShape: @staticmethod def pos_to_tuple(pos): - if isinstance(pos, tuple) or isinstance(pos, np.ndarray): + if isinstance(pos, tuple) or isinstance(pos, numpy.ndarray): return pos - elif isinstance(pos, Qc.QPoint) or isinstance(pos, Qc.QPointF): + elif isinstance(pos, QtCore.QPoint) or isinstance(pos, QtCore.QPointF): return pos.x(), pos.y() else: raise TypeError("Position must be a valid type!") @@ -32,7 +32,7 @@ class PrimitiveShape: @classmethod def circle(cls, position, radius): pos_x, pos_y = PrimitiveShape.pos_to_tuple(position) - newCircle = x2a.asyPath() + newCircle = xasy2asy.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. @@ -45,16 +45,16 @@ class PrimitiveShape: 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): + for ang in numpy.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) + qpoints = [QtCore.QPointF(x, y) for (x, y) in ptsList] + return QtGui.QPolygonF(qpoints) else: ptsList.append('cycle') - newPoly = x2a.asyPath() + newPoly = xasy2asy.asyPath() newPoly.initFromNodeList(ptsList, lkList) return newPoly diff --git a/Build/source/utils/asymptote/GUI/SetCustomAnchor.py b/Build/source/utils/asymptote/GUI/SetCustomAnchor.py index ad5925cddb4..e4414fecc4e 100644 --- a/Build/source/utils/asymptote/GUI/SetCustomAnchor.py +++ b/Build/source/utils/asymptote/GUI/SetCustomAnchor.py @@ -1,20 +1,20 @@ #!/usr/bin/env python3 -import PyQt5.QtWidgets as Qw -import PyQt5.QtGui as Qg -import PyQt5.QtCore as Qc +import PyQt5.QtWidgets as QtWidgets +import PyQt5.QtGui as QtGui +import PyQt5.QtCore as QtCore from pyUIClass.setCustomAnchor import Ui_Dialog -class CustomAnchorDialog(Qw.QDialog): +class CustomAnchorDialog(QtWidgets.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) + self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Reset).clicked.connect(self.resetDialog) - validator = Qg.QDoubleValidator() + validator = QtGui.QDoubleValidator() self.ui.lineEditX.setValidator(validator) self.ui.lineEditY.setValidator(validator) @@ -24,18 +24,18 @@ class CustomAnchorDialog(Qw.QDialog): def checkTextChanged(self, text): if str(text) not in {'.', '-', '.-', '-.'} and str(text): - self.ui.buttonBox.button(Qw.QDialogButtonBox.Ok).setEnabled(True) + self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(True) else: - self.ui.buttonBox.button(Qw.QDialogButtonBox.Ok).setEnabled(False) + self.ui.buttonBox.button(QtWidgets.QDialogButtonBox.Ok).setEnabled(False) def getPoint(self): xPoint = float(self.ui.lineEditX.text()) yPoint = float(self.ui.lineEditY.text()) - return Qc.QPointF(xPoint, yPoint) + return QtCore.QPointF(xPoint, yPoint) def handleBtnBoxClick(self, button): - assert isinstance(button, Qw.QAbstractButton) + assert isinstance(button, QtWidgets.QAbstractButton) if button.text() == 'Reset': self.resetDialog() diff --git a/Build/source/utils/asymptote/GUI/Widg_addLabel.py b/Build/source/utils/asymptote/GUI/Widg_addLabel.py index 776d3e02df9..a5a6503503b 100644 --- a/Build/source/utils/asymptote/GUI/Widg_addLabel.py +++ b/Build/source/utils/asymptote/GUI/Widg_addLabel.py @@ -1,14 +1,14 @@ #!/usr/bin/env python3 from pyUIClass.widg_addLabel import Ui_Form -import PyQt5.QtWidgets as Qw -import PyQt5.QtGui as Qg +import PyQt5.QtWidgets as QtWidgets +import PyQt5.QtGui as QtGui import labelEditor import xasyUtils as xu -class Widg_addLabel(Qw.QWidget): +class Widg_addLabel(QtWidgets.QWidget): def __init__(self, info): super().__init__() self.ui = Ui_Form() @@ -34,11 +34,11 @@ class Widg_addLabel(Qw.QWidget): 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() + validator = QtGui.QDoubleValidator() self.ui.txtShiftX.setValidator(validator) self.ui.txtShiftY.setValidator(validator) @@ -53,7 +53,7 @@ class Widg_addLabel(Qw.QWidget): self.updateCheck(self.ui.cmbAlign.currentText()) - def cmbFontSizeTextChanged(self, text: str): + def cmbFontSizeTextChanged(self, text: str): tryParseVal = xu.tryParse(text, float) self.info['fontSize'] = tryParseVal @@ -61,7 +61,7 @@ class Widg_addLabel(Qw.QWidget): advancedEditDialog = labelEditor.labelEditor(self.ui.txtLabelText.text()) advancedEditDialog.show() result = advancedEditDialog.exec_() - if result == Qw.QDialog.Accepted: + if result == QtWidgets.QDialog.Accepted: self.ui.txtLabelText.setText(advancedEditDialog.getText()) @property diff --git a/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py b/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py index b9b9a77f7a1..3d1e419d890 100644 --- a/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py +++ b/Build/source/utils/asymptote/GUI/Widg_addPolyOpt.py @@ -1,14 +1,13 @@ #!/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 PyQt5.QtWidgets as QtWidgets +import PyQt5.QtGui as QtGui import sys -class Widg_addPolyOpt(Qw.QWidget): +class Widg_addPolyOpt(QtWidgets.QWidget): def __init__(self, info): super().__init__() self.ui = Ui_Form() @@ -18,7 +17,7 @@ class Widg_addPolyOpt(Qw.QWidget): self.ui.chkInscribed.setChecked(self.info['inscribed']) self.ui.txtSides.setText(str(self.info['sides'])) - self.ui.txtSides.setValidator(Qg.QIntValidator()) + self.ui.txtSides.setValidator(QtGui.QIntValidator()) self.ui.chkInscribed.stateChanged.connect(self.chkInscribedUpdate) self.ui.txtSides.textChanged.connect(self.txtSidesUpdate) diff --git a/Build/source/utils/asymptote/GUI/Widg_editBezier.py b/Build/source/utils/asymptote/GUI/Widg_editBezier.py index 3a3cbab94ab..161715e0fc0 100644 --- a/Build/source/utils/asymptote/GUI/Widg_editBezier.py +++ b/Build/source/utils/asymptote/GUI/Widg_editBezier.py @@ -2,16 +2,15 @@ from pyUIClass.widg_editBezier import Ui_Form -import PyQt5.QtCore as Qc -import PyQt5.QtWidgets as Qw -import PyQt5.QtGui as Qg +import PyQt5.QtWidgets as QtWidgets +import PyQt5.QtCore as QtCore class LockMode: noLock = 0 angleLock = 1 angleAndScaleLock = 2 -class Widg_editBezier(Qw.QWidget): +class Widg_editBezier(QtWidgets.QWidget): def __init__(self, info: dict, enableCurveFeatures: bool=True): super().__init__() self.ui = Ui_Form() @@ -38,16 +37,16 @@ class Widg_editBezier(Qw.QWidget): def lockMode(self) -> int: return self.ui.cmbLockMode.currentIndex() - @Qc.pyqtSlot(int) + @QtCore.pyqtSlot(int) def cmbLockIndexChange(self, index: int): self.info['editBezierlockMode'] = index - @Qc.pyqtSlot(int) + @QtCore.pyqtSlot(int) def chkRecomputeChanged(self, checked: int): isChecked = (checked == 2) for obj in self.disableOnAutoRecompute: obj.setEnabled(not checked) self.info['autoRecompute'] = checked - + if isChecked: self.ui.btnForceRecompute.clicked.emit() diff --git a/Build/source/utils/asymptote/GUI/Window1.py b/Build/source/utils/asymptote/GUI/Window1.py index 1f7b67b1fa1..134d3cd1968 100644 --- a/Build/source/utils/asymptote/GUI/Window1.py +++ b/Build/source/utils/asymptote/GUI/Window1.py @@ -18,6 +18,7 @@ import tempfile import datetime import string import atexit +import pickle import xasyUtils as xu import xasy2asy as x2a @@ -50,7 +51,6 @@ class TransformationChanges(ActionChanges): self.transformation = transformation self.isLocal = isLocal - class ObjCreationChanges(ActionChanges): def __init__(self, obj): self.object = obj @@ -60,6 +60,18 @@ class HardDeletionChanges(ActionChanges): self.item = obj self.objIndex = pos +class SoftDeletionChanges(ActionChanges): + def __init__(self, obj, keyPos): + self.item = obj + self.keyMap = keyPos + +class EditBezierChanges(ActionChanges): + def __init__(self, obj, pos, oldPath, newPath): + self.item = obj + self.objIndex = pos + self.oldPath = oldPath + self.newPath = newPath + class AnchorMode: center = 0 origin = 1 @@ -68,7 +80,7 @@ class AnchorMode: bottomRight = 4 bottomLeft = 5 customAnchor = 6 - + class GridMode: cartesian = 0 @@ -84,6 +96,14 @@ class SelectionMode: delete = 5 setAnchor = 6 selectEdit = 7 + openPoly = 8 + closedPoly = 9 + openCurve = 10 + closedCurve = 11 + addPoly = 12 + addCircle = 13 + addLabel = 14 + addFreehand = 15 class AddObjectMode: Circle = 0 @@ -92,14 +112,15 @@ class AddObjectMode: class MainWindow1(Qw.QMainWindow): defaultFrameStyle = """ - QFrame{{ + QFrame{{ padding: 4.0; - border-radius: 3.0; + border-radius: 3.0; background: rgb({0}, {1}, {2}) }} """ def __init__(self): + self.testingActions = [] super().__init__() self.ui = Ui_MainWindow() global devicePixelRatio @@ -109,12 +130,13 @@ class MainWindow1(Qw.QMainWindow): self.settings = xo.BasicConfigs.defaultOpt self.keyMaps = xo.BasicConfigs.keymaps + self.openRecent = xo.BasicConfigs.openRecent self.raw_args = Qc.QCoreApplication.arguments() self.args = xa.parseArgs(self.raw_args) self.strings = xs.xasyString(self.args.language) - self.asy2psmap = x2a.identity() + self.asy2psmap = x2a.yflip() if self.settings['asyBaseLocation'] is not None: os.environ['ASYMPTOTE_DIR'] = self.settings['asyBaseLocation'] @@ -134,7 +156,8 @@ class MainWindow1(Qw.QMainWindow): # For initialization purposes self.canvSize = Qc.QSize() - self.filename = None + self.fileName = None + self.asyFileName = None self.currDir = None self.mainCanvas = None self.dpi = 300 @@ -165,9 +188,9 @@ class MainWindow1(Qw.QMainWindow): self.inMidTransformation = False self.addMode = None self.currentlySelectedObj = {'key': None, 'allSameKey': set(), 'selectedIndex': None, 'keyIndex': None} - self.pendingSelectedObjList = [] + self.pendingSelectedObjList = [] self.pendingSelectedObjIndex = -1 - + self.savedMousePosition = None self.currentBoundingBox = None self.selectionDelta = None @@ -177,9 +200,12 @@ class MainWindow1(Qw.QMainWindow): self.scaleFactor = 1 self.panOffset = [0, 0] + # Keyboard can focus outside of textboxes + self.setFocusPolicy(Qc.Qt.StrongFocus) + super().setMouseTracking(True) # setMouseTracking(True) - + self.undoRedoStack = Urs.actionStack() self.lockX = False @@ -211,8 +237,10 @@ class MainWindow1(Qw.QMainWindow): 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.ui.btnPan, self.ui.btnDeleteMode, self.ui.btnAnchor, + self.ui.btnSelectEdit, self.ui.btnOpenPoly, self.ui.btnClosedPoly, + self.ui.btnOpenCurve, self.ui.btnClosedCurve, self.ui.btnAddPoly, + self.ui.btnAddCircle, self.ui.btnAddLabel, self.ui.btnAddFreehand } self.objButtons = {self.ui.btnCustTransform, self.ui.actionTransform, self.ui.btnSendForwards, @@ -225,17 +253,17 @@ class MainWindow1(Qw.QMainWindow): self.currAddOptionsWgt = None self.currAddOptions = { - 'options': self.settings, + 'options': self.settings, 'inscribed': True, 'sides': 3, 'centermode': True, - 'fontSize': None, + 'fontSize': None, 'asyengine': self.asyEngine, 'fill': self.ui.btnFill.isChecked(), 'closedPath': False, - 'useBezier': True, + 'useBezier': True, 'magnification': self.magnification, - 'editBezierlockMode': xbi.Web.LockMode.angleLock, + 'editBezierlockMode': xbi.Web.LockMode.angleLock, 'autoRecompute': False } @@ -249,7 +277,7 @@ class MainWindow1(Qw.QMainWindow): # commands switchboard self.commandsFunc = { - 'quit': Qc.QCoreApplication.quit, + 'quit': self.btnCloseFileonClick, 'undo': self.btnUndoOnClick, 'redo': self.btnRedoOnClick, 'manual': self.actionManual, @@ -261,10 +289,10 @@ class MainWindow1(Qw.QMainWindow): 'commandPalette': self.enterCustomCommand, 'clearGuide': self.clearGuides, 'finalizeAddObj': self.finalizeAddObj, - 'finalizeCurve': self.finalizeCurve, - 'finalizeCurveClosed': self.finalizeCurveClosed, + 'finalizeCurve': self.finalizeCurve, + 'finalizeCurveClosed': self.finalizeCurveClosed, 'setMag': self.setMagPrompt, - 'deleteObject': self.btnSelectiveDeleteOnClick, + 'deleteObject': self.btnSelectiveDeleteOnClick, 'anchorMode': self.switchToAnchorMode, 'moveUp': lambda: self.translate(0, -1), 'moveDown': lambda: self.translate(0, 1), @@ -274,10 +302,17 @@ class MainWindow1(Qw.QMainWindow): '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), + 'scrollDown': lambda: self.arrowButtons(0, -1, True), + + 'zoomIn': lambda: self.arrowButtons(0, 1, False, True), + 'zoomOut': lambda: self.arrowButtons(0, -1, False, True), + + 'open': self.btnLoadFileonClick, + 'save': self.actionSave, + 'export': self.btnExportAsymptoteOnClick, - 'zoomIn': lambda: self.arrowButtons(0, 1, False, True), - 'zoomOut': lambda: self.arrowButtons(0, -1, False, True) + 'copy': self.copyItem, + 'paste': self.pasteItem } self.hiddenKeys = set() @@ -291,6 +326,7 @@ class MainWindow1(Qw.QMainWindow): # from xasyoptions config file self.loadKeyMaps() self.setupXasyOptions() + self.populateOpenRecent() self.colorDialog = Qw.QColorDialog(x2a.asyPen.convertToQColor(self._currentPen.color), self) self.initPenInterface() @@ -320,7 +356,7 @@ class MainWindow1(Qw.QMainWindow): def getScrsTransform(self): # pipeline: # assuming origin <==> top left - # (Pan) * (Translate) * (Flip the images) * (Zoom) * (Obj transform) * (Base Information) + # (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) @@ -366,6 +402,12 @@ class MainWindow1(Qw.QMainWindow): self.settings.load() self.quickUpdate() + def openAndReloadKeymaps(self): + keymapsFile = self.keyMaps.settingsFileLocation() + subprocess.run(args=self.getExternalEditor(asypath=keymapsFile)) + self.settings.load() + self.quickUpdate() + def setMagPrompt(self): commandText, result = Qw.QInputDialog.getText(self, '', 'Enter magnification:') if result: @@ -373,6 +415,11 @@ class MainWindow1(Qw.QMainWindow): self.currAddOptions['magnification'] = self.magnification self.quickUpdate() + def setTextPrompt(self): + commandText, result = Qw.QInputDialog.getText(self, '', 'Enter new text:') + if result: + return commandText + def btnTogglePythonOnClick(self, checked): self.terminalPythonMode = checked @@ -381,7 +428,10 @@ class MainWindow1(Qw.QMainWindow): def handleArguments(self): if self.args.filename is not None: - self.loadFile(self.args.filename) + if os.path.exists(self.args.filename): + self.actionOpen(os.path.abspath(self.args.filename)) + else: + self.loadFile(self.args.filename) else: self.initializeEmptyFile() @@ -417,14 +467,18 @@ class MainWindow1(Qw.QMainWindow): self.ui.actionRedo.triggered.connect(lambda: self.execCustomCommand('redo')) self.ui.actionTransform.triggered.connect(lambda: self.execCustomCommand('transform')) + self.ui.actionNewFile.triggered.connect(self.actionNewFile) self.ui.actionOpen.triggered.connect(self.actionOpen) + self.ui.actionClearRecent.triggered.connect(self.actionClearRecent) 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.actionKeymaps.triggered.connect(self.openAndReloadKeymaps) self.ui.actionEnterCommand.triggered.connect(self.enterCustomCommand) - self.ui.actionExportAsymptote.triggered.connect(self.btnExportAsyOnClick) + self.ui.actionExportAsymptote.triggered.connect(self.btnExportAsymptoteOnClick) + self.ui.actionExportToAsy.triggered.connect(self.btnExportToAsyOnClick) def setupXasyOptions(self): if self.settings['debugMode']: @@ -443,7 +497,7 @@ class MainWindow1(Qw.QMainWindow): self.ui.btnSave.clicked.connect(self.btnSaveonClick) self.ui.btnQuickScreenshot.clicked.connect(self.btnQuickScreenshotOnClick) - # self.ui.btnExportAsy.clicked.connect(self.btnExportAsyOnClick) + # self.ui.btnExportAsy.clicked.connect(self.btnExportAsymptoteOnClick) self.ui.btnDrawAxes.clicked.connect(self.btnDrawAxesOnClick) # self.ui.btnAsyfy.clicked.connect(lambda: self.asyfyCanvas(True)) @@ -467,7 +521,7 @@ class MainWindow1(Qw.QMainWindow): self.ui.btnAnchor.clicked.connect(self.btnAnchorModeOnClick) self.ui.btnSelectColor.clicked.connect(self.btnColorSelectOnClick) - self.ui.txtLineWidth.textEdited.connect(self.txtLineWithEdited) + self.ui.txtLineWidth.textEdited.connect(self.txtLineWidthEdited) # self.ui.btnCreateCurve.clicked.connect(self.btnCreateCurveOnClick) self.ui.btnDrawGrid.clicked.connect(self.btnDrawGridOnClick) @@ -475,6 +529,7 @@ class MainWindow1(Qw.QMainWindow): self.ui.btnAddCircle.clicked.connect(self.btnAddCircleOnClick) self.ui.btnAddPoly.clicked.connect(self.btnAddPolyOnClick) self.ui.btnAddLabel.clicked.connect(self.btnAddLabelOnClick) + self.ui.btnAddFreehand.clicked.connect(self.btnAddFreehandOnClick) # self.ui.btnAddBezierInplace.clicked.connect(self.btnAddBezierInplaceOnClick) self.ui.btnClosedCurve.clicked.connect(self.btnAddClosedCurveOnClick) self.ui.btnOpenCurve.clicked.connect(self.btnAddOpenCurveOnClick) @@ -489,16 +544,19 @@ class MainWindow1(Qw.QMainWindow): 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() + if self.currentModeStack[-1] != SelectionMode.delete: + self.currentModeStack = [SelectionMode.delete] + self.ui.statusbar.showMessage('Delete mode') + self.clearSelection() + self.updateChecks() + else: + self.btnTranslateonClick() def btnTerminalCommandOnClick(self): if self.terminalPythonMode: @@ -507,18 +565,25 @@ class MainWindow1(Qw.QMainWindow): else: pass # TODO: How to handle this case? - # Like AutoCAD? + # Like AutoCAD? self.ui.txtTerminalPrompt.clear() - def btnFillOnClick(self, checked): + def btnFillOnClick(self, checked): + if self.currentModeStack == [SelectionMode.selectEdit]: + if isinstance(self.addMode,xbi.InteractiveBezierEditor): + self.addMode.swapObjFill() #Check for crashes 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() + if self.currentModeStack[-1] != SelectionMode.selectEdit: + self.currentModeStack = [SelectionMode.selectEdit] + self.ui.statusbar.showMessage('Edit mode') + self.clearSelection() + self.updateChecks() + else: + self.btnTranslateonClick() @property def currentPen(self): @@ -544,7 +609,7 @@ class MainWindow1(Qw.QMainWindow): except Exception: pass - self.currentModeStack[-1] = None + #self.currentModeStack[-1] = None self.addMode.objectCreated.connect(self.addInPlace) self.updateModeBtnsOnly() @@ -557,7 +622,10 @@ class MainWindow1(Qw.QMainWindow): def addInPlace(self, obj): obj.asyengine = self.asyEngine - obj.pen = self.currentPen + if isinstance(obj, x2a.xasyText): + obj.label.pen = self.currentPen + else: + obj.pen = self.currentPen obj.onCanvas = self.xasyDrawObj obj.setKey(str(self.globalObjectCounter)) self.globalObjectCounter = self.globalObjectCounter + 1 @@ -576,11 +644,6 @@ class MainWindow1(Qw.QMainWindow): 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.' @@ -598,49 +661,90 @@ class MainWindow1(Qw.QMainWindow): self.ui.statusbar.showMessage(self.Hint+self.HintClose) def btnAddBezierInplaceOnClick(self): + self.fileChanged = True self.addMode = InplaceAddObj.AddBezierShape(self) self.updateOptionWidget() def btnAddOpenLineOnClick(self): - self.currAddOptions['useBezier'] = False - self.currAddOptions['closedPath'] = False - self.drawHintOpen() - self.btnAddBezierInplaceOnClick() + if self.currentModeStack[-1] != SelectionMode.openPoly: + self.currentModeStack = [SelectionMode.openPoly] + self.currAddOptions['useBezier'] = False + self.currAddOptions['closedPath'] = False + self.drawHintOpen() + self.btnAddBezierInplaceOnClick() + else: + self.btnTranslateonClick() def btnAddClosedLineOnClick(self): - self.currAddOptions['useBezier'] = False - self.currAddOptions['closedPath'] = True - self.drawHint() - self.btnAddBezierInplaceOnClick() + if self.currentModeStack[-1] != SelectionMode.closedPoly: + self.currentModeStack = [SelectionMode.closedPoly] + self.currAddOptions['useBezier'] = False + self.currAddOptions['closedPath'] = True + self.drawHint() + self.btnAddBezierInplaceOnClick() + else: + self.btnTranslateonClick() def btnAddOpenCurveOnClick(self): - self.currAddOptions['useBezier'] = True - self.currAddOptions['closedPath'] = False - self.drawHintOpen() - self.btnAddBezierInplaceOnClick() + if self.currentModeStack[-1] != SelectionMode.openCurve: + self.currentModeStack = [SelectionMode.openCurve] + self.currAddOptions['useBezier'] = True + self.currAddOptions['closedPath'] = False + self.drawHintOpen() + self.btnAddBezierInplaceOnClick() + else: + self.btnTranslateonClick() def btnAddClosedCurveOnClick(self): - self.currAddOptions['useBezier'] = True - self.currAddOptions['closedPath'] = True - self.drawHint() - self.btnAddBezierInplaceOnClick() + if self.currentModeStack[-1] != SelectionMode.closedCurve: + self.currentModeStack = [SelectionMode.closedCurve] + self.currAddOptions['useBezier'] = True + self.currAddOptions['closedPath'] = True + self.drawHint() + self.btnAddBezierInplaceOnClick() + else: + self.btnTranslateonClick() def btnAddPolyOnClick(self): - self.addMode = InplaceAddObj.AddPoly(self) - self.ui.statusbar.showMessage('') - self.updateOptionWidget() + if self.currentModeStack[-1] != SelectionMode.addPoly: + self.currentModeStack = [SelectionMode.addPoly] + self.addMode = InplaceAddObj.AddPoly(self) + self.ui.statusbar.showMessage('Add polygon on click') + self.updateOptionWidget() + else: + self.btnTranslateonClick() - def btnAddLabelOnClick(self): - self.addMode = InplaceAddObj.AddLabel(self) - self.ui.statusbar.showMessage('') - self.updateOptionWidget() + def btnAddCircleOnClick(self): + if self.currentModeStack[-1] != SelectionMode.addCircle: + self.currentModeStack = [SelectionMode.addCircle] + self.addMode = InplaceAddObj.AddCircle(self) + self.ui.statusbar.showMessage('Add circle on click') + self.updateOptionWidget() + else: + self.btnTranslateonClick() - def updateCurve(self, valid, newCurve): - self.previewCurve = newCurve - self.quickUpdate() + def btnAddLabelOnClick(self): + if self.currentModeStack[-1] != SelectionMode.addLabel: + self.currentModeStack = [SelectionMode.addLabel] + self.addMode = InplaceAddObj.AddLabel(self) + self.ui.statusbar.showMessage('Add label on click') + self.updateOptionWidget() + else: + self.btnTranslateonClick() + + def btnAddFreehandOnClick(self): + if self.currentModeStack[-1] != SelectionMode.addFreehand: + self.currentModeStack = [SelectionMode.addFreehand] + self.currAddOptions['useBezier'] = False + self.currAddOptions['closedPath'] = False + self.ui.statusbar.showMessage("Draw freehand") + self.addMode = InplaceAddObj.AddFreehand(self) + self.updateOptionWidget() + else: + self.btnTranslateonClick() def addTransformationChanges(self, objIndex, transform, isLocal=False): - self.undoRedoStack.add(self.createAction(TransformationChanges(objIndex, + self.undoRedoStack.add(self.createAction(TransformationChanges(objIndex, transform, isLocal))) self.checkUndoRedoButtons() @@ -665,7 +769,11 @@ class MainWindow1(Qw.QMainWindow): parent = selectedObj.parent() if isinstance(parent, x2a.xasyScript): - self.hiddenKeys.add((selectedObj.key, selectedObj.keyIndex)) + objKey=(selectedObj.key, selectedObj.keyIndex) + self.hiddenKeys.add(objKey) + self.undoRedoStack.add(self.createAction( + SoftDeletionChanges(selectedObj.parent(), objKey) + )) self.softDeleteObj((maj, minor)) else: index = self.fileItems.index(selectedObj.parent()) @@ -673,10 +781,10 @@ class MainWindow1(Qw.QMainWindow): self.undoRedoStack.add(self.createAction( HardDeletionChanges(selectedObj.parent(), index) )) - self.checkUndoRedoButtons() - + self.fileItems.remove(selectedObj.parent()) + self.checkUndoRedoButtons() self.fileChanged = True self.clearSelection() self.asyfyCanvas() @@ -709,8 +817,16 @@ class MainWindow1(Qw.QMainWindow): def btnUndoOnClick(self): - self.undoRedoStack.undo() - self.checkUndoRedoButtons() + if self.currentlySelectedObj['selectedIndex'] is not None: + # avoid deleting currently selected object + maj, minor = self.currentlySelectedObj['selectedIndex'] + selectedObj = self.drawObjects[maj][minor] + if selectedObj != self.drawObjects[-1][0]: + self.undoRedoStack.undo() + self.checkUndoRedoButtons() + else: + self.undoRedoStack.undo() + self.checkUndoRedoButtons() def btnRedoOnClick(self): self.undoRedoStack.redo() @@ -731,6 +847,12 @@ class MainWindow1(Qw.QMainWindow): self.fileItems.pop() elif isinstance(change, HardDeletionChanges): self.fileItems.insert(change.objIndex, change.item) + elif isinstance(change, SoftDeletionChanges): + key, keyIndex = change.keyMap + self.hiddenKeys.remove((key, keyIndex)) + change.item.transfKeymap[key][keyIndex].deleted = False + elif isinstance(change, EditBezierChanges): + self.fileItems[change.objIndex].path = change.oldPath self.asyfyCanvas() def handleRedoChanges(self, change): @@ -742,6 +864,12 @@ class MainWindow1(Qw.QMainWindow): self.fileItems.append(change.object) elif isinstance(change, HardDeletionChanges): self.fileItems.remove(change.item) + elif isinstance(change, SoftDeletionChanges): + key, keyIndex = change.keyMap + self.hiddenKeys.add((key, keyIndex)) + change.item.transfKeymap[key][keyIndex].deleted = True + elif isinstance(change, EditBezierChanges): + self.fileItems[change.objIndex].path = change.newPath self.asyfyCanvas() # is this a "pythonic" way? @@ -765,11 +893,26 @@ class MainWindow1(Qw.QMainWindow): if result: self.execCustomCommand(commandText) - def addItemFromPath(self, path): - newItem = x2a.xasyShape(path, self.asyEngine, pen=self.currentPen) + def addXasyShapeFromPath(self, path, pen = None, transform = x2a.identity(), key = None): + if not pen: + pen = self.currentPen + else: + pen = x2a.asyPen(self.asyEngine, color = pen['color'], width = pen['width'], pen_options = pen['options']) + + newItem = x2a.xasyShape(path, self.asyEngine, pen = pen, transform = transform) + newItem.setKey(key) self.fileItems.append(newItem) - self.fileChanged = True - self.asyfyCanvas() + + def addXasyTextFromData(self, text, location, pen, transform, key, align, fontSize): + if not pen: + pen = self.currentPen + else: + pen = x2a.asyPen(self.asyEngine, color = pen['color'], width = pen['width'], pen_options = pen['options']) + newItem = x2a.xasyText(text, location, self.asyEngine, pen, transform, key, align, fontSize) + newItem.setKey(key) + newItem.onCanvas = self.xasyDrawObj + self.fileItems.append(newItem) + def actionManual(self): asyManualURL = 'https://asymptote.sourceforge.io/asymptote.pdf' @@ -778,11 +921,35 @@ class MainWindow1(Qw.QMainWindow): def actionAbout(self): Qw.QMessageBox.about(self,"xasy","This is xasy "+xasyVersion.xasyVersion+"; a graphical front end to the Asymptote vector graphics language: https://asymptote.sourceforge.io/") - def btnExportAsyOnClick(self): + def actionExport(self, pathToFile): + asyFile = io.open(os.path.realpath(pathToFile), 'w') + xf.saveFile(asyFile, self.fileItems, self.asy2psmap) + asyFile.close() + self.ui.statusbar.showMessage(f"Exported to '{pathToFile}' as Asymptote File.") + + def btnExportToAsyOnClick(self): + if self.fileName: + pathToFile = os.path.splitext(self.fileName)[0]+'.asy' + else: + self.btnExportAsymptoteOnClick() + return + if os.path.isfile(pathToFile): + reply = Qw.QMessageBox.question(self, 'Message', + f'"{os.path.split(pathToFile)[1]}" already exists. Do you want to overwrite it?', + Qw.QMessageBox.Yes, Qw.QMessageBox.No) + if reply == Qw.QMessageBox.No: + return + self.actionExport(pathToFile) + + def btnExportAsymptoteOnClick(self): diag = Qw.QFileDialog(self) diag.setAcceptMode(Qw.QFileDialog.AcceptSave) formatId = { + 'asy': { + 'name': 'Asymptote Files', + 'ext': ['*.asy'] + }, 'pdf': { 'name': 'PDF Files', 'ext': ['*.pdf'] @@ -805,14 +972,14 @@ class MainWindow1(Qw.QMainWindow): } } - formats = ['pdf', 'svg', 'eps', 'png', '*'] + formats = ['asy', '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' + rawFile = os.path.splitext(os.path.basename(self.fileName))[0] + '.asy' diag.selectFile(rawFile) diag.setNameFilter(formatText) @@ -823,25 +990,107 @@ class MainWindow1(Qw.QMainWindow): return finalFiles = diag.selectedFiles() - - with io.StringIO() as finalCode: - xf.saveFile(finalCode, self.fileItems, self.asy2psmap) - finalString = finalCode.getvalue() + finalString = xf.xasy2asyCode(self.fileItems, self.asy2psmap) for file in finalFiles: ext = os.path.splitext(file) if len(ext) < 2: - ext = 'pdf' + ext = 'asy' else: ext = ext[1][1:] + if ext == 'asy': + pathToFile = os.path.splitext(file)[0]+'.'+ext + asyFile = io.open(os.path.realpath(pathToFile), 'w') + xf.saveFile(asyFile, self.fileItems, self.asy2psmap) + asyFile.close() + else: + with subprocess.Popen(args=[self.asyPath, '-f{0}'.format(ext), '-o{0}'.format(file), '-'], encoding='utf-8', + stdin=subprocess.PIPE) as asy: + + asy.stdin.write(finalString) + asy.stdin.close() + asy.wait(timeout=35) + + def actionExportXasy(self, file): + xasyObjects, asyItems = xf.xasyToDict(self.fileName, self.fileItems, self.asy2psmap) - 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) + if asyItems: + # Save imported items into the twin asy file + asyScriptItems = [item['item'] for item in asyItems if item['type'] == 'xasyScript'] + + prefix = os.path.splitext(self.fileName)[0] + asyFilePath = prefix + '.asy' + + saveAsyFile = io.open(asyFilePath, 'w') + xf.saveFile(saveAsyFile, asyScriptItems, self.asy2psmap) + saveAsyFile.close() + self.updateScript() + + openFile = open(file, 'wb') + pickle.dump(xasyObjects, openFile) + openFile.close() + + def actionLoadXasy(self, file): + self.erase() + self.ui.statusbar.showMessage('Load {0}'.format(file)) # TODO: This doesn't show on the UI + self.fileName = file + self.currDir = os.path.dirname(self.fileName) + + input_file = open(file, 'rb') + xasyObjects = pickle.load(input_file) + input_file.close() + + prefix = os.path.splitext(self.fileName)[0] + asyFilePath = prefix + '.asy' + rawText = None + existsAsy = False + + if os.path.isfile(asyFilePath): + asyFile = io.open(asyFilePath, 'r') + rawText = asyFile.read() + asyFile.close() + rawText, transfDict = xf.extractTransformsFromFile(rawText) + obj = x2a.xasyScript(canvas=self.xasyDrawObj, engine=self.asyEngine, transfKeyMap=transfDict) + obj.setScript(rawText) + self.fileItems.append(obj) + existsAsy = True + + self.asyfyCanvas(force=True) + + for item in xasyObjects['objects']: + key=item['transfKey'] + if(key) in obj.transfKeymap.keys(): + continue + obj.maxKey=max(obj.maxKey,int(key)) + if item['type'] == 'xasyScript': + print("Uh oh, there should not be any asy objects loaded") + + elif item['type'] == 'xasyText': + self.addXasyTextFromData( text = item['text'], + location = item['location'], pen = None, + transform = x2a.asyTransform(item['transform']), key = item['transfKey'], + align = item['align'], fontSize = item['fontSize'] + ) + + elif item['type'] == 'xasyShape': + nodeSet = item['nodes'] + linkSet = item['links'] + path = x2a.asyPath(self.asyEngine) + path.initFromNodeList(nodeSet, linkSet) + self.addXasyShapeFromPath(path, pen = item['pen'], transform = x2a.asyTransform(item['transform']), key = item['transfKey']) + else: + print("ERROR") + + self.asy2psmap = x2a.asyTransform(xasyObjects['asy2psmap']) + self.globalObjectCounter = obj.maxKey+1 + + self.asyfyCanvas() + + if existsAsy: + self.ui.statusbar.showMessage(f"Corresponding Asymptote File '{os.path.basename(asyFilePath)}' found. Loaded both files.") + else: + self.ui.statusbar.showMessage("No Asymptote file found. Loaded exclusively GUI objects.") def loadKeyMaps(self): """Inverts the mapping of the key @@ -865,28 +1114,147 @@ class MainWindow1(Qw.QMainWindow): def erase(self): self.fileItems.clear() + self.hiddenKeys.clear() + self.undoRedoStack.clear() + self.checkUndoRedoButtons() self.fileChanged = False - def actionOpen(self): + #We include this function to keep the general program flow consistent + def closeEvent(self, event): + if self.actionClose() == Qw.QMessageBox.Cancel: + event.ignore() + + def actionNewFile(self): if self.fileChanged: - save="Save current file?" - reply=Qw.QMessageBox.question(self,'Message',save,Qw.QMessageBox.Yes, - Qw.QMessageBox.No) + reply = self.saveDialog() if reply == Qw.QMessageBox.Yes: self.actionSave() + elif reply == Qw.QMessageBox.Cancel: + return + self.erase() + self.asyfyCanvas(force=True) + self.fileName = None + self.updateTitle() + + + def actionOpen(self, fileName = None): + if self.fileChanged: + reply = self.saveDialog() + if reply == Qw.QMessageBox.Yes: + self.actionSave() + elif reply == Qw.QMessageBox.Cancel: + return - filename = Qw.QFileDialog.getOpenFileName(self, 'Open Asymptote File','', '*.asy') - if filename[0]: - self.loadFile(filename[0]) + if fileName: + # Opening via open recent or cmd args + _, file_extension = os.path.splitext(fileName) + if file_extension == '.xasy': + self.actionLoadXasy(fileName) + else: + self.loadFile(fileName) + self.populateOpenRecent(fileName) + else: + filename = Qw.QFileDialog.getOpenFileName(self, 'Open Xasy/Asymptote File','', '(*.xasy *.asy)') + if filename[0]: + _, file_extension = os.path.splitext(filename[0]) + if file_extension == '.xasy': + self.actionLoadXasy(filename[0]) + else: + self.loadFile(filename[0]) + + self.populateOpenRecent(filename[0].strip()) + + def actionClearRecent(self): + self.ui.menuOpenRecent.clear() + self.openRecent.clear() + self.ui.menuOpenRecent.addAction("Clear", self.actionClearRecent) + + def populateOpenRecent(self, recentOpenedFile = None): + self.ui.menuOpenRecent.clear() + if recentOpenedFile: + self.openRecent.insert(recentOpenedFile) + for count, path in enumerate(self.openRecent.pathList): + if count > 8: + break + action = Qw.QAction(path, self, triggered = lambda state, path = path: self.actionOpen(fileName = path)) + self.ui.menuOpenRecent.addAction(action) + self.ui.menuOpenRecent.addSeparator() + self.ui.menuOpenRecent.addAction("Clear", self.actionClearRecent) + + def saveDialog(self) -> bool: + save = "Save current file?" + replyBox = Qw.QMessageBox() + replyBox.setText("Save current file?") + replyBox.setWindowTitle("Message") + replyBox.setStandardButtons(Qw.QMessageBox.Yes | Qw.QMessageBox.No | Qw.QMessageBox.Cancel) + reply = replyBox.exec() + + return reply + + def actionClose(self): + if self.fileChanged: + reply = self.saveDialog() + if reply == Qw.QMessageBox.Yes: + self.actionSave() + Qc.QCoreApplication.quit() + elif reply == Qw.QMessageBox.No: + Qc.QCoreApplication.quit() + else: + return reply + else: + Qc.QCoreApplication.quit() def actionSave(self): - if self.filename is None: + if self.fileName is None: self.actionSaveAs() + else: - saveFile = io.open(self.filename, 'w') - xf.saveFile(saveFile, self.fileItems, self.asy2psmap) - saveFile.close() + _, file_extension = os.path.splitext(self.fileName) + if file_extension == ".asy": + if self.existsXasy(): + warning = "Choose save format. Note that objects saved in asy format cannot be edited graphically." + replyBox = Qw.QMessageBox() + replyBox.setWindowTitle('Warning') + replyBox.setText(warning) + replyBox.addButton("Save as .xasy", replyBox.NoRole) + replyBox.addButton("Save as .asy", replyBox.YesRole) + replyBox.addButton(Qw.QMessageBox.Cancel) + reply = replyBox.exec() + if reply == 1: + saveFile = io.open(self.fileName, 'w') + xf.saveFile(saveFile, self.fileItems, self.asy2psmap) + saveFile.close() + self.ui.statusbar.showMessage('File saved as {}'.format(self.fileName)) + self.fileChanged = False + elif reply == 0: + prefix = os.path.splitext(self.fileName)[0] + xasyFilePath = prefix + '.xasy' + if os.path.isfile(xasyFilePath): + warning = f'"{os.path.basename(xasyFilePath)}" already exists. Do you want to overwrite it?' + reply = Qw.QMessageBox.question(self, "Same File", warning, Qw.QMessageBox.No, Qw.QMessageBox.Yes) + if reply == Qw.QMessageBox.No: + return + + self.actionExportXasy(xasyFilePath) + self.fileName = xasyFilePath + self.ui.statusbar.showMessage('File saved as {}'.format(self.fileName)) + self.fileChanged = False + else: + return + + else: + saveFile = io.open(self.fileName, 'w') + xf.saveFile(saveFile, self.fileItems, self.asy2psmap) + saveFile.close() + self.fileChanged = False + elif file_extension == ".xasy": + self.actionExportXasy(self.fileName) + self.ui.statusbar.showMessage('File saved as {}'.format(self.fileName)) + self.fileChanged = False + else: + print("ERROR: file extension not supported") self.updateScript() + self.updateTitle() def updateScript(self): for item in self.fileItems: @@ -895,15 +1263,30 @@ class MainWindow1(Qw.QMainWindow): item.setScript(item.updatedCode) item.updatedCode = None + def existsXasy(self): + for item in self.fileItems: + if not isinstance(item, x2a.xasyScript): + return True + return False + def actionSaveAs(self): - saveLocation = Qw.QFileDialog.getSaveFileName(self, 'Save File')[0] + initSave = os.path.splitext(str(self.fileName))[0]+'.xasy' + saveLocation = Qw.QFileDialog.getSaveFileName(self, 'Save File', initSave, "Xasy File (*.xasy)")[0] if saveLocation: - saveFile = io.open(saveLocation, 'w') - xf.saveFile(saveFile, self.fileItems, self.asy2psmap) - saveFile.close() - self.filename = saveLocation + _, file_extension = os.path.splitext(saveLocation) + if not file_extension: + saveLocation += '.xasy' + self.actionExportXasy(saveLocation) + elif file_extension == ".xasy": + self.actionExportXasy(saveLocation) + else: + print("ERROR: file extension not supported") + self.fileName = saveLocation self.updateScript() - + self.fileChanged = False + self.updateTitle() + self.populateOpenRecent(saveLocation) + def btnQuickScreenshotOnClick(self): saveLocation = Qw.QFileDialog.getSaveFileName(self, 'Save Screenshot','') @@ -913,6 +1296,9 @@ class MainWindow1(Qw.QMainWindow): def btnLoadFileonClick(self): self.actionOpen() + def btnCloseFileonClick(self): + self.actionClose() + def btnSaveonClick(self): self.actionSave() @@ -933,7 +1319,7 @@ class MainWindow1(Qw.QMainWindow): self._currentPen.setColorFromQColor(self.colorDialog.selectedColor()) self.updateFrameDispColor() - def txtLineWithEdited(self, text): + def txtLineWidthEdited(self, text): new_val = xu.tryParse(text, float) if new_val is not None: if new_val > 0: @@ -985,12 +1371,12 @@ class MainWindow1(Qw.QMainWindow): def mouseMoveEvent(self, mouseEvent: Qg.QMouseEvent): # TODO: Actually refine grid snapping... if not self.ui.imgLabel.underMouse() and not self.mouseDown: - return + return self.updateMouseCoordLabel() asyPos, canvasPos = self.getAsyCoordinates() - # add mode + # add mode if self.addMode is not None: if self.addMode.active: self.addMode.mouseMove(asyPos, mouseEvent) @@ -1016,7 +1402,7 @@ class MainWindow1(Qw.QMainWindow): self.quickUpdate() return - # otherwise, in transformation + # otherwise, in transformation if self.inMidTransformation: if self.currentModeStack[-1] == SelectionMode.translate: newPos = canvasPos - self.savedMousePosition @@ -1080,11 +1466,11 @@ class MainWindow1(Qw.QMainWindow): self.pendingSelectedObjList.clear() self.pendingSelectedObjIndex = -1 self.quickUpdate() - return + return def mouseReleaseEvent(self, mouseEvent): - assert isinstance(mouseEvent, Qg.QMouseEvent) + assert isinstance(mouseEvent, Qg.QMouseEvent) if not self.mouseDown: return @@ -1124,8 +1510,7 @@ class MainWindow1(Qw.QMainWindow): keyModifiers = keyModifiers | defaultModifiers if keyModifiers & int(Qc.Qt.ControlModifier): oldMag = self.magnification - - factor=0.5/devicePixelRatio; + factor = 0.5/devicePixelRatio cx, cy = self.canvSize.width()*factor, self.canvSize.height()*factor centerPoint = Qc.QPointF(cx, cy) * self.getScrsTransform().inverted()[0] @@ -1203,7 +1588,7 @@ class MainWindow1(Qw.QMainWindow): 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 @@ -1252,7 +1637,15 @@ class MainWindow1(Qw.QMainWindow): self.addMode = None self.deleteAddOptions() - def editFinalized(self): + def editAccepted(self, obj, objIndex): + self.undoRedoStack.add(self.createAction( + EditBezierChanges(obj, objIndex, + self.addMode.asyPathBackup, + self.addMode.asyPath + ) + )) + self.checkUndoRedoButtons() + self.addMode.forceFinalize() self.removeAddMode() self.fileChanged = True @@ -1260,7 +1653,10 @@ class MainWindow1(Qw.QMainWindow): def editRejected(self): self.addMode.resetObj() - self.editFinalized() + self.addMode.forceFinalize() + self.removeAddMode() + self.fileChanged = True + self.quickUpdate() def setupSelectEdit(self): """For Select-Edit mode. For now, if the object selected is a bezier curve, opens up a bezier editor""" @@ -1270,12 +1666,20 @@ class MainWindow1(Qw.QMainWindow): # bezier path self.addMode = xbi.InteractiveBezierEditor(self, obj, self.currAddOptions) self.addMode.objectUpdated.connect(self.objectUpdated) - self.addMode.editAccepted.connect(self.editFinalized) + self.addMode.editAccepted.connect(lambda: self.editAccepted(obj, maj)) self.addMode.editRejected.connect(self.editRejected) self.updateOptionWidget() self.currentModeStack[-1] = SelectionMode.selectEdit self.fileChanged = True + elif isinstance(obj, x2a.xasyText): + newText = self.setTextPrompt() + if newText: + self.drawObjects.remove(obj.generateDrawObjects(False)) + obj.label.setText(newText) + self.drawObjects.append(obj.generateDrawObjects(True)) + self.fileChanged = True else: + self.ui.statusbar.showMessage('Warning: Selected object cannot be edited') self.clearSelection() self.quickUpdate() @@ -1359,7 +1763,7 @@ class MainWindow1(Qw.QMainWindow): # but it's much more work... newCenter = self.magnification * newCenter self.panOffset = [-newCenter.x(), newCenter.y()] - + self.quickUpdate() def selectObject(self): @@ -1410,7 +1814,7 @@ class MainWindow1(Qw.QMainWindow): def getWindowCoordinates(self): # assert self.ui.imgLabel.underMouse() return self.mapFromGlobal(Qg.QCursor.pos()) - + def refreshCanvas(self): if self.mainCanvas.isActive(): self.mainCanvas.end() @@ -1430,16 +1834,20 @@ class MainWindow1(Qw.QMainWindow): self.coordLabel.setText('{0:.2f}, {1:.2f} '.format(nx, ny)) def quickUpdate(self): + # TODO: Some documentation here would be nice since this is one of the + # main functions that gets called everywhere. self.updateMouseCoordLabel() self.refreshCanvas() - self.preDraw(self.mainCanvas) + self.preDraw(self.mainCanvas) # coordinates/background self.quickDraw() self.mainCanvas.end() self.postDraw() self.updateScreen() + self.updateTitle() + def quickDraw(self): assert self.isReady() dpi = self.magnification * self.dpi @@ -1466,7 +1874,7 @@ class MainWindow1(Qw.QMainWindow): if self.pendingSelectedObjList: maj, minor = self.pendingSelectedObjList[self.pendingSelectedObjIndex] self.drawObjects[maj][minor].draw(canvas=self.mainCanvas, dpi=dpi) - # and apply the preview too... + # and apply the preview too... elif activeItem is not None: if self.useGlobalCoords: activeItem.draw(self.newTransform, canvas=self.mainCanvas, dpi=dpi) @@ -1474,6 +1882,17 @@ class MainWindow1(Qw.QMainWindow): activeItem.draw(self.newTransform, applyReverse=True, canvas=self.mainCanvas, dpi=dpi) activeItem = None + def updateTitle(self): + # TODO: Undo redo doesn't update appropriately. Have to find a fix for this. + title = '' + if self.fileName: + title += os.path.basename(self.fileName) + else: + title += "[Not Saved]" + if self.fileChanged: + title += ' *' + self.setWindowTitle(title) + def updateScreen(self): self.finalPixmap = Qg.QPixmap(self.canvSize) self.finalPixmap.setDevicePixelRatio(devicePixelRatio) @@ -1502,6 +1921,7 @@ class MainWindow1(Qw.QMainWindow): for x in np.arange(0, 2 * x_range + 1, majorGrid): # have to do # this in two stages... preCanvas.setPen(minorGridCol) + self.makePenCosmetic(preCanvas) for xMinor in range(1, minorGridCount + 1): xCoord = x + ((xMinor / (minorGridCount + 1)) * majorGrid) preCanvas.drawLine(Qc.QLine(xCoord, -9999, xCoord, 9999)) @@ -1509,17 +1929,20 @@ class MainWindow1(Qw.QMainWindow): for y in np.arange(0, 2 * y_range + 1, majorGrid): preCanvas.setPen(minorGridCol) + self.makePenCosmetic(preCanvas) 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) + self.makePenCosmetic(preCanvas) 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) + self.makePenCosmetic(preCanvas) preCanvas.drawLine(Qc.QLine(x, -9999, x, 9999)) preCanvas.drawLine(Qc.QLine(-x, -9999, -x, 9999)) @@ -1568,6 +1991,7 @@ class MainWindow1(Qw.QMainWindow): if self.drawAxes: preCanvas.setPen(Qc.Qt.gray) + self.makePenCosmetic(preCanvas) preCanvas.drawLine(Qc.QLine(-9999, 0, 9999, 0)) preCanvas.drawLine(Qc.QLine(0, -9999, 0, 9999)) @@ -1590,13 +2014,14 @@ class MainWindow1(Qw.QMainWindow): 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] + self.makePenCosmetic(painter) if not self.useGlobalCoords: painter.save() painter.setTransform( @@ -1621,13 +2046,14 @@ class MainWindow1(Qw.QMainWindow): with Qg.QPainter(self.postCanvasPixmap) as postCanvas: postCanvas.setRenderHints(self.mainCanvas.renderHints()) postCanvas.setTransform(self.getScrsTransform()) + # self.makePenCosmetic(postCanvas) 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: @@ -1657,11 +2083,29 @@ class MainWindow1(Qw.QMainWindow): activeBtn = self.ui.btnDeleteMode elif self.currentModeStack[-1] == SelectionMode.selectEdit: activeBtn = self.ui.btnSelectEdit + elif self.currentModeStack[-1] == SelectionMode.openPoly: + activeBtn = self.ui.btnOpenPoly + elif self.currentModeStack[-1] == SelectionMode.closedPoly: + activeBtn = self.ui.btnClosedPoly + elif self.currentModeStack[-1] == SelectionMode.openCurve: + activeBtn = self.ui.btnOpenCurve + elif self.currentModeStack[-1] == SelectionMode.closedCurve: + activeBtn = self.ui.btnClosedCurve + elif self.currentModeStack[-1] == SelectionMode.addPoly: + activeBtn = self.ui.btnAddPoly + elif self.currentModeStack[-1] == SelectionMode.addCircle: + activeBtn = self.ui.btnAddCircle + elif self.currentModeStack[-1] == SelectionMode.addLabel: + activeBtn = self.ui.btnAddLabel + elif self.currentModeStack[-1] == SelectionMode.addFreehand: + activeBtn = self.ui.btnAddFreehand else: activeBtn = None - + disableFill = isinstance(self.addMode, InplaceAddObj.AddBezierShape) and not self.currAddOptions['closedPath'] + if isinstance(self.addMode, xbi.InteractiveBezierEditor): + disableFill = disableFill or not (self.addMode.obj.path.nodeSet[-1] == "cycle") self.ui.btnFill.setEnabled(not disableFill) if disableFill and self.ui.btnFill.isEnabled(): self.ui.btnFill.setChecked(not disableFill) @@ -1670,22 +2114,36 @@ class MainWindow1(Qw.QMainWindow): for button in self.modeButtons: button.setChecked(button is activeBtn) + if activeBtn in [self.ui.btnDeleteMode,self.ui.btnSelectEdit]: + self.ui.btnAlignX.setEnabled(False) + self.ui.btnAlignY.setEnabled(False) + else: + self.ui.btnAlignX.setEnabled(True) + self.ui.btnAlignY.setEnabled(True) + + 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) + if self.currentModeStack[0] in [SelectionMode.selectEdit,SelectionMode.delete]: + self.ui.btnAlignX.setChecked(False) + else: + 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) + if self.currentModeStack[0] in [SelectionMode.selectEdit,SelectionMode.delete]: + self.ui.btnAlignY.setChecked(False) + else: + self.lockX = checked + if self.lockY: + self.lockY = False + self.ui.btnAlignX.setChecked(False) def btnAnchorModeOnClick(self): if self.currentModeStack[-1] != SelectionMode.setAnchor: @@ -1704,22 +2162,31 @@ class MainWindow1(Qw.QMainWindow): self.updateChecks() def btnRotateOnClick(self): - self.currentModeStack = [SelectionMode.rotate] - self.ui.statusbar.showMessage('Rotate mode') - self.clearSelection() - self.updateChecks() + if self.currentModeStack[-1] != SelectionMode.rotate: + self.currentModeStack = [SelectionMode.rotate] + self.ui.statusbar.showMessage('Rotate mode') + self.clearSelection() + self.updateChecks() + else: + self.btnTranslateonClick() def btnScaleOnClick(self): - self.currentModeStack = [SelectionMode.scale] - self.ui.statusbar.showMessage('Scale mode') - self.clearSelection() - self.updateChecks() + if self.currentModeStack[-1] != SelectionMode.scale: + self.currentModeStack = [SelectionMode.scale] + self.ui.statusbar.showMessage('Scale mode') + self.clearSelection() + self.updateChecks() + else: + self.btnTranslateonClick() def btnPanOnClick(self): - self.currentModeStack = [SelectionMode.pan] - self.ui.statusbar.showMessage('Pan mode') - self.clearSelection() - self.updateChecks() + if self.currentModeStack[-1] != SelectionMode.pan: + self.currentModeStack = [SelectionMode.pan] + self.ui.statusbar.showMessage('Pan mode') + self.clearSelection() + self.updateChecks() + else: + self.btnTranslateonClick() def btnWorldCoordsOnClick(self, checked): self.useGlobalCoords = checked @@ -1754,24 +2221,26 @@ class MainWindow1(Qw.QMainWindow): self.quickUpdate() def btnLoadEditorOnClick(self): + pathToFile = os.path.splitext(self.fileName)[0]+'.asy' if self.fileChanged: save = "Save current file?" reply = Qw.QMessageBox.question(self, 'Message', save, Qw.QMessageBox.Yes, Qw.QMessageBox.No) if reply == Qw.QMessageBox.Yes: - self.actionSave() - - subprocess.Popen(args=self.getExternalEditor(asypath=self.filename)); + self.actionExport(pathToFile) + + subprocess.run(args=self.getExternalEditor(asypath=pathToFile)); + self.loadFile(pathToFile) def btnAddCodeOnClick(self): header = """ -// xasy object created at $time +// xasy object created at $time // Object Number: $uid -// This header is automatically generated by xasy. +// 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') @@ -1791,6 +2260,7 @@ class MainWindow1(Qw.QMainWindow): self.asyfyCanvas() self.globalObjectCounter = self.globalObjectCounter + 1 + def softDeleteObj(self, objKey): maj, minor = objKey drawObj = self.drawObjects[maj][minor] @@ -1869,7 +2339,7 @@ class MainWindow1(Qw.QMainWindow): s = editor.split() rawExternalEditor = s[0] rawExtEditorArgs = s[1:]+["$asypath"] - + execEditor = [rawExternalEditor] for arg in rawExtEditorArgs: @@ -1881,34 +2351,37 @@ class MainWindow1(Qw.QMainWindow): def loadFile(self, name): filename = os.path.abspath(name) if not os.path.isfile(filename): - filename = filename + '.asy' + parts = os.path.splitext(filename) + if parts[1] == '': + filename = parts[0] + '.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.fileName = filename + self.asyFileName = filename + self.currDir = os.path.dirname(self.fileName) self.erase() - f = open(self.filename, 'rt') + 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) + rawText, transfDict = xf.extractTransformsFromFile(rawFileStr) item = x2a.xasyScript(canvas=self.xasyDrawObj, engine=self.asyEngine, transfKeyMap=transfDict) item.setScript(rawText) self.fileItems.append(item) - self.asyfyCanvas(True) + self.asyfyCanvas(force=True) - maxKey2 = item.getMaxKeyCounter() + self.globalObjectCounter = item.maxKey+1 self.asy2psmap = item.asy2psmap - self.globalObjectCounter = max(maxKey + 1, maxKey2) + finally: f.close() @@ -1916,3 +2389,37 @@ class MainWindow1(Qw.QMainWindow): self.itemCount = 0 for item in self.fileItems: self.drawObjects.append(item.generateDrawObjects(forceUpdate)) + + def makePenCosmetic(self, painter): + localPen = painter.pen() + localPen.setCosmetic(True) + painter.setPen(localPen) + + def copyItem(self): + self.selectOnHover() + if self.currentlySelectedObj['selectedIndex'] is not None: + maj, minor = self.currentlySelectedObj['selectedIndex'] + if isinstance(self.fileItems[maj],x2a.xasyShape) or isinstance(self.fileItems[maj],x2a.xasyText): + self.copiedObject = self.fileItems[maj].copy() + else: + self.ui.statusbar.showMessage('Copying not supported with current item type') + else: + self.ui.statusbar.showMessage('No object selected to copy') + self.copiedObject = None + self.clearSelection() + + def pasteItem(self): + if hasattr(self, 'copiedObject') and not self.copiedObject is None: + self.copiedObject = self.copiedObject.copy() + self.addInPlace(self.copiedObject) + mousePos = self.getWindowCoordinates() - self.copiedObject.path.toQPainterPath().boundingRect().center() - (Qc.QPointF(self.canvSize.width(), self.canvSize.height()) + Qc.QPointF(62, 201))/2 #I don't really know what that last constant is? Is it the size of the framing? + newTransform = Qg.QTransform.fromTranslate(mousePos.x(), mousePos.y()) + self.currentlySelectedObj['selectedIndex'] = (self.globalObjectCounter - 1,0) + self.currentlySelectedObj['key'], self.currentlySelectedObj['allSameKey'] = self.selectObjectSet() + newTransform = x2a.asyTransform.fromQTransform(newTransform) + objKey = self.currentlySelectedObj['selectedIndex'] + self.addTransformationChanges(objKey, newTransform, not self.useGlobalCoords) + self.transformObject(objKey, newTransform, not self.useGlobalCoords) + self.quickUpdate() + else: + self.ui.statusbar.showMessage('No object to paste') diff --git a/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson b/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson index c87f8c5b531..5f0c1abc17b 100644 --- a/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson +++ b/Build/source/utils/asymptote/GUI/configs/xasyconfig.cson @@ -45,6 +45,9 @@ gridMinorAxesColor: "#dddddd" gridMajorAxesSpacing: 5 gridMinorAxesCount: 9 +# Number of pixels per bp in 3D rendered bitmaps +renderDensity: 2 + # Magnification Settings minimumMagnification: 0.01 maximumMagnification: 100 diff --git a/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson b/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson index 1e3e3b0a11e..867c08db7d9 100644 --- a/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson +++ b/Build/source/utils/asymptote/GUI/configs/xasykeymap.cson @@ -23,4 +23,11 @@ scrollLeft: 'Shift+Left' scrollRight: 'Shift+Right' zoomIn: 'Ctrl+Up' -zoomOut: 'Ctrl+Down'
\ No newline at end of file +zoomOut: 'Ctrl+Down' + +open: 'Ctrl+O' +save: 'Ctrl+S' +export: 'Ctrl+E' + +copy: 'Ctrl+C' +paste: 'Ctrl+V' diff --git a/Build/source/utils/asymptote/GUI/icons_rc.py b/Build/source/utils/asymptote/GUI/icons_rc.py deleted file mode 100644 index e74ded8d750..00000000000 --- a/Build/source/utils/asymptote/GUI/icons_rc.py +++ /dev/null @@ -1,2721 +0,0 @@ -# -*- coding: utf-8 -*- - -# Resource object code -# -# Created by: The Resource Compiler for PyQt5 (Qt v5.12.5) -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore - -qt_resource_data = b"\ -\x00\x00\x04\xa2\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\ -\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\ -\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\ -\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\ -\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\ -\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\ -\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\ -\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\ -\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\x27\x20\x76\x69\x65\x77\ -\x42\x6f\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\ -\x38\x35\x38\x33\x20\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\ -\x39\x39\x39\x37\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\ -\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\ -\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\ -\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\ -\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x43\x20\x34\ -\x2e\x31\x35\x35\x35\x36\x20\x2d\x33\x39\x2e\x32\x37\x34\x35\x20\ -\x36\x2e\x39\x38\x34\x37\x33\x20\x2d\x34\x36\x2e\x31\x30\x34\x37\ -\x20\x31\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\ -\x39\x43\x20\x32\x37\x2e\x34\x34\x31\x31\x20\x2d\x36\x37\x2e\x37\ -\x32\x36\x39\x20\x35\x33\x2e\x33\x30\x32\x31\x20\x2d\x36\x31\x2e\ -\x35\x34\x30\x35\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\ -\x2e\x35\x30\x32\x32\x43\x20\x35\x37\x2e\x36\x32\x37\x20\x2d\x33\ -\x32\x2e\x36\x35\x31\x39\x20\x35\x30\x2e\x35\x38\x35\x36\x20\x2d\ -\x32\x33\x2e\x35\x36\x32\x31\x20\x34\x30\x2e\x36\x37\x39\x34\x20\ -\x2d\x32\x32\x2e\x35\x32\x38\x31\x27\x20\x66\x69\x6c\x6c\x3d\x27\ -\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\ -\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\ -\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\ -\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\ -\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\ -\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\ -\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\ -\x32\x2e\x35\x30\x39\x33\x37\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\ -\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\ -\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\ -\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\ -\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\ -\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x39\x35\x37\x33\ -\x35\x27\x20\x63\x79\x3d\x27\x2d\x33\x32\x2e\x31\x32\x27\x20\x66\ -\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\ -\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\ -\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\ -\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\ -\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\ -\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\ -\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x31\x31\x2e\x39\x30\x33\ -\x36\x27\x20\x63\x79\x3d\x27\x2d\x35\x31\x2e\x33\x30\x33\x39\x27\ -\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\ -\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\ -\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\ -\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\ -\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\ -\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\ -\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x35\x36\x2e\x31\ -\x35\x32\x33\x27\x20\x63\x79\x3d\x27\x2d\x34\x32\x2e\x35\x30\x32\ -\x32\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\ -\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\ -\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\ -\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\ -\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\ -\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\ -\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x34\x30\ -\x2e\x36\x37\x39\x34\x27\x20\x63\x79\x3d\x27\x2d\x32\x32\x2e\x35\ -\x32\x38\x31\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\ -\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\ -\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\ -\x3e\ -\x00\x00\x03\x0c\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x43\x68\x65\x63\x6b\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\x79\ -\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\ -\x78\x3d\x22\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\x65\x6e\ -\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\ -\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x32\x30\x20\x32\x30\x22\x20\ -\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\ -\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ -\x4d\x38\x2e\x32\x39\x34\x2c\x31\x36\x2e\x39\x39\x38\x63\x2d\x30\ -\x2e\x34\x33\x35\x2c\x30\x2d\x30\x2e\x38\x34\x37\x2d\x30\x2e\x32\ -\x30\x33\x2d\x31\x2e\x31\x31\x31\x2d\x30\x2e\x35\x35\x33\x4c\x33\ -\x2e\x36\x31\x2c\x31\x31\x2e\x37\x32\x34\x63\x2d\x30\x2e\x34\x36\ -\x35\x2d\x30\x2e\x36\x31\x33\x2d\x30\x2e\x33\x34\x34\x2d\x31\x2e\ -\x34\x38\x36\x2c\x30\x2e\x32\x37\x2d\x31\x2e\x39\x35\x31\x0d\x0a\ -\x09\x63\x30\x2e\x36\x31\x35\x2d\x30\x2e\x34\x36\x37\x2c\x31\x2e\ -\x34\x38\x38\x2d\x30\x2e\x33\x34\x34\x2c\x31\x2e\x39\x35\x33\x2c\ -\x30\x2e\x32\x37\x6c\x32\x2e\x33\x35\x31\x2c\x33\x2e\x31\x30\x34\ -\x6c\x35\x2e\x39\x31\x31\x2d\x39\x2e\x34\x39\x32\x63\x30\x2e\x34\ -\x30\x37\x2d\x30\x2e\x36\x35\x32\x2c\x31\x2e\x32\x36\x37\x2d\x30\ -\x2e\x38\x35\x32\x2c\x31\x2e\x39\x32\x31\x2d\x30\x2e\x34\x34\x35\ -\x0d\x0a\x09\x63\x30\x2e\x36\x35\x33\x2c\x30\x2e\x34\x30\x36\x2c\ -\x30\x2e\x38\x35\x34\x2c\x31\x2e\x32\x36\x36\x2c\x30\x2e\x34\x34\ -\x36\x2c\x31\x2e\x39\x32\x4c\x39\x2e\x34\x37\x38\x2c\x31\x36\x2e\ -\x33\x34\x63\x2d\x30\x2e\x32\x34\x32\x2c\x30\x2e\x33\x39\x31\x2d\ -\x30\x2e\x36\x36\x31\x2c\x30\x2e\x36\x33\x35\x2d\x31\x2e\x31\x32\ -\x2c\x30\x2e\x36\x35\x36\x43\x38\x2e\x33\x33\x36\x2c\x31\x36\x2e\ -\x39\x39\x38\x2c\x38\x2e\x33\x31\x36\x2c\x31\x36\x2e\x39\x39\x38\ -\x2c\x38\x2e\x32\x39\x34\x2c\x31\x36\x2e\x39\x39\x38\x7a\x22\x2f\ -\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x03\xc4\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4d\x61\x67\x6e\x69\x66\x79\x69\x6e\x67\x5f\x67\x6c\x61\ -\x73\x73\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ -\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x78\x6c\x69\ -\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\ -\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\x6c\x69\x6e\x6b\ -\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x79\x3d\x22\ -\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\ -\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\x6e\x61\x62\x6c\ -\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\x3d\x22\x6e\x65\ -\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x78\ -\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\ -\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x32\x34\x20\x30\x20\ -\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\x3e\x0d\x0a\x3c\x70\x61\ -\x74\x68\x20\x64\x3d\x22\x4d\x31\x37\x2e\x35\x34\x35\x2c\x31\x35\ -\x2e\x34\x36\x37\x6c\x2d\x33\x2e\x37\x37\x39\x2d\x33\x2e\x37\x37\ -\x39\x63\x30\x2e\x35\x37\x2d\x30\x2e\x39\x33\x35\x2c\x30\x2e\x38\ -\x39\x38\x2d\x32\x2e\x30\x33\x35\x2c\x30\x2e\x38\x39\x38\x2d\x33\ -\x2e\x32\x31\x63\x30\x2d\x33\x2e\x34\x31\x37\x2d\x32\x2e\x39\x36\ -\x31\x2d\x36\x2e\x33\x37\x37\x2d\x36\x2e\x33\x37\x38\x2d\x36\x2e\ -\x33\x37\x37\x0d\x0a\x09\x43\x34\x2e\x38\x36\x39\x2c\x32\x2e\x31\ -\x2c\x32\x2e\x31\x2c\x34\x2e\x38\x37\x2c\x32\x2e\x31\x2c\x38\x2e\ -\x32\x38\x37\x63\x30\x2c\x33\x2e\x34\x31\x36\x2c\x32\x2e\x39\x36\ -\x31\x2c\x36\x2e\x33\x37\x37\x2c\x36\x2e\x33\x37\x37\x2c\x36\x2e\ -\x33\x37\x37\x63\x31\x2e\x31\x33\x37\x2c\x30\x2c\x32\x2e\x32\x2d\ -\x30\x2e\x33\x30\x39\x2c\x33\x2e\x31\x31\x35\x2d\x30\x2e\x38\x34\ -\x34\x6c\x33\x2e\x37\x39\x39\x2c\x33\x2e\x38\x30\x31\x0d\x0a\x09\ -\x63\x30\x2e\x33\x37\x32\x2c\x30\x2e\x33\x37\x31\x2c\x30\x2e\x39\ -\x37\x35\x2c\x30\x2e\x33\x37\x31\x2c\x31\x2e\x33\x34\x36\x2c\x30\ -\x6c\x30\x2e\x39\x34\x33\x2d\x30\x2e\x39\x34\x33\x43\x31\x38\x2e\ -\x30\x35\x31\x2c\x31\x36\x2e\x33\x30\x37\x2c\x31\x37\x2e\x39\x31\ -\x36\x2c\x31\x35\x2e\x38\x33\x38\x2c\x31\x37\x2e\x35\x34\x35\x2c\ -\x31\x35\x2e\x34\x36\x37\x7a\x20\x4d\x34\x2e\x30\x30\x34\x2c\x38\ -\x2e\x32\x38\x37\x0d\x0a\x09\x63\x30\x2d\x32\x2e\x33\x36\x36\x2c\ -\x31\x2e\x39\x31\x37\x2d\x34\x2e\x32\x38\x33\x2c\x34\x2e\x32\x38\ -\x32\x2d\x34\x2e\x32\x38\x33\x63\x32\x2e\x33\x36\x36\x2c\x30\x2c\ -\x34\x2e\x34\x37\x34\x2c\x32\x2e\x31\x30\x37\x2c\x34\x2e\x34\x37\ -\x34\x2c\x34\x2e\x34\x37\x34\x63\x30\x2c\x32\x2e\x33\x36\x35\x2d\ -\x31\x2e\x39\x31\x38\x2c\x34\x2e\x32\x38\x33\x2d\x34\x2e\x32\x38\ -\x33\x2c\x34\x2e\x32\x38\x33\x0d\x0a\x09\x43\x36\x2e\x31\x31\x31\ -\x2c\x31\x32\x2e\x37\x36\x2c\x34\x2e\x30\x30\x34\x2c\x31\x30\x2e\ -\x36\x35\x32\x2c\x34\x2e\x30\x30\x34\x2c\x38\x2e\x32\x38\x37\x7a\ -\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\ -\x3e\x0d\x0a\ -\x00\x00\x01\x69\ -\x3c\ -\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ -\x30\x2f\x73\x76\x67\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x35\x31\ -\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x35\x31\x32\ -\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\ -\x20\x35\x31\x32\x20\x35\x31\x32\x22\x3e\x3c\x67\x20\x74\x72\x61\ -\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x32\ -\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\x3e\x3c\ -\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x2e\x33\x34\x20\x31\x35\ -\x2e\x36\x36\x41\x37\x2e\x39\x37\x20\x37\x2e\x39\x37\x20\x30\x20\ -\x30\x20\x30\x20\x39\x20\x31\x37\x2e\x39\x34\x56\x31\x30\x48\x35\ -\x56\x38\x68\x34\x56\x35\x2e\x38\x33\x61\x33\x20\x33\x20\x30\x20\ -\x31\x20\x31\x20\x32\x20\x30\x56\x38\x68\x34\x76\x32\x68\x2d\x34\ -\x76\x37\x2e\x39\x34\x61\x37\x2e\x39\x37\x20\x37\x2e\x39\x37\x20\ -\x30\x20\x30\x20\x30\x20\x34\x2e\x36\x36\x2d\x32\x2e\x32\x38\x6c\ -\x2d\x31\x2e\x34\x32\x2d\x31\x2e\x34\x32\x68\x35\x2e\x36\x36\x6c\ -\x2d\x32\x2e\x38\x33\x20\x32\x2e\x38\x33\x61\x31\x30\x20\x31\x30\ -\x20\x30\x20\x30\x20\x31\x2d\x31\x34\x2e\x31\x34\x20\x30\x4c\x2e\ -\x31\x20\x31\x34\x2e\x32\x34\x68\x35\x2e\x36\x36\x6c\x2d\x31\x2e\ -\x34\x32\x20\x31\x2e\x34\x32\x7a\x4d\x31\x30\x20\x34\x61\x31\x20\ -\x31\x20\x30\x20\x31\x20\x30\x20\x30\x2d\x32\x20\x31\x20\x31\x20\ -\x30\x20\x30\x20\x30\x20\x30\x20\x32\x7a\x22\x2f\x3e\x3c\x2f\x67\ -\x3e\x3c\x2f\x73\x76\x67\x3e\x0a\ -\x00\x00\x03\x7c\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\ -\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\ -\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\ -\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\ -\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\ -\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\ -\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\ -\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\ -\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\x27\x20\x76\x69\x65\x77\ -\x42\x6f\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\ -\x38\x35\x38\x33\x20\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\ -\x39\x39\x39\x37\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\ -\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\ -\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\ -\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x32\ -\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\x36\ -\x32\x2e\x32\x33\x32\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\ -\x36\x32\x2e\x32\x33\x32\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\x35\ -\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\ -\x35\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\ -\x35\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\ -\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\ -\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\ -\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ -\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\ -\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\ -\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\ -\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x34\x2e\x30\x31\x35\x27\ -\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\ -\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\ -\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\ -\x36\x34\x20\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\ -\x35\x38\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\ -\x20\x34\x37\x2e\x31\x37\x36\x32\x20\x2d\x33\x32\x2e\x31\x32\x43\ -\x20\x34\x37\x2e\x31\x37\x36\x32\x20\x2d\x34\x30\x2e\x34\x33\x35\ -\x33\x20\x34\x30\x2e\x34\x33\x35\x33\x20\x2d\x34\x37\x2e\x31\x37\ -\x36\x32\x20\x33\x32\x2e\x31\x32\x20\x2d\x34\x37\x2e\x31\x37\x36\ -\x32\x43\x20\x32\x33\x2e\x38\x30\x34\x37\x20\x2d\x34\x37\x2e\x31\ -\x37\x36\x32\x20\x31\x37\x2e\x30\x36\x33\x37\x20\x2d\x34\x30\x2e\ -\x34\x33\x35\x33\x20\x31\x37\x2e\x30\x36\x33\x37\x20\x2d\x33\x32\ -\x2e\x31\x32\x43\x20\x31\x37\x2e\x30\x36\x33\x37\x20\x2d\x32\x33\ -\x2e\x38\x30\x34\x37\x20\x32\x33\x2e\x38\x30\x34\x37\x20\x2d\x31\ -\x37\x2e\x30\x36\x33\x37\x20\x33\x32\x2e\x31\x32\x20\x2d\x31\x37\ -\x2e\x30\x36\x33\x37\x43\x20\x34\x30\x2e\x34\x33\x35\x33\x20\x2d\ -\x31\x37\x2e\x30\x36\x33\x37\x20\x34\x37\x2e\x31\x37\x36\x32\x20\ -\x2d\x32\x33\x2e\x38\x30\x34\x37\x20\x34\x37\x2e\x31\x37\x36\x32\ -\x20\x2d\x33\x32\x2e\x31\x32\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\ -\x23\x30\x30\x30\x30\x30\x30\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\ -\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\ -\x00\x00\x02\x21\ -\x00\ -\x00\x07\xaf\x78\x9c\xdd\x55\x4d\x6f\x9c\x30\x10\xbd\xf7\x57\x4c\ -\xd5\x83\xdb\x03\xc6\xdf\x86\x28\x24\x52\x57\xea\x29\xbd\x25\x97\ -\xde\x68\xf0\x82\x9b\x5d\x58\x01\x5d\xb6\xff\xbe\x66\xd7\x60\x4a\ -\xaa\xf4\x92\x43\x15\x90\x30\xf3\x18\xbf\x99\xe7\xf1\x98\xeb\xdb\ -\xd3\x7e\x07\x47\xd3\x76\xb6\xa9\x33\x44\x31\x41\x60\xea\xc7\xa6\ -\xb0\x75\x99\xa1\x87\xfb\x2f\x51\x82\x6e\x6f\xde\x5d\xbf\x8f\x22\ -\xb8\xaf\x6c\x07\x5b\xbb\x33\x30\xe4\x1d\x94\xa6\x36\x6d\xde\x9b\ -\x02\xbe\xff\x82\xe2\x68\xbb\x63\xb9\x07\x86\x13\x88\x22\xe7\xef\ -\xac\x25\x2b\x45\xe0\xe2\xd4\x5d\x86\xaa\xbe\x3f\x5c\xc5\xf1\x30\ -\x0c\x78\xe0\xb8\x69\xcb\x98\x11\x42\x62\xe7\xef\x5d\xae\x4e\x3b\ -\x5b\x3f\xfd\xcd\x91\xa6\x69\x1a\x9f\xbf\x22\x18\x6c\xd1\x57\x19\ -\x52\x1c\x3b\x50\x1d\x7a\x04\x95\xb1\x65\xd5\x4f\x90\x1e\xa1\xa3\ -\x35\xc3\xe7\xe6\x94\x21\xa9\xb0\x20\xa9\x00\xc9\x71\x22\x13\x0e\ -\x7e\x9a\x1f\x35\x72\x09\x97\x60\x8b\x0c\x1d\xf2\xd2\xd0\x8b\xd9\ -\xb7\x79\xdd\x6d\x9b\x76\x9f\xa1\x7d\xde\xb7\xf6\xf4\x91\x38\x67\ -\xc5\x94\x00\x32\xde\x93\x31\x71\x53\xaa\x47\xf2\x4f\xe3\xec\x43\ -\xde\x57\xe0\xe8\xbe\x42\x8a\xb9\xd0\x82\x41\xc4\x38\x26\x94\xde\ -\x05\xc0\xbf\x3c\x47\x36\xcf\x90\x7f\x03\x8b\x39\x12\x53\x29\x29\ -\x05\x9a\x62\x29\x38\x85\x88\x62\x2d\x95\x54\xc0\x19\xa6\x6c\x36\ -\x37\x20\x04\x56\xa9\x4a\x83\x83\x14\x38\x49\x99\x0a\x14\x33\x30\ -\xe7\xfa\x02\x32\x09\x9c\x01\xae\xb0\xd2\x42\x6e\x02\x22\x08\x4e\ -\x94\x4a\x42\x64\xf7\xc2\x94\x14\x53\x6a\xde\xdc\x84\xdc\x27\x87\ -\x59\xdd\x44\x31\x03\x3e\xca\xdd\x7a\xa5\xbf\xa1\x71\xab\xee\x32\ -\xf4\x41\x6f\xc7\x1b\xc5\xae\x2e\x71\xf9\x8a\xa5\x0d\x42\x53\xac\ -\x29\x49\x97\x42\xdd\xbe\x22\x9c\x2d\x84\x6a\xcc\x09\xd5\xb3\xd0\ -\x8b\xb9\x14\xea\x1d\x82\x50\x4f\x11\x84\x4e\x51\x02\x22\xb1\xa4\ -\x89\x0c\x24\x17\x76\x1f\xe3\x3c\x2c\xaa\x7c\x81\x43\xd2\x7e\xf2\ -\x5a\xc5\xbc\x6e\x75\x53\x1b\x04\x5d\xdf\x36\x4f\xc6\xad\x22\x39\ -\x5f\x13\x10\xb9\x2e\x34\x8f\xf9\x21\x43\x6d\xf3\xb3\x2e\xfe\x80\ -\x7f\x34\xb6\x5e\xe3\x7b\xdb\x9b\x76\x67\xdd\xe0\x4e\x03\x82\x09\ -\xd7\x72\xfe\xe6\x5b\x99\xbb\x7c\x38\x65\xaf\x5f\xa7\xf5\x0a\xbe\ -\xe1\x1e\xf4\x0a\xdf\x5c\x09\x5f\x68\x35\xc9\x30\x4b\xf4\xe2\x4c\ -\x51\x0c\x8b\x84\xcf\x67\x8a\x37\x17\xad\x36\x39\x84\x6a\x79\x8a\ -\xf5\x46\xf9\x6f\x96\xf1\xf2\x70\xbf\xc8\x9b\xdf\xf9\x80\xe2\xe1\ -\ -\x00\x00\x04\x1c\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\ -\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\ -\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\ -\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\ -\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\ -\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\ -\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\ -\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\ -\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\x27\x20\x76\x69\x65\x77\ -\x42\x6f\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\ -\x38\x35\x38\x33\x20\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\ -\x39\x39\x39\x37\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\ -\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\ -\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\ -\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x32\ -\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\x36\ -\x32\x2e\x32\x33\x32\x35\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\ -\x36\x32\x2e\x32\x33\x32\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\x35\ -\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x36\x32\x2e\x32\x33\x32\ -\x35\x4c\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x32\x2e\x30\x30\x37\ -\x35\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\ -\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\ -\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\ -\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ -\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\ -\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\ -\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\ -\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x34\x2e\x30\x31\x35\x27\ -\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\ -\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\ -\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\ -\x36\x34\x20\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\ -\x35\x38\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\ -\x20\x32\x2e\x30\x30\x37\x35\x20\x2d\x33\x32\x2e\x31\x32\x4c\x20\ -\x36\x32\x2e\x32\x33\x32\x35\x20\x2d\x33\x32\x2e\x31\x32\x27\x20\ -\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\ -\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\ -\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\ -\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\ -\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\ -\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\ -\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\ -\x69\x64\x74\x68\x3d\x27\x34\x2e\x30\x31\x35\x27\x2f\x3e\x0a\x3c\ -\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\ -\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\ -\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\ -\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\ -\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\x32\x2e\ -\x31\x32\x20\x2d\x32\x2e\x30\x30\x37\x35\x4c\x20\x33\x32\x2e\x31\ -\x32\x20\x2d\x36\x32\x2e\x32\x33\x32\x35\x27\x20\x66\x69\x6c\x6c\ -\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\ -\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\ -\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\ -\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\ -\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\ -\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\ -\x3d\x27\x34\x2e\x30\x31\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\ -\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\ -\x00\x00\x02\xa1\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x53\x61\x76\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\ -\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\ -\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ -\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\ -\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x35\x31\x32\x70\x78\x22\x20\ -\x79\x3d\x22\x35\x31\x32\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\ -\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\ -\x32\x22\x20\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\ -\x6f\x75\x6e\x64\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\ -\x32\x20\x35\x31\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\ -\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\ -\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\ -\x69\x78\x28\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\ -\x29\x27\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\ -\x35\x2e\x31\x37\x33\x2c\x32\x48\x34\x43\x32\x2e\x38\x39\x39\x2c\ -\x32\x2c\x32\x2c\x32\x2e\x39\x2c\x32\x2c\x34\x76\x31\x32\x63\x30\ -\x2c\x31\x2e\x31\x2c\x30\x2e\x38\x39\x39\x2c\x32\x2c\x32\x2c\x32\ -\x68\x31\x32\x63\x31\x2e\x31\x30\x31\x2c\x30\x2c\x32\x2d\x30\x2e\ -\x39\x2c\x32\x2d\x32\x56\x35\x2e\x31\x32\x37\x4c\x31\x35\x2e\x31\ -\x37\x33\x2c\x32\x7a\x20\x4d\x31\x34\x2c\x38\x63\x30\x2c\x30\x2e\ -\x35\x34\x39\x2d\x30\x2e\x34\x35\x2c\x31\x2d\x31\x2c\x31\x48\x37\ -\x0d\x0a\x09\x43\x36\x2e\x34\x35\x2c\x39\x2c\x36\x2c\x38\x2e\x35\ -\x34\x39\x2c\x36\x2c\x38\x56\x33\x68\x38\x56\x38\x7a\x20\x4d\x31\ -\x33\x2c\x34\x68\x2d\x32\x76\x34\x68\x32\x56\x34\x7a\x22\x2f\x3e\ -\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\ -\x00\x00\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\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\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\xf5\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x43\x68\x65\x76\x72\x6f\x6e\x5f\x63\x69\x72\x63\x6c\x65\ -\x64\x5f\x6c\x65\x66\x74\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\ -\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\ -\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ -\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\ -\x6c\x69\x6e\x6b\x22\x0d\x0a\x09\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\ -\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ -\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\ -\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\ -\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x74\x72\x61\ -\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x32\ -\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\x3e\x0d\ -\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x31\x2e\x33\x30\ -\x32\x2c\x36\x2e\x37\x37\x36\x63\x2d\x30\x2e\x31\x39\x36\x2d\x30\ -\x2e\x31\x39\x37\x2d\x30\x2e\x35\x31\x35\x2d\x30\x2e\x31\x39\x37\ -\x2d\x30\x2e\x37\x31\x2c\x30\x4c\x37\x2e\x37\x38\x35\x2c\x39\x2e\ -\x36\x34\x31\x63\x2d\x30\x2e\x31\x39\x36\x2c\x30\x2e\x31\x39\x39\ -\x2d\x30\x2e\x31\x39\x36\x2c\x30\x2e\x35\x32\x2c\x30\x2c\x30\x2e\ -\x37\x31\x37\x6c\x32\x2e\x38\x30\x37\x2c\x32\x2e\x38\x36\x34\x0d\ -\x0a\x09\x63\x30\x2e\x31\x39\x35\x2c\x30\x2e\x31\x39\x39\x2c\x30\ -\x2e\x35\x31\x34\x2c\x30\x2e\x31\x39\x38\x2c\x30\x2e\x37\x31\x2c\ -\x30\x63\x30\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2c\x30\x2e\ -\x31\x39\x36\x2d\x30\x2e\x35\x31\x38\x2c\x30\x2d\x30\x2e\x37\x31\ -\x37\x4c\x39\x2c\x31\x30\x6c\x32\x2e\x33\x30\x32\x2d\x32\x2e\x35\ -\x30\x36\x43\x31\x31\x2e\x34\x39\x38\x2c\x37\x2e\x32\x39\x36\x2c\ -\x31\x31\x2e\x34\x39\x38\x2c\x36\x2e\x39\x37\x36\x2c\x31\x31\x2e\ -\x33\x30\x32\x2c\x36\x2e\x37\x37\x36\x7a\x0d\x0a\x09\x20\x4d\x31\ -\x30\x2c\x30\x2e\x34\x63\x2d\x35\x2e\x33\x30\x32\x2c\x30\x2d\x39\ -\x2e\x36\x2c\x34\x2e\x32\x39\x38\x2d\x39\x2e\x36\x2c\x39\x2e\x36\ -\x63\x30\x2c\x35\x2e\x33\x30\x33\x2c\x34\x2e\x32\x39\x38\x2c\x39\ -\x2e\x36\x2c\x39\x2e\x36\x2c\x39\x2e\x36\x73\x39\x2e\x36\x2d\x34\ -\x2e\x32\x39\x37\x2c\x39\x2e\x36\x2d\x39\x2e\x36\x43\x31\x39\x2e\ -\x36\x2c\x34\x2e\x36\x39\x38\x2c\x31\x35\x2e\x33\x30\x32\x2c\x30\ -\x2e\x34\x2c\x31\x30\x2c\x30\x2e\x34\x7a\x20\x4d\x31\x30\x2c\x31\ -\x38\x2e\x33\x35\x34\x0d\x0a\x09\x63\x2d\x34\x2e\x36\x31\x35\x2c\ -\x30\x2d\x38\x2e\x33\x35\x34\x2d\x33\x2e\x37\x34\x2d\x38\x2e\x33\ -\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x30\x2d\x34\x2e\x36\x31\x34\ -\x2c\x33\x2e\x37\x33\x39\x2d\x38\x2e\x33\x35\x34\x2c\x38\x2e\x33\ -\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x34\x2e\x36\x31\x33\x2c\x30\ -\x2c\x38\x2e\x33\x35\x34\x2c\x33\x2e\x37\x34\x2c\x38\x2e\x33\x35\ -\x34\x2c\x38\x2e\x33\x35\x34\x0d\x0a\x09\x43\x31\x38\x2e\x33\x35\ -\x34\x2c\x31\x34\x2e\x36\x31\x34\x2c\x31\x34\x2e\x36\x31\x33\x2c\ -\x31\x38\x2e\x33\x35\x34\x2c\x31\x30\x2c\x31\x38\x2e\x33\x35\x34\ -\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\ -\x67\x3e\x0d\x0a\ -\x00\x00\x02\xb7\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\ -\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\ -\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\ -\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\ -\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ -\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\ -\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\ -\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\ -\x22\x49\x63\x6f\x6e\x5f\x35\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\ -\x0d\x0a\x09\x09\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\ -\x6e\x74\x73\x3d\x22\x34\x30\x35\x2c\x31\x33\x36\x2e\x37\x39\x38\ -\x20\x33\x37\x35\x2e\x32\x30\x32\x2c\x31\x30\x37\x20\x32\x35\x36\ -\x2c\x32\x32\x36\x2e\x32\x30\x32\x20\x31\x33\x36\x2e\x37\x39\x38\ -\x2c\x31\x30\x37\x20\x31\x30\x37\x2c\x31\x33\x36\x2e\x37\x39\x38\ -\x20\x32\x32\x36\x2e\x32\x30\x32\x2c\x32\x35\x36\x20\x31\x30\x37\ -\x2c\x33\x37\x35\x2e\x32\x30\x32\x20\x31\x33\x36\x2e\x37\x39\x38\ -\x2c\x34\x30\x35\x20\x32\x35\x36\x2c\x32\x38\x35\x2e\x37\x39\x38\ -\x20\x0d\x0a\x09\x09\x09\x33\x37\x35\x2e\x32\x30\x32\x2c\x34\x30\ -\x35\x20\x34\x30\x35\x2c\x33\x37\x35\x2e\x32\x30\x32\x20\x32\x38\ -\x35\x2e\x37\x39\x38\x2c\x32\x35\x36\x20\x09\x09\x22\x2f\x3e\x0d\ -\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\ -\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x04\xca\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\x72\ -\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\x75\ -\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x39\x2e\x32\x2e\x31\x2c\x20\ -\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\x2d\ -\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\x6e\ -\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\x20\ -\x20\x2d\x2d\x3e\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\x20\x73\ -\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\x57\x33\ -\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\x2f\x2f\ -\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\ -\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\x73\x2f\ -\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\x67\x31\ -\x31\x2e\x64\x74\x64\x22\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\ -\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x0a\x09\x20\x69\x64\x3d\ -\x22\x73\x76\x67\x34\x36\x31\x39\x22\x20\x69\x6e\x6b\x73\x63\x61\ -\x70\x65\x3a\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x30\x2e\x39\x31\ -\x2b\x64\x65\x76\x65\x6c\x2b\x6f\x73\x78\x6d\x65\x6e\x75\x20\x72\ -\x31\x32\x39\x31\x31\x22\x20\x73\x6f\x64\x69\x70\x6f\x64\x69\x3a\ -\x64\x6f\x63\x6e\x61\x6d\x65\x3d\x22\x74\x72\x69\x61\x6e\x67\x6c\ -\x65\x2d\x73\x74\x72\x6f\x6b\x65\x64\x2d\x31\x35\x2e\x73\x76\x67\ -\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x63\x63\x3d\x22\x68\x74\x74\x70\ -\x3a\x2f\x2f\x63\x72\x65\x61\x74\x69\x76\x65\x63\x6f\x6d\x6d\x6f\ -\x6e\x73\x2e\x6f\x72\x67\x2f\x6e\x73\x23\x22\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x64\x63\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x70\x75\x72\ -\x6c\x2e\x6f\x72\x67\x2f\x64\x63\x2f\x65\x6c\x65\x6d\x65\x6e\x74\ -\x73\x2f\x31\x2e\x31\x2f\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x69\x6e\ -\x6b\x73\x63\x61\x70\x65\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ -\x77\x77\x2e\x69\x6e\x6b\x73\x63\x61\x70\x65\x2e\x6f\x72\x67\x2f\ -\x6e\x61\x6d\x65\x73\x70\x61\x63\x65\x73\x2f\x69\x6e\x6b\x73\x63\ -\x61\x70\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3a\x72\x64\x66\x3d\x22\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x31\x39\x39\x39\x2f\x30\x32\x2f\x32\x32\x2d\x72\x64\x66\ -\x2d\x73\x79\x6e\x74\x61\x78\x2d\x6e\x73\x23\x22\x20\x78\x6d\x6c\ -\x6e\x73\x3a\x73\x6f\x64\x69\x70\x6f\x64\x69\x3d\x22\x68\x74\x74\ -\x70\x3a\x2f\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2e\x73\x6f\x75\ -\x72\x63\x65\x66\x6f\x72\x67\x65\x2e\x6e\x65\x74\x2f\x44\x54\x44\ -\x2f\x73\x6f\x64\x69\x70\x6f\x64\x69\x2d\x30\x2e\x64\x74\x64\x22\ -\x20\x78\x6d\x6c\x6e\x73\x3a\x73\x76\x67\x3d\x22\x68\x74\x74\x70\ -\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\ -\x30\x30\x2f\x73\x76\x67\x22\x0a\x09\x20\x78\x6d\x6c\x6e\x73\x3d\ -\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ -\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\ -\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\ -\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\ -\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\x20\ -\x79\x3d\x22\x30\x70\x78\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x36\ -\x34\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x36\x34\x70\ -\x78\x22\x0a\x09\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\ -\x30\x20\x31\x35\x20\x31\x35\x22\x20\x73\x74\x79\x6c\x65\x3d\x22\ -\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ -\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\x31\x35\x20\x31\x35\x3b\ -\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\x65\ -\x73\x65\x72\x76\x65\x22\x3e\x0a\x3c\x70\x61\x74\x68\x20\x69\x64\ -\x3d\x22\x72\x65\x63\x74\x33\x33\x33\x38\x22\x20\x69\x6e\x6b\x73\ -\x63\x61\x70\x65\x3a\x63\x6f\x6e\x6e\x65\x63\x74\x6f\x72\x2d\x63\ -\x75\x72\x76\x61\x74\x75\x72\x65\x3d\x22\x30\x22\x20\x73\x6f\x64\ -\x69\x70\x6f\x64\x69\x3a\x6e\x6f\x64\x65\x74\x79\x70\x65\x73\x3d\ -\x22\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x63\x22\x20\x64\ -\x3d\x22\x4d\x37\x2e\x35\x32\x34\x33\x2c\x31\x2e\x35\x30\x30\x34\ -\x0a\x09\x43\x37\x2e\x32\x34\x32\x39\x2c\x31\x2e\x34\x39\x31\x33\ -\x2c\x36\x2e\x39\x37\x38\x37\x2c\x31\x2e\x36\x34\x32\x33\x2c\x36\ -\x2e\x38\x33\x33\x36\x2c\x31\x2e\x38\x39\x35\x32\x6c\x2d\x35\x2e\ -\x35\x2c\x39\x2e\x38\x36\x39\x32\x43\x31\x2e\x30\x32\x31\x38\x2c\ -\x31\x32\x2e\x33\x30\x37\x38\x2c\x31\x2e\x33\x39\x35\x2c\x31\x32\ -\x2e\x39\x39\x39\x39\x2c\x32\x2c\x31\x33\x68\x31\x31\x0a\x09\x63\ -\x30\x2e\x36\x30\x35\x2d\x30\x2e\x30\x30\x30\x31\x2c\x30\x2e\x39\ -\x37\x38\x32\x2d\x30\x2e\x36\x39\x32\x32\x2c\x30\x2e\x36\x36\x36\ -\x34\x2d\x31\x2e\x32\x33\x35\x35\x6c\x2d\x35\x2e\x35\x2d\x39\x2e\ -\x38\x36\x39\x32\x43\x38\x2e\x30\x33\x30\x32\x2c\x31\x2e\x36\x35\ -\x37\x39\x2c\x37\x2e\x37\x38\x38\x34\x2c\x31\x2e\x35\x30\x39\x32\ -\x2c\x37\x2e\x35\x32\x34\x33\x2c\x31\x2e\x35\x30\x30\x34\x7a\x20\ -\x4d\x37\x2e\x35\x2c\x33\x2e\x38\x39\x39\x33\x6c\x34\x2e\x31\x32\ -\x36\x37\x2c\x37\x2e\x34\x37\x30\x34\x0a\x09\x48\x33\x2e\x33\x37\ -\x33\x33\x4c\x37\x2e\x35\x2c\x33\x2e\x38\x39\x39\x33\x7a\x22\x2f\ -\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ -\x00\x00\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\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\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\x05\xd4\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\ -\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\ -\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\ -\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\ -\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\ -\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\ -\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\ -\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\ -\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\x27\x20\x76\x69\x65\x77\ -\x42\x6f\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\ -\x38\x35\x38\x33\x20\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\ -\x39\x39\x39\x37\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\ -\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\ -\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x35\x36\x2e\x34\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\ -\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x35\ -\x34\x2e\x38\x39\x32\x36\x20\x2d\x33\x39\x2e\x37\x31\x30\x39\x43\ -\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x34\x33\x2e\x39\x30\x33\ -\x32\x20\x34\x34\x2e\x36\x39\x36\x39\x20\x2d\x34\x37\x2e\x33\x30\ -\x31\x37\x20\x33\x32\x2e\x31\x32\x20\x2d\x34\x37\x2e\x33\x30\x31\ -\x37\x43\x20\x31\x39\x2e\x35\x34\x33\x31\x20\x2d\x34\x37\x2e\x33\ -\x30\x31\x37\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x34\x33\x2e\ -\x39\x30\x33\x32\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x33\x39\ -\x2e\x37\x31\x30\x39\x43\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\ -\x33\x35\x2e\x35\x31\x38\x35\x20\x31\x39\x2e\x35\x34\x33\x31\x20\ -\x2d\x33\x32\x2e\x31\x32\x20\x33\x32\x2e\x31\x32\x20\x2d\x33\x32\ -\x2e\x31\x32\x43\x20\x34\x34\x2e\x36\x39\x36\x39\x20\x2d\x33\x32\ -\x2e\x31\x32\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x33\x35\x2e\ -\x35\x31\x38\x35\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x33\x39\ -\x2e\x37\x31\x30\x39\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\ -\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\ -\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\ -\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\ -\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\ -\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\ -\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\ -\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x33\x2e\ -\x35\x31\x33\x31\x32\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\ -\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\ -\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\ -\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x36\x2e\x34\x30\x39\x34\ -\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x70\x61\x74\ -\x68\x20\x64\x3d\x27\x4d\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\ -\x33\x39\x2e\x37\x31\x30\x39\x4c\x20\x39\x2e\x33\x34\x37\x34\x32\ -\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x4c\x20\x39\x2e\x33\x34\x37\ -\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x43\x20\x39\x2e\x33\ -\x34\x37\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x20\x39\x2e\ -\x33\x34\x37\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x20\x39\ -\x2e\x33\x34\x37\x34\x32\x20\x2d\x39\x2e\x33\x34\x37\x34\x32\x43\ -\x20\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x35\x2e\x31\x35\x35\x31\ -\x31\x20\x31\x39\x2e\x35\x34\x33\x31\x20\x2d\x31\x2e\x37\x35\x36\ -\x35\x36\x20\x33\x32\x2e\x31\x32\x20\x2d\x31\x2e\x37\x35\x36\x35\ -\x36\x43\x20\x34\x34\x2e\x36\x39\x36\x39\x20\x2d\x31\x2e\x37\x35\ -\x36\x35\x36\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x35\x2e\x31\ -\x35\x35\x31\x31\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\x39\x2e\ -\x33\x34\x37\x34\x32\x4c\x20\x35\x34\x2e\x38\x39\x32\x36\x20\x2d\ -\x39\x2e\x33\x34\x37\x34\x32\x4c\x20\x35\x34\x2e\x38\x39\x32\x36\ -\x20\x2d\x33\x39\x2e\x37\x31\x30\x39\x27\x20\x66\x69\x6c\x6c\x3d\ -\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\ -\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\ -\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\ -\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\ -\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\ -\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\ -\x27\x33\x2e\x35\x31\x33\x31\x32\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\ -\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\ -\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\ -\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x36\x2e\x34\ -\x30\x39\x34\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\ -\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x35\x34\x2e\x38\x39\x32\ -\x36\x20\x2d\x33\x39\x2e\x37\x31\x30\x39\x43\x20\x35\x34\x2e\x38\ -\x39\x32\x36\x20\x2d\x35\x32\x2e\x32\x38\x37\x38\x20\x34\x34\x2e\ -\x36\x39\x36\x39\x20\x2d\x36\x32\x2e\x34\x38\x33\x34\x20\x33\x32\ -\x2e\x31\x32\x20\x2d\x36\x32\x2e\x34\x38\x33\x34\x43\x20\x31\x39\ -\x2e\x35\x34\x33\x31\x20\x2d\x36\x32\x2e\x34\x38\x33\x34\x20\x39\ -\x2e\x33\x34\x37\x34\x32\x20\x2d\x35\x32\x2e\x32\x38\x37\x38\x20\ -\x39\x2e\x33\x34\x37\x34\x32\x20\x2d\x33\x39\x2e\x37\x31\x30\x39\ -\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\ -\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\ -\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\ -\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\ -\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\ -\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\ -\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\ -\x2d\x77\x69\x64\x74\x68\x3d\x27\x33\x2e\x35\x31\x33\x31\x32\x27\ -\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\ -\x76\x67\x3e\ -\x00\x00\x03\xe6\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x43\x68\x65\x76\x72\x6f\x6e\x5f\x63\x69\x72\x63\x6c\x65\ -\x64\x5f\x72\x69\x67\x68\x74\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x22\x0d\x0a\x09\x20\x78\x3d\x22\x30\x70\x78\ -\x22\x20\x79\x3d\x22\x30\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\ -\x78\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\ -\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\ -\x64\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\ -\x31\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\ -\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x74\x72\ -\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\ -\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\x3e\ -\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x31\x2c\x31\ -\x30\x4c\x38\x2e\x36\x39\x38\x2c\x37\x2e\x34\x39\x34\x63\x2d\x30\ -\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x38\x2d\x30\x2e\x31\x39\x36\ -\x2d\x30\x2e\x35\x31\x39\x2c\x30\x2d\x30\x2e\x37\x31\x38\x63\x30\ -\x2e\x31\x39\x36\x2d\x30\x2e\x31\x39\x37\x2c\x30\x2e\x35\x31\x35\ -\x2d\x30\x2e\x31\x39\x37\x2c\x30\x2e\x37\x31\x2c\x30\x6c\x32\x2e\ -\x38\x30\x37\x2c\x32\x2e\x38\x36\x34\x0d\x0a\x09\x63\x30\x2e\x31\ -\x39\x36\x2c\x30\x2e\x31\x39\x39\x2c\x30\x2e\x31\x39\x36\x2c\x30\ -\x2e\x35\x32\x2c\x30\x2c\x30\x2e\x37\x31\x37\x6c\x2d\x32\x2e\x38\ -\x30\x37\x2c\x32\x2e\x38\x36\x34\x63\x2d\x30\x2e\x31\x39\x35\x2c\ -\x30\x2e\x31\x39\x39\x2d\x30\x2e\x35\x31\x34\x2c\x30\x2e\x31\x39\ -\x38\x2d\x30\x2e\x37\x31\x2c\x30\x63\x2d\x30\x2e\x31\x39\x36\x2d\ -\x30\x2e\x31\x39\x37\x2d\x30\x2e\x31\x39\x36\x2d\x30\x2e\x35\x31\ -\x38\x2c\x30\x2d\x30\x2e\x37\x31\x37\x4c\x31\x31\x2c\x31\x30\x7a\ -\x20\x4d\x31\x30\x2c\x30\x2e\x34\x0d\x0a\x09\x63\x35\x2e\x33\x30\ -\x32\x2c\x30\x2c\x39\x2e\x36\x2c\x34\x2e\x32\x39\x38\x2c\x39\x2e\ -\x36\x2c\x39\x2e\x36\x63\x30\x2c\x35\x2e\x33\x30\x33\x2d\x34\x2e\ -\x32\x39\x38\x2c\x39\x2e\x36\x2d\x39\x2e\x36\x2c\x39\x2e\x36\x53\ -\x30\x2e\x34\x2c\x31\x35\x2e\x33\x30\x33\x2c\x30\x2e\x34\x2c\x31\ -\x30\x43\x30\x2e\x34\x2c\x34\x2e\x36\x39\x38\x2c\x34\x2e\x36\x39\ -\x38\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\x34\x7a\x20\x4d\x31\ -\x30\x2c\x31\x38\x2e\x33\x35\x34\x0d\x0a\x09\x63\x34\x2e\x36\x31\ -\x33\x2c\x30\x2c\x38\x2e\x33\x35\x34\x2d\x33\x2e\x37\x34\x2c\x38\ -\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x30\x2d\x34\x2e\x36\ -\x31\x34\x2d\x33\x2e\x37\x34\x31\x2d\x38\x2e\x33\x35\x34\x2d\x38\ -\x2e\x33\x35\x34\x2d\x38\x2e\x33\x35\x34\x63\x2d\x34\x2e\x36\x31\ -\x35\x2c\x30\x2d\x38\x2e\x33\x35\x34\x2c\x33\x2e\x37\x34\x2d\x38\ -\x2e\x33\x35\x34\x2c\x38\x2e\x33\x35\x34\x0d\x0a\x09\x43\x31\x2e\ -\x36\x34\x35\x2c\x31\x34\x2e\x36\x31\x34\x2c\x35\x2e\x33\x38\x35\ -\x2c\x31\x38\x2e\x33\x35\x34\x2c\x31\x30\x2c\x31\x38\x2e\x33\x35\ -\x34\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\ -\x76\x67\x3e\x0d\x0a\ -\x00\x00\x01\x1c\ -\x3c\ -\x73\x76\x67\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x32\x30\x30\ -\x30\x2f\x73\x76\x67\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x35\x31\ -\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x35\x31\x32\ -\x70\x78\x22\x0a\x20\x20\x20\x20\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x3e\x0a\ -\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\ -\x74\x72\x69\x78\x28\x34\x38\x20\x30\x20\x30\x20\x34\x38\x20\x34\ -\x38\x20\x34\x38\x29\x27\x3e\x0a\x20\x20\x3c\x70\x61\x74\x68\x20\ -\x64\x3d\x22\x4d\x30\x20\x30\x76\x32\x68\x2e\x35\x63\x30\x2d\x2e\ -\x35\x35\x2e\x34\x35\x2d\x31\x20\x31\x2d\x31\x68\x31\x2e\x35\x76\ -\x35\x2e\x35\x63\x30\x20\x2e\x32\x38\x2d\x2e\x32\x32\x2e\x35\x2d\ -\x2e\x35\x2e\x35\x68\x2d\x2e\x35\x76\x31\x68\x34\x76\x2d\x31\x68\ -\x2d\x2e\x35\x63\x2d\x2e\x32\x38\x20\x30\x2d\x2e\x35\x2d\x2e\x32\ -\x32\x2d\x2e\x35\x2d\x2e\x35\x76\x2d\x35\x2e\x35\x68\x31\x2e\x35\ -\x63\x2e\x35\x35\x20\x30\x20\x31\x20\x2e\x34\x35\x20\x31\x20\x31\ -\x68\x2e\x35\x76\x2d\x32\x68\x2d\x38\x7a\x22\x20\x2f\x3e\x0a\x3c\ -\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\ -\x00\x00\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\x04\xaa\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x43\x6f\x64\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\x22\x68\ -\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\ -\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\ -\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\x78\ -\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x32\x34\x70\x78\x22\x20\x79\ -\x3d\x22\x32\x34\x70\x78\x22\x0d\x0a\x09\x20\x76\x69\x65\x77\x42\ -\x6f\x78\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\ -\x20\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\ -\x6e\x64\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\ -\x35\x31\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\ -\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x74\ -\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\ -\x28\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\x20\x30\x29\x27\ -\x3e\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x35\x2e\x37\x31\x39\ -\x2c\x31\x34\x2e\x37\x35\x63\x2d\x30\x2e\x32\x33\x36\x2c\x30\x2d\ -\x30\x2e\x34\x37\x34\x2d\x30\x2e\x30\x38\x33\x2d\x30\x2e\x36\x36\ -\x34\x2d\x30\x2e\x32\x35\x32\x4c\x2d\x30\x2e\x30\x30\x35\x2c\x31\ -\x30\x6c\x35\x2e\x33\x34\x31\x2d\x34\x2e\x37\x34\x38\x43\x35\x2e\ -\x37\x34\x38\x2c\x34\x2e\x38\x38\x37\x2c\x36\x2e\x33\x38\x2c\x34\ -\x2e\x39\x32\x32\x2c\x36\x2e\x37\x34\x37\x2c\x35\x2e\x33\x33\x35\ -\x0d\x0a\x09\x63\x30\x2e\x33\x36\x37\x2c\x30\x2e\x34\x31\x33\x2c\ -\x30\x2e\x33\x33\x2c\x31\x2e\x30\x34\x35\x2d\x30\x2e\x30\x38\x33\ -\x2c\x31\x2e\x34\x31\x32\x4c\x33\x2e\x30\x30\x35\x2c\x31\x30\x6c\ -\x33\x2e\x33\x37\x38\x2c\x33\x2e\x30\x30\x32\x63\x30\x2e\x34\x31\ -\x33\x2c\x30\x2e\x33\x36\x37\x2c\x30\x2e\x34\x35\x2c\x30\x2e\x39\ -\x39\x39\x2c\x30\x2e\x30\x38\x33\x2c\x31\x2e\x34\x31\x32\x0d\x0a\ -\x09\x43\x36\x2e\x32\x36\x39\x2c\x31\x34\x2e\x36\x33\x37\x2c\x35\ -\x2e\x39\x39\x34\x2c\x31\x34\x2e\x37\x35\x2c\x35\x2e\x37\x31\x39\ -\x2c\x31\x34\x2e\x37\x35\x7a\x20\x4d\x31\x34\x2e\x36\x36\x34\x2c\ -\x31\x34\x2e\x37\x34\x38\x4c\x32\x30\x2e\x30\x30\x35\x2c\x31\x30\ -\x6c\x2d\x35\x2e\x30\x36\x2d\x34\x2e\x34\x39\x38\x63\x2d\x30\x2e\ -\x34\x31\x33\x2d\x30\x2e\x33\x36\x37\x2d\x31\x2e\x30\x34\x35\x2d\ -\x30\x2e\x33\x33\x2d\x31\x2e\x34\x31\x31\x2c\x30\x2e\x30\x38\x33\ -\x0d\x0a\x09\x63\x2d\x30\x2e\x33\x36\x37\x2c\x30\x2e\x34\x31\x33\ -\x2d\x30\x2e\x33\x33\x2c\x31\x2e\x30\x34\x35\x2c\x30\x2e\x30\x38\ -\x33\x2c\x31\x2e\x34\x31\x32\x4c\x31\x36\x2e\x39\x39\x35\x2c\x31\ -\x30\x6c\x2d\x33\x2e\x36\x35\x39\x2c\x33\x2e\x32\x35\x32\x63\x2d\ -\x30\x2e\x34\x31\x33\x2c\x30\x2e\x33\x36\x37\x2d\x30\x2e\x34\x35\ -\x2c\x30\x2e\x39\x39\x39\x2d\x30\x2e\x30\x38\x33\x2c\x31\x2e\x34\ -\x31\x32\x43\x31\x33\x2e\x34\x35\x2c\x31\x34\x2e\x38\x38\x37\x2c\ -\x31\x33\x2e\x37\x32\x35\x2c\x31\x35\x2c\x31\x34\x2c\x31\x35\x0d\ -\x0a\x09\x43\x31\x34\x2e\x32\x33\x36\x2c\x31\x35\x2c\x31\x34\x2e\ -\x34\x37\x34\x2c\x31\x34\x2e\x39\x31\x37\x2c\x31\x34\x2e\x36\x36\ -\x34\x2c\x31\x34\x2e\x37\x34\x38\x7a\x20\x4d\x39\x2e\x39\x38\x36\ -\x2c\x31\x36\x2e\x31\x36\x35\x6c\x32\x2d\x31\x32\x63\x30\x2e\x30\ -\x39\x31\x2d\x30\x2e\x35\x34\x35\x2d\x30\x2e\x32\x37\x37\x2d\x31\ -\x2e\x30\x36\x2d\x30\x2e\x38\x32\x32\x2d\x31\x2e\x31\x35\x31\x0d\ -\x0a\x09\x63\x2d\x30\x2e\x35\x34\x37\x2d\x30\x2e\x30\x39\x32\x2d\ -\x31\x2e\x30\x36\x31\x2c\x30\x2e\x32\x37\x37\x2d\x31\x2e\x31\x35\ -\x2c\x30\x2e\x38\x32\x32\x6c\x2d\x32\x2c\x31\x32\x63\x2d\x30\x2e\ -\x30\x39\x31\x2c\x30\x2e\x35\x34\x35\x2c\x30\x2e\x32\x37\x37\x2c\ -\x31\x2e\x30\x36\x2c\x30\x2e\x38\x32\x32\x2c\x31\x2e\x31\x35\x31\ -\x43\x38\x2e\x38\x39\x32\x2c\x31\x36\x2e\x39\x39\x36\x2c\x38\x2e\ -\x39\x34\x36\x2c\x31\x37\x2c\x39\x2e\x30\x30\x31\x2c\x31\x37\x0d\ -\x0a\x09\x43\x39\x2e\x34\x38\x31\x2c\x31\x37\x2c\x39\x2e\x39\x30\ -\x35\x2c\x31\x36\x2e\x36\x35\x33\x2c\x39\x2e\x39\x38\x36\x2c\x31\ -\x36\x2e\x31\x36\x35\x7a\x22\x2f\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\ -\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x02\x7d\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\ -\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\ -\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\ -\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\ -\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ -\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\ -\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\ -\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\ -\x22\x49\x63\x6f\x6e\x5f\x38\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\ -\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x38\x35\ -\x2c\x32\x37\x37\x2e\x33\x37\x35\x68\x32\x35\x39\x2e\x37\x30\x34\ -\x4c\x32\x32\x35\x2e\x30\x30\x32\x2c\x33\x39\x37\x2e\x30\x37\x37\ -\x4c\x32\x35\x36\x2c\x34\x32\x37\x6c\x31\x37\x31\x2d\x31\x37\x31\ -\x4c\x32\x35\x36\x2c\x38\x35\x6c\x2d\x32\x39\x2e\x39\x32\x32\x2c\ -\x32\x39\x2e\x39\x32\x34\x6c\x31\x31\x38\x2e\x36\x32\x36\x2c\x31\ -\x31\x39\x2e\x37\x30\x31\x48\x38\x35\x56\x32\x37\x37\x2e\x33\x37\ -\x35\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\ -\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x04\x4e\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\ -\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\ -\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\ -\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\ -\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\ -\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\ -\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\ -\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\ -\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\x27\x20\x76\x69\x65\x77\ -\x42\x6f\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\ -\x38\x35\x38\x33\x20\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\ -\x39\x39\x39\x37\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\ -\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\ -\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\ -\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\ -\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x4c\x20\x31\ -\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\x39\x4c\ -\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\x2e\x35\x30\x32\ -\x32\x4c\x20\x34\x30\x2e\x36\x37\x39\x34\x20\x2d\x32\x32\x2e\x35\ -\x32\x38\x31\x4c\x20\x33\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\ -\x2e\x31\x32\x5a\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\ -\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\ -\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\ -\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\ -\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\ -\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\ -\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\ -\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x32\x2e\x35\x30\ -\x39\x33\x37\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\ -\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\ -\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\ -\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\ -\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\ -\x65\x20\x63\x78\x3d\x27\x33\x2e\x39\x35\x37\x33\x35\x27\x20\x63\ -\x79\x3d\x27\x2d\x33\x32\x2e\x31\x32\x27\x20\x66\x69\x6c\x6c\x3d\ -\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\ -\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\ -\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\ -\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\ -\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\ -\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\ -\x65\x20\x63\x78\x3d\x27\x31\x31\x2e\x39\x30\x33\x36\x27\x20\x63\ -\x79\x3d\x27\x2d\x35\x31\x2e\x33\x30\x33\x39\x27\x20\x66\x69\x6c\ -\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\ -\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\ -\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\ -\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\ -\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\x36\x39\ -\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\ -\x63\x6c\x65\x20\x63\x78\x3d\x27\x35\x36\x2e\x31\x35\x32\x33\x27\ -\x20\x63\x79\x3d\x27\x2d\x34\x32\x2e\x35\x30\x32\x32\x27\x20\x66\ -\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\ -\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\ -\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\ -\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\ -\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\ -\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\ -\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x34\x30\x2e\x36\x37\x39\ -\x34\x27\x20\x63\x79\x3d\x27\x2d\x32\x32\x2e\x35\x32\x38\x31\x27\ -\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\ -\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\ -\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\ -\x00\x00\x04\xd5\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\ -\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\ -\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\ -\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\ -\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\ -\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\ -\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\ -\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\ -\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\x27\x20\x76\x69\x65\x77\ -\x42\x6f\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\ -\x38\x35\x38\x33\x20\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\ -\x39\x39\x39\x37\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\ -\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\ -\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\ -\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\ -\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x43\x20\x32\ -\x2e\x32\x38\x39\x32\x32\x20\x2d\x33\x39\x2e\x33\x31\x31\x33\x20\ -\x36\x2e\x33\x36\x37\x30\x32\x20\x2d\x34\x36\x2e\x32\x33\x38\x36\ -\x20\x31\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\ -\x39\x43\x20\x32\x39\x2e\x36\x36\x38\x37\x20\x2d\x36\x37\x2e\x35\ -\x35\x36\x38\x20\x35\x35\x2e\x32\x32\x39\x32\x20\x2d\x36\x30\x2e\ -\x36\x34\x32\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\x2e\ -\x35\x30\x32\x32\x43\x20\x35\x36\x2e\x36\x31\x33\x36\x20\x2d\x33\ -\x33\x2e\x34\x33\x38\x31\x20\x34\x39\x2e\x31\x31\x33\x32\x20\x2d\ -\x32\x36\x2e\x35\x39\x35\x39\x20\x34\x30\x2e\x36\x37\x39\x34\x20\ -\x2d\x32\x32\x2e\x35\x32\x38\x31\x43\x20\x32\x35\x2e\x33\x39\x39\ -\x35\x20\x2d\x31\x35\x2e\x31\x35\x38\x32\x20\x37\x2e\x31\x39\x39\ -\x33\x35\x20\x2d\x31\x38\x2e\x31\x34\x33\x36\x20\x33\x2e\x39\x35\ -\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x5a\x27\x20\x66\x69\x6c\ -\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\x20\x73\x74\x72\x6f\x6b\x65\x3d\ -\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x73\x74\x72\x6f\x6b\x65\ -\x2d\x6c\x69\x6e\x65\x63\x61\x70\x3d\x27\x72\x6f\x75\x6e\x64\x27\ -\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\ -\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6d\x69\x74\x65\x72\x6c\x69\x6d\x69\x74\x3d\x27\x31\x30\x2e\x30\ -\x33\x37\x35\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\ -\x68\x3d\x27\x32\x2e\x35\x30\x39\x33\x37\x27\x2f\x3e\x0a\x3c\x2f\ -\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ -\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\ -\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\ -\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x33\x2e\x39\ -\x35\x37\x33\x35\x27\x20\x63\x79\x3d\x27\x2d\x33\x32\x2e\x31\x32\ -\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\ -\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\ -\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\ -\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\ -\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\ -\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x31\x31\x2e\ -\x39\x30\x33\x36\x27\x20\x63\x79\x3d\x27\x2d\x35\x31\x2e\x33\x30\ -\x33\x39\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\ -\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\ -\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\ -\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\ -\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\ -\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\ -\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x35\ -\x36\x2e\x31\x35\x32\x33\x27\x20\x63\x79\x3d\x27\x2d\x34\x32\x2e\ -\x35\x30\x32\x32\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\ -\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\ -\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\ -\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\ -\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\ -\x34\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\ -\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x78\x3d\ -\x27\x34\x30\x2e\x36\x37\x39\x34\x27\x20\x63\x79\x3d\x27\x2d\x32\ -\x32\x2e\x35\x32\x38\x31\x27\x20\x66\x69\x6c\x6c\x3d\x27\x23\x30\ -\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\x32\x35\ -\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\ -\x73\x76\x67\x3e\ -\x00\x00\x02\xf2\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x38\x2e\x31\x2e\x30\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x43\x69\x72\x63\x6c\x65\x22\x20\x78\x6d\x6c\x6e\x73\x3d\ -\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\ -\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\x6c\ -\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\x2f\ -\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\ -\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x35\x31\x32\x70\x78\ -\x22\x20\x79\x3d\x22\x35\x31\x32\x70\x78\x22\x0d\x0a\x09\x20\x76\ -\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\ -\x35\x31\x32\x22\x20\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\ -\x67\x72\x6f\x75\x6e\x64\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\ -\x35\x31\x32\x20\x35\x31\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\ -\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\ -\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\ -\x74\x72\x69\x78\x28\x32\x34\x20\x30\x20\x30\x20\x32\x34\x20\x30\ -\x20\x30\x29\x27\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ -\x4d\x31\x30\x2c\x30\x2e\x34\x43\x34\x2e\x36\x39\x38\x2c\x30\x2e\ -\x34\x2c\x30\x2e\x34\x2c\x34\x2e\x36\x39\x38\x2c\x30\x2e\x34\x2c\ -\x31\x30\x43\x30\x2e\x34\x2c\x31\x35\x2e\x33\x30\x32\x2c\x34\x2e\ -\x36\x39\x38\x2c\x31\x39\x2e\x36\x2c\x31\x30\x2c\x31\x39\x2e\x36\ -\x63\x35\x2e\x33\x30\x31\x2c\x30\x2c\x39\x2e\x36\x2d\x34\x2e\x32\ -\x39\x38\x2c\x39\x2e\x36\x2d\x39\x2e\x36\x30\x31\x0d\x0a\x09\x43\ -\x31\x39\x2e\x36\x2c\x34\x2e\x36\x39\x38\x2c\x31\x35\x2e\x33\x30\ -\x31\x2c\x30\x2e\x34\x2c\x31\x30\x2c\x30\x2e\x34\x7a\x20\x4d\x31\ -\x30\x2c\x31\x37\x2e\x35\x39\x39\x63\x2d\x34\x2e\x31\x39\x37\x2c\ -\x30\x2d\x37\x2e\x36\x2d\x33\x2e\x34\x30\x32\x2d\x37\x2e\x36\x2d\ -\x37\x2e\x36\x53\x35\x2e\x38\x30\x32\x2c\x32\x2e\x34\x2c\x31\x30\ -\x2c\x32\x2e\x34\x63\x34\x2e\x31\x39\x37\x2c\x30\x2c\x37\x2e\x36\ -\x30\x31\x2c\x33\x2e\x34\x30\x32\x2c\x37\x2e\x36\x30\x31\x2c\x37\ -\x2e\x36\x0d\x0a\x09\x53\x31\x34\x2e\x31\x39\x37\x2c\x31\x37\x2e\ -\x35\x39\x39\x2c\x31\x30\x2c\x31\x37\x2e\x35\x39\x39\x7a\x22\x2f\ -\x3e\x0d\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\ -\x0a\ -\x00\x00\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\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\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\x04\x3d\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x27\x31\x2e\ -\x30\x27\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x27\x55\x54\x46\ -\x2d\x38\x27\x3f\x3e\x0a\x3c\x21\x2d\x2d\x20\x54\x68\x69\x73\x20\ -\x66\x69\x6c\x65\x20\x77\x61\x73\x20\x67\x65\x6e\x65\x72\x61\x74\ -\x65\x64\x20\x62\x79\x20\x64\x76\x69\x73\x76\x67\x6d\x20\x32\x2e\ -\x38\x20\x2d\x2d\x3e\x0a\x3c\x73\x76\x67\x20\x76\x65\x72\x73\x69\ -\x6f\x6e\x3d\x27\x31\x2e\x31\x27\x20\x78\x6d\x6c\x6e\x73\x3d\x27\ -\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\ -\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x27\x20\x78\x6d\x6c\x6e\ -\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x27\x68\x74\x74\x70\x3a\x2f\x2f\ -\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\x39\x2f\ -\x78\x6c\x69\x6e\x6b\x27\x20\x77\x69\x64\x74\x68\x3d\x27\x36\x33\ -\x2e\x39\x39\x39\x36\x70\x74\x27\x20\x68\x65\x69\x67\x68\x74\x3d\ -\x27\x36\x33\x2e\x39\x39\x39\x37\x70\x74\x27\x20\x76\x69\x65\x77\ -\x42\x6f\x78\x3d\x27\x35\x36\x2e\x34\x30\x39\x34\x20\x35\x33\x2e\ -\x38\x35\x38\x33\x20\x36\x33\x2e\x39\x39\x39\x36\x20\x36\x33\x2e\ -\x39\x39\x39\x37\x27\x3e\x0a\x3c\x67\x20\x69\x64\x3d\x27\x70\x61\ -\x67\x65\x31\x27\x3e\x0a\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\ -\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\x30\x2e\x39\x39\x36\ -\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\x39\x36\x32\x36\x34\ -\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\x37\x2e\x38\x35\x38\ -\x29\x27\x3e\x0a\x3c\x70\x61\x74\x68\x20\x64\x3d\x27\x4d\x20\x33\ -\x2e\x39\x35\x37\x33\x35\x20\x2d\x33\x32\x2e\x31\x32\x4c\x20\x31\ -\x31\x2e\x39\x30\x33\x36\x20\x2d\x35\x31\x2e\x33\x30\x33\x39\x4c\ -\x20\x35\x36\x2e\x31\x35\x32\x33\x20\x2d\x34\x32\x2e\x35\x30\x32\ -\x32\x4c\x20\x34\x30\x2e\x36\x37\x39\x34\x20\x2d\x32\x32\x2e\x35\ -\x32\x38\x31\x27\x20\x66\x69\x6c\x6c\x3d\x27\x6e\x6f\x6e\x65\x27\ -\x20\x73\x74\x72\x6f\x6b\x65\x3d\x27\x23\x30\x30\x30\x30\x30\x30\ -\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6c\x69\x6e\x65\x63\x61\x70\ -\x3d\x27\x72\x6f\x75\x6e\x64\x27\x20\x73\x74\x72\x6f\x6b\x65\x2d\ -\x6c\x69\x6e\x65\x6a\x6f\x69\x6e\x3d\x27\x72\x6f\x75\x6e\x64\x27\ -\x20\x73\x74\x72\x6f\x6b\x65\x2d\x6d\x69\x74\x65\x72\x6c\x69\x6d\ -\x69\x74\x3d\x27\x31\x30\x2e\x30\x33\x37\x35\x27\x20\x73\x74\x72\ -\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x27\x32\x2e\x35\x30\x39\ -\x33\x37\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\ -\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\ -\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\ -\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\ -\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\ -\x20\x63\x78\x3d\x27\x33\x2e\x39\x35\x37\x33\x35\x27\x20\x63\x79\ -\x3d\x27\x2d\x33\x32\x2e\x31\x32\x27\x20\x66\x69\x6c\x6c\x3d\x27\ -\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\x30\x32\ -\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\x74\x72\ -\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\x78\x28\ -\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\x2e\x39\ -\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\x36\x39\x20\x31\x31\ -\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\x6c\x65\ -\x20\x63\x78\x3d\x27\x31\x31\x2e\x39\x30\x33\x36\x27\x20\x63\x79\ -\x3d\x27\x2d\x35\x31\x2e\x33\x30\x33\x39\x27\x20\x66\x69\x6c\x6c\ -\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\x36\x2e\ -\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\x67\x20\ -\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\x72\x69\ -\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\x20\x30\ -\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\x36\x39\x20\ -\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\x72\x63\ -\x6c\x65\x20\x63\x78\x3d\x27\x35\x36\x2e\x31\x35\x32\x33\x27\x20\ -\x63\x79\x3d\x27\x2d\x34\x32\x2e\x35\x30\x32\x32\x27\x20\x66\x69\ -\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\x3d\x27\ -\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\x0a\x3c\ -\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x27\x6d\x61\x74\ -\x72\x69\x78\x28\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x30\x20\x30\ -\x20\x30\x2e\x39\x39\x36\x32\x36\x34\x20\x35\x38\x2e\x34\x36\x36\ -\x39\x20\x31\x31\x37\x2e\x38\x35\x38\x29\x27\x3e\x0a\x3c\x63\x69\ -\x72\x63\x6c\x65\x20\x63\x78\x3d\x27\x34\x30\x2e\x36\x37\x39\x34\ -\x27\x20\x63\x79\x3d\x27\x2d\x32\x32\x2e\x35\x32\x38\x31\x27\x20\ -\x66\x69\x6c\x6c\x3d\x27\x23\x30\x30\x30\x30\x30\x30\x27\x20\x72\ -\x3d\x27\x36\x2e\x30\x32\x32\x35\x27\x2f\x3e\x0a\x3c\x2f\x67\x3e\ -\x0a\x3c\x2f\x67\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\ -\x00\x00\x02\x7d\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\ -\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\ -\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\ -\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\ -\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ -\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\ -\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\ -\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x20\x69\x64\x3d\ -\x22\x49\x63\x6f\x6e\x5f\x38\x5f\x22\x3e\x0d\x0a\x09\x3c\x67\x3e\ -\x0d\x0a\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\x32\ -\x37\x2c\x32\x33\x34\x2e\x36\x32\x35\x48\x31\x36\x37\x2e\x32\x39\ -\x36\x6c\x31\x31\x39\x2e\x37\x30\x32\x2d\x31\x31\x39\x2e\x37\x30\ -\x32\x4c\x32\x35\x36\x2c\x38\x35\x4c\x38\x35\x2c\x32\x35\x36\x6c\ -\x31\x37\x31\x2c\x31\x37\x31\x6c\x32\x39\x2e\x39\x32\x32\x2d\x32\ -\x39\x2e\x39\x32\x34\x4c\x31\x36\x37\x2e\x32\x39\x36\x2c\x32\x37\ -\x37\x2e\x33\x37\x35\x48\x34\x32\x37\x56\x32\x33\x34\x2e\x36\x32\ -\x35\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\ -\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x02\xc9\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\ -\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\ -\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\ -\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\ -\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\ -\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\ -\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\ -\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\ -\x0a\x3c\x70\x6f\x6c\x79\x67\x6f\x6e\x20\x70\x6f\x69\x6e\x74\x73\ -\x3d\x22\x34\x38\x30\x2c\x32\x35\x36\x20\x33\x38\x34\x2c\x31\x36\ -\x30\x20\x33\x38\x34\x2c\x32\x33\x36\x20\x32\x37\x36\x2c\x32\x33\ -\x36\x20\x32\x37\x36\x2c\x31\x32\x38\x20\x33\x35\x32\x2c\x31\x32\ -\x38\x20\x32\x35\x36\x2c\x33\x32\x20\x31\x36\x30\x2c\x31\x32\x38\ -\x20\x32\x33\x36\x2c\x31\x32\x38\x20\x32\x33\x36\x2c\x32\x33\x36\ -\x20\x31\x32\x38\x2c\x32\x33\x36\x20\x31\x32\x38\x2c\x31\x36\x30\ -\x20\x33\x32\x2c\x32\x35\x36\x20\x31\x32\x38\x2c\x33\x35\x32\x20\ -\x0d\x0a\x09\x31\x32\x38\x2c\x32\x37\x36\x20\x32\x33\x36\x2c\x32\ -\x37\x36\x20\x32\x33\x36\x2c\x33\x38\x34\x20\x31\x36\x30\x2c\x33\ -\x38\x34\x20\x32\x35\x36\x2c\x34\x38\x30\x20\x33\x35\x32\x2c\x33\ -\x38\x34\x20\x32\x37\x35\x2e\x38\x2c\x33\x38\x34\x20\x32\x37\x35\ -\x2e\x34\x2c\x32\x37\x35\x2e\x35\x20\x33\x38\x34\x2c\x32\x37\x35\ -\x2e\x38\x20\x33\x38\x34\x2c\x33\x35\x32\x20\x22\x2f\x3e\x0d\x0a\ -\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x05\xca\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\ -\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\ -\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\ -\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\ -\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ -\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\ -\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\ -\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x70\x61\x74\x68\x20\ -\x64\x3d\x22\x4d\x34\x35\x30\x2e\x36\x37\x39\x2c\x32\x37\x33\x2e\ -\x35\x63\x2d\x31\x34\x2e\x35\x38\x35\x2d\x31\x34\x2e\x35\x37\x37\ -\x2d\x33\x36\x2e\x30\x35\x34\x2d\x31\x35\x2e\x38\x39\x2d\x35\x30\ -\x2e\x36\x33\x39\x2d\x31\x2e\x33\x31\x32\x6c\x2d\x34\x31\x2e\x36\ -\x38\x37\x2c\x34\x31\x2e\x36\x36\x34\x63\x2d\x31\x30\x2e\x38\x35\ -\x32\x2c\x31\x30\x2e\x38\x33\x36\x2d\x32\x33\x2e\x39\x33\x2c\x31\ -\x30\x2e\x38\x35\x39\x2d\x33\x31\x2e\x35\x36\x34\x2c\x31\x2e\x38\ -\x35\x32\x0d\x0a\x09\x63\x2d\x35\x2e\x30\x35\x37\x2d\x35\x2e\x39\ -\x36\x38\x2d\x33\x2e\x30\x36\x31\x2d\x32\x34\x2e\x33\x37\x34\x2d\ -\x31\x2e\x36\x34\x34\x2d\x33\x36\x2e\x30\x34\x39\x6c\x32\x30\x2e\ -\x39\x30\x37\x2d\x31\x37\x31\x2e\x38\x34\x39\x63\x31\x2e\x38\x36\ -\x37\x2d\x31\x35\x2e\x33\x35\x33\x2d\x39\x2e\x30\x37\x2d\x33\x30\ -\x2e\x31\x38\x35\x2d\x32\x34\x2e\x34\x33\x2d\x33\x32\x2e\x30\x35\ -\x31\x0d\x0a\x09\x63\x2d\x31\x35\x2e\x33\x35\x38\x2d\x31\x2e\x38\ -\x36\x37\x2d\x32\x39\x2e\x33\x32\x32\x2c\x39\x2e\x39\x33\x39\x2d\ -\x33\x31\x2e\x31\x39\x31\x2c\x32\x35\x2e\x32\x38\x39\x4c\x32\x36\ -\x37\x2e\x33\x37\x2c\x32\x33\x36\x2e\x30\x32\x31\x63\x2d\x31\x2e\ -\x32\x30\x35\x2c\x33\x2e\x33\x35\x38\x2d\x33\x2e\x37\x39\x2c\x33\ -\x2e\x39\x33\x38\x2d\x34\x2e\x30\x38\x31\x2d\x30\x2e\x35\x38\x32\ -\x4c\x32\x35\x35\x2e\x34\x34\x2c\x36\x30\x0d\x0a\x09\x63\x30\x2d\ -\x31\x35\x2e\x34\x36\x35\x2d\x31\x32\x2e\x35\x34\x32\x2d\x32\x38\ -\x2d\x32\x38\x2e\x30\x31\x34\x2d\x32\x38\x63\x2d\x31\x35\x2e\x34\ -\x37\x33\x2c\x30\x2d\x32\x38\x2e\x30\x31\x35\x2c\x31\x32\x2e\x35\ -\x33\x35\x2d\x32\x38\x2e\x30\x31\x35\x2c\x32\x38\x6c\x2d\x30\x2e\ -\x35\x35\x32\x2c\x31\x37\x36\x2e\x37\x35\x32\x63\x30\x2e\x31\x34\ -\x36\x2c\x32\x2e\x30\x34\x2d\x31\x2e\x36\x30\x34\x2c\x32\x2e\x36\ -\x32\x34\x2d\x31\x2e\x39\x32\x2c\x30\x2e\x32\x39\x34\x4c\x31\x37\ -\x32\x2e\x30\x31\x36\x2c\x39\x39\x2e\x30\x37\x37\x0d\x0a\x09\x63\ -\x2d\x32\x2e\x37\x35\x2d\x31\x35\x2e\x32\x31\x39\x2d\x31\x37\x2e\ -\x33\x32\x33\x2d\x32\x36\x2e\x32\x30\x33\x2d\x33\x32\x2e\x35\x34\ -\x38\x2d\x32\x33\x2e\x34\x35\x33\x63\x2d\x31\x35\x2e\x32\x32\x37\ -\x2c\x32\x2e\x37\x34\x38\x2d\x32\x35\x2e\x33\x33\x39\x2c\x31\x38\ -\x2e\x31\x38\x37\x2d\x32\x32\x2e\x35\x39\x31\x2c\x33\x33\x2e\x34\ -\x30\x33\x6c\x32\x32\x2e\x31\x39\x33\x2c\x31\x36\x31\x2e\x34\x35\ -\x35\x0d\x0a\x09\x63\x30\x2e\x30\x32\x33\x2c\x32\x2e\x38\x37\x32\ -\x2d\x30\x2e\x39\x34\x31\x2c\x34\x2e\x35\x31\x33\x2d\x32\x2e\x33\ -\x30\x38\x2c\x30\x2e\x38\x33\x31\x6c\x2d\x33\x33\x2e\x31\x30\x39\ -\x2d\x38\x38\x2e\x35\x31\x37\x63\x2d\x35\x2e\x31\x38\x2d\x31\x34\ -\x2e\x35\x37\x32\x2d\x32\x31\x2e\x31\x39\x36\x2d\x32\x33\x2e\x30\ -\x36\x35\x2d\x33\x35\x2e\x37\x37\x36\x2d\x31\x37\x2e\x38\x38\x39\ -\x0d\x0a\x09\x63\x2d\x31\x34\x2e\x35\x37\x39\x2c\x35\x2e\x31\x37\ -\x37\x2d\x32\x32\x2e\x32\x30\x31\x2c\x32\x32\x2e\x30\x36\x31\x2d\ -\x31\x37\x2e\x30\x32\x33\x2c\x33\x36\x2e\x36\x33\x31\x6c\x35\x38\ -\x2e\x30\x34\x32\x2c\x31\x38\x39\x2e\x36\x32\x35\x63\x30\x2e\x33\ -\x30\x33\x2c\x31\x2e\x30\x34\x36\x2c\x30\x2e\x36\x32\x34\x2c\x32\ -\x2e\x30\x38\x35\x2c\x30\x2e\x39\x35\x33\x2c\x33\x2e\x31\x31\x38\ -\x6c\x30\x2e\x31\x32\x31\x2c\x30\x2e\x33\x39\x0d\x0a\x09\x63\x30\ -\x2e\x30\x31\x31\x2c\x30\x2e\x30\x33\x31\x2c\x30\x2e\x30\x32\x35\ -\x2c\x30\x2e\x30\x35\x38\x2c\x30\x2e\x30\x33\x35\x2c\x30\x2e\x30\ -\x38\x38\x43\x31\x32\x36\x2e\x30\x37\x39\x2c\x34\x34\x34\x2e\x32\ -\x33\x33\x2c\x31\x37\x32\x2e\x35\x37\x2c\x34\x38\x30\x2c\x32\x32\ -\x37\x2e\x34\x32\x37\x2c\x34\x38\x30\x63\x33\x35\x2e\x31\x31\x36\ -\x2c\x30\x2c\x37\x31\x2e\x35\x39\x31\x2d\x31\x32\x2e\x33\x37\x38\ -\x2c\x39\x39\x2e\x33\x35\x37\x2d\x33\x33\x2e\x36\x37\x32\x0d\x0a\ -\x09\x63\x30\x2e\x30\x30\x31\x2c\x30\x2c\x30\x2e\x30\x30\x33\x2d\ -\x30\x2e\x30\x30\x32\x2c\x30\x2e\x30\x30\x33\x2d\x30\x2e\x30\x30\ -\x32\x63\x32\x39\x2e\x39\x39\x2d\x31\x38\x2e\x30\x35\x31\x2c\x31\ -\x32\x36\x2e\x30\x37\x31\x2d\x31\x32\x31\x2e\x33\x34\x37\x2c\x31\ -\x32\x36\x2e\x30\x37\x31\x2d\x31\x32\x31\x2e\x33\x34\x37\x43\x34\ -\x36\x37\x2e\x34\x34\x35\x2c\x33\x31\x30\x2e\x34\x30\x32\x2c\x34\ -\x36\x35\x2e\x32\x36\x36\x2c\x32\x38\x38\x2e\x30\x38\x2c\x34\x35\ -\x30\x2e\x36\x37\x39\x2c\x32\x37\x33\x2e\x35\x7a\x22\x2f\x3e\x0d\ -\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x03\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\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\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\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\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\x07\x80\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\ -\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\ -\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\ -\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x65\ -\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\x6b\x67\x72\x6f\x75\x6e\x64\ -\x3d\x22\x6e\x65\x77\x20\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\ -\x32\x22\x20\x78\x6d\x6c\x3a\x73\x70\x61\x63\x65\x3d\x22\x70\x72\ -\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\x0a\x3c\x67\x3e\x0d\x0a\x09\ -\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x31\x39\x33\x2e\x34\x36\ -\x2c\x32\x34\x39\x2e\x30\x35\x36\x63\x33\x2e\x37\x32\x33\x2d\x30\ -\x2e\x36\x37\x2c\x37\x2e\x35\x38\x39\x2d\x31\x2e\x30\x34\x31\x2c\ -\x31\x31\x2e\x35\x38\x36\x2d\x31\x2e\x30\x34\x31\x4c\x32\x30\x31\ -\x2e\x39\x32\x34\x2c\x32\x34\x38\x68\x31\x30\x33\x2e\x38\x32\x33\ -\x63\x34\x2e\x35\x30\x33\x2c\x30\x2c\x38\x2e\x38\x30\x36\x2d\x30\ -\x2e\x36\x31\x37\x2c\x31\x32\x2e\x39\x30\x38\x2d\x31\x2e\x37\x35\ -\x34\x0d\x0a\x09\x09\x63\x31\x39\x2e\x33\x37\x2d\x35\x2e\x33\x36\ -\x33\x2c\x33\x33\x2e\x33\x34\x35\x2d\x32\x32\x2e\x35\x33\x37\x2c\ -\x33\x33\x2e\x33\x34\x35\x2d\x34\x33\x2e\x36\x36\x33\x76\x2d\x33\ -\x30\x2e\x38\x32\x32\x76\x2d\x35\x36\x2e\x34\x30\x32\x63\x30\x2d\ -\x32\x34\x2e\x38\x33\x32\x2d\x32\x31\x2e\x31\x35\x2d\x34\x33\x2e\ -\x34\x38\x34\x2d\x34\x36\x2e\x32\x38\x39\x2d\x34\x37\x2e\x36\x30\ -\x36\x0d\x0a\x09\x09\x63\x2d\x31\x35\x2e\x39\x33\x31\x2d\x32\x2e\ -\x36\x32\x34\x2d\x33\x39\x2e\x32\x35\x38\x2d\x33\x2e\x38\x32\x37\ -\x2d\x35\x35\x2e\x30\x38\x39\x2d\x33\x2e\x37\x34\x39\x63\x2d\x31\ -\x35\x2e\x38\x32\x39\x2c\x30\x2e\x30\x38\x36\x2d\x33\x30\x2e\x39\ -\x38\x31\x2c\x31\x2e\x34\x30\x34\x2d\x34\x34\x2e\x32\x37\x37\x2c\ -\x33\x2e\x37\x34\x39\x43\x31\x36\x37\x2e\x31\x34\x33\x2c\x37\x34\ -\x2e\x35\x37\x36\x2c\x31\x36\x30\x2c\x38\x38\x2e\x39\x32\x38\x2c\ -\x31\x36\x30\x2c\x31\x31\x35\x2e\x33\x35\x39\x56\x31\x34\x34\x68\ -\x39\x36\x0d\x0a\x09\x09\x76\x31\x36\x48\x31\x32\x38\x2e\x38\x32\ -\x63\x2d\x33\x35\x2e\x36\x32\x38\x2c\x30\x2d\x36\x34\x2e\x35\x33\ -\x38\x2c\x34\x32\x2e\x35\x37\x31\x2d\x36\x34\x2e\x38\x31\x33\x2c\ -\x39\x35\x2e\x32\x34\x32\x43\x36\x34\x2e\x30\x30\x35\x2c\x32\x35\ -\x35\x2e\x34\x39\x35\x2c\x36\x34\x2c\x32\x35\x35\x2e\x37\x34\x37\ -\x2c\x36\x34\x2c\x32\x35\x36\x63\x30\x2c\x39\x2e\x35\x32\x33\x2c\ -\x30\x2e\x39\x34\x2c\x31\x38\x2e\x37\x32\x2c\x32\x2e\x36\x38\x35\ -\x2c\x32\x37\x2e\x34\x30\x34\x0d\x0a\x09\x09\x43\x37\x34\x2e\x36\ -\x34\x38\x2c\x33\x32\x33\x2e\x30\x37\x2c\x39\x39\x2e\x34\x35\x31\ -\x2c\x33\x35\x32\x2c\x31\x32\x38\x2e\x38\x32\x2c\x33\x35\x32\x48\ -\x31\x34\x34\x76\x2d\x32\x2e\x36\x36\x32\x76\x2d\x34\x33\x2e\x32\ -\x37\x33\x43\x31\x34\x34\x2c\x32\x37\x39\x2e\x32\x33\x38\x2c\x31\ -\x36\x34\x2e\x31\x34\x36\x2c\x32\x35\x34\x2e\x33\x33\x32\x2c\x31\ -\x39\x33\x2e\x34\x36\x2c\x32\x34\x39\x2e\x30\x35\x36\x7a\x20\x4d\ -\x32\x30\x33\x2e\x36\x35\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x0d\ -\x0a\x09\x09\x63\x2d\x39\x2e\x35\x39\x32\x2c\x30\x2d\x31\x37\x2e\ -\x33\x38\x34\x2d\x37\x2e\x37\x38\x35\x2d\x31\x37\x2e\x33\x38\x34\ -\x2d\x31\x37\x2e\x34\x30\x33\x63\x30\x2d\x39\x2e\x36\x36\x34\x2c\ -\x37\x2e\x37\x37\x34\x2d\x31\x37\x2e\x35\x32\x2c\x31\x37\x2e\x33\ -\x38\x34\x2d\x31\x37\x2e\x35\x32\x63\x39\x2e\x35\x37\x34\x2c\x30\ -\x2c\x31\x37\x2e\x33\x39\x39\x2c\x37\x2e\x38\x35\x35\x2c\x31\x37\ -\x2e\x33\x39\x39\x2c\x31\x37\x2e\x35\x32\x0d\x0a\x09\x09\x43\x32\ -\x32\x31\x2e\x30\x35\x36\x2c\x31\x31\x39\x2e\x32\x31\x37\x2c\x32\ -\x31\x33\x2e\x32\x34\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x2c\x32\ -\x30\x33\x2e\x36\x35\x36\x2c\x31\x32\x37\x2e\x30\x30\x32\x7a\x22\ -\x2f\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x34\ -\x34\x33\x2e\x39\x35\x31\x2c\x32\x32\x32\x2e\x35\x34\x33\x43\x34\ -\x33\x34\x2e\x37\x38\x2c\x31\x38\x36\x2e\x30\x32\x31\x2c\x34\x31\ -\x31\x2e\x30\x33\x33\x2c\x31\x36\x30\x2c\x33\x38\x33\x2e\x31\x38\ -\x2c\x31\x36\x30\x48\x33\x36\x38\x76\x32\x2e\x36\x32\x36\x76\x33\ -\x38\x2e\x30\x34\x36\x63\x30\x2c\x33\x33\x2e\x39\x31\x35\x2d\x32\ -\x32\x2e\x32\x38\x36\x2c\x35\x38\x2e\x34\x37\x34\x2d\x34\x39\x2e\ -\x34\x38\x39\x2c\x36\x32\x2e\x36\x38\x31\x0d\x0a\x09\x09\x63\x2d\ -\x32\x2e\x37\x33\x37\x2c\x30\x2e\x34\x32\x34\x2d\x35\x2e\x34\x38\ -\x33\x2c\x30\x2e\x36\x34\x36\x2d\x38\x2e\x33\x30\x31\x2c\x30\x2e\ -\x36\x34\x36\x48\x32\x30\x36\x2e\x33\x35\x31\x63\x2d\x34\x2e\x35\ -\x31\x38\x2c\x30\x2d\x38\x2e\x39\x30\x34\x2c\x30\x2e\x35\x38\x34\ -\x2d\x31\x33\x2e\x30\x34\x39\x2c\x31\x2e\x36\x37\x32\x43\x31\x37\ -\x34\x2e\x31\x38\x2c\x32\x37\x30\x2e\x36\x38\x39\x2c\x31\x36\x30\ -\x2c\x32\x38\x36\x2e\x36\x2c\x31\x36\x30\x2c\x33\x30\x37\x2e\x32\ -\x33\x36\x76\x33\x32\x2e\x39\x32\x32\x0d\x0a\x09\x09\x76\x35\x34\ -\x2e\x33\x30\x35\x63\x30\x2c\x32\x34\x2e\x38\x33\x32\x2c\x32\x34\ -\x2e\x39\x37\x37\x2c\x33\x39\x2e\x34\x32\x36\x2c\x34\x39\x2e\x34\ -\x38\x31\x2c\x34\x36\x2e\x35\x35\x31\x63\x32\x39\x2e\x33\x32\x37\ -\x2c\x38\x2e\x35\x33\x31\x2c\x36\x31\x2e\x32\x36\x37\x2c\x31\x30\ -\x2e\x30\x36\x38\x2c\x39\x36\x2e\x33\x36\x36\x2c\x30\x43\x33\x32\ -\x39\x2e\x31\x35\x2c\x34\x33\x34\x2e\x33\x35\x34\x2c\x33\x35\x32\ -\x2c\x34\x32\x30\x2e\x38\x39\x33\x2c\x33\x35\x32\x2c\x33\x39\x34\ -\x2e\x34\x36\x33\x56\x33\x36\x38\x0d\x0a\x09\x09\x68\x2d\x39\x36\ -\x76\x2d\x31\x36\x68\x31\x32\x37\x2e\x31\x38\x63\x32\x35\x2e\x32\ -\x34\x2c\x30\x2c\x34\x37\x2e\x31\x30\x37\x2d\x32\x31\x2e\x33\x36\ -\x35\x2c\x35\x37\x2e\x38\x31\x34\x2d\x35\x32\x2e\x35\x34\x39\x43\ -\x34\x34\x35\x2e\x34\x37\x34\x2c\x32\x38\x36\x2e\x34\x30\x34\x2c\ -\x34\x34\x38\x2c\x32\x37\x31\x2e\x36\x34\x31\x2c\x34\x34\x38\x2c\ -\x32\x35\x36\x0d\x0a\x09\x09\x43\x34\x34\x38\x2c\x32\x34\x34\x2e\ -\x32\x33\x32\x2c\x34\x34\x36\x2e\x35\x36\x37\x2c\x32\x33\x32\x2e\ -\x39\x36\x32\x2c\x34\x34\x33\x2e\x39\x35\x31\x2c\x32\x32\x32\x2e\ -\x35\x34\x33\x7a\x20\x4d\x33\x30\x37\x2e\x38\x36\x37\x2c\x33\x38\ -\x32\x2e\x38\x32\x63\x39\x2e\x35\x39\x2c\x30\x2c\x31\x37\x2e\x33\ -\x38\x31\x2c\x37\x2e\x37\x38\x35\x2c\x31\x37\x2e\x33\x38\x31\x2c\ -\x31\x37\x2e\x34\x0d\x0a\x09\x09\x63\x30\x2c\x39\x2e\x36\x35\x2d\ -\x37\x2e\x37\x39\x31\x2c\x31\x37\x2e\x35\x32\x31\x2d\x31\x37\x2e\ -\x33\x38\x31\x2c\x31\x37\x2e\x35\x32\x31\x63\x2d\x39\x2e\x35\x37\ -\x37\x2c\x30\x2d\x31\x37\x2e\x33\x39\x39\x2d\x37\x2e\x38\x37\x31\ -\x2d\x31\x37\x2e\x33\x39\x39\x2d\x31\x37\x2e\x35\x32\x31\x43\x32\ -\x39\x30\x2e\x34\x36\x38\x2c\x33\x39\x30\x2e\x35\x39\x2c\x32\x39\ -\x38\x2e\x32\x37\x34\x2c\x33\x38\x32\x2e\x38\x32\x2c\x33\x30\x37\ -\x2e\x38\x36\x37\x2c\x33\x38\x32\x2e\x38\x32\x7a\x22\x2f\x3e\x0d\ -\x0a\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -\x00\x00\x03\xeb\ -\x3c\ -\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\ -\x30\x22\x20\x65\x6e\x63\x6f\x64\x69\x6e\x67\x3d\x22\x75\x74\x66\ -\x2d\x38\x22\x3f\x3e\x0d\x0a\x3c\x21\x2d\x2d\x20\x47\x65\x6e\x65\ -\x72\x61\x74\x6f\x72\x3a\x20\x41\x64\x6f\x62\x65\x20\x49\x6c\x6c\ -\x75\x73\x74\x72\x61\x74\x6f\x72\x20\x31\x36\x2e\x32\x2e\x31\x2c\ -\x20\x53\x56\x47\x20\x45\x78\x70\x6f\x72\x74\x20\x50\x6c\x75\x67\ -\x2d\x49\x6e\x20\x2e\x20\x53\x56\x47\x20\x56\x65\x72\x73\x69\x6f\ -\x6e\x3a\x20\x36\x2e\x30\x30\x20\x42\x75\x69\x6c\x64\x20\x30\x29\ -\x20\x20\x2d\x2d\x3e\x0d\x0a\x3c\x21\x44\x4f\x43\x54\x59\x50\x45\ -\x20\x73\x76\x67\x20\x50\x55\x42\x4c\x49\x43\x20\x22\x2d\x2f\x2f\ -\x57\x33\x43\x2f\x2f\x44\x54\x44\x20\x53\x56\x47\x20\x31\x2e\x31\ -\x2f\x2f\x45\x4e\x22\x20\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\ -\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x47\x72\x61\x70\x68\x69\x63\ -\x73\x2f\x53\x56\x47\x2f\x31\x2e\x31\x2f\x44\x54\x44\x2f\x73\x76\ -\x67\x31\x31\x2e\x64\x74\x64\x22\x3e\x0d\x0a\x3c\x73\x76\x67\x20\ -\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x31\x22\x20\x69\x64\ -\x3d\x22\x4c\x61\x79\x65\x72\x5f\x31\x22\x20\x78\x6d\x6c\x6e\x73\ -\x3d\x22\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\ -\x6f\x72\x67\x2f\x32\x30\x30\x30\x2f\x73\x76\x67\x22\x20\x78\x6d\ -\x6c\x6e\x73\x3a\x78\x6c\x69\x6e\x6b\x3d\x22\x68\x74\x74\x70\x3a\ -\x2f\x2f\x77\x77\x77\x2e\x77\x33\x2e\x6f\x72\x67\x2f\x31\x39\x39\ -\x39\x2f\x78\x6c\x69\x6e\x6b\x22\x20\x78\x3d\x22\x30\x70\x78\x22\ -\x20\x79\x3d\x22\x30\x70\x78\x22\x0d\x0a\x09\x20\x77\x69\x64\x74\ -\x68\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x68\x65\x69\x67\x68\x74\ -\x3d\x22\x35\x31\x32\x70\x78\x22\x20\x76\x69\x65\x77\x42\x6f\x78\ -\x3d\x22\x30\x20\x30\x20\x35\x31\x32\x20\x35\x31\x32\x22\x20\x73\ -\x74\x79\x6c\x65\x3d\x22\x65\x6e\x61\x62\x6c\x65\x2d\x62\x61\x63\ -\x6b\x67\x72\x6f\x75\x6e\x64\x3a\x6e\x65\x77\x20\x30\x20\x30\x20\ -\x35\x31\x32\x20\x35\x31\x32\x3b\x22\x20\x78\x6d\x6c\x3a\x73\x70\ -\x61\x63\x65\x3d\x22\x70\x72\x65\x73\x65\x72\x76\x65\x22\x3e\x0d\ -\x0a\x3c\x67\x3e\x0d\x0a\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\ -\x4d\x32\x35\x36\x2c\x31\x32\x38\x63\x2d\x38\x31\x2e\x39\x2c\x30\ -\x2d\x31\x34\x35\x2e\x37\x2c\x34\x38\x2e\x38\x2d\x32\x32\x34\x2c\ -\x31\x32\x38\x63\x36\x37\x2e\x34\x2c\x36\x37\x2e\x37\x2c\x31\x32\ -\x34\x2c\x31\x32\x38\x2c\x32\x32\x34\x2c\x31\x32\x38\x63\x39\x39\ -\x2e\x39\x2c\x30\x2c\x31\x37\x33\x2e\x34\x2d\x37\x36\x2e\x34\x2c\ -\x32\x32\x34\x2d\x31\x32\x36\x2e\x36\x0d\x0a\x09\x09\x43\x34\x32\ -\x38\x2e\x32\x2c\x31\x39\x38\x2e\x36\x2c\x33\x35\x34\x2e\x38\x2c\ -\x31\x32\x38\x2c\x32\x35\x36\x2c\x31\x32\x38\x7a\x20\x4d\x32\x35\ -\x36\x2c\x33\x34\x37\x2e\x33\x63\x2d\x34\x39\x2e\x34\x2c\x30\x2d\ -\x38\x39\x2e\x36\x2d\x34\x31\x2d\x38\x39\x2e\x36\x2d\x39\x31\x2e\ -\x33\x63\x30\x2d\x35\x30\x2e\x34\x2c\x34\x30\x2e\x32\x2d\x39\x31\ -\x2e\x33\x2c\x38\x39\x2e\x36\x2d\x39\x31\x2e\x33\x73\x38\x39\x2e\ -\x36\x2c\x34\x31\x2c\x38\x39\x2e\x36\x2c\x39\x31\x2e\x33\x0d\x0a\ -\x09\x09\x43\x33\x34\x35\x2e\x36\x2c\x33\x30\x36\x2e\x34\x2c\x33\ -\x30\x35\x2e\x34\x2c\x33\x34\x37\x2e\x33\x2c\x32\x35\x36\x2c\x33\ -\x34\x37\x2e\x33\x7a\x22\x2f\x3e\x0d\x0a\x09\x3c\x67\x3e\x0d\x0a\ -\x09\x09\x3c\x70\x61\x74\x68\x20\x64\x3d\x22\x4d\x32\x35\x36\x2c\ -\x32\x32\x34\x63\x30\x2d\x37\x2e\x39\x2c\x32\x2e\x39\x2d\x31\x35\ -\x2e\x31\x2c\x37\x2e\x36\x2d\x32\x30\x2e\x37\x63\x2d\x32\x2e\x35\ -\x2d\x30\x2e\x34\x2d\x35\x2d\x30\x2e\x36\x2d\x37\x2e\x36\x2d\x30\ -\x2e\x36\x63\x2d\x32\x38\x2e\x38\x2c\x30\x2d\x35\x32\x2e\x33\x2c\ -\x32\x33\x2e\x39\x2d\x35\x32\x2e\x33\x2c\x35\x33\x2e\x33\x63\x30\ -\x2c\x32\x39\x2e\x34\x2c\x32\x33\x2e\x35\x2c\x35\x33\x2e\x33\x2c\ -\x35\x32\x2e\x33\x2c\x35\x33\x2e\x33\x0d\x0a\x09\x09\x09\x73\x35\ -\x32\x2e\x33\x2d\x32\x33\x2e\x39\x2c\x35\x32\x2e\x33\x2d\x35\x33\ -\x2e\x33\x63\x30\x2d\x32\x2e\x33\x2d\x30\x2e\x32\x2d\x34\x2e\x36\ -\x2d\x30\x2e\x34\x2d\x36\x2e\x39\x63\x2d\x35\x2e\x35\x2c\x34\x2e\ -\x33\x2d\x31\x32\x2e\x33\x2c\x36\x2e\x39\x2d\x31\x39\x2e\x38\x2c\ -\x36\x2e\x39\x43\x32\x37\x30\x2e\x33\x2c\x32\x35\x36\x2c\x32\x35\ -\x36\x2c\x32\x34\x31\x2e\x37\x2c\x32\x35\x36\x2c\x32\x32\x34\x7a\ -\x22\x2f\x3e\x0d\x0a\x09\x3c\x2f\x67\x3e\x0d\x0a\x3c\x2f\x67\x3e\ -\x0d\x0a\x3c\x2f\x73\x76\x67\x3e\x0d\x0a\ -" - -qt_resource_name = b"\ -\x00\x05\ -\x00\x6f\xa6\x53\ -\x00\x69\ -\x00\x63\x00\x6f\x00\x6e\x00\x73\ -\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\x09\ -\x0b\x9e\x89\x07\ -\x00\x63\ -\x00\x68\x00\x65\x00\x63\x00\x6b\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\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\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\ -\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\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\x08\ -\x08\xc8\x55\xe7\ -\x00\x73\ -\x00\x61\x00\x76\x00\x65\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\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\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\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\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\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\x08\ -\x08\xf7\x57\x07\ -\x00\x67\ -\x00\x72\x00\x69\x00\x64\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\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\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\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\x08\ -\x0c\xf7\x55\x87\ -\x00\x74\ -\x00\x65\x00\x78\x00\x74\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\x08\ -\x05\xa8\x57\x87\ -\x00\x63\ -\x00\x6f\x00\x64\x00\x65\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\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\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\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\x1b\ -\x0e\xb5\x68\xe7\ -\x00\x61\ -\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x72\x00\x61\x00\x64\x00\x69\x00\x6f\x00\x2d\x00\x62\x00\x75\x00\x74\ -\x00\x74\x00\x6f\x00\x6e\x00\x2d\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\ -\x00\x10\ -\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\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\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\x16\ -\x01\xfb\x76\x27\ -\x00\x61\ -\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x61\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x62\x00\x61\x00\x63\ -\x00\x6b\x00\x2e\x00\x73\x00\x76\x00\x67\ -\x00\x0e\ -\x05\xed\x38\x67\ -\x00\x61\ -\x00\x72\x00\x72\x00\x6f\x00\x77\x00\x2d\x00\x6d\x00\x6f\x00\x76\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ -\x00\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\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\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\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\ -\x0b\x07\x57\xa7\ -\x00\x65\ -\x00\x64\x00\x69\x00\x74\x00\x2e\x00\x73\x00\x76\x00\x67\ -\x00\x19\ -\x0f\xef\x7b\xe7\ -\x00\x61\ -\x00\x6e\x00\x64\x00\x72\x00\x6f\x00\x69\x00\x64\x00\x2d\x00\x63\x00\x6f\x00\x6c\x00\x6f\x00\x72\x00\x2d\x00\x70\x00\x61\x00\x6c\ -\x00\x65\x00\x74\x00\x74\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ -\x00\x11\ -\x01\x60\xbc\x47\ -\x00\x73\ -\x00\x6f\x00\x63\x00\x69\x00\x61\x00\x6c\x00\x2d\x00\x70\x00\x79\x00\x74\x00\x68\x00\x6f\x00\x6e\x00\x2e\x00\x73\x00\x76\x00\x67\ -\ -\x00\x07\ -\x0c\xf8\x5a\x07\ -\x00\x65\ -\x00\x79\x00\x65\x00\x2e\x00\x73\x00\x76\x00\x67\ -" - -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\x06\x10\x00\x00\x00\x00\x00\x01\x00\x00\x82\xd5\ -\x00\x00\x02\x96\x00\x00\x00\x00\x00\x01\x00\x00\x36\x4d\ -\x00\x00\x04\xbe\x00\x00\x00\x00\x00\x01\x00\x00\x68\xdb\ -\x00\x00\x02\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x33\x23\ -\x00\x00\x01\x96\x00\x00\x00\x00\x00\x01\x00\x00\x22\x76\ -\x00\x00\x00\xaa\x00\x01\x00\x00\x00\x01\x00\x00\x10\x6b\ -\x00\x00\x03\x30\x00\x00\x00\x00\x00\x01\x00\x00\x45\x97\ -\x00\x00\x03\xd0\x00\x00\x00\x00\x00\x01\x00\x00\x54\x52\ -\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x03\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x48\xd1\ -\x00\x00\x04\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x6b\x5c\ -\x00\x00\x01\xfc\x00\x00\x00\x00\x00\x01\x00\x00\x29\x2a\ -\x00\x00\x05\x12\x00\x00\x00\x00\x00\x01\x00\x00\x6e\x29\ -\x00\x00\x02\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x25\ -\x00\x00\x04\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x64\x9a\ -\x00\x00\x05\x38\x00\x00\x00\x00\x00\x01\x00\x00\x73\xf7\ -\x00\x00\x04\x70\x00\x00\x00\x00\x00\x01\x00\x00\x61\xf4\ -\x00\x00\x01\x2e\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x50\ -\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x00\x12\x90\ -\x00\x00\x01\x58\x00\x00\x00\x00\x00\x01\x00\x00\x1f\x76\ -\x00\x00\x00\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x16\xb0\ -\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x77\xbd\ -\x00\x00\x02\x30\x00\x01\x00\x00\x00\x01\x00\x00\x2d\xf8\ -\x00\x00\x02\x46\x00\x00\x00\x00\x00\x01\x00\x00\x2f\xd9\ -\x00\x00\x03\xf4\x00\x00\x00\x00\x00\x01\x00\x00\x59\x2b\ -\x00\x00\x03\x70\x00\x00\x00\x00\x00\x01\x00\x00\x4d\x7f\ -\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xeb\ -\x00\x00\x05\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x7a\x3a\ -\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x04\xa6\ -\x00\x00\x04\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x5f\x71\ -\x00\x00\x03\x06\x00\x00\x00\x00\x00\x01\x00\x00\x41\x2f\ -\x00\x00\x03\xa8\x00\x00\x00\x00\x00\x01\x00\x00\x50\x00\ -\x00\x00\x01\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x26\x6f\ -\x00\x00\x02\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x40\x0f\ -\x00\x00\x06\x38\x00\x00\x00\x00\x00\x01\x00\x00\x8a\x59\ -\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x5c\x21\ -\x00\x00\x00\x76\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x7e\ -\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x07\xb6\ -\x00\x00\x05\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x77\x4d\ -\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x19\x55\ -\x00\x00\x05\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x7d\xaa\ -" - -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\x06\x10\x00\x00\x00\x00\x00\x01\x00\x00\x82\xd5\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x02\x96\x00\x00\x00\x00\x00\x01\x00\x00\x36\x4d\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x04\xbe\x00\x00\x00\x00\x00\x01\x00\x00\x68\xdb\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x02\x6a\x00\x00\x00\x00\x00\x01\x00\x00\x33\x23\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x01\x96\x00\x00\x00\x00\x00\x01\x00\x00\x22\x76\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x00\xaa\x00\x01\x00\x00\x00\x01\x00\x00\x10\x6b\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x03\x30\x00\x00\x00\x00\x00\x01\x00\x00\x45\x97\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x03\xd0\x00\x00\x00\x00\x00\x01\x00\x00\x54\x52\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x03\x5a\x00\x00\x00\x00\x00\x01\x00\x00\x48\xd1\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x04\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x6b\x5c\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x01\xfc\x00\x00\x00\x00\x00\x01\x00\x00\x29\x2a\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x05\x12\x00\x00\x00\x00\x00\x01\x00\x00\x6e\x29\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x02\xb0\x00\x00\x00\x00\x00\x01\x00\x00\x3c\x25\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x04\x9a\x00\x00\x00\x00\x00\x01\x00\x00\x64\x9a\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x05\x38\x00\x00\x00\x00\x00\x01\x00\x00\x73\xf7\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x04\x70\x00\x00\x00\x00\x00\x01\x00\x00\x61\xf4\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x01\x2e\x00\x00\x00\x00\x00\x01\x00\x00\x1c\x50\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x00\x12\x90\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x01\x58\x00\x00\x00\x00\x00\x01\x00\x00\x1f\x76\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x00\xf6\x00\x00\x00\x00\x00\x01\x00\x00\x16\xb0\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x05\x9c\x00\x00\x00\x00\x00\x01\x00\x00\x77\xbd\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x02\x30\x00\x01\x00\x00\x00\x01\x00\x00\x2d\xf8\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x02\x46\x00\x00\x00\x00\x00\x01\x00\x00\x2f\xd9\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x03\xf4\x00\x00\x00\x00\x00\x01\x00\x00\x59\x2b\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x03\x70\x00\x00\x00\x00\x00\x01\x00\x00\x4d\x7f\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x00\x90\x00\x00\x00\x00\x00\x01\x00\x00\x0c\xeb\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x05\xc2\x00\x00\x00\x00\x00\x01\x00\x00\x7a\x3a\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x00\x30\x00\x00\x00\x00\x00\x01\x00\x00\x04\xa6\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x04\x4a\x00\x00\x00\x00\x00\x01\x00\x00\x5f\x71\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x03\x06\x00\x00\x00\x00\x00\x01\x00\x00\x41\x2f\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x03\xa8\x00\x00\x00\x00\x00\x01\x00\x00\x50\x00\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x01\xd4\x00\x00\x00\x00\x00\x01\x00\x00\x26\x6f\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x02\xf0\x00\x00\x00\x00\x00\x01\x00\x00\x40\x0f\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x06\x38\x00\x00\x00\x00\x00\x01\x00\x00\x8a\x59\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x04\x0e\x00\x00\x00\x00\x00\x01\x00\x00\x5c\x21\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x00\x76\x00\x00\x00\x00\x00\x01\x00\x00\x0b\x7e\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -\x00\x00\x00\x48\x00\x00\x00\x00\x00\x01\x00\x00\x07\xb6\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x05\x6c\x00\x00\x00\x00\x00\x01\x00\x00\x77\x4d\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x01\x0c\x00\x00\x00\x00\x00\x01\x00\x00\x19\x55\ -\x00\x00\x01\x78\x33\x4a\x26\xbc\ -\x00\x00\x05\xd8\x00\x00\x00\x00\x00\x01\x00\x00\x7d\xaa\ -\x00\x00\x01\x78\x33\x4a\x26\xbb\ -" - -qt_version = [int(v) for v in QtCore.qVersion().split('.')] -if qt_version < [5, 8, 0]: - rcc_version = 1 - qt_resource_struct = qt_resource_struct_v1 -else: - rcc_version = 2 - qt_resource_struct = qt_resource_struct_v2 - -def qInitResources(): - QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -def qCleanupResources(): - QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) - -qInitResources() diff --git a/Build/source/utils/asymptote/GUI/labelEditor.py b/Build/source/utils/asymptote/GUI/labelEditor.py index 76bc8d7d0a1..7da1c5f9037 100644 --- a/Build/source/utils/asymptote/GUI/labelEditor.py +++ b/Build/source/utils/asymptote/GUI/labelEditor.py @@ -1,22 +1,22 @@ #!/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 PyQt5.QtWidgets as QtWidgets +import PyQt5.QtSvg as QtSvg +import PyQt5.QtGui as QtGui +import PyQt5.QtCore as QtCore +import xasyArgs as xasyArgs +import xasy2asy as xasy2asy +import xasyOptions as xasyOptions +import xasyUtils as xasyUtils import subprocess -import xasyOptions as xo -import xasyUtils as xu import tempfile import uuid import os import io -class labelEditor(Qw.QDialog): +class labelEditor(QtWidgets.QDialog): def __init__(self, text=''): super().__init__() self.ui = Ui_Dialog() @@ -67,9 +67,9 @@ class labelEditor(Qw.QDialog): return rawText def btnPreviewOnClick(self): - path = xa.getArgs().asypath + path = xasyArgs.getArgs().asypath if path is None: - opt = xo.xasyOptions().load() + opt = xo.BasicConfigs.defaultOpt path = opt['asyPath'] asyInput = """ @@ -80,7 +80,7 @@ class labelEditor(Qw.QDialog): shipout(f); """ - self.svgPreview = Qs.QSvgRenderer() + self.svgPreview = QtSvg.QSvgRenderer() with tempfile.TemporaryDirectory(prefix='xasylbl_') as tmpdir: id = str(uuid.uuid4()) tmpFile = os.path.join(tmpdir, 'lbl-{0}.svg'.format(id)) @@ -95,8 +95,8 @@ class labelEditor(Qw.QDialog): 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)) + min_bounds = xasyUtils.listize(bounds_1, (float, float)) + max_bounds = xasyUtils.listize(bounds_2, (float, float)) new_rect = self.processBounds(min_bounds, max_bounds) self.svgPreview.load(tmpFile) @@ -106,12 +106,12 @@ class labelEditor(Qw.QDialog): self.drawPreview(new_rect) def drawPreview(self, naturalBounds): - img = Qg.QPixmap(self.ui.lblLabelPreview.size()) - img.fill(Qg.QColor.fromRgbF(1, 1, 1, 1)) + img = QtGui.QPixmap(self.ui.lblLabelPreview.size()) + img.fill(QtGui.QColor.fromRgbF(1, 1, 1, 1)) if self.svgPreview is None: pass else: - with Qg.QPainter(img) as pnt: + with QtGui.QPainter(img) as pnt: scale_ratio = self.getIdealScaleRatio(naturalBounds, self.ui.lblLabelPreview.rect()) pnt.translate(self.ui.lblLabelPreview.rect().center()) @@ -121,8 +121,8 @@ class labelEditor(Qw.QDialog): def getIdealScaleRatio(self, rect, boundsRect): - assert isinstance(rect, (Qc.QRect, Qc.QRectF)) - assert isinstance(rect, (Qc.QRect, Qc.QRectF)) + assert isinstance(rect, (QtCore.QRect, QtCore.QRectF)) + assert isinstance(rect, (QtCore.QRect, QtCore.QRectF)) magic_ratio = 0.50 idealRatioHeight = (magic_ratio * boundsRect.height()) / rect.height() @@ -139,15 +139,15 @@ class labelEditor(Qw.QDialog): p1x, p1y = minPt p2x, p2y = maxPt - minPt = Qc.QPointF(p1x, p1y) - maxPt = Qc.QPointF(p2x, p2y) + minPt = QtCore.QPointF(p1x, p1y) + maxPt = QtCore.QPointF(p2x, p2y) - newRect = Qc.QRectF(minPt, maxPt) + newRect = QtCore.QRectF(minPt, maxPt) return newRect def btnGetTextOnClick(self): - msgbox = Qw.QMessageBox() + msgbox = QtWidgets.QMessageBox() msgbox.setText('Text Preview:\n' + self.getText()) msgbox.setWindowTitle('Text preview') msgbox.show() diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py b/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py index d0bddd46458..aeaf61f9a26 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/custMatTransform.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/custMatTransform.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py b/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py index 3cb24c9e2fe..fc35454c83e 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/labelTextEditor.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/labelTextEditor.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py b/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py index 9b76e5d6d0e..ab0fc77c0b6 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/setCustomAnchor.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/setCustomAnchor.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py index 0412fc550d5..9b17990e6bc 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addLabel.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/widg_addLabel.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py index 2c91681bce6..69cf2a4630c 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/widg_addPolyOpt.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/widg_addPolyOpt.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets @@ -31,11 +32,21 @@ class Ui_Form(object): self.chkInscribed = QtWidgets.QCheckBox(Form) self.chkInscribed.setObjectName("chkInscribed") self.horizontalLayout.addWidget(self.chkInscribed) + spacerItem = QtWidgets.QSpacerItem(19, 20, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.label = QtWidgets.QLabel(Form) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) + self.label.setSizePolicy(sizePolicy) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) 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) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem1) self.horizontalLayout_2.addLayout(self.horizontalLayout) self.retranslateUi(Form) @@ -45,5 +56,6 @@ class Ui_Form(object): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "Form")) self.chkInscribed.setText(_translate("Form", "Start at Vertex")) + self.label.setText(_translate("Form", "Sides: ")) self.txtSides.setToolTip(_translate("Form", "Number of Sides")) self.txtSides.setPlaceholderText(_translate("Form", "Sides")) diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py b/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py index d39e49e4b98..4c2d90d7127 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/widg_editBezier.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/widg_editBezier.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py b/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py index a38790bdecd..0b4f5d94935 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/widgetPointEditor.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/widgetPointEditor.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets diff --git a/Build/source/utils/asymptote/GUI/pyUIClass/window1.py b/Build/source/utils/asymptote/GUI/pyUIClass/window1.py index 6180d5fed3f..edf87b84c1a 100644 --- a/Build/source/utils/asymptote/GUI/pyUIClass/window1.py +++ b/Build/source/utils/asymptote/GUI/pyUIClass/window1.py @@ -2,9 +2,10 @@ # Form implementation generated from reading ui file 'GUI/windows/window1.ui' # -# Created by: PyQt5 UI code generator 5.13.1 +# Created by: PyQt5 UI code generator 5.15.0 # -# WARNING! All changes made in this file will be lost! +# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# run again. Do not edit this file unless you know what you are doing. from PyQt5 import QtCore, QtGui, QtWidgets @@ -62,7 +63,7 @@ class Ui_MainWindow(object): 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) + icon.addPixmap(QtGui.QPixmap(":/icons/undo.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnUndo.setIcon(icon) self.btnUndo.setIconSize(QtCore.QSize(16, 16)) self.btnUndo.setFlat(True) @@ -79,7 +80,7 @@ class Ui_MainWindow(object): 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) + icon1.addPixmap(QtGui.QPixmap(":/icons/redo.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnRedo.setIcon(icon1) self.btnRedo.setIconSize(QtCore.QSize(16, 16)) self.btnRedo.setFlat(True) @@ -251,7 +252,7 @@ class Ui_MainWindow(object): sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.btnAlignX.sizePolicy().hasHeightForWidth()) self.btnAlignX.setSizePolicy(sizePolicy) - self.btnAlignX.setMaximumSize(QtCore.QSize(25, 25)) + self.btnAlignX.setMaximumSize(QtCore.QSize(32, 25)) self.btnAlignX.setBaseSize(QtCore.QSize(32, 32)) font = QtGui.QFont() font.setFamily("Roboto") @@ -269,9 +270,10 @@ class Ui_MainWindow(object): sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.btnAlignY.sizePolicy().hasHeightForWidth()) self.btnAlignY.setSizePolicy(sizePolicy) - self.btnAlignY.setMaximumSize(QtCore.QSize(25, 25)) + self.btnAlignY.setMaximumSize(QtCore.QSize(32, 25)) self.btnAlignY.setBaseSize(QtCore.QSize(32, 32)) font = QtGui.QFont() + font.setFamily("Roboto") font.setBold(True) font.setWeight(75) self.btnAlignY.setFont(font) @@ -295,6 +297,7 @@ class Ui_MainWindow(object): icon11.addPixmap(QtGui.QPixmap(":/icons/edit.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnSelectEdit.setIcon(icon11) self.btnSelectEdit.setIconSize(QtCore.QSize(16, 16)) + self.btnSelectEdit.setCheckable(True) self.btnSelectEdit.setFlat(True) self.btnSelectEdit.setObjectName("btnSelectEdit") self.horizontalLayout.addWidget(self.btnSelectEdit) @@ -312,7 +315,7 @@ class Ui_MainWindow(object): icon12.addPixmap(QtGui.QPixmap(":/icons/android-delete.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnDeleteMode.setIcon(icon12) self.btnDeleteMode.setIconSize(QtCore.QSize(16, 16)) - self.btnDeleteMode.setCheckable(False) + self.btnDeleteMode.setCheckable(True) self.btnDeleteMode.setFlat(True) self.btnDeleteMode.setObjectName("btnDeleteMode") self.horizontalLayout.addWidget(self.btnDeleteMode) @@ -646,6 +649,7 @@ class Ui_MainWindow(object): icon24.addPixmap(QtGui.QPixmap(":/icons/openpolygon.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnOpenPoly.setIcon(icon24) self.btnOpenPoly.setIconSize(QtCore.QSize(16, 16)) + self.btnOpenPoly.setCheckable(True) self.btnOpenPoly.setFlat(True) self.btnOpenPoly.setObjectName("btnOpenPoly") self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.btnOpenPoly) @@ -662,6 +666,7 @@ class Ui_MainWindow(object): icon25.addPixmap(QtGui.QPixmap(":/icons/closedpolygon.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnClosedPoly.setIcon(icon25) self.btnClosedPoly.setIconSize(QtCore.QSize(16, 16)) + self.btnClosedPoly.setCheckable(True) self.btnClosedPoly.setFlat(True) self.btnClosedPoly.setObjectName("btnClosedPoly") self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.btnClosedPoly) @@ -678,6 +683,7 @@ class Ui_MainWindow(object): icon26.addPixmap(QtGui.QPixmap(":/icons/opencurve.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnOpenCurve.setIcon(icon26) self.btnOpenCurve.setIconSize(QtCore.QSize(16, 16)) + self.btnOpenCurve.setCheckable(True) self.btnOpenCurve.setFlat(True) self.btnOpenCurve.setObjectName("btnOpenCurve") self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.btnOpenCurve) @@ -694,6 +700,7 @@ class Ui_MainWindow(object): icon27.addPixmap(QtGui.QPixmap(":/icons/closedcurve.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnClosedCurve.setIcon(icon27) self.btnClosedCurve.setIconSize(QtCore.QSize(16, 16)) + self.btnClosedCurve.setCheckable(True) self.btnClosedCurve.setFlat(True) self.btnClosedCurve.setObjectName("btnClosedCurve") self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.btnClosedCurve) @@ -710,6 +717,7 @@ class Ui_MainWindow(object): icon28.addPixmap(QtGui.QPixmap(":/icons/triangle-stroked-15.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnAddPoly.setIcon(icon28) self.btnAddPoly.setIconSize(QtCore.QSize(16, 16)) + self.btnAddPoly.setCheckable(True) self.btnAddPoly.setFlat(True) self.btnAddPoly.setObjectName("btnAddPoly") self.formLayout.setWidget(8, QtWidgets.QFormLayout.LabelRole, self.btnAddPoly) @@ -726,6 +734,7 @@ class Ui_MainWindow(object): icon29.addPixmap(QtGui.QPixmap(":/icons/circle.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnAddCircle.setIcon(icon29) self.btnAddCircle.setIconSize(QtCore.QSize(16, 16)) + self.btnAddCircle.setCheckable(True) self.btnAddCircle.setFlat(True) self.btnAddCircle.setObjectName("btnAddCircle") self.formLayout.setWidget(10, QtWidgets.QFormLayout.LabelRole, self.btnAddCircle) @@ -742,9 +751,27 @@ class Ui_MainWindow(object): icon30.addPixmap(QtGui.QPixmap(":/icons/text.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) self.btnAddLabel.setIcon(icon30) self.btnAddLabel.setIconSize(QtCore.QSize(16, 16)) + self.btnAddLabel.setCheckable(True) self.btnAddLabel.setFlat(True) self.btnAddLabel.setObjectName("btnAddLabel") self.formLayout.setWidget(11, QtWidgets.QFormLayout.LabelRole, self.btnAddLabel) + self.btnAddFreehand = QtWidgets.QPushButton(self.formFrame) + self.btnAddFreehand.setEnabled(True) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.btnAddFreehand.sizePolicy().hasHeightForWidth()) + self.btnAddFreehand.setSizePolicy(sizePolicy) + self.btnAddFreehand.setMaximumSize(QtCore.QSize(32, 32)) + self.btnAddFreehand.setText("") + icon31 = QtGui.QIcon() + icon31.addPixmap(QtGui.QPixmap(":/icons/brush.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.btnAddFreehand.setIcon(icon31) + self.btnAddFreehand.setIconSize(QtCore.QSize(16, 16)) + self.btnAddFreehand.setCheckable(True) + self.btnAddFreehand.setFlat(True) + self.btnAddFreehand.setObjectName("btnAddFreehand") + self.formLayout.setWidget(12, QtWidgets.QFormLayout.LabelRole, self.btnAddFreehand) self.horizontalLayout_7.addWidget(self.formFrame) self.imgFrame = QtWidgets.QFrame(self.mainWidget) self.imgFrame.setMinimumSize(QtCore.QSize(0, 6)) @@ -783,9 +810,9 @@ class Ui_MainWindow(object): 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) + icon32 = QtGui.QIcon() + icon32.addPixmap(QtGui.QPixmap(":/icons/social-python.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.btnTogglePython.setIcon(icon32) self.btnTogglePython.setIconSize(QtCore.QSize(16, 16)) self.btnTogglePython.setCheckable(True) self.btnTogglePython.setFlat(True) @@ -807,9 +834,9 @@ class Ui_MainWindow(object): 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) + icon33 = QtGui.QIcon() + icon33.addPixmap(QtGui.QPixmap(":/icons/subdirectory-left.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + self.btnEnterCommand.setIcon(icon33) self.btnEnterCommand.setIconSize(QtCore.QSize(16, 16)) self.btnEnterCommand.setFlat(True) self.btnEnterCommand.setObjectName("btnEnterCommand") @@ -820,10 +847,12 @@ class Ui_MainWindow(object): self.horizontalLayout_4.addWidget(self.mainWidget) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 1000, 29)) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1000, 26)) self.menubar.setObjectName("menubar") self.menuFIle = QtWidgets.QMenu(self.menubar) self.menuFIle.setObjectName("menuFIle") + self.menuOpenRecent = QtWidgets.QMenu(self.menuFIle) + self.menuOpenRecent.setObjectName("menuOpenRecent") self.menuEdit = QtWidgets.QMenu(self.menubar) self.menuEdit.setObjectName("menuEdit") self.menuOptions = QtWidgets.QMenu(self.menubar) @@ -869,9 +898,22 @@ class Ui_MainWindow(object): self.actionSave.setObjectName("actionSave") self.actionOpen = QtWidgets.QAction(MainWindow) self.actionOpen.setObjectName("actionOpen") + self.actionClearRecent = QtWidgets.QAction(MainWindow) + self.actionClearRecent.setObjectName("actionClearRecent") + self.actionNewFile = QtWidgets.QAction(MainWindow) + self.actionNewFile.setObjectName("actionNewFile") + self.actionExportToAsy = QtWidgets.QAction(MainWindow) + self.actionExportToAsy.setObjectName("actionExportToAsy") + self.actionKeymaps = QtWidgets.QAction(MainWindow) + self.actionKeymaps.setObjectName("actionKeymaps") + self.menuOpenRecent.addSeparator() + self.menuOpenRecent.addAction(self.actionClearRecent) + self.menuFIle.addAction(self.actionNewFile) self.menuFIle.addAction(self.actionOpen) + self.menuFIle.addAction(self.menuOpenRecent.menuAction()) self.menuFIle.addAction(self.actionSave) self.menuFIle.addAction(self.actionSaveAs) + self.menuFIle.addAction(self.actionExportToAsy) self.menuFIle.addAction(self.actionExportAsymptote) self.menuFIle.addSeparator() self.menuFIle.addAction(self.actionQuit) @@ -879,6 +921,7 @@ class Ui_MainWindow(object): self.menuEdit.addAction(self.actionRedo) self.menuEdit.addSeparator() self.menuOptions.addAction(self.actionSettings) + self.menuOptions.addAction(self.actionKeymaps) self.menuHelp.addAction(self.actionManual) self.menuHelp.addAction(self.actionAbout) self.menuTools.addAction(self.actionEnterCommand) @@ -941,7 +984,9 @@ class Ui_MainWindow(object): 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.btnAddFreehand.setToolTip(_translate("MainWindow", "<html><head/><body><p>Freehand</p></body></html>")) self.menuFIle.setTitle(_translate("MainWindow", "&File")) + self.menuOpenRecent.setTitle(_translate("MainWindow", "Open Recent")) self.menuEdit.setTitle(_translate("MainWindow", "&Edit")) self.menuOptions.setTitle(_translate("MainWindow", "Optio&ns")) self.menuHelp.setTitle(_translate("MainWindow", "&Help")) @@ -950,7 +995,7 @@ class Ui_MainWindow(object): 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.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")) @@ -958,7 +1003,11 @@ class Ui_MainWindow(object): 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.actionExportAsymptote.setText(_translate("MainWindow", "Export as...")) self.actionSave.setText(_translate("MainWindow", "Save")) self.actionOpen.setText(_translate("MainWindow", "Open")) + self.actionClearRecent.setText(_translate("MainWindow", "Clear Menu")) + self.actionNewFile.setText(_translate("MainWindow", "New File")) + self.actionExportToAsy.setText(_translate("MainWindow", "Export as Asy")) + self.actionKeymaps.setText(_translate("MainWindow", "&Keymaps")) import icons_rc diff --git a/Build/source/utils/asymptote/GUI/res/icons.qrc b/Build/source/utils/asymptote/GUI/res/icons.qrc index 50928ef9b74..5ca468acc2a 100644 --- a/Build/source/utils/asymptote/GUI/res/icons.qrc +++ b/Build/source/utils/asymptote/GUI/res/icons.qrc @@ -41,5 +41,8 @@ <file>icons/android-radio-button-off.svg</file> <file>icons/android-locate.svg</file> <file>icons/close-round.svg</file> + <file>icons/brush.svg</file> + <file>icons/undo.svg</file> + <file>icons/redo.svg</file> </qresource> </RCC> diff --git a/Build/source/utils/asymptote/GUI/res/icons/brush.svg b/Build/source/utils/asymptote/GUI/res/icons/brush.svg new file mode 100644 index 00000000000..0c6a54340bd --- /dev/null +++ b/Build/source/utils/asymptote/GUI/res/icons/brush.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.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="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="M48.451,464.828c40.023-0.315,45.01-9.955,58.052-50.132c24.057-63.408,132.419,16.591,65.269,44.374
+ C104.622,486.852,8.428,465.143,48.451,464.828z"/>
+ <path d="M458.857,46.902c-19.417-15.647-51.592-7.938-71.864,17.219L181.645,355.849c-20.272,25.154-20.171,20.347-0.754,35.992
+ c19.417,15.648,14.738,16.77,35.011-8.388l241.406-262.669C477.581,95.628,478.275,62.55,458.857,46.902z M406.065,81.825
+ c0,0-3-3.5-13-11.5c15-24.5,44.5-20,44.5-20C409.565,66.825,406.065,81.825,406.065,81.825z"/>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/bucket.asy b/Build/source/utils/asymptote/GUI/res/icons/bucket.asy index 87447436981..5f6e071cce8 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/bucket.asy +++ b/Build/source/utils/asymptote/GUI/res/icons/bucket.asy @@ -9,7 +9,7 @@ path left=(-r,h)--(-r,0); path right=(r,0)--(r,h); path bottom=xscale(r)*arc(0,1,180,360); -real H=0.9h; +real H=0.8h; path Left=(-r,H/2)--(-r,0); path Right=(r,0)--(r,H/2); @@ -17,7 +17,7 @@ bool fill=false; // Set to true for filled bucket. usersetting(); if(fill) - fill(Left--bottom--Right--shift(0,H)*xscale(r)*arc(0,1,0,180)--cycle,gray); + fill(Left--bottom--Right--shift(0,H)*xscale(r)*arc(0,1,0,180)--cycle,paleblue); draw(shift(0,h)*xscale(r)*unitcircle); draw(left--bottom--right); diff --git a/Build/source/utils/asymptote/GUI/res/icons/bucket.svg b/Build/source/utils/asymptote/GUI/res/icons/bucket.svg index 4a41e9873b2..11a867ac9ff 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/bucket.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/bucket.svg @@ -1,15 +1,15 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='64pt' viewBox='56.4094 117.858 63.9996 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 54.8926 -39.7109C 54.8926 -43.9032 44.6969 -47.3017 32.12 -47.3017C 19.5431 -47.3017 9.34742 -43.9032 9.34742 -39.7109C 9.34742 -35.5185 19.5431 -32.12 32.12 -32.12C 44.6969 -32.12 54.8926 -35.5185 54.8926 -39.7109Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 54.8926 24.5291C 54.8926 20.3368 44.6969 16.9383 32.12 16.9383C 19.5431 16.9383 9.34742 20.3368 9.34742 24.5291C 9.34742 28.7215 19.5431 32.12 32.12 32.12C 44.6969 32.12 54.8926 28.7215 54.8926 24.5291Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 9.34742 -39.7109L 9.34742 -9.34742L 9.34742 -9.34742C 9.34742 -9.34742 9.34742 -9.34742 9.34742 -9.34742C 9.34742 -5.15511 19.5431 -1.75656 32.12 -1.75656C 44.6969 -1.75656 54.8926 -5.15511 54.8926 -9.34742L 54.8926 -9.34742L 54.8926 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 9.34742 24.5291L 9.34742 54.8926L 9.34742 54.8926C 9.34742 54.8926 9.34742 54.8926 9.34742 54.8926C 9.34742 59.0849 19.5431 62.4834 32.12 62.4834C 44.6969 62.4834 54.8926 59.0849 54.8926 54.8926L 54.8926 54.8926L 54.8926 24.5291' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 54.8926 -39.7109C 54.8926 -52.2878 44.6969 -62.4834 32.12 -62.4834C 19.5431 -62.4834 9.34742 -52.2878 9.34742 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 54.8926 24.5291C 54.8926 11.9522 44.6969 1.75656 32.12 1.75656C 19.5431 1.75656 9.34742 11.9522 9.34742 24.5291' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/center.svg b/Build/source/utils/asymptote/GUI/res/icons/center.svg index 9a7cb1b17d7..6c378d1e7e7 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/center.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/center.svg @@ -1,12 +1,12 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='64pt' viewBox='56.4094 117.858 63.9996 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 2.0075 -2.0075L 62.2325 -2.0075L 62.2325 -62.2325L 2.0075 -62.2325L 2.0075 -2.0075Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 2.0075 62.2325L 62.2325 62.2325L 62.2325 2.0075L 2.0075 2.0075L 2.0075 62.2325Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 47.1762 -32.12C 47.1762 -40.4353 40.4353 -47.1762 32.12 -47.1762C 23.8047 -47.1762 17.0637 -40.4353 17.0637 -32.12C 17.0637 -23.8047 23.8047 -17.0637 32.12 -17.0637C 40.4353 -17.0637 47.1762 -23.8047 47.1762 -32.12Z' fill='#000000'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 47.1762 32.12C 47.1762 23.8047 40.4353 17.0637 32.12 17.0637C 23.8047 17.0637 17.0637 23.8047 17.0637 32.12C 17.0637 40.4353 23.8047 47.1762 32.12 47.1762C 40.4353 47.1762 47.1762 40.4353 47.1762 32.12Z' fill='#000000'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg b/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg index ee3cca26293..cce97c373b2 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/centerorigin.svg @@ -1,15 +1,15 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='64pt' viewBox='56.4094 117.858 63.9996 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 2.0075 -2.0075L 62.2325 -2.0075L 62.2325 -62.2325L 2.0075 -62.2325L 2.0075 -2.0075Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 2.0075 62.2325L 62.2325 62.2325L 62.2325 2.0075L 2.0075 2.0075L 2.0075 62.2325Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 2.0075 -32.12L 62.2325 -32.12' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 2.0075 32.12L 62.2325 32.12' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 32.12 -2.0075L 32.12 -62.2325' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 32.12 62.2325L 32.12 2.0075' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='4.015'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy index 80e70619717..9d1679b4999 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy +++ b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.asy @@ -2,6 +2,6 @@ defaultpen(2.5); path p=W..NW..ENE..0.5*SE..cycle; draw(p); -dot(p,linewidth(12)); +dot(p,red+linewidth(12)); shipout(pad(64,64)); diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg index 32cf982cf1c..33de78fc383 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/closedcurve.svg @@ -1,21 +1,21 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='64.0001pt' height='64pt' viewBox='58.4669 117.858 64.0001 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<path d='M 3.95735 -32.12C 2.28922 -39.3113 6.36702 -46.2386 11.9036 -51.3039C 29.6687 -67.5568 55.2292 -60.642 56.1523 -42.5022C 56.6136 -33.4381 49.1132 -26.5959 40.6794 -22.5281C 25.3995 -15.1582 7.19935 -18.1436 3.95735 -32.12Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<path d='M 6.0225 32.12C 4.35438 24.9287 8.43217 18.0014 13.9687 12.9361C 31.7339 -3.31675 57.2943 3.59797 58.2175 21.7378C 58.6788 30.8019 51.1783 37.6441 42.7445 41.7119C 27.4646 49.0818 9.26451 46.0964 6.0225 32.12Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='6.0225' cy='32.12' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='13.9687' cy='12.9361' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='58.2175' cy='21.7378' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='42.7445' cy='41.7119' fill='#ff0000' r='6.0225'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy index 612bdcf010a..871af18c85c 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy +++ b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.asy @@ -2,6 +2,6 @@ defaultpen(2.5); path p=W--NW--ENE--0.5*SE--cycle; draw(p); -dot(p,linewidth(12)); +dot(p,red+linewidth(12)); shipout(pad(64,64)); diff --git a/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg index 89e2c5f2303..ce6960bb841 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/closedpolygon.svg @@ -1,21 +1,21 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='64.0001pt' height='64pt' viewBox='58.4669 117.858 64.0001 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<path d='M 3.95735 -32.12L 11.9036 -51.3039L 56.1523 -42.5022L 40.6794 -22.5281L 3.95735 -32.12Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<path d='M 6.0225 32.12L 13.9687 12.9361L 58.2175 21.7378L 42.7445 41.7119L 6.0225 32.12Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='6.0225' cy='32.12' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='13.9687' cy='12.9361' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='58.2175' cy='21.7378' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='42.7445' cy='41.7119' fill='#ff0000' r='6.0225'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg b/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg index d2197375b9f..b6b279840fc 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/filledbucket.svg @@ -1,18 +1,18 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='64pt' viewBox='56.4094 117.858 63.9996 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 9.34742 -23.011L 9.34742 -9.34742L 9.34742 -9.34742C 9.34742 -9.34742 9.34742 -9.34742 9.34742 -9.34742C 9.34742 -5.15511 19.5431 -1.75656 32.12 -1.75656C 44.6969 -1.75656 54.8926 -5.15511 54.8926 -9.34742L 54.8926 -9.34742L 54.8926 -23.011L 54.8926 -36.6745C 54.8926 -40.8668 44.6969 -44.2654 32.12 -44.2654C 19.5431 -44.2654 9.34742 -40.8668 9.34742 -36.6745L 9.34742 -23.011Z' fill='#7f7f7f'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 9.34742 42.7472L 9.34742 54.8926L 9.34742 54.8926C 9.34742 54.8926 9.34742 54.8926 9.34742 54.8926C 9.34742 59.0849 19.5431 62.4834 32.12 62.4834C 44.6969 62.4834 54.8926 59.0849 54.8926 54.8926L 54.8926 54.8926L 54.8926 42.7472L 54.8926 30.6018C 54.8926 26.4095 44.6969 23.011 32.12 23.011C 19.5431 23.011 9.34742 26.4095 9.34742 30.6018L 9.34742 42.7472Z' fill='#bfbfff'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 54.8926 -39.7109C 54.8926 -43.9032 44.6969 -47.3017 32.12 -47.3017C 19.5431 -47.3017 9.34742 -43.9032 9.34742 -39.7109C 9.34742 -35.5185 19.5431 -32.12 32.12 -32.12C 44.6969 -32.12 54.8926 -35.5185 54.8926 -39.7109Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 54.8926 24.5291C 54.8926 20.3368 44.6969 16.9383 32.12 16.9383C 19.5431 16.9383 9.34742 20.3368 9.34742 24.5291C 9.34742 28.7215 19.5431 32.12 32.12 32.12C 44.6969 32.12 54.8926 28.7215 54.8926 24.5291Z' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 9.34742 -39.7109L 9.34742 -9.34742L 9.34742 -9.34742C 9.34742 -9.34742 9.34742 -9.34742 9.34742 -9.34742C 9.34742 -5.15511 19.5431 -1.75656 32.12 -1.75656C 44.6969 -1.75656 54.8926 -5.15511 54.8926 -9.34742L 54.8926 -9.34742L 54.8926 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 9.34742 24.5291L 9.34742 54.8926L 9.34742 54.8926C 9.34742 54.8926 9.34742 54.8926 9.34742 54.8926C 9.34742 59.0849 19.5431 62.4834 32.12 62.4834C 44.6969 62.4834 54.8926 59.0849 54.8926 54.8926L 54.8926 54.8926L 54.8926 24.5291' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 56.4094 117.858)'> -<path d='M 54.8926 -39.7109C 54.8926 -52.2878 44.6969 -62.4834 32.12 -62.4834C 19.5431 -62.4834 9.34742 -52.2878 9.34742 -39.7109' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> +<g transform='translate(56.4094 117.858)scale(.996264)'> +<path d='M 54.8926 24.5291C 54.8926 11.9522 44.6969 1.75656 32.12 1.75656C 19.5431 1.75656 9.34742 11.9522 9.34742 24.5291' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='3.51312'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy b/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy index e8fca0f2e81..8094e3ea7b6 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy +++ b/Build/source/utils/asymptote/GUI/res/icons/opencurve.asy @@ -2,6 +2,6 @@ defaultpen(2.5); path p=W..NW..ENE..0.5*SE; draw(p); -dot(p,linewidth(12)); +dot(p,red+linewidth(12)); shipout(pad(64,64)); diff --git a/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg b/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg index 3c02ba29060..16151d7e980 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/opencurve.svg @@ -1,21 +1,21 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='64.0001pt' height='64pt' viewBox='58.4669 117.858 64.0001 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<path d='M 3.95735 -32.12C 4.15556 -39.2745 6.98473 -46.1047 11.9036 -51.3039C 27.4411 -67.7269 53.3021 -61.5405 56.1523 -42.5022C 57.627 -32.6519 50.5856 -23.5621 40.6794 -22.5281' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<path d='M 6.0225 32.12C 6.22072 24.9655 9.04989 18.1353 13.9687 12.9361C 29.5062 -3.48686 55.3673 2.6995 58.2175 21.7378C 59.6922 31.5881 52.6508 40.6779 42.7445 41.7119' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='6.0225' cy='32.12' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='13.9687' cy='12.9361' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='58.2175' cy='21.7378' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='42.7445' cy='41.7119' fill='#ff0000' r='6.0225'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy index 22f7b09da72..976cc7b1cf9 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy +++ b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.asy @@ -2,6 +2,6 @@ defaultpen(2.5); path p=W--NW--ENE--0.5*SE; draw(p); -dot(p,linewidth(12)); +dot(p,red+linewidth(12)); shipout(pad(64,64)); diff --git a/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg index 5386aa64332..eb38eef8c1d 100644 --- a/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg +++ b/Build/source/utils/asymptote/GUI/res/icons/openpolygon.svg @@ -1,21 +1,21 @@ <?xml version='1.0' encoding='UTF-8'?> -<!-- This file was generated by dvisvgm 2.8 --> -<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='63.9996pt' height='63.9997pt' viewBox='56.4094 53.8583 63.9996 63.9997'> +<!-- This file was generated by dvisvgm 2.11.1 --> +<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='64.0001pt' height='64pt' viewBox='58.4669 117.858 64.0001 64'> <g id='page1'> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<path d='M 3.95735 -32.12L 11.9036 -51.3039L 56.1523 -42.5022L 40.6794 -22.5281' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<path d='M 6.0225 32.12L 13.9687 12.9361L 58.2175 21.7378L 42.7445 41.7119' fill='none' stroke='#000000' stroke-linecap='round' stroke-linejoin='round' stroke-miterlimit='10.0375' stroke-width='2.50937'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='3.95735' cy='-32.12' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='6.0225' cy='32.12' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='11.9036' cy='-51.3039' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='13.9687' cy='12.9361' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='56.1523' cy='-42.5022' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='58.2175' cy='21.7378' fill='#ff0000' r='6.0225'/> </g> -<g transform='matrix(0.996264 0 0 0.996264 58.4669 117.858)'> -<circle cx='40.6794' cy='-22.5281' fill='#000000' r='6.0225'/> +<g transform='translate(58.4669 117.858)scale(.996264)'> +<circle cx='42.7445' cy='41.7119' fill='#ff0000' r='6.0225'/> </g> </g> </svg>
\ No newline at end of file diff --git a/Build/source/utils/asymptote/GUI/res/icons/redo.svg b/Build/source/utils/asymptote/GUI/res/icons/redo.svg new file mode 100644 index 00000000000..a8647d7a3c1 --- /dev/null +++ b/Build/source/utils/asymptote/GUI/res/icons/redo.svg @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<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"
+ viewBox="0 0 423.754 423.754" style="enable-background:new 0 0 423.754 423.754;" xml:space="preserve">
+<path d="M407.516,123.239l-27.717,11.48c18.585,44.869,18.585,94.291,0,139.159c-18.585,44.869-53.531,79.815-98.4,98.4
+ c-22.438,9.293-46.004,13.94-69.579,13.939c-23.569-0.001-47.147-4.647-69.579-13.939c-44.869-18.585-79.815-53.531-98.4-98.4
+ C13.507,200.647,34.758,118.71,90.758,68.644l60.801,60.801V7.521H29.635L69.514,47.4C5.222,105.826-18.985,200.6,16.123,285.359
+ c21.652,52.272,62.364,92.984,114.636,114.636c26.137,10.826,53.599,16.239,81.061,16.239s54.924-5.413,81.06-16.239
+ c52.272-21.652,92.984-62.364,114.637-114.636C429.167,233.087,429.167,175.511,407.516,123.239z"/>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/res/icons/undo.svg b/Build/source/utils/asymptote/GUI/res/icons/undo.svg new file mode 100644 index 00000000000..76a7f0d32c8 --- /dev/null +++ b/Build/source/utils/asymptote/GUI/res/icons/undo.svg @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<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"
+ viewBox="0 0 423.754 423.754" style="enable-background:new 0 0 423.754 423.754;" xml:space="preserve">
+<path d="M354.24,47.4l39.879-39.879H272.196v121.924l60.801-60.801c56,50.066,77.251,132.004,46.918,205.235
+ c-18.585,44.869-53.531,79.815-98.4,98.4c-44.866,18.585-94.288,18.585-139.158,0c-44.869-18.585-79.815-53.531-98.4-98.4
+ c-18.585-44.869-18.585-94.29,0-139.159l-27.717-11.48c-21.651,52.272-21.651,109.848,0,162.12
+ c21.652,52.272,62.364,92.984,114.637,114.636c26.14,10.827,53.595,16.24,81.06,16.239c27.459-0.001,54.927-5.414,81.061-16.239
+ c52.271-21.652,92.983-62.364,114.636-114.636C442.739,200.6,418.532,105.826,354.24,47.4z"/>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/Build/source/utils/asymptote/GUI/setup.py b/Build/source/utils/asymptote/GUI/setup.py index e49e3468d7f..a1b25d809a7 100644 --- a/Build/source/utils/asymptote/GUI/setup.py +++ b/Build/source/utils/asymptote/GUI/setup.py @@ -7,7 +7,7 @@ setup( name="xasy", version=xasyVersion.xasyVersion, author="Supakorn Rassameemasmuang, Orest Shardt, and John C. Bowman", - description="User interface for Asymptote, a vector graphics language", + description="User interface for Asymptote, a vector graphics language", url="https://asymptote.sourceforge.io", download_url="https://sourceforge.net/projects/asymptote/" ) diff --git a/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui b/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui index b8bde4236a9..01fbc3e7613 100644 --- a/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui +++ b/Build/source/utils/asymptote/GUI/windows/widg_addPolyOpt.ui @@ -60,6 +60,35 @@ </widget> </item> <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>19</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Sides: </string> + </property> + </widget> + </item> + <item> <widget class="QLineEdit" name="txtSides"> <property name="toolTip"> <string>Number of Sides</string> diff --git a/Build/source/utils/asymptote/GUI/windows/window1.ui b/Build/source/utils/asymptote/GUI/windows/window1.ui index ed7c964e154..d16400a884b 100644 --- a/Build/source/utils/asymptote/GUI/windows/window1.ui +++ b/Build/source/utils/asymptote/GUI/windows/window1.ui @@ -127,7 +127,7 @@ </property> <property name="icon"> <iconset resource="../res/icons.qrc"> - <normaloff>:/icons/android-arrow-back.svg</normaloff>:/icons/android-arrow-back.svg</iconset> + <normaloff>:/icons/undo.svg</normaloff>:/icons/undo.svg</iconset> </property> <property name="iconSize"> <size> @@ -171,7 +171,7 @@ </property> <property name="icon"> <iconset resource="../res/icons.qrc"> - <normaloff>:/icons/android-arrow-forward.svg</normaloff>:/icons/android-arrow-forward.svg</iconset> + <normaloff>:/icons/redo.svg</normaloff>:/icons/redo.svg</iconset> </property> <property name="iconSize"> <size> @@ -605,7 +605,7 @@ </property> <property name="maximumSize"> <size> - <width>25</width> + <width>32</width> <height>25</height> </size> </property> @@ -652,7 +652,7 @@ </property> <property name="maximumSize"> <size> - <width>25</width> + <width>32</width> <height>25</height> </size> </property> @@ -664,6 +664,7 @@ </property> <property name="font"> <font> + <family>Roboto</family> <weight>75</weight> <bold>true</bold> </font> @@ -737,6 +738,9 @@ <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -782,7 +786,7 @@ </size> </property> <property name="checkable"> - <bool>false</bool> + <bool>true</bool> </property> <property name="flat"> <bool>true</bool> @@ -1644,6 +1648,9 @@ background: rgb(0, 0, 0) <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -1682,6 +1689,9 @@ background: rgb(0, 0, 0) <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -1720,6 +1730,9 @@ background: rgb(0, 0, 0) <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -1758,6 +1771,9 @@ background: rgb(0, 0, 0) <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -1796,6 +1812,9 @@ background: rgb(0, 0, 0) <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -1834,6 +1853,9 @@ background: rgb(0, 0, 0) <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -1872,6 +1894,50 @@ background: rgb(0, 0, 0) <height>16</height> </size> </property> + <property name="checkable"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="12" column="0"> + <widget class="QPushButton" name="btnAddFreehand"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>32</width> + <height>32</height> + </size> + </property> + <property name="toolTip"> + <string><html><head/><body><p>Freehand</p></body></html></string> + </property> + <property name="text"> + <string/> + </property> + <property name="icon"> + <iconset resource="../res/icons.qrc"> + <normaloff>:/icons/brush.svg</normaloff>:/icons/brush.svg</iconset> + </property> + <property name="iconSize"> + <size> + <width>16</width> + <height>16</height> + </size> + </property> + <property name="checkable"> + <bool>true</bool> + </property> <property name="flat"> <bool>true</bool> </property> @@ -2039,16 +2105,26 @@ background: rgb(0, 0, 0) <x>0</x> <y>0</y> <width>1000</width> - <height>29</height> + <height>26</height> </rect> </property> <widget class="QMenu" name="menuFIle"> <property name="title"> <string>&File</string> </property> + <widget class="QMenu" name="menuOpenRecent"> + <property name="title"> + <string>Open Recent</string> + </property> + <addaction name="separator"/> + <addaction name="actionClearRecent"/> + </widget> + <addaction name="actionNewFile"/> <addaction name="actionOpen"/> + <addaction name="menuOpenRecent"/> <addaction name="actionSave"/> <addaction name="actionSaveAs"/> + <addaction name="actionExportToAsy"/> <addaction name="actionExportAsymptote"/> <addaction name="separator"/> <addaction name="actionQuit"/> @@ -2066,6 +2142,7 @@ background: rgb(0, 0, 0) <string>Optio&ns</string> </property> <addaction name="actionSettings"/> + <addaction name="actionKeymaps"/> </widget> <widget class="QMenu" name="menuHelp"> <property name="title"> @@ -2113,7 +2190,7 @@ background: rgb(0, 0, 0) </action> <action name="actionSaveAs"> <property name="text"> - <string>&Save As</string> + <string>&Save as</string> </property> </action> <action name="actionEnterCommand"> @@ -2159,7 +2236,7 @@ background: rgb(0, 0, 0) </action> <action name="actionExportAsymptote"> <property name="text"> - <string>Export</string> + <string>Export as...</string> </property> </action> <action name="actionSave"> @@ -2172,6 +2249,26 @@ background: rgb(0, 0, 0) <string>Open</string> </property> </action> + <action name="actionClearRecent"> + <property name="text"> + <string>Clear Menu</string> + </property> + </action> + <action name="actionNewFile"> + <property name="text"> + <string>New File</string> + </property> + </action> + <action name="actionExportToAsy"> + <property name="text"> + <string>Export as Asy</string> + </property> + </action> + <action name="actionKeymaps"> + <property name="text"> + <string>&Keymaps</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="9"/> <resources> diff --git a/Build/source/utils/asymptote/GUI/xasy.py b/Build/source/utils/asymptote/GUI/xasy.py index 7a8ee9b2f71..a078690b68b 100755 --- a/Build/source/utils/asymptote/GUI/xasy.py +++ b/Build/source/utils/asymptote/GUI/xasy.py @@ -1,14 +1,15 @@ #!/usr/bin/env python3 -import sys,signal,os -import PyQt5.QtWidgets as Qw -import PyQt5.QtCore as Qc +import sys, signal, os +import PyQt5.QtWidgets as QtWidgets +import PyQt5.QtCore as QtCore from Window1 import MainWindow1 def main(args): - Qw.QApplication.setAttribute(Qc.Qt.AA_UseHighDpiPixmaps,True) - Qw.QApplication.setAttribute(Qc.Qt.AA_EnableHighDpiScaling,True) - qtApp = Qw.QApplication(args) + os.environ["QT_LOGGING_RULES"]="*.debug=false;qt.qpa.*=false" + QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps,True) + QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling,True) + qtApp = QtWidgets.QApplication(args) signal.signal(signal.SIGINT,signal.SIG_DFL) mainWin1 = MainWindow1() mainWin1.show() diff --git a/Build/source/utils/asymptote/GUI/xasy2asy.py b/Build/source/utils/asymptote/GUI/xasy2asy.py index 12bccb453cf..1829ce436ba 100755 --- a/Build/source/utils/asymptote/GUI/xasy2asy.py +++ b/Build/source/utils/asymptote/GUI/xasy2asy.py @@ -9,12 +9,12 @@ # ########################################################################### -import PyQt5.QtWidgets as Qw -import PyQt5.QtGui as Qg -import PyQt5.QtCore as Qc -import PyQt5.QtSvg as Qs +import PyQt5.QtWidgets as QtWidgets +import PyQt5.QtGui as QtGui +import PyQt5.QtCore as QtCore +import PyQt5.QtSvg as QtSvg -import numpy as np +import numpy as numpy import sys import os @@ -37,8 +37,39 @@ import xasyOptions as xo import xasySvg as xs class AsymptoteEngine: - xasy=chr(4)+"\n" - + """ + Purpose: + -------- + Class that makes it possible for xasy to communicate with asy + through a background pipe. It communicates with asy through a + subprocess of an existing xasy process. + + Attributes: + ----------- + istream : input stream + ostream : output stream + keepFiles : keep communicated files + tmpdir : temporary directory + args : system call arguments to start a required subprocess + asyPath : directory path to asymptote + asyProcess : the subprocess through which xasy communicates with asy + + Virtual Methods: NULL + ---------------- + Static Methods: + --------------- NULL + Class Methods: + -------------- NULL + + Object Methods: + --------------- + start() + wait() + stop() + cleanup() + """ + + xasy=chr(4)+'\n' def __init__(self, path=None, keepFiles=DebugFlags.keepFiles, keepDefaultArgs=True): if path is None: path = xa.getArgs().asypath @@ -59,19 +90,29 @@ class AsymptoteEngine: os.set_inheritable(wa, True) self.ostream = os.fdopen(wx, 'w') self.istream = os.fdopen(ra, 'r') - + self.keepFiles = keepFiles if sys.platform[:3] == 'win': self.tmpdir = tempfile.mkdtemp(prefix='xasyData_',dir='./')+'/' else: self.tmpdir = tempfile.mkdtemp(prefix='xasyData_')+os.sep - self.args=['-xasy', '-noV', '-q', '-inpipe=' + str(rx), '-outpipe=' + str(wa), '-o', self.tmpdir] + if xa.getArgs().render: + renderDensity=xa.getArgs().render + else: + try: + renderDensity = xo.BasicConfigs.defaultOpt['renderDensity'] + except: + renderDensity = 2 + renderDensity=max(renderDensity,1) + + self.args=['-xasy', '-noV', '-q', '-outformat=', '-inpipe=' + str(rx), '-outpipe=' + str(wa), '-render='+str(renderDensity), '-o', self.tmpdir] self.asyPath = path self.asyProcess = None def start(self): + """ starts a subprocess (opens a pipe) """ try: if sys.platform[:3] == 'win': self.asyProcess = subprocess.Popen([self.asyPath] + self.args, @@ -85,6 +126,7 @@ class AsymptoteEngine: atexit.register(self.cleanup) def wait(self): + """ wait for the pipe to finish any outstanding communication """ if self.asyProcess.returncode is not None: return else: @@ -114,10 +156,12 @@ class AsymptoteEngine: return self.asyProcess.returncode is None def stop(self): + """ kill an active asyProcess and close the pipe """ if self.active: self.asyProcess.kill() def cleanup(self): + """ terminate processes and cleans up communication files """ self.stop() if self.asyProcess is not None: self.asyProcess.wait() @@ -125,11 +169,46 @@ class AsymptoteEngine: 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""" +class asyTransform(QtCore.QObject): + """ + Purpose: + -------- + A python implementation of an asy transform. This class takes care of calibrating asymptote + coordinate system with the one used in PyQt to handle all existing inconsistencies. + To understand how this class works, having enough acquaintance with asymptote transform + feature is required. It is a child class of QtCore.QObject class. + + Attributes: + ----------- + t : The tuple + x, y, xx, xy, yx, yy : Coordinates corresponding to 6 entries + _deleted : Private local flag + + Virtual Methods: NULL + ---------------- + Static Methods: NULL + --------------- + + Class Methods: + -------------- + zero : Class method that returns an asyTransform object initialized with 6 zero entries + fromQTransform : Class method that converts QTransform object to asyTransform object + fromNumpyMatrix : Class method that converts transform matrix object to asyTransform object + + Object Methods: + -------------- + getRawCode : Returns the tuple entries + getCode : Returns the textual format of the asy code corresponding to the given transform + scale : Returns the scales version of the existing asyTransform + toQTransform : Converts asy transform object to QTransform object + identity : Return Identity asyTransform object + isIdentity : Check whether the asyTransform object is identity object + inverted : Applies the QTransform object's inverted method on the asyTransform object + yflip : Returns y-flipped asyTransform object + """ def __init__(self, initTuple, delete=False): - """Initialize the transform with a 6 entry tuple""" + """ Initialize the transform with a 6 entry tuple """ super().__init__() if isinstance(initTuple, (tuple, list)) and len(initTuple) == 6: self.t = initTuple @@ -151,14 +230,14 @@ class asyTransform(Qc.QObject): return asyTransform((0, 0, 0, 0, 0, 0)) @classmethod - def fromQTransform(cls, transform: Qg.QTransform): + def fromQTransform(cls, transform: QtGui.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): + def fromNumpyMatrix(cls, transform: numpy.ndarray): assert transform.shape == (3, 3) tx = transform[0, 2] @@ -171,8 +250,8 @@ class asyTransform(Qc.QObject): def getRawCode(self): return xu.tuple2StrWOspaces(self.t) - def getCode(self, asy2psmap=None): - """Obtain the asy code that represents this transform""" + 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: @@ -184,10 +263,10 @@ class asyTransform(Qc.QObject): 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) + return QtGui.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.""" + """ Equivalent functionality to getCode(). It allows the expression str(asyTransform) to be meaningful """ return self.getCode() def isIdentity(self): @@ -200,7 +279,7 @@ class asyTransform(Qc.QObject): return list(self.t) == list(other.t) def __mul__(self, other): - """Define multiplication of transforms as composition.""" + """ Define multiplication of transforms as composition """ if isinstance(other, tuple): if len(other) == 6: return self * asyTransform(other) @@ -234,25 +313,88 @@ def identity(): def yflip(): return asyTransform((0, 0, 1, 0, 0, -1)) -class asyObj(Qc.QObject): - """A base class for asy objects: an item represented by asymptote code.""" +class asyObj(QtCore.QObject): + """ + Purpose: + -------- + A base class to create a Python object which contains all common + data and behaviors required during the translation of an xasy + object to its Asymptote code. + + Attributes: + ----------- + asyCode :The corresponding Asymptote code for the asyObj instance + + Virtual Methods: + ---------------- + updateCode :Must to be re-implemented + + Static Methods: NULL + -------------- + Class Methods: NULL + -------------- + + Object Methods: + --------------- + getCode :Return the Asymptote code that corresponds to the passed object + + """ + def __init__(self): - """Initialize the object""" + """ Initialize the object """ super().__init__() self.asyCode = '' - def updateCode(self, ps2asymap=identity()): - """Update the object's code: should be overriden.""" + def updateCode(self, ps2asymap = identity()): + """ Update the object's code: should be overridden """ raise NotImplementedError - def getCode(self, ps2asymap=identity()): - """Return the code describing the object""" + 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""" + """ + Purpose: + -------- + A Python object that corresponds to an Asymptote pen type. It + extends the 'asyObj' class to include a pen object. This object + will be used to make the corresponding Asymptote pen when + an xasy object gets translated to Asymptote code. + + Attributes: + ----------- + color : The color of Path + options : The options that can be passed to the path + width : The path width + _asyengine : The Asymptote engine that will be used + _deferAsyfy : ? + + Virtual Methods: NULL + ---------------- + Static Methods: + --------------- + getColorFromQColor : + convertToQColor : + + Class Methods: + -------------- + fromAsyPen : + + Object Methods: + --------------- + asyEngine : + updateCode : + setWidth : + setColor : + setColorFromQColor : + computeColor : + tkColor : + toQPen : + """ + @staticmethod def getColorFromQColor(color): return color.redF(), color.greenF(), color.blueF() @@ -260,15 +402,16 @@ class asyPen(asyObj): @staticmethod def convertToQColor(color): r, g, b = color - return Qg.QColor.fromRgbF(r, g, b) + return QtGui.QColor.fromRgbF(r, g, b) @classmethod def fromAsyPen(cls, pen): assert isinstance(pen, cls) - return cls(asyengine=pen._asyengine, color=pen.color, width=pen.width, pen_options=pen.options) + return cls(asyengine = pen._asyengine, color = pen.color, width = pen.width, + pen_options = pen.options) - def __init__(self, asyengine=None, color=(0, 0, 0), width=0.5, pen_options=""): - """Initialize the pen""" + 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 @@ -288,8 +431,8 @@ class asyPen(asyObj): def asyEngine(self, value): self._asyengine = value - def updateCode(self, asy2psmap=identity()): - """Generate the pen's code""" + 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)) @@ -297,12 +440,12 @@ class asyPen(asyObj): self.asyCode = self.asyCode + '+' + self.options def setWidth(self, newWidth): - """Set the pen's width""" + """ Set the pen's width """ self.width = newWidth self.updateCode() def setColor(self, color): - """Set the pen's color""" + """ Set the pen's color """ if isinstance(color, tuple) and len(color) == 3: self.color = color else: @@ -313,13 +456,12 @@ class asyPen(asyObj): self.setColor(asyPen.getColorFromQColor(color)) def computeColor(self): - """Find out the color of an arbitrary asymptote pen.""" + """ 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") @@ -347,15 +489,10 @@ class asyPen(asyObj): 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 = QtGui.QPen() newPen.setColor(asyPen.convertToQColor(self.color)) newPen.setWidthF(self.width) @@ -363,10 +500,34 @@ class asyPen(asyObj): class asyPath(asyObj): - """A python wrapper for an asymptote path""" + """ + Purpose: + -------- + A Python object that corresponds to an Asymptote path type. It + extends the 'asyObj' class to include a path object. This object + will be used to make the corresponding Asymptote path object when + an xasy object gets translated to its Asymptote code. + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + 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.""" + """ Initialize the path to be an empty path: a path with no nodes, control points, or links """ super().__init__() self.nodeSet = [] self.linkSet = [] @@ -374,12 +535,14 @@ class asyPath(asyObj): self.controlSet = [] self.computed = False self.asyengine = asyengine + self.fill = False @classmethod def fromPath(cls, oldPath): newObj = asyPath(None) newObj.nodeSet = copy.copy(oldPath.nodeSet) newObj.linkSet = copy.copy(oldPath.linkSet) + newObj.fill = copy.copy(oldPath.fill) newObj.controlSet = copy.deepcopy(oldPath.controlSet) newObj.computed = oldPath.computed newObj.asyengine = oldPath.asyengine @@ -406,6 +569,7 @@ class asyPath(asyObj): def setInfo(self, path): self.nodeSet = copy.copy(path.nodeSet) self.linkSet = copy.copy(path.linkSet) + self.fill = copy.copy(path.fill) self.controlSet = copy.deepcopy(path.controlSet) self.computed = path.computed @@ -417,12 +581,12 @@ class asyPath(asyObj): def isDrawable(self): return len(self.nodeSet) >= 2 - def toQPainterPath(self) -> Qg.QPainterPath: + def toQPainterPath(self) -> QtGui.QPainterPath: return self.toQPainterPathCurve() if self.containsCurve else self.toQPainterPathLine() def toQPainterPathLine(self): baseX, baseY = self.nodeSet[0] - painterPath = Qg.QPainterPath(Qc.QPointF(baseX, baseY)) + painterPath = QtGui.QPainterPath(QtCore.QPointF(baseX, baseY)) for pointIndex in range(1, len(self.nodeSet)): node = self.nodeSet[pointIndex] @@ -439,43 +603,43 @@ class asyPath(asyObj): self.computeControls() baseX, baseY = self.nodeSet[0] - painterPath = Qg.QPainterPath(Qc.QPointF(baseX, baseY)) + painterPath = QtGui.QPainterPath(QtCore.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]) + endPoint = QtCore.QPointF(node[0], node[1]) + ctrlPoint1 = QtCore.QPointF(self.controlSet[pointIndex-1][0][0], self.controlSet[pointIndex-1][0][1]) + ctrlPoint2 = QtCore.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 "::" """ + """ 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""" + """ 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""" + """ 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... + # 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""" + """ Generate the code describing the path """ # currently at postscript. Convert to asy asy2psmap = ps2asymap.inverted() with io.StringIO() as rawAsyCode: @@ -499,28 +663,28 @@ class asyPath(asyObj): return '..' in self.linkSet or self.forceCurve def getNode(self, index): - """Return the requested node""" + """ Return the requested node """ return self.nodeSet[index] def getLink(self, index): - """Return the requested link""" + """ Return the requested link """ return self.linkSet[index] def setNode(self, index, newNode): - """Set a node to a new position""" + """ Set a node to a new position """ self.nodeSet[index] = newNode def moveNode(self, index, offset): - """Translate a node""" + """ 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""" + """ Change the specified link """ self.linkSet[index] = ltype def addNode(self, point, ltype): - """Add a node to the end of a path""" + """ Add a node to the end of a path """ self.nodeSet.append(point) if len(self.nodeSet) != 1: self.linkSet.append(ltype) @@ -528,14 +692,14 @@ class asyPath(asyObj): self.computeControls() def insertNode(self, index, point, ltype=".."): - """Insert a node, and its corresponding link, at the given index""" + """ 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""" + """ Set a control point to a new position """ self.controlSet[index] = position def popNode(self): @@ -545,11 +709,11 @@ class asyPath(asyObj): self.linkSet.pop() def moveControl(self, index, offset): - """Translate a control point""" + """ 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""" + """ 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: @@ -595,9 +759,33 @@ class asyPath(asyObj): asy.stop() class asyLabel(asyObj): - """A python wrapper for an asy label""" + """ + Purpose: + -------- + A Python object that corresponds to an asymptote label + type. It extends the 'asyObj' class to include a label + object. This object will be used to make the corresponding + Asymptote label object when an xasy object gets translated to its + asymptote code. + + Attributes: + ----------- + + Virtual Methods: + ---------------- - def __init__(self, text="", location=(0, 0), pen=None, align=None, fontSize:int=None): + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + + 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 @@ -610,8 +798,8 @@ class asyLabel(asyObj): self.text = text self.location = location - def updateCode(self, asy2psmap=identity()): - """Generate the code describing the label""" + 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, @@ -624,22 +812,45 @@ class asyLabel(asyObj): return '' def setText(self, text): - """Set the label's text""" + """ Set the label's text """ self.text = text self.updateCode() def setPen(self, pen): - """Set the label's pen""" + """ Set the label's pen """ self.pen = pen self.updateCode() def moveTo(self, newl): - """Translate the label's location""" + """ Translate the label's location """ self.location = newl class asyImage: - """A structure containing an image and its format, bbox, and IDTag""" + """ + Purpose: + -------- + A Python object that is a container for an image coming from + Asymptote that is populated with the format, bounding box, and + IDTag, Asymptote key. + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + def __init__(self, image, format, bbox, transfKey=None, keyIndex=0): self.image = image self.format = format @@ -648,15 +859,38 @@ class asyImage: self.key = transfKey self.keyIndex = keyIndex -class xasyItem(Qc.QObject): - """A base class for items in the xasy GUI""" +class xasyItem(QtCore.QObject): + """ + Purpose: + -------- + A base class for any xasy object that can be drawn in PyQt. This class takes + care of all common behaviors available on any xasy item as well as all common + actions that can be done or applied to every xasy item. + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + 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""" + """ Initialize the item to an empty item """ super().__init__() self.transfKeymap = {} # the new keymap. # should be a dictionary to a list... @@ -672,18 +906,17 @@ class xasyItem(Qc.QObject): self.setKeyed = True self.unsetKeys = set() self.userKeys = set() - self.lineOffset = 0 self.imageHandleQueue = queue.Queue() - def updateCode(self, ps2asymap=identity()): - """Update the item's code: to be overriden""" + def updateCode(self, ps2asymap = identity()): + """ Update the item's code: to be overridden """ with io.StringIO() as rawCode: transfCode = self.getTransformCode() objCode = self.getObjectCode() rawCode.write(transfCode) rawCode.write(objCode) - self.asyCode = rawCode.getvalue() + self.asyCode = rawCode.getvalue() return len(transfCode.splitlines()), len(objCode.splitlines()) @@ -695,34 +928,32 @@ class xasyItem(Qc.QObject): def asyengine(self, value): self._asyengine = value - def getCode(self, ps2asymap=identity()): - """Return the code describing the item""" + def getCode(self, ps2asymap = identity()): + """ Return the code describing the item """ self.updateCode(ps2asymap) return self.asyCode - def getTransformCode(self, asy2psmap=identity()): + def getTransformCode(self, asy2psmap = identity()): raise NotImplementedError - def getObjectCode(self, asy2psmap=identity()): + 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.""" + 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 fileformat == 'svg': if containsClip: image = xs.SvgObject(self.asyengine.tempDirName+file) else: - image = Qs.QSvgRenderer(file) + image = QtSvg.QSvgRenderer(file) assert image.isValid() else: - raise Exception('Format not supported!') - self.imageList.append(asyImage(image, fileformat, bbox, transfKey=key, keyIndex=localCount)) + raise Exception('Format {} not supported!'.format(fileformat)) + 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] @@ -733,7 +964,7 @@ class xasyItem(Qc.QObject): currImage.performCanvasTransform = False # handle this case if transform is not in the map yet. - # if deleted - set transform to 0, 0, 0, 0, 0 + # if deleted - set transform to (0,0,0,0,0,0) transfExists = key in self.transfKeymap.keys() if transfExists: transfExists = localCount <= len(self.transfKeymap[key]) - 1 @@ -745,7 +976,7 @@ class xasyItem(Qc.QObject): 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, + btmRightanchor=QtCore.QPointF(bbox[0], bbox[2]), drawOrder=-1, key=key, parentObj=self, keyIndex=localCount) newDrawObj.setBoundingBoxPs(bbox) newDrawObj.setParent(self) @@ -757,7 +988,8 @@ class xasyItem(Qc.QObject): else: self.drawObjectsMap[key].append(newDrawObj) return containsClip - def asyfy(self, force=False): + + def asyfy(self, force = False): if self.asyengine is None: return 1 if self.asyfied and not force: @@ -772,7 +1004,7 @@ class xasyItem(Qc.QObject): self.userKeys.clear() self.imageHandleQueue = queue.Queue() - worker = threading.Thread(target=self.asyfyThread, args=[]) + worker = threading.Thread(target = self.asyfyThread, args = []) worker.start() item = self.imageHandleQueue.get() cwd=os.getcwd(); @@ -797,22 +1029,25 @@ class xasyItem(Qc.QObject): worker.join() def asyfyThread(self): - """Convert the item to a list of images by deconstructing this item's code""" + """ + 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()) + self.maxKey=0 fout.write("reset\n") fout.flush(); for line in self.getCode().splitlines(): - if DebugFlags.printDeconstTranscript: - print('fout:', line) + if DebugFlags.printAsyTranscript: + print(line) fout.write(line+"\n") fout.write(self.asySize) - fout.write("deconstruct();\n") + + fout.write('deconstruct();\n') fout.write('write(_outpipe,yscale(-1)*currentpicture.calculateTransform(),endl);\n') fout.write(self.asyengine.xasy) fout.flush() @@ -826,37 +1061,44 @@ class xasyItem(Qc.QObject): for i in range(len(imageInfos)): box, key, localCount, useClip = imageInfos[i] l, b, r, t = [float(a) for a in box.split()] - name = "_{:d}.{:s}".format(i, fileformat) + name = '_{:d}.{:s}'.format(1+i, fileformat) self.imageHandleQueue.put((name, fileformat, (l, -t, r, -b), i, key, localCount, useClip)) # key first, box second. - # if key is "Done" + # if key is 'Done' raw_text = fin.readline() - text = "" + text = '' if DebugFlags.printDeconstTranscript: + print(self.asyengine.tmpdir) print(raw_text.strip()) - # template=AsyTempDir+"%d_%d.%s" - fileformat = 'svg' + fileformat = 'svg' # Output format - while raw_text != "Done\n" and raw_text != "Error\n": + 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' + deleted = keydata[-1] == '2' userkey = keydata[-2] == '1' keydata = keydata[:-3] if not userkey: - self.unsetKeys.add(keydata) # the line and column to replace. + self.unsetKeys.add(keydata) # the line and column to replace. else: + if keydata.isdigit(): + self.maxKey=max(self.maxKey,int(keydata)) self.userKeys.add(keydata) - + # print(line, col) + if deleted: + raw_text = fin.readline() + continue + if keydata not in keyCounts.keys(): keyCounts[keydata] = 0 @@ -873,23 +1115,45 @@ class xasyItem(Qc.QObject): n += 1 - if raw_text != "Error\n": - if text == "Error\n": - self.imageHandleQueue.put(("ERROR", fin.readline())) + if raw_text != 'Error\n': + if text == 'Error\n': + self.imageHandleQueue.put(('ERROR', fin.readline())) else: render() self.asy2psmap = asyTransform(xu.listize(fin.readline().rstrip(),float)) else: - self.asy2psmap = identity() + self.asy2psmap = yflip() 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.""" + """ + Purpose: + -------- + A base class dedicated to any xasy item that is drawn on GUI. Every object of this class + will correspond to a particular drawn xasy item on GUI, which contains all its particular + data. + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- - def __init__(self, path, engine, pen=None, transform=identity(), key=None): - """Initialize the item with a path, pen, and transform""" + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + + 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() @@ -921,7 +1185,9 @@ class xasyDrawnItem(xasyItem): raise NotImplementedError def appendPoint(self, point, link=None): - """Append a point to the path. If the path is cyclic, add this point before the 'cycle' node.""" + """ 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') @@ -933,12 +1199,14 @@ class xasyDrawnItem(xasyItem): self.path.linkSet.append(link) def clearTransform(self): - """Reset the item's transform""" + """ 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.""" + """ 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: @@ -948,7 +1216,9 @@ class xasyDrawnItem(xasyItem): self.asyfied = False def setLastPoint(self, point): - """Modify the last point in the path. If the path is cyclic, modify the node before the 'cycle' node.""" + """ 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: @@ -958,13 +1228,38 @@ class xasyDrawnItem(xasyItem): class xasyShape(xasyDrawnItem): - """An outlined shape drawn on the GUI""" + """ An outlined shape drawn on the GUI """ + """ + Purpose: + -------- + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + + def __init__(self, path, asyengine, pen=None, transform=identity()): """Initialize the shape with a path, pen, and transform""" super().__init__(path=path, engine=asyengine, pen=pen, transform=transform) def getObjectCode(self, asy2psmap=identity()): - return 'draw(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n' + if self.path.fill: + return 'fill(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n' + else: + return 'draw(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n' def getTransformCode(self, asy2psmap=identity()): transf = self.transfKeymap[self.transfKey][0] @@ -982,63 +1277,121 @@ class xasyShape(xasyDrawnItem): key=self.transfKey) newObj.originalObj = self newObj.setParent(self) + newObj.fill=self.path.fill return [newObj] def __str__(self): - """Create a string describing this shape""" + """ Create a string describing this shape """ return "xasyShape code:{:s}".format("\n\t".join(self.getCode().splitlines())) + def swapFill(self): + self.path.fill = not self.path.fill + + def copy(self): + return type(self)(self.path,self._asyengine,self.pen) + class xasyFilledShape(xasyShape): - """A filled shape drawn on the GUI""" + """ 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""" + """ + Purpose: + -------- + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + + 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) + self.path.fill=True def getObjectCode(self, asy2psmap=identity()): - return 'fill(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n' + if self.path.fill: + return 'fill(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n' + else: + return 'draw(KEY="{0}",{1},{2});'.format(self.transfKey, self.path.getCode(asy2psmap), self.pen.getCode())+'\n\n' - def generateDrawObjects(self, forceUpdate=False): + 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 = 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) + newObj.fill=self.path.fill return [newObj] def __str__(self): - """Return a string describing this shape""" + """ Return a string describing this shape """ return "xasyFilledShape code:{:s}".format("\n\t".join(self.getCode().splitlines())) + def swapFill(self): + self.path.fill = not self.path.fill + class xasyText(xasyItem): - """Text created by the GUI""" + """ Text created by the GUI """ + + """ + Purpose: + -------- + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- - 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) + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + + 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) + pen = asyPen(asyengine = asyengine) if pen.asyEngine is None: pen.asyEngine = asyengine - self.label = asyLabel(text, location, pen, align, fontSize=fontsize) + 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): + self.pen = pen + + def setKey(self, newKey = None): transform = self.transfKeymap[self.transfKey][0] self.transfKey = newKey self.transfKeymap = {self.transfKey: [transform]} - def getTransformCode(self, asy2psmap=yflip()): + def getTransformCode(self, asy2psmap = yflip()): transf = self.transfKeymap[self.transfKey][0] if transf == yflip(): # return xasyItem.setKeyAloneFormatStr.format(self.transfKey) @@ -1046,10 +1399,10 @@ class xasyText(xasyItem): else: return xasyItem.setKeyFormatStr.format(self.transfKey, transf.getCode(asy2psmap))+"\n" - def getObjectCode(self, asy2psmap=yflip()): + def getObjectCode(self, asy2psmap = yflip()): return 'label(KEY="{0}",{1});'.format(self.transfKey, self.label.getCode(asy2psmap))+'\n' - def generateDrawObjects(self, forceUpdate=False): + def generateDrawObjects(self, forceUpdate = False): self.asyfy(forceUpdate) return self.drawObjects @@ -1060,12 +1413,36 @@ class xasyText(xasyItem): def __str__(self): return "xasyText code:{:s}".format("\n\t".join(self.getCode().splitlines())) + def copy(self): + return type(self)(self.label.text,self.label.location,self._asyengine) + class xasyScript(xasyItem): - """A set of images create from asymptote code. It is always deconstructed.""" + """ A set of images create from asymptote code. It is always deconstructed """ + + """ + Purpose: + -------- + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ def __init__(self, canvas, engine, script="", transforms=None, transfKeyMap=None): - """Initialize this script item""" + """ Initialize this script item """ super().__init__(canvas, asyengine=engine) if transfKeyMap is not None: self.transfKeymap = transfKeyMap @@ -1080,7 +1457,7 @@ class xasyScript(xasyItem): self.updatedPrefix = True def clearTransform(self): - """Reset the transforms for each of the deconstructed images""" + """ Reset the transforms for each of the deconstructed images """ # self.transform = [identity()] * len(self.imageList) keyCount = {} @@ -1093,14 +1470,6 @@ class xasyScript(xasyItem): for key in keyCount: self.transfKeymap[key] = [identity()] * keyCount[key] - def getMaxKeyCounter(self): - maxCounter = -1 - for key in self.transfKeymap: - testNum = re.match(r'^x(\d+)$', key) - if testNum is not None: - maxCounter = max(maxCounter, int(testNum.group(1))) - return maxCounter + 1 - def getTransformCode(self, asy2psmap=identity()): with io.StringIO() as rawAsyCode: if self.transfKeymap: @@ -1109,21 +1478,22 @@ class xasyScript(xasyItem): 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: + # unfortunately, have to check all transformations in the list. + while not all((checktransf == identity() and not checktransf.deleted) 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))) + else: + if transf == identity(): + 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]) } + return {key for key in self.transfKeymap if not all(not transf.deleted and transf == identity() for transf in self.transfKeymap[key]) } def getObjectCode(self, asy2psmap=identity()): numeric=r'([-+]?(?:(?:\d*\.\d+)|(?:\d+\.?)))' @@ -1144,7 +1514,7 @@ class xasyScript(xasyItem): return self.updatedCode def setScript(self, script): - """Sets the content of the script item.""" + """ Sets the content of the script item """ self.script = script self.updateCode() @@ -1155,7 +1525,7 @@ class xasyScript(xasyItem): def getReplacedKeysCode(self, key2replace: set=None) -> str: keylist = {} prefix = '' - + key2replaceSet = self.unsetKeys if key2replace is None else \ self.unsetKeys & key2replace @@ -1180,9 +1550,8 @@ class xasyScript(xasyItem): 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] + for i in range(len(raw_code_lines)): + curr_str = raw_code_lines[i] if i + 1 in keylist.keys(): # this case, we have a key. with io.StringIO() as raw_line: @@ -1205,11 +1574,13 @@ class xasyScript(xasyItem): 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.""" + 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 + # Id --> Transf --> asyfied --> Transf # Transf should keep the original, raw transformation # but for all new drawn objects - assign Id as transform. @@ -1246,7 +1617,7 @@ class xasyScript(xasyItem): else: self.key2imagemap[im.key].append(im) - + for key in keyCount: if key not in self.transfKeymap.keys(): @@ -1258,7 +1629,7 @@ class xasyScript(xasyItem): # while len(self.transfKeymap[key]) > keyCount[key]: # self.transfKeymap[key].pop() - # change of basis + # change of basis for keylist in self.transfKeymap.values(): for i in range(len(keylist)): if keylist[i] != identity(): @@ -1272,17 +1643,41 @@ class xasyScript(xasyItem): return self.drawObjects def __str__(self): - """Return a string describing this script""" + """ Return a string describing this script """ retVal = "xasyScript\n\tTransforms:\n" for xform in self.transform: retVal += "\t" + str(xform) + "\n" - retVal += "\tCode Ommitted" + retVal += "\tCode Omitted" 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): +class DrawObject(QtCore.QObject): + """ + Purpose: + -------- + The main Python class to draw an object with the help of PyQt graphical library. + Every instance of the class is + + + Attributes: + ----------- + + Virtual Methods: + ---------------- + + Static Methods: + --------------- + + Class Methods: + -------------- + + Object Methods: + --------------- + + """ + + def __init__(self, drawObject, mainCanvas = None, transform = identity(), btmRightanchor = QtCore.QPointF(0, 0), + drawOrder = (-1, -1), pen = None, key = None, parentObj = None, fill = False, keyIndex = 0): super().__init__() self.drawObject = drawObject self.mainCanvas = mainCanvas @@ -1302,8 +1697,8 @@ class DrawObject(Qc.QObject): self.fill = fill def getInteriorScrTransform(self, transform): - """Generates the transform with Interior transform applied beforehand.""" - if isinstance(transform, Qg.QTransform): + """ Generates the transform with Interior transform applied beforehand """ + if isinstance(transform, QtGui.QTransform): transform = asyTransform.fromQTransform(transform) return self.transform * transform * self.baseTransform.inverted() @@ -1317,25 +1712,36 @@ class DrawObject(Qc.QObject): 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) + self.explicitBoundingBox = QtCore.QRectF(QtCore.QPointF(l, b), QtCore.QPointF(r, t)) + # self.explicitBoundingBox = QtCore.QRectF(0, 0, 100, 100) @property def boundingBox(self): if self.explicitBoundingBox is not None: - testBbox = self.explicitBoundingBox + tempItem = self.baseTransform.toQTransform().mapRect(self.explicitBoundingBox) + testBbox = self.getScreenTransform().toQTransform().mapRect(tempItem) + elif isinstance(self.drawObject, QtGui.QPainterPath): + tempItem = self.baseTransform.toQTransform().map(self.drawObject) + testBbox = self.getScreenTransform().toQTransform().map(tempItem).boundingRect() 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() + raise TypeError('drawObject is not a valid type!') + + if self.pen is not None: + lineWidth = self.pen.width + const = lineWidth/2 + bl = QtCore.QPointF(-const, const) + br = QtCore.QPointF(const, const) + tl = QtCore.QPointF(-const, -const) + tr = QtCore.QPointF(const, -const) + + pointList = [testBbox.topLeft(), testBbox.topRight(), testBbox.bottomLeft(), testBbox.bottomRight() + ] + + else: + pointList = [testBbox.topLeft(), testBbox.topRight(), testBbox.bottomLeft(), testBbox.bottomRight() + ] + + return QtGui.QPolygonF(pointList).boundingRect() @property def localBoundingBox(self): @@ -1345,22 +1751,25 @@ class DrawObject(Qc.QObject): def getScreenTransform(self): scrTransf = self.baseTransform.toQTransform().inverted()[0] * self.pTransform.toQTransform() + # print(asyTransform.fromQTransform(scrTransf).t) return asyTransform.fromQTransform(scrTransf) - def draw(self, additionalTransformation=None, applyReverse=False, canvas: Qg.QPainter=None, dpi=300): + def draw(self, additionalTransformation = None, applyReverse = False, canvas: QtGui.QPainter = None, dpi = 300): if canvas is None: canvas = self.mainCanvas if additionalTransformation is None: - additionalTransformation = Qg.QTransform() - + additionalTransformation = QtGui.QTransform() + assert canvas.isActive() canvas.save() if self.pen: - oldPen = Qg.QPen(canvas.pen()) - canvas.setPen(self.pen.toQPen()) + oldPen = QtGui.QPen(canvas.pen()) + localPen = self.pen.toQPen() + # localPen.setCosmetic(True) + canvas.setPen(localPen) #this fixes the object but not the box else: - oldPen = Qg.QPen() + oldPen = QtGui.QPen() if not applyReverse: canvas.setTransform(additionalTransformation, True) @@ -1371,11 +1780,9 @@ class DrawObject(Qc.QObject): 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): + if 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 @@ -1383,15 +1790,15 @@ class DrawObject(Qc.QObject): self.cachedSvgImg = self.drawObject.render(dpi) canvas.drawImage(self.explicitBoundingBox, self.cachedSvgImg) - elif isinstance(self.drawObject, Qs.QSvgRenderer): + elif isinstance(self.drawObject, QtSvg.QSvgRenderer): self.drawObject.render(canvas, self.explicitBoundingBox) - elif isinstance(self.drawObject, Qg.QPainterPath): + elif isinstance(self.drawObject, QtGui.QPainterPath): path = self.baseTransform.toQTransform().map(self.drawObject) if self.fill: if self.pen: brush = self.pen.toQPen().brush() else: - brush = Qg.QBrush() + brush = QtGui.QBrush() canvas.fillPath(path, brush) else: canvas.drawPath(path) @@ -1400,14 +1807,14 @@ class DrawObject(Qc.QObject): canvas.setPen(oldPen) canvas.restore() - def collide(self, coords, canvasCoordinates=True): - # modify these values to grow/shrink the fuzz. + 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) + newMargin = QtCore.QMarginsF(leftMargin, topMargin, leftMargin, topMargin) return self.boundingBox.marginsAdded(newMargin).contains(coords) def getID(self): diff --git a/Build/source/utils/asymptote/GUI/xasyArgs.py b/Build/source/utils/asymptote/GUI/xasyArgs.py index 045f4bc6692..b9e1518f1e8 100644 --- a/Build/source/utils/asymptote/GUI/xasyArgs.py +++ b/Build/source/utils/asymptote/GUI/xasyArgs.py @@ -1,23 +1,32 @@ #!/usr/bin/env python3 import argparse import xasyVersion -import PyQt5.QtCore as Qc +import PyQt5.QtCore as QtCore # 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', + parser.add_argument('-p', '-asypath', '--asypath', + help='Custom path to asy executable') + parser.add_argument('-v', '-version', '--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('-l', '-language', '--language', + help='language') + parser.add_argument('-x', '-mag', '--mag', + help='Initial magnification. Defaults to 1', + default=1, type=float) + parser.add_argument('-render', '--render', + help='Number of pixels per bp in 3D rendered bitmaps', + default=None, type=float) parser.add_argument( - 'filename', help='Filename to load. If empty, initializes empty xasy canvas.', nargs='?', default=None) + 'filename', + help='Filename to load (if omitted, initialize blank canvas)', + nargs='?', default=None) return parser.parse_args() def getArgs(): - return parseArgs(Qc.QCoreApplication.arguments()) + return parseArgs(QtCore.QCoreApplication.arguments()) diff --git a/Build/source/utils/asymptote/GUI/xasyBezierInterface.py b/Build/source/utils/asymptote/GUI/xasyBezierInterface.py index 0a5c689bffe..b10c8d4350c 100644 --- a/Build/source/utils/asymptote/GUI/xasyBezierInterface.py +++ b/Build/source/utils/asymptote/GUI/xasyBezierInterface.py @@ -1,16 +1,14 @@ #!/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 PyQt5.QtWidgets as QtWidgets +import PyQt5.QtCore as QtCore +import PyQt5.QtGui as QtGui +import xasy2asy as xasy2asy +import xasyUtils as xasyUtils import Widg_editBezier as Web import InplaceAddObj - import math class CurrentlySelctedType: @@ -19,16 +17,16 @@ class CurrentlySelctedType: ctrlPoint = 1 class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): - editAccepted = Qc.pyqtSignal() - editRejected = Qc.pyqtSignal() + editAccepted = QtCore.pyqtSignal() + editRejected = QtCore.pyqtSignal() - def __init__(self, parent: Qc.QObject, obj: x2a.xasyDrawnItem, info: dict={}): + def __init__(self, parent: QtCore.QObject, obj: xasy2asy.xasyDrawnItem, info: dict={}): super().__init__(parent) self.info = info - self.asyPathBackup = x2a.asyPath.fromPath(obj.path) + self.asyPathBackup = xasy2asy.asyPath.fromPath(obj.path) self.asyPath = obj.path self.curveMode = self.asyPath.containsCurve - assert isinstance(self.asyPath, x2a.asyPath) + assert isinstance(self.asyPath, xasy2asy.asyPath) self.transf = obj.transfKeymap[obj.transfKey][0] self._active = True @@ -47,10 +45,20 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): self.inTransformMode = False self.opt = None + self.obj = obj self.prosectiveNodes = [] self.prospectiveCtrlPts = [] + #The magnification isn't being set. Here I'm manually setting it to be the square root of the determinant. + self.info['magnification'] = math.sqrt(self.transf.xx * self.transf.yy - self.transf.xy * self.transf.yx) + self.parent = parent + if isinstance(obj,xasy2asy.xasyFilledShape) or isinstance(obj,xasy2asy.xasyShape): + parent.ui.btnFill.setChecked(obj.path.fill) + + def swapObjFill(self): + self.obj.swapFill() #This may end up being more in the future + def setSelectionBoundaries(self): self.nodeSelRects = self.handleNodeSelectionBounds() @@ -66,11 +74,11 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): continue selEpsilon = 6/self.info['magnification'] - newRect = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon) + newRect = QtCore.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)) + newRect.moveCenter(QtCore.QPoint(x, y)) nodeSelectionBoundaries.append(newRect) @@ -84,8 +92,8 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): selEpsilon = 6/self.info['magnification'] - newRect = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon) - newRectb = Qc.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon) + newRect = QtCore.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon) + newRectb = QtCore.QRect(0, 0, 2 * selEpsilon, 2 * selEpsilon) x, y = self.transf * nodea x2, y2 = self.transf * nodeb @@ -96,18 +104,19 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): x2 = int(round(x2)) y2 = int(round(y2)) - newRect.moveCenter(Qc.QPoint(x, y)) - newRectb.moveCenter(Qc.QPoint(x2, y2)) + newRect.moveCenter(QtCore.QPoint(x, y)) + newRectb.moveCenter(QtCore.QPoint(x2, y2)) ctrlPointSelBoundaries.append((newRect, newRectb)) return ctrlPointSelBoundaries - def postDrawPreview(self, canvas: Qg.QPainter): + + def postDrawPreview(self, canvas: QtGui.QPainter): assert canvas.isActive() - dashedPen = Qg.QPen(Qc.Qt.DashLine) - dashedPen.setWidthF(1/self.info['magnification']) + dashedPen = QtGui.QPen(QtCore.Qt.DashLine) + dashedPen.setCosmetic(True) # draw the base points canvas.save() canvas.setWorldTransform(self.transf.toQTransform(), True) @@ -123,27 +132,27 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): canvas.drawPath(self.asyPath.toQPainterPath()) - nodePen = Qg.QPen(Qg.QColor('blue')) - nodePen.setWidthF(1/self.info['magnification']) + nodePen = QtGui.QPen(QtGui.QColor('blue')) + nodePen.setCosmetic(True) - ctlPtsPen = Qg.QPen(Qg.QColor(ctrlPtsColor)) - ctlPtsPen.setWidthF(1/self.info['magnification']) + ctlPtsPen = QtGui.QPen(QtGui.QColor(ctrlPtsColor)) + ctlPtsPen.setCosmetic(True) for index in range(len(self.asyPath.nodeSet)): point = self.asyPath.nodeSet[index] - + if point != 'cycle': - basePoint = Qc.QPointF(point[0], point[1]) + basePoint = QtCore.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: + basePoint = QtCore.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]) + postCtrlPoint = QtCore.QPointF(postCtrolSet[0], postCtrolSet[1]) canvas.drawEllipse(postCtrlPoint, epsilonSize, epsilonSize) canvas.setPen(dashedPen) @@ -152,7 +161,7 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): if index != len(self.asyPath.nodeSet) - 1: canvas.setPen(ctlPtsPen) preCtrlSet = self.asyPath.controlSet[index][0] - preCtrlPoint = Qc.QPointF(preCtrlSet[0], preCtrlSet[1]) + preCtrlPoint = QtCore.QPointF(preCtrlSet[0], preCtrlSet[1]) canvas.drawEllipse(preCtrlPoint, epsilonSize, epsilonSize) canvas.setPen(dashedPen) @@ -189,7 +198,7 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): self.asyPath.setInfo(self.asyPathBackup) self.setSelectionBoundaries() - def mouseDown(self, pos, info, mouseEvent: Qg.QMouseEvent=None): + def mouseDown(self, pos, info, mouseEvent: QtGui.QMouseEvent=None): self.lastSelPoint = pos if self.inTransformMode: return @@ -204,13 +213,13 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): 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 + return preCtrl, postCtrl = self.getPreAndPostCtrlPts(self.parentNodeIndex) @@ -219,20 +228,20 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): self.parentNodeIndex = 0 if preCtrl is not None: - self.preCtrlOffset = xu.funcOnList( + self.preCtrlOffset = xasyUtils.funcOnList( preCtrl, parentNode, lambda a, b: a - b) else: self.preCtrlOffset = None if postCtrl is not None: - self.postCtrlOffset = xu.funcOnList( + self.postCtrlOffset = xasyUtils.funcOnList( postCtrl, parentNode, lambda a, b: a - b) else: self.postCtrlOffset = None - def mouseMove(self, pos, event: Qg.QMouseEvent): + def mouseMove(self, pos, event: QtGui.QMouseEvent): if self.currentSelMode is None and not self.inTransformMode: - # in this case, search for prosective nodes. + # in this case, search for prosective nodes. prospectiveNodes = [] prospectiveCtrlpts = [] @@ -262,32 +271,31 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): if self.inTransformMode: index, subindex = self.currentSelIndex - deltaPos = pos - self.lastSelPoint - newNode = (pos.x(), pos.y()) + newNode = (self.transf.inverted().toQTransform().map(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 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 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( + self.asyPath.controlSet[index - 1][1] = xasyUtils.funcOnList( newNode, self.preCtrlOffset, lambda a, b: a + b ) if checkPost is not None: - self.asyPath.controlSet[index][0] = xu.funcOnList( + self.asyPath.controlSet[index][0] = xasyUtils.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 @@ -302,46 +310,46 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): if self.parentNodeIndex == 0 and self.asyPath.nodeSet[-1] == 'cycle': isCycle = True - rawNewNode = xu.funcOnList(newNode, parentNode, lambda a, b: a - b) + rawNewNode = xasyUtils.funcOnList(newNode, parentNode, lambda a, b: a - b) rawAngle = math.atan2(rawNewNode[1], rawNewNode[0]) - newNorm = xu.twonorm(rawNewNode) + newNorm = xasyUtils.twonorm(rawNewNode) if self.info['editBezierlockMode'] >= Web.LockMode.angleLock: - otherIndex = 1 - subindex # 1 if 0, 0 otherwise. + 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( + oldOtherCtrlPnt = xasyUtils.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) + rawNorm = xasyUtils.twonorm(oldOtherCtrlPnt) - newPnt = (rawNorm * math.cos(rawAngle + math.pi), + newPnt = (rawNorm * math.cos(rawAngle + math.pi), rawNorm * math.sin(rawAngle + math.pi)) - - self.asyPath.controlSet[newIndex][0] = xu.funcOnList( + + self.asyPath.controlSet[newIndex][0] = xasyUtils.funcOnList( newPnt, parentNode, lambda a, b: a + b) else: if index > 0 or isCycle: newIndex = -1 if isCycle else index - 1 - oldOtherCtrlPnt = xu.funcOnList( + oldOtherCtrlPnt = xasyUtils.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) + rawNorm = xasyUtils.twonorm(oldOtherCtrlPnt) newPnt = (rawNorm * math.cos(rawAngle + math.pi), rawNorm * math.sin(rawAngle + math.pi)) - self.asyPath.controlSet[newIndex][1] = xu.funcOnList( + self.asyPath.controlSet[newIndex][1] = xasyUtils.funcOnList( newPnt, parentNode, lambda a, b: a + b) - + def recalculateCtrls(self): self.quickRecalculateCtrls() self.setSelectionBoundaries() @@ -356,7 +364,7 @@ class InteractiveBezierEditor(InplaceAddObj.InplaceObjProcess): self.currentSelMode = None self.setSelectionBoundaries() - + def forceFinalize(self): self.objectUpdated.emit() diff --git a/Build/source/utils/asymptote/GUI/xasyFile.py b/Build/source/utils/asymptote/GUI/xasyFile.py index eee6d69a856..54c70cf5c2b 100755 --- a/Build/source/utils/asymptote/GUI/xasyFile.py +++ b/Build/source/utils/asymptote/GUI/xasyFile.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ########################################################################### # -# xasyFile implements the loading, parsing, and saving of an xasy file. +# xasyFile implements the loading, parsing, and saving of an asy file. # # # Author: Orest Shardt @@ -10,7 +10,7 @@ ############################################################################ from string import * -import xasy2asy as x2a +import xasy2asy as xasy2asy import io import re @@ -28,7 +28,7 @@ class xasyFileError(Exception): def extractTransform(line): """Returns key and the new transform.""" # see https://regex101.com/r/6DqkRJ/4 for info - mapString = x2a.xasyItem.mapString + mapString = xasy2asy.xasyItem.mapString testMatch = re.match( r'^{0:s}\s*\(\s*\"([^\"]+)\"\s*,\s*\(([-\d, .]+)\)\s*\)'.format(mapString), line.strip()) if testMatch is None: @@ -37,7 +37,7 @@ def extractTransform(line): return None else: key = mapOnlyMatch.group(1) - return key, x2a.identity() + return key, xasy2asy.identity() else: key = testMatch.group(1) rawStr = testMatch.group(2) @@ -46,7 +46,7 @@ def extractTransform(line): if len(rawStrArray) != 6: return None transf = [float(val.strip()) for val in rawStrArray] - return key, x2a.asyTransform(transf) + return key, xasy2asy.asyTransform(transf) def extractTransformsFromFile(fileStr): @@ -62,22 +62,58 @@ def extractTransformsFromFile(fileStr): if key not in transfDict.keys(): transfDict[key] = [] transfDict[key].append(transf) - - # see https://regex101.com/r/RgeBVc/2 for regex - - testNum = re.match(r'^x(\d+)($|:.*$)', key) - if testNum is not None: - maxItemCount = max(maxItemCount, int(testNum.group(1))) final_str = rawCode.getvalue() - return final_str, transfDict, maxItemCount + return final_str, transfDict + +def xasy2asyCode(xasyItems, asy2psmap): + asyCode = '' + for item in xasyItems: + asyCode += item.getTransformCode(asy2psmap) + for item in xasyItems: + asyCode += item.getObjectCode(asy2psmap) + asyCode += 'size('+str(asy2psmap*xasy2asy.yflip())+'); '+ xasy2asy.xasyItem.resizeComment+'\n' + return asyCode def saveFile(file, xasyItems, asy2psmap): """Write a list of xasyItems to a file""" - for item in xasyItems: - file.write(item.getTransformCode(asy2psmap)) + file.write(xasy2asyCode(xasyItems, asy2psmap)) +def xasyToDict(file, xasyItems, asy2psmap): + fileItems = [] + asyItems = [] for item in xasyItems: - file.write(item.getObjectCode(asy2psmap)) + if isinstance(item, xasy2asy.xasyScript): + # reusing xasyFile code for objects + # imported from asy script. + asyItems.append({'item':item, 'type': 'xasyScript'}) + + elif isinstance(item, xasy2asy.xasyText): + # At the moment xasyText cannot be edited + # so we treat it the same as xasyScript + penData = {'color': item.pen.color, 'width': item.pen.width, 'options': item.pen.options} + fileItems.append({'type': 'xasyText', + 'align': item.label.align, + 'location': item.label.location, + 'fontSize': item.label.fontSize, + 'text': item.label.text, + 'transform': item.transfKeymap[item.transfKey][0].t, + 'transfKey': item.transfKey, + 'pen': penData + }) + + elif isinstance(item, xasy2asy.xasyShape): + penData = {'color': item.pen.color, 'width': item.pen.width, 'options': item.pen.options} + fileItems.append({'type': 'xasyShape', + 'nodes': item.path.nodeSet, + 'links': item.path.linkSet, + 'transform': item.transfKeymap[item.transfKey][0].t, + 'transfKey': item.transfKey, + 'pen': penData + }) + + else: + # DEBUGGING PURPOSES ONLY + print(type(item)) - file.write('size('+str(asy2psmap*x2a.yflip())+'); '+ x2a.xasyItem.resizeComment+'\n') + return {'objects': fileItems, 'asy2psmap': asy2psmap.t}, asyItems diff --git a/Build/source/utils/asymptote/GUI/xasyOptions.py b/Build/source/utils/asymptote/GUI/xasyOptions.py index 1923990fae6..458dd9cb3c9 100755 --- a/Build/source/utils/asymptote/GUI/xasyOptions.py +++ b/Build/source/utils/asymptote/GUI/xasyOptions.py @@ -10,25 +10,13 @@ # ########################################################################### -import json import sys import io import os import platform import shutil - import configs - -try: - import cson -except ModuleNotFoundError: - cson = None - -try: - pass -# import yaml -except ModuleNotFoundError: - yaml = None +import cson class xasyOptions: def defaultOptions(self): @@ -49,12 +37,12 @@ class xasyOptions: for key in self.options[settingsName]: self.options[key] = self.options[settingsName][key] - - + + def settingsFileLocation(self): folder = os.path.expanduser("~/.asy/") - searchOrder = ['.cson', '.yaml', '.json', ''] + searchOrder = ['.cson', ''] searchIndex = 0 found = False @@ -64,7 +52,7 @@ class xasyOptions: if os.path.isfile(currentFile): found = True searchIndex += 1 - + if found: return os.path.normcase(currentFile) else: @@ -79,7 +67,6 @@ class xasyOptions: self.options = self.defaultOptions() self.load() - self.overrideSettings() def __getitem__(self, item): return self.options[item] @@ -100,16 +87,7 @@ class xasyOptions: 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()) + newOptions = cson.loads(f.read()) except (IOError, ModuleNotFoundError): self.setDefaults() else: @@ -121,6 +99,7 @@ class xasyOptions: self.options = newOptions finally: f.close() + self.overrideSettings() def setDefaults(self): self.options = self.defaultOptions() @@ -130,7 +109,7 @@ class xasyOptions: folder = os.path.expanduser("~/.asy/") defaultPath = os.path.join(folder, self.configName + '.cson') shutil.copy2(self._defaultOptLocation, defaultPath) - + # TODO: Figure out how to merge this back. """ @@ -150,6 +129,72 @@ def setAsyPathFromWindowsRegistry(): registry.CloseKey(key) """ +class xasyOpenRecent: + def __init__(self, configName, defaultConfigLocation): + self.configName = configName + self.fileName = self.settingsFileLocation() + if not os.path.isfile(self.fileName): + f = io.open(self.fileName, 'w') + f.write('') + f.close() + + def settingsFileLocation(self): + folder = os.path.expanduser("~/.asy/") + + currentFile = os.path.join(folder, self.configName + '.txt') + return os.path.normcase(currentFile) + + def insert(self, path): + if not os.path.exists(self.fileName): + # make folder + thedir = os.path.dirname(self.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") + + f = io.open(self.fileName, 'r') + lines = f.readlines() + f.close() + + f = io.open(self.fileName, 'w') + f.write(path.strip() + '\n') + for line in lines: + if line.strip() != path.strip(): + f.write(line.strip() + '\n') + f.close() + + @property + def pathList(self): + self.findingPaths=True + return self.findPath() + + def findPath(self): + f = io.open(self.fileName, 'r') + paths = [path.strip() for path in f.readlines()] + f.close() + + trueFiles = list(map(lambda path: os.path.isfile(os.path.expanduser(path)), paths)) + if all(trueFiles): + return paths + else: + if self.findingPaths == False: + raise RecursionError + self.findingPaths = False + self.removeNotFound(list(trueFiles), paths) + return self.findPath() + + def removeNotFound(self, trueFiles, paths): + f = io.open(self.fileName, 'w') + for index, path in enumerate(paths): + if trueFiles[index] == True: + f.write(path + '\n') + f.close() + + def clear(self): + f = io.open(self.fileName, 'w') + f.write('') + f.close() class BasicConfigs: _configPath = list(configs.__path__)[0] @@ -157,3 +202,4 @@ class BasicConfigs: 'xasyconfig', os.path.join(_configPath, 'xasyconfig.cson')) keymaps = xasyOptions('xasykeymap', os.path.join( _configPath, 'xasykeymap.cson')) + openRecent = xasyOpenRecent('xasyrecents', os.path.join( _configPath, "xasyrecent.txt")) diff --git a/Build/source/utils/asymptote/GUI/xasyStrings.py b/Build/source/utils/asymptote/GUI/xasyStrings.py index 53f83a64f14..4f2ca0d2ed2 100644 --- a/Build/source/utils/asymptote/GUI/xasyStrings.py +++ b/Build/source/utils/asymptote/GUI/xasyStrings.py @@ -8,12 +8,12 @@ class xasyString: def __init__(self, lang=None): s = self if lang is None: - _ = lambda x: x + _ = 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') diff --git a/Build/source/utils/asymptote/GUI/xasySvg.py b/Build/source/utils/asymptote/GUI/xasySvg.py index a5325f9bdd6..7261dc5b691 100644 --- a/Build/source/utils/asymptote/GUI/xasySvg.py +++ b/Build/source/utils/asymptote/GUI/xasySvg.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 -import PyQt5.QtGui as Qg -import PyQt5.QtWidgets as Qw +import PyQt5.QtGui as QtGui +import PyQt5.QtWidgets as QtWidgets import io import subprocess import sys @@ -10,13 +10,13 @@ class SvgObject(): def __init__(self, file: str): self.file=file - def render(self, dpi:int) -> Qg.QImage: + def render(self, dpi:int) -> QtGui.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.') + QtWidgets.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') + return QtGui.QImage.fromData(rawDataProc.stdout.read(), 'PNG') diff --git a/Build/source/utils/asymptote/GUI/xasyTransform.py b/Build/source/utils/asymptote/GUI/xasyTransform.py index 928e9011f0a..cb70bf1edb1 100644 --- a/Build/source/utils/asymptote/GUI/xasyTransform.py +++ b/Build/source/utils/asymptote/GUI/xasyTransform.py @@ -1,24 +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 xasy2asy as xasy2asy +import PyQt5.QtGui as QtGui +import PyQt5.QtCore as QtCore +import numpy as numpy import math class xasyTransform: @classmethod def makeRotTransform(cls, theta, origin): - if isinstance(origin, Qc.QPointF) or isinstance(origin, Qc.QPoint): + if isinstance(origin, QtCore.QPointF) or isinstance(origin, QtCore.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])) + shift = xasy2asy.asyTransform((0, 0, 1 - rotMat[0], -rotMat[1], -rotMat[2], 1 - rotMat[3])) * origin + return xasy2asy.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): + if isinstance(origin, QtCore.QPointF) or isinstance(origin, QtCore.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)) + shiftMat = xasy2asy.asyTransform((0, 0, 1 - sx, 0, 0, 1 - sy)) * origin + return xasy2asy.asyTransform((shiftMat[0], shiftMat[1], sx, 0, 0, sy)) diff --git a/Build/source/utils/asymptote/GUI/xasyUtils.py b/Build/source/utils/asymptote/GUI/xasyUtils.py index 255e8b6addc..04e327bb443 100644 --- a/Build/source/utils/asymptote/GUI/xasyUtils.py +++ b/Build/source/utils/asymptote/GUI/xasyUtils.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import re -import typing as ty +import typing as typing import math import itertools @@ -15,12 +15,12 @@ def tryParse(val, typ=float): 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 +def funcOnList(list1: typing.Union[typing.List, typing.Tuple], list2: typing.Union[typing.List, typing.Tuple], func: typing.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))]) + return tuple([func(list1[i], list2[i]) for i in range(len(list1))]) def listize(str, typ, delim='()') -> list: @@ -39,7 +39,7 @@ def listize(str, typ, delim='()') -> list: final_list.append(typ(elem.strip())) return final_list -def twonorm(vec: ty.Iterable[ty.Union[float, int]]) -> float: +def twonorm(vec: typing.Iterable[typing.Union[float, int]]) -> float: rawSquared = sum(map(lambda x: x*x, vec)) return math.sqrt(rawSquared) |