aboutsummaryrefslogtreecommitdiffstats
path: root/examples/widgets/painting
diff options
context:
space:
mode:
Diffstat (limited to 'examples/widgets/painting')
-rw-r--r--examples/widgets/painting/README28
-rwxr-xr-xexamples/widgets/painting/basicdrawing/basicdrawing.py350
-rw-r--r--examples/widgets/painting/basicdrawing/basicdrawing.qrc6
-rw-r--r--examples/widgets/painting/basicdrawing/basicdrawing_rc.py174
-rw-r--r--examples/widgets/painting/basicdrawing/images/brick.pngbin0 -> 856 bytes
-rw-r--r--examples/widgets/painting/basicdrawing/images/qt-logo.pngbin0 -> 533 bytes
-rwxr-xr-xexamples/widgets/painting/concentriccircles.py147
-rwxr-xr-xexamples/widgets/painting/painterpaths.py283
-rw-r--r--examples/widgets/painting/svgviewer/files/bubbles.svg215
-rw-r--r--examples/widgets/painting/svgviewer/files/cubic.svg77
-rw-r--r--examples/widgets/painting/svgviewer/files/spheres.svg79
-rwxr-xr-xexamples/widgets/painting/svgviewer/svgviewer.py254
-rw-r--r--examples/widgets/painting/svgviewer/svgviewer.qrc7
-rw-r--r--examples/widgets/painting/svgviewer/svgviewer_rc.py639
-rwxr-xr-xexamples/widgets/painting/transformations.py232
15 files changed, 2491 insertions, 0 deletions
diff --git a/examples/widgets/painting/README b/examples/widgets/painting/README
new file mode 100644
index 0000000..83f2bbb
--- /dev/null
+++ b/examples/widgets/painting/README
@@ -0,0 +1,28 @@
+PyQt's painting system is able to render vector graphics, images, and outline
+font-based text with sub-pixel accuracy accuracy using anti-aliasing to
+improve rendering quality.
+
+These examples show the most common techniques that are used when painting
+with PyQt, from basic concepts such as drawing simple primitives to the use of
+transformations.
+
+
+The example launcher provided with PyQt can be used to explore each of the
+examples in this directory.
+
+Documentation for these examples can be found via the Tutorial and Examples
+link in the main Qt documentation.
+
+
+Finding the PyQt Examples and Demos launcher
+============================================
+
+On Windows:
+
+The launcher can be accessed via the Windows Start menu. Select the menu
+entry entitled "Examples and Demos" entry in the submenu containing PySide.
+
+On all platforms:
+
+The source code for the launcher can be found in the examples/tools/qtdemo
+directory in the PyQt package.
diff --git a/examples/widgets/painting/basicdrawing/basicdrawing.py b/examples/widgets/painting/basicdrawing/basicdrawing.py
new file mode 100755
index 0000000..c2f3e67
--- /dev/null
+++ b/examples/widgets/painting/basicdrawing/basicdrawing.py
@@ -0,0 +1,350 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the widgets/painting/basicdrawing example from Qt v5.x, originating from PyQt"""
+
+from PySide2.QtCore import QPoint, QRect, QSize, Qt, qVersion
+from PySide2.QtGui import (QBrush, QConicalGradient, QLinearGradient, QPainter,
+ QPainterPath, QPalette, QPen, QPixmap, QPolygon, QRadialGradient)
+from PySide2.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout,
+ QLabel, QSpinBox, QWidget)
+
+import basicdrawing_rc
+
+
+class RenderArea(QWidget):
+ points = QPolygon([
+ QPoint(10, 80),
+ QPoint(20, 10),
+ QPoint(80, 30),
+ QPoint(90, 70)
+ ])
+
+ Line, Points, Polyline, Polygon, Rect, RoundedRect, Ellipse, Arc, Chord, \
+ Pie, Path, Text, Pixmap = range(13)
+
+ def __init__(self, parent=None):
+ super(RenderArea, self).__init__(parent)
+
+ self.pen = QPen()
+ self.brush = QBrush()
+ self.pixmap = QPixmap()
+
+ self.shape = RenderArea.Polygon
+ self.antialiased = False
+ self.transformed = False
+ self.pixmap.load(':/images/qt-logo.png')
+
+ self.setBackgroundRole(QPalette.Base)
+ self.setAutoFillBackground(True)
+
+ def minimumSizeHint(self):
+ return QSize(100, 100)
+
+ def sizeHint(self):
+ return QSize(400, 200)
+
+ def setShape(self, shape):
+ self.shape = shape
+ self.update()
+
+ def setPen(self, pen):
+ self.pen = pen
+ self.update()
+
+ def setBrush(self, brush):
+ self.brush = brush
+ self.update()
+
+ def setAntialiased(self, antialiased):
+ self.antialiased = antialiased
+ self.update()
+
+ def setTransformed(self, transformed):
+ self.transformed = transformed
+ self.update()
+
+ def paintEvent(self, event):
+ rect = QRect(10, 20, 80, 60)
+
+ path = QPainterPath()
+ path.moveTo(20, 80)
+ path.lineTo(20, 30)
+ path.cubicTo(80, 0, 50, 50, 80, 80)
+
+ startAngle = 30 * 16
+ arcLength = 120 * 16
+
+ painter = QPainter(self)
+ painter.setPen(self.pen)
+ painter.setBrush(self.brush)
+ if self.antialiased:
+ painter.setRenderHint(QPainter.Antialiasing)
+
+ for x in range(0, self.width(), 100):
+ for y in range(0, self.height(), 100):
+ painter.save()
+ painter.translate(x, y)
+ if self.transformed:
+ painter.translate(50, 50)
+ painter.rotate(60.0)
+ painter.scale(0.6, 0.9)
+ painter.translate(-50, -50)
+
+ if self.shape == RenderArea.Line:
+ painter.drawLine(rect.bottomLeft(), rect.topRight())
+ elif self.shape == RenderArea.Points:
+ painter.drawPoints(RenderArea.points)
+ elif self.shape == RenderArea.Polyline:
+ painter.drawPolyline(RenderArea.points)
+ elif self.shape == RenderArea.Polygon:
+ painter.drawPolygon(RenderArea.points)
+ elif self.shape == RenderArea.Rect:
+ painter.drawRect(rect)
+ elif self.shape == RenderArea.RoundedRect:
+ painter.drawRoundedRect(rect, 25, 25, Qt.RelativeSize)
+ elif self.shape == RenderArea.Ellipse:
+ painter.drawEllipse(rect)
+ elif self.shape == RenderArea.Arc:
+ painter.drawArc(rect, startAngle, arcLength)
+ elif self.shape == RenderArea.Chord:
+ painter.drawChord(rect, startAngle, arcLength)
+ elif self.shape == RenderArea.Pie:
+ painter.drawPie(rect, startAngle, arcLength)
+ elif self.shape == RenderArea.Path:
+ painter.drawPath(path)
+ elif self.shape == RenderArea.Text:
+ painter.drawText(rect, Qt.AlignCenter,
+ "PySide 2\nQt %s" % qVersion())
+ elif self.shape == RenderArea.Pixmap:
+ painter.drawPixmap(10, 10, self.pixmap)
+
+ painter.restore()
+
+ painter.setPen(self.palette().dark().color())
+ painter.setBrush(Qt.NoBrush)
+ painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
+
+
+IdRole = Qt.UserRole
+
+class Window(QWidget):
+ def __init__(self):
+ super(Window, self).__init__()
+
+ self.renderArea = RenderArea()
+
+ self.shapeComboBox = QComboBox()
+ self.shapeComboBox.addItem("Polygon", RenderArea.Polygon)
+ self.shapeComboBox.addItem("Rectangle", RenderArea.Rect)
+ self.shapeComboBox.addItem("Rounded Rectangle", RenderArea.RoundedRect)
+ self.shapeComboBox.addItem("Ellipse", RenderArea.Ellipse)
+ self.shapeComboBox.addItem("Pie", RenderArea.Pie)
+ self.shapeComboBox.addItem("Chord", RenderArea.Chord)
+ self.shapeComboBox.addItem("Path", RenderArea.Path)
+ self.shapeComboBox.addItem("Line", RenderArea.Line)
+ self.shapeComboBox.addItem("Polyline", RenderArea.Polyline)
+ self.shapeComboBox.addItem("Arc", RenderArea.Arc)
+ self.shapeComboBox.addItem("Points", RenderArea.Points)
+ self.shapeComboBox.addItem("Text", RenderArea.Text)
+ self.shapeComboBox.addItem("Pixmap", RenderArea.Pixmap)
+
+ shapeLabel = QLabel("&Shape:")
+ shapeLabel.setBuddy(self.shapeComboBox)
+
+ self.penWidthSpinBox = QSpinBox()
+ self.penWidthSpinBox.setRange(0, 20)
+ self.penWidthSpinBox.setSpecialValueText("0 (cosmetic pen)")
+
+ penWidthLabel = QLabel("Pen &Width:")
+ penWidthLabel.setBuddy(self.penWidthSpinBox)
+
+ self.penStyleComboBox = QComboBox()
+ self.penStyleComboBox.addItem("Solid", Qt.SolidLine)
+ self.penStyleComboBox.addItem("Dash", Qt.DashLine)
+ self.penStyleComboBox.addItem("Dot", Qt.DotLine)
+ self.penStyleComboBox.addItem("Dash Dot", Qt.DashDotLine)
+ self.penStyleComboBox.addItem("Dash Dot Dot", Qt.DashDotDotLine)
+ self.penStyleComboBox.addItem("None", Qt.NoPen)
+
+ penStyleLabel = QLabel("&Pen Style:")
+ penStyleLabel.setBuddy(self.penStyleComboBox)
+
+ self.penCapComboBox = QComboBox()
+ self.penCapComboBox.addItem("Flat", Qt.FlatCap)
+ self.penCapComboBox.addItem("Square", Qt.SquareCap)
+ self.penCapComboBox.addItem("Round", Qt.RoundCap)
+
+ penCapLabel = QLabel("Pen &Cap:")
+ penCapLabel.setBuddy(self.penCapComboBox)
+
+ self.penJoinComboBox = QComboBox()
+ self.penJoinComboBox.addItem("Miter", Qt.MiterJoin)
+ self.penJoinComboBox.addItem("Bevel", Qt.BevelJoin)
+ self.penJoinComboBox.addItem("Round", Qt.RoundJoin)
+
+ penJoinLabel = QLabel("Pen &Join:")
+ penJoinLabel.setBuddy(self.penJoinComboBox)
+
+ self.brushStyleComboBox = QComboBox()
+ self.brushStyleComboBox.addItem("Linear Gradient",
+ Qt.LinearGradientPattern)
+ self.brushStyleComboBox.addItem("Radial Gradient",
+ Qt.RadialGradientPattern)
+ self.brushStyleComboBox.addItem("Conical Gradient",
+ Qt.ConicalGradientPattern)
+ self.brushStyleComboBox.addItem("Texture", Qt.TexturePattern)
+ self.brushStyleComboBox.addItem("Solid", Qt.SolidPattern)
+ self.brushStyleComboBox.addItem("Horizontal", Qt.HorPattern)
+ self.brushStyleComboBox.addItem("Vertical", Qt.VerPattern)
+ self.brushStyleComboBox.addItem("Cross", Qt.CrossPattern)
+ self.brushStyleComboBox.addItem("Backward Diagonal", Qt.BDiagPattern)
+ self.brushStyleComboBox.addItem("Forward Diagonal", Qt.FDiagPattern)
+ self.brushStyleComboBox.addItem("Diagonal Cross", Qt.DiagCrossPattern)
+ self.brushStyleComboBox.addItem("Dense 1", Qt.Dense1Pattern)
+ self.brushStyleComboBox.addItem("Dense 2", Qt.Dense2Pattern)
+ self.brushStyleComboBox.addItem("Dense 3", Qt.Dense3Pattern)
+ self.brushStyleComboBox.addItem("Dense 4", Qt.Dense4Pattern)
+ self.brushStyleComboBox.addItem("Dense 5", Qt.Dense5Pattern)
+ self.brushStyleComboBox.addItem("Dense 6", Qt.Dense6Pattern)
+ self.brushStyleComboBox.addItem("Dense 7", Qt.Dense7Pattern)
+ self.brushStyleComboBox.addItem("None", Qt.NoBrush)
+
+ brushStyleLabel = QLabel("&Brush Style:")
+ brushStyleLabel.setBuddy(self.brushStyleComboBox)
+
+ otherOptionsLabel = QLabel("Other Options:")
+ self.antialiasingCheckBox = QCheckBox("&Antialiasing")
+ self.transformationsCheckBox = QCheckBox("&Transformations")
+
+ self.shapeComboBox.activated.connect(self.shapeChanged)
+ self.penWidthSpinBox.valueChanged.connect(self.penChanged)
+ self.penStyleComboBox.activated.connect(self.penChanged)
+ self.penCapComboBox.activated.connect(self.penChanged)
+ self.penJoinComboBox.activated.connect(self.penChanged)
+ self.brushStyleComboBox.activated.connect(self.brushChanged)
+ self.antialiasingCheckBox.toggled.connect(self.renderArea.setAntialiased)
+ self.transformationsCheckBox.toggled.connect(self.renderArea.setTransformed)
+
+ mainLayout = QGridLayout()
+ mainLayout.setColumnStretch(0, 1)
+ mainLayout.setColumnStretch(3, 1)
+ mainLayout.addWidget(self.renderArea, 0, 0, 1, 4)
+ mainLayout.setRowMinimumHeight(1, 6)
+ mainLayout.addWidget(shapeLabel, 2, 1, Qt.AlignRight)
+ mainLayout.addWidget(self.shapeComboBox, 2, 2)
+ mainLayout.addWidget(penWidthLabel, 3, 1, Qt.AlignRight)
+ mainLayout.addWidget(self.penWidthSpinBox, 3, 2)
+ mainLayout.addWidget(penStyleLabel, 4, 1, Qt.AlignRight)
+ mainLayout.addWidget(self.penStyleComboBox, 4, 2)
+ mainLayout.addWidget(penCapLabel, 5, 1, Qt.AlignRight)
+ mainLayout.addWidget(self.penCapComboBox, 5, 2)
+ mainLayout.addWidget(penJoinLabel, 6, 1, Qt.AlignRight)
+ mainLayout.addWidget(self.penJoinComboBox, 6, 2)
+ mainLayout.addWidget(brushStyleLabel, 7, 1, Qt.AlignRight)
+ mainLayout.addWidget(self.brushStyleComboBox, 7, 2)
+ mainLayout.setRowMinimumHeight(8, 6)
+ mainLayout.addWidget(otherOptionsLabel, 9, 1, Qt.AlignRight)
+ mainLayout.addWidget(self.antialiasingCheckBox, 9, 2)
+ mainLayout.addWidget(self.transformationsCheckBox, 10, 2)
+ self.setLayout(mainLayout)
+
+ self.shapeChanged()
+ self.penChanged()
+ self.brushChanged()
+ self.antialiasingCheckBox.setChecked(True)
+
+ self.setWindowTitle("Basic Drawing")
+
+ def shapeChanged(self):
+ shape = self.shapeComboBox.itemData(self.shapeComboBox.currentIndex(),
+ IdRole)
+ self.renderArea.setShape(shape)
+
+ def penChanged(self):
+ width = self.penWidthSpinBox.value()
+ style = Qt.PenStyle(self.penStyleComboBox.itemData(
+ self.penStyleComboBox.currentIndex(), IdRole))
+ cap = Qt.PenCapStyle(self.penCapComboBox.itemData(
+ self.penCapComboBox.currentIndex(), IdRole))
+ join = Qt.PenJoinStyle(self.penJoinComboBox.itemData(
+ self.penJoinComboBox.currentIndex(), IdRole))
+
+ self.renderArea.setPen(QPen(Qt.blue, width, style, cap, join))
+
+ def brushChanged(self):
+ style = Qt.BrushStyle(self.brushStyleComboBox.itemData(
+ self.brushStyleComboBox.currentIndex(), IdRole))
+
+ if style == Qt.LinearGradientPattern:
+ linearGradient = QLinearGradient(0, 0, 100, 100)
+ linearGradient.setColorAt(0.0, Qt.white)
+ linearGradient.setColorAt(0.2, Qt.green)
+ linearGradient.setColorAt(1.0, Qt.black)
+ self.renderArea.setBrush(QBrush(linearGradient))
+ elif style == Qt.RadialGradientPattern:
+ radialGradient = QRadialGradient(50, 50, 50, 70, 70)
+ radialGradient.setColorAt(0.0, Qt.white)
+ radialGradient.setColorAt(0.2, Qt.green)
+ radialGradient.setColorAt(1.0, Qt.black)
+ self.renderArea.setBrush(QBrush(radialGradient))
+ elif style == Qt.ConicalGradientPattern:
+ conicalGradient = QConicalGradient(50, 50, 150)
+ conicalGradient.setColorAt(0.0, Qt.white)
+ conicalGradient.setColorAt(0.2, Qt.green)
+ conicalGradient.setColorAt(1.0, Qt.black)
+ self.renderArea.setBrush(QBrush(conicalGradient))
+ elif style == Qt.TexturePattern:
+ self.renderArea.setBrush(QBrush(QPixmap(':/images/brick.png')))
+ else:
+ self.renderArea.setBrush(QBrush(Qt.green, style))
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QApplication(sys.argv)
+ window = Window()
+ window.show()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/painting/basicdrawing/basicdrawing.qrc b/examples/widgets/painting/basicdrawing/basicdrawing.qrc
new file mode 100644
index 0000000..9d8a23a
--- /dev/null
+++ b/examples/widgets/painting/basicdrawing/basicdrawing.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>images/brick.png</file>
+ <file>images/qt-logo.png</file>
+</qresource>
+</RCC>
diff --git a/examples/widgets/painting/basicdrawing/basicdrawing_rc.py b/examples/widgets/painting/basicdrawing/basicdrawing_rc.py
new file mode 100644
index 0000000..b9de903
--- /dev/null
+++ b/examples/widgets/painting/basicdrawing/basicdrawing_rc.py
@@ -0,0 +1,174 @@
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# Resource object code
+#
+# Created: Wed Dec 28 19:54:31 2005
+# by: The Resource Compiler for PyQt (Qt v4.1.0)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PySide2 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x03\x58\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x20\x00\x00\x00\x10\x08\x02\x00\x00\x00\xf8\x62\xea\x0e\
+\x00\x00\x00\x04\x67\x41\x4d\x41\x00\x00\xb1\x8e\x7c\xfb\x51\x93\
+\x00\x00\x00\x20\x63\x48\x52\x4d\x00\x00\x7a\x25\x00\x00\x80\x83\
+\x00\x00\xf9\xff\x00\x00\x80\xe8\x00\x00\x75\x30\x00\x00\xea\x60\
+\x00\x00\x3a\x97\x00\x00\x17\x6f\x97\xa9\x99\xd4\x00\x00\x02\xe3\
+\x49\x44\x41\x54\x38\xcb\x45\x94\xcb\x8d\x1e\x45\x10\xc7\x7f\x55\
+\xd5\x33\xb3\xf6\x6a\x9d\x09\x49\x90\x04\x0e\x05\x09\x99\x78\xe0\
+\xc4\xc1\x12\x07\x42\x20\x04\x08\xc1\x96\xd7\xcb\xb7\xf3\xcd\xf4\
+\xa3\xaa\x38\x4c\x5b\xee\x73\xbd\xfa\xff\x92\xcf\xff\xfc\xa6\x86\
+\x1a\x28\x2a\x20\x64\x42\x92\x41\x04\x38\x1e\xa4\x93\x41\x38\x39\
+\x40\x11\x41\x94\x8c\x59\x93\x57\x41\x42\x62\x2b\x65\xc3\x16\xac\
+\x20\x85\xf7\x3f\xbd\x2f\x08\xf5\xf6\x6f\xd9\x50\x25\x0c\x35\xc4\
+\x48\xc7\x3b\x31\x18\x8d\x18\xa4\x13\x4e\x74\x7c\x20\x82\x16\x80\
+\x74\xdc\xf1\x46\x0c\xc2\x11\x00\xa4\xb0\xbc\xe1\xe1\x09\xdb\xf8\
+\xf5\xc3\x87\x0c\x8a\x1a\xaa\xd4\x97\xbf\xcb\x82\x2e\xf3\x04\x9c\
+\xa8\xd4\x9d\x7e\xa7\x9f\xf3\xd8\xd1\xf0\x93\x70\xb4\x20\x82\x77\
+\xfa\xc1\x68\x10\x44\x02\xa8\x62\x0b\xeb\x23\xfd\x1d\x7f\xfe\xf5\
+\x31\x02\x51\x8a\x16\xd4\x10\xa5\xdd\x3e\x6a\x61\x7b\x22\x20\x06\
+\x7d\xe7\xfc\xc2\xf9\x1f\xc7\x33\xf5\x75\x82\xd0\x76\x46\x45\x94\
+\x18\x78\xa7\xef\x8c\x8e\x2a\xde\xc9\xc4\x0a\xdb\x3b\x1e\x9e\x58\
+\x1e\xf1\x0e\x01\x50\x44\x10\xc3\x0a\x61\x94\x07\xca\x86\x2e\x84\
+\x93\x01\x4c\x32\xc6\x81\x0f\xd2\x69\x07\x5e\x01\xc4\x88\x81\x18\
+\x0c\xbc\x33\x1a\xd1\xf1\x42\xd9\x68\x85\x4c\x62\x90\x49\x06\xe5\
+\xc2\x54\x0c\x51\x6c\x45\x0b\x19\x64\xe2\x83\x76\xe7\xf8\x4a\xdb\
+\x49\x68\x77\xc6\x9d\xd1\x89\x41\x06\xb6\x20\x4a\x3f\x21\x18\x8d\
+\xbe\x93\x49\x11\xbc\x61\x1b\xfd\xa0\xef\x8c\x13\xef\x17\x07\x05\
+\x51\x44\x11\x21\x9c\x51\xa9\x37\xce\x17\x8e\xaf\xd4\xdb\xe4\x60\
+\x9c\xdc\xbf\x90\x17\xb7\x83\xf5\x11\x51\xfa\x7d\x76\x89\x92\x8e\
+\x08\x11\x78\x87\xa4\x9f\xf4\x93\x51\x2f\x88\x14\xb9\x78\x1b\x8c\
+\xca\xf9\xc2\xf1\xc2\xf1\x3c\xfb\xc9\x89\xd5\x68\x78\xbb\xb4\x42\
+\x0c\x80\x51\x51\xa3\x6c\x2c\x6f\x21\x27\x6e\x5e\x51\x9d\xda\x8d\
+\xa0\x44\x00\x98\x12\x2b\x80\x57\xfa\x49\xbb\x51\x6f\xb4\x57\x32\
+\x09\x67\x1c\x64\xa0\x85\x7e\xc7\x3b\x5a\xe8\x8a\x15\xc8\x39\xb7\
+\xac\x08\x88\x52\x1e\xa6\x82\x33\x41\x20\x29\x17\x99\x62\xa8\x11\
+\x8e\x77\xbc\x11\x41\x38\x75\xa7\x1f\x53\x91\xa3\x7e\xf7\x97\x77\
+\x32\x88\x95\x70\x60\xee\x36\xc3\x16\x96\x47\x32\xbe\x41\xa7\x20\
+\x14\x51\x08\x62\xd0\x0e\x54\x19\x95\xe8\x4c\x62\x8c\x4c\x46\x65\
+\x1c\xd4\x1d\x3f\x49\x07\x21\x83\x14\xa2\x91\x49\xef\xa0\xac\x6f\
+\x91\x85\x64\xb2\x7d\xad\xbc\x0e\x2a\x99\x78\xa7\xed\xec\x9f\xb0\
+\x85\x18\x93\x0f\x35\xca\x4a\x37\x86\x53\x5f\x69\xfb\x34\xd4\x25\
+\x41\x35\x10\x46\x23\x1d\x35\xfa\x1d\x35\xb2\x93\x81\x28\x6a\x13\
+\x15\x5b\x28\x31\xe8\x07\xf7\x67\xf6\x4f\xac\x4f\xa8\xe1\x8d\x51\
+\x21\xb0\x82\x95\xef\x6e\xb8\xac\x24\x42\x0f\x60\xc6\x43\x79\x83\
+\x6d\x84\xd3\x4f\x00\xdb\xe6\xee\xeb\x44\x2b\x94\x70\x7c\xf0\xc7\
+\xef\x1f\x23\xd8\x9e\xa6\x4b\x11\xa2\xd1\x76\xda\x9d\xfa\x4a\xbb\
+\x31\x2a\x97\xf5\x2f\x45\x66\x80\x20\x8a\x1e\x58\xc5\xf6\xc9\xa2\
+\x1a\xba\x00\x94\x6f\x9b\x4a\x38\xbf\xfc\xfc\xe1\x32\x9e\xad\x88\
+\xcc\x54\xf1\x41\xdd\x89\x2b\xf2\xea\x4c\xba\xab\x87\x2b\x68\xa1\
+\xac\xe8\x82\x74\x54\x41\xd0\x05\x55\x00\x51\x74\x41\x8d\x4c\xe4\
+\xc7\x1f\x40\x67\x16\x5e\xc0\x5d\xef\x92\x53\xe6\x84\x3e\x06\x04\
+\x57\x5d\x06\xe4\xfc\x41\x59\xbf\xb5\x08\x57\x6e\x8a\xce\x39\x97\
+\xe4\xfe\x07\xb6\x84\x15\x24\x5c\xbc\x4f\xce\x00\x00\x00\x00\x49\
+\x45\x4e\x44\xae\x42\x60\x82\
+\x00\x00\x02\x15\
+\x89\
+\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
+\x00\x00\x50\x00\x00\x00\x50\x04\x03\x00\x00\x00\x7c\x3f\xef\x9e\
+\x00\x00\x00\x15\x50\x4c\x54\x45\xa3\xc2\x00\xf4\xf8\xe1\x8a\xa1\
+\x09\x14\x14\x18\x3f\x47\x16\xd3\xe2\x86\x70\x82\x0e\xfd\x17\x22\
+\x39\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x00\x48\x00\x00\x00\
+\x48\x00\x46\xc9\x6b\x3e\x00\x00\x01\xa6\x49\x44\x41\x54\x48\xc7\
+\xed\x56\x4b\x6e\x84\x30\x0c\x45\x66\xc4\x39\xa2\x49\xd5\x35\x22\
+\x11\x6b\xd4\x48\x73\x0e\x54\x10\xf7\x3f\x42\x0b\xc4\x4c\xfc\x83\
+\xd9\x75\xd1\xf1\x0a\xa2\x97\x17\xdb\xb1\x9f\x53\x55\x6f\xfb\x6b\
+\xbb\x2f\xcb\xfd\x1a\x05\x73\x0a\xbf\x16\x1f\xee\x1c\xd7\x6c\xb0\
+\x0d\x3a\x9e\xe2\x42\x61\xe3\x8b\xb8\x13\x24\x24\x0a\x8c\x96\x9f\
+\x53\x60\xd6\xeb\xb8\x5b\x10\x36\xa8\xc0\x24\x81\xf1\x45\x42\x9d\
+\x12\x09\xe3\x63\x59\xe6\x64\x53\x62\x6a\xf6\x2b\x81\xd9\xa4\xf4\
+\x19\x87\xff\x1f\x56\xe0\x89\xaf\xe7\x64\x39\x3d\x14\x27\xd2\x3f\
+\xa8\x27\x7f\xc9\xbd\x9d\x7a\xf2\x93\x6e\xc4\x35\x16\x37\xb0\xdd\
+\x7e\x75\xb6\x56\x4a\xe3\x46\xd7\x60\xfb\x06\xc5\xc9\x9a\x9e\xe2\
+\xf7\xf8\x93\x74\x72\x22\x4b\x90\xe9\x6b\x99\xc9\x44\x0e\xf1\x19\
+\xd0\xc8\x68\x52\x99\x44\xc0\x02\x07\x91\x72\x20\x5b\xf3\x6d\xb6\
+\x6c\xff\x51\x11\x3d\x25\x5c\x9d\x9c\x78\x7e\x08\x30\x13\x76\xf8\
+\x39\xf0\x34\x76\x94\xd0\x61\xd6\x04\xb0\x15\x84\xfb\xba\x01\x84\
+\xb2\xa9\x75\xe0\x50\x12\xf6\xd5\x05\x23\x84\x6b\xc6\xb6\x20\xcc\
+\x94\x37\x33\x6a\xa0\xca\x23\xa2\x3e\xf2\xe8\xa9\x9e\x78\x15\x18\
+\x09\xa1\x7e\x33\x78\xd7\x35\x93\x28\x71\xd7\xb8\x02\x54\x1f\x81\
+\x36\x52\x59\x8f\x9b\x53\x1d\xe6\x52\xa9\x47\xac\x70\x28\x98\x42\
+\x98\x64\x85\x1f\x3d\xb3\x77\x4b\x11\x3c\xeb\x99\xa3\x0b\x61\x73\
+\x1e\x4c\xe5\x7b\xf6\xb5\xef\x2a\x9a\x4f\xa7\x29\x85\xcb\x1a\x51\
+\x50\x46\x55\x7b\x3a\xae\x82\x52\x7b\x1a\x76\x0e\x98\xe2\xcc\xf5\
+\x11\x29\x2d\xc5\x3d\x90\xb3\x35\xbe\x50\xc3\x7b\xaa\xe1\xa6\x36\
+\xb3\xa9\xa0\x51\xaa\x73\xe6\x94\x92\xdb\x78\x31\x84\x4f\xa6\xd7\
+\xa4\xe2\xe2\x0b\xf3\x7a\xb2\xc6\x61\x93\x64\x85\xc7\x8b\xb7\xc7\
+\x1e\x84\xb7\x46\x36\x7f\xa5\x80\x41\xb8\xda\x92\xdf\x3d\xf9\x62\
+\x87\xb3\x97\xd4\xe7\xf7\xf1\x92\x02\xf7\x7e\x59\xfe\x3f\xfb\x01\
+\xbd\xf6\xdd\x91\xa2\xf3\xda\xd4\x00\x00\x00\x00\x49\x45\x4e\x44\
+\xae\x42\x60\x82\
+"
+
+qt_resource_name = b"\
+\x00\x06\
+\x07\x03\x7d\xc3\
+\x00\x69\
+\x00\x6d\x00\x61\x00\x67\x00\x65\x00\x73\
+\x00\x09\
+\x0f\x9e\x84\x47\
+\x00\x62\
+\x00\x72\x00\x69\x00\x63\x00\x6b\x00\x2e\x00\x70\x00\x6e\x00\x67\
+\x00\x0b\
+\x05\x52\xbf\x27\
+\x00\x71\
+\x00\x74\x00\x2d\x00\x6c\x00\x6f\x00\x67\x00\x6f\x00\x2e\x00\x70\x00\x6e\x00\x67\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\
+\x00\x00\x00\x2a\x00\x00\x00\x00\x00\x01\x00\x00\x03\x5c\
+\x00\x00\x00\x12\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/widgets/painting/basicdrawing/images/brick.png b/examples/widgets/painting/basicdrawing/images/brick.png
new file mode 100644
index 0000000..ab5e383
--- /dev/null
+++ b/examples/widgets/painting/basicdrawing/images/brick.png
Binary files differ
diff --git a/examples/widgets/painting/basicdrawing/images/qt-logo.png b/examples/widgets/painting/basicdrawing/images/qt-logo.png
new file mode 100644
index 0000000..9c27cf6
--- /dev/null
+++ b/examples/widgets/painting/basicdrawing/images/qt-logo.png
Binary files differ
diff --git a/examples/widgets/painting/concentriccircles.py b/examples/widgets/painting/concentriccircles.py
new file mode 100755
index 0000000..5fecfc0
--- /dev/null
+++ b/examples/widgets/painting/concentriccircles.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+"""PySide2 port of the widgets/painting/concentriccircles example from Qt v5.x, originating from PyQt"""
+
+from PySide2.QtCore import QRect, QRectF, QSize, Qt, QTimer
+from PySide2.QtGui import QColor, QPainter, QPalette, QPen
+from PySide2.QtWidgets import (QApplication, QFrame, QGridLayout, QLabel,
+ QSizePolicy, QWidget)
+
+
+class CircleWidget(QWidget):
+ def __init__(self, parent=None):
+ super(CircleWidget, self).__init__(parent)
+
+ self.floatBased = False
+ self.antialiased = False
+ self.frameNo = 0
+
+ self.setBackgroundRole(QPalette.Base)
+ self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+
+ def setFloatBased(self, floatBased):
+ self.floatBased = floatBased
+ self.update()
+
+ def setAntialiased(self, antialiased):
+ self.antialiased = antialiased
+ self.update()
+
+ def minimumSizeHint(self):
+ return QSize(50, 50)
+
+ def sizeHint(self):
+ return QSize(180, 180)
+
+ def nextAnimationFrame(self):
+ self.frameNo += 1
+ self.update()
+
+ def paintEvent(self, event):
+ painter = QPainter(self)
+ painter.setRenderHint(QPainter.Antialiasing, self.antialiased)
+ painter.translate(self.width() / 2, self.height() / 2)
+
+ for diameter in range(0, 256, 9):
+ delta = abs((self.frameNo % 128) - diameter / 2)
+ alpha = 255 - (delta * delta) / 4 - diameter
+ if alpha > 0:
+ painter.setPen(QPen(QColor(0, diameter / 2, 127, alpha), 3))
+
+ if self.floatBased:
+ painter.drawEllipse(QRectF(-diameter / 2.0,
+ -diameter / 2.0, diameter, diameter))
+ else:
+ painter.drawEllipse(QRect(-diameter / 2,
+ -diameter / 2, diameter, diameter))
+
+
+class Window(QWidget):
+ def __init__(self):
+ super(Window, self).__init__()
+
+ aliasedLabel = self.createLabel("Aliased")
+ antialiasedLabel = self.createLabel("Antialiased")
+ intLabel = self.createLabel("Int")
+ floatLabel = self.createLabel("Float")
+
+ layout = QGridLayout()
+ layout.addWidget(aliasedLabel, 0, 1)
+ layout.addWidget(antialiasedLabel, 0, 2)
+ layout.addWidget(intLabel, 1, 0)
+ layout.addWidget(floatLabel, 2, 0)
+
+ timer = QTimer(self)
+
+ for i in range(2):
+ for j in range(2):
+ w = CircleWidget()
+ w.setAntialiased(j != 0)
+ w.setFloatBased(i != 0)
+
+ timer.timeout.connect(w.nextAnimationFrame)
+
+ layout.addWidget(w, i + 1, j + 1)
+
+ timer.start(100)
+ self.setLayout(layout)
+
+ self.setWindowTitle("Concentric Circles")
+
+ def createLabel(self, text):
+ label = QLabel(text)
+ label.setAlignment(Qt.AlignCenter)
+ label.setMargin(2)
+ label.setFrameStyle(QFrame.Box | QFrame.Sunken)
+ return label
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QApplication(sys.argv)
+ window = Window()
+ window.show()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/painting/painterpaths.py b/examples/widgets/painting/painterpaths.py
new file mode 100755
index 0000000..04c311c
--- /dev/null
+++ b/examples/widgets/painting/painterpaths.py
@@ -0,0 +1,283 @@
+#!/usr/bin/env python
+
+############################################################################
+##
+## Copyright (C) 2005-2005 Trolltech AS. All rights reserved.
+##
+## This file is part of the example classes of the Qt Toolkit.
+##
+## This file may be used under the terms of the GNU General Public
+## License version 2.0 as published by the Free Software Foundation
+## and appearing in the file LICENSE.GPL included in the packaging of
+## this file. Please review the following information to ensure GNU
+## General Public Licensing requirements will be met:
+## http://www.trolltech.com/products/qt/opensource.html
+##
+## If you are unsure which license is appropriate for your use, please
+## review the following information:
+## http://www.trolltech.com/products/qt/licensing.html or contact the
+## sales department at sales@trolltech.com.
+##
+## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+##
+############################################################################
+
+from math import cos, pi, sin
+
+from PySide2 import QtCore, QtGui
+
+
+class RenderArea(QtGui.QWidget):
+ def __init__(self, path, parent=None):
+ super(RenderArea, self).__init__(parent)
+
+ self.path = path
+
+ self.penWidth = 1
+ self.rotationAngle = 0
+ self.setBackgroundRole(QtGui.QPalette.Base)
+
+ def minimumSizeHint(self):
+ return QtCore.QSize(50, 50)
+
+ def sizeHint(self):
+ return QtCore.QSize(100, 100)
+
+ def setFillRule(self, rule):
+ self.path.setFillRule(rule)
+ self.update()
+
+ def setFillGradient(self, color1, color2):
+ self.fillColor1 = color1
+ self.fillColor2 = color2
+ self.update()
+
+ def setPenWidth(self, width):
+ self.penWidth = width
+ self.update()
+
+ def setPenColor(self, color):
+ self.penColor = color
+ self.update()
+
+ def setRotationAngle(self, degrees):
+ self.rotationAngle = degrees
+ self.update()
+
+ def paintEvent(self, event):
+ painter = QtGui.QPainter(self)
+ painter.setRenderHint(QtGui.QPainter.Antialiasing)
+ painter.scale(self.width() / 100.0, self.height() / 100.0)
+ painter.translate(50.0, 50.0)
+ painter.rotate(-self.rotationAngle)
+ painter.translate(-50.0, -50.0)
+
+ painter.setPen(QtGui.QPen(self.penColor, self.penWidth,
+ QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin))
+ gradient = QtGui.QLinearGradient(0, 0, 0, 100)
+ gradient.setColorAt(0.0, self.fillColor1)
+ gradient.setColorAt(1.0, self.fillColor2)
+ painter.setBrush(QtGui.QBrush(gradient))
+ painter.drawPath(self.path)
+
+
+class Window(QtGui.QWidget):
+ NumRenderAreas = 9
+
+ def __init__(self):
+ super(Window, self).__init__()
+
+ rectPath = QtGui.QPainterPath()
+ rectPath.moveTo(20.0, 30.0)
+ rectPath.lineTo(80.0, 30.0)
+ rectPath.lineTo(80.0, 70.0)
+ rectPath.lineTo(20.0, 70.0)
+ rectPath.closeSubpath()
+
+ roundRectPath = QtGui.QPainterPath()
+ roundRectPath.moveTo(80.0, 35.0)
+ roundRectPath.arcTo(70.0, 30.0, 10.0, 10.0, 0.0, 90.0)
+ roundRectPath.lineTo(25.0, 30.0)
+ roundRectPath.arcTo(20.0, 30.0, 10.0, 10.0, 90.0, 90.0)
+ roundRectPath.lineTo(20.0, 65.0)
+ roundRectPath.arcTo(20.0, 60.0, 10.0, 10.0, 180.0, 90.0)
+ roundRectPath.lineTo(75.0, 70.0)
+ roundRectPath.arcTo(70.0, 60.0, 10.0, 10.0, 270.0, 90.0)
+ roundRectPath.closeSubpath()
+
+ ellipsePath = QtGui.QPainterPath()
+ ellipsePath.moveTo(80.0, 50.0)
+ ellipsePath.arcTo(20.0, 30.0, 60.0, 40.0, 0.0, 360.0)
+
+ piePath = QtGui.QPainterPath()
+ piePath.moveTo(50.0, 50.0)
+ piePath.lineTo(65.0, 32.6795)
+ piePath.arcTo(20.0, 30.0, 60.0, 40.0, 60.0, 240.0)
+ piePath.closeSubpath()
+
+ polygonPath = QtGui.QPainterPath()
+ polygonPath.moveTo(10.0, 80.0)
+ polygonPath.lineTo(20.0, 10.0)
+ polygonPath.lineTo(80.0, 30.0)
+ polygonPath.lineTo(90.0, 70.0)
+ polygonPath.closeSubpath()
+
+ groupPath = QtGui.QPainterPath()
+ groupPath.moveTo(60.0, 40.0)
+ groupPath.arcTo(20.0, 20.0, 40.0, 40.0, 0.0, 360.0)
+ groupPath.moveTo(40.0, 40.0)
+ groupPath.lineTo(40.0, 80.0)
+ groupPath.lineTo(80.0, 80.0)
+ groupPath.lineTo(80.0, 40.0)
+ groupPath.closeSubpath()
+
+ textPath = QtGui.QPainterPath()
+ timesFont = QtGui.QFont("Times", 50)
+ timesFont.setStyleStrategy(QtGui.QFont.ForceOutline)
+ textPath.addText(10, 70, timesFont, "Qt")
+
+ bezierPath = QtGui.QPainterPath()
+ bezierPath.moveTo(20, 30)
+ bezierPath.cubicTo(80, 0, 50, 50, 80, 80)
+
+ starPath = QtGui.QPainterPath()
+ starPath.moveTo(90, 50)
+ for i in range(1, 5):
+ starPath.lineTo(50 + 40 * cos(0.8 * i * pi),
+ 50 + 40 * sin(0.8 * i * pi))
+ starPath.closeSubpath()
+
+ self.renderAreas = [RenderArea(rectPath), RenderArea(roundRectPath),
+ RenderArea(ellipsePath), RenderArea(piePath),
+ RenderArea(polygonPath), RenderArea(groupPath),
+ RenderArea(textPath), RenderArea(bezierPath),
+ RenderArea(starPath)]
+ assert len(self.renderAreas) == 9
+
+ self.fillRuleComboBox = QtGui.QComboBox()
+ self.fillRuleComboBox.addItem("Odd Even", QtCore.Qt.OddEvenFill)
+ self.fillRuleComboBox.addItem("Winding", QtCore.Qt.WindingFill)
+
+ fillRuleLabel = QtGui.QLabel("Fill &Rule:")
+ fillRuleLabel.setBuddy(self.fillRuleComboBox)
+
+ self.fillColor1ComboBox = QtGui.QComboBox()
+ self.populateWithColors(self.fillColor1ComboBox)
+ self.fillColor1ComboBox.setCurrentIndex(
+ self.fillColor1ComboBox.findText("mediumslateblue"))
+
+ self.fillColor2ComboBox = QtGui.QComboBox()
+ self.populateWithColors(self.fillColor2ComboBox)
+ self.fillColor2ComboBox.setCurrentIndex(
+ self.fillColor2ComboBox.findText("cornsilk"))
+
+ fillGradientLabel = QtGui.QLabel("&Fill Gradient:")
+ fillGradientLabel.setBuddy(self.fillColor1ComboBox)
+
+ fillToLabel = QtGui.QLabel("to")
+ fillToLabel.setSizePolicy(QtGui.QSizePolicy.Fixed,
+ QtGui.QSizePolicy.Fixed)
+
+ self.penWidthSpinBox = QtGui.QSpinBox()
+ self.penWidthSpinBox.setRange(0, 20)
+
+ penWidthLabel = QtGui.QLabel("&Pen Width:")
+ penWidthLabel.setBuddy(self.penWidthSpinBox)
+
+ self.penColorComboBox = QtGui.QComboBox()
+ self.populateWithColors(self.penColorComboBox)
+ self.penColorComboBox.setCurrentIndex(
+ self.penColorComboBox.findText('darkslateblue'))
+
+ penColorLabel = QtGui.QLabel("Pen &Color:")
+ penColorLabel.setBuddy(self.penColorComboBox)
+
+ self.rotationAngleSpinBox = QtGui.QSpinBox()
+ self.rotationAngleSpinBox.setRange(0, 359)
+ self.rotationAngleSpinBox.setWrapping(True)
+ self.rotationAngleSpinBox.setSuffix('\xB0')
+
+ rotationAngleLabel = QtGui.QLabel("&Rotation Angle:")
+ rotationAngleLabel.setBuddy(self.rotationAngleSpinBox)
+
+ self.fillRuleComboBox.activated.connect(self.fillRuleChanged)
+ self.fillColor1ComboBox.activated.connect(self.fillGradientChanged)
+ self.fillColor2ComboBox.activated.connect(self.fillGradientChanged)
+ self.penColorComboBox.activated.connect(self.penColorChanged)
+
+ for i in range(Window.NumRenderAreas):
+ self.penWidthSpinBox.valueChanged[int].connect(self.renderAreas[i].setPenWidth)
+ self.rotationAngleSpinBox.valueChanged[int].connect(self.renderAreas[i].setRotationAngle)
+
+ topLayout = QtGui.QGridLayout()
+ for i in range(Window.NumRenderAreas):
+ topLayout.addWidget(self.renderAreas[i], i / 3, i % 3)
+
+ mainLayout = QtGui.QGridLayout()
+ mainLayout.addLayout(topLayout, 0, 0, 1, 4)
+ mainLayout.addWidget(fillRuleLabel, 1, 0)
+ mainLayout.addWidget(self.fillRuleComboBox, 1, 1, 1, 3)
+ mainLayout.addWidget(fillGradientLabel, 2, 0)
+ mainLayout.addWidget(self.fillColor1ComboBox, 2, 1)
+ mainLayout.addWidget(fillToLabel, 2, 2)
+ mainLayout.addWidget(self.fillColor2ComboBox, 2, 3)
+ mainLayout.addWidget(penWidthLabel, 3, 0)
+ mainLayout.addWidget(self.penWidthSpinBox, 3, 1, 1, 3)
+ mainLayout.addWidget(penColorLabel, 4, 0)
+ mainLayout.addWidget(self.penColorComboBox, 4, 1, 1, 3)
+ mainLayout.addWidget(rotationAngleLabel, 5, 0)
+ mainLayout.addWidget(self.rotationAngleSpinBox, 5, 1, 1, 3)
+ self.setLayout(mainLayout)
+
+ """
+ for i in range(Window.NumRenderAreas):
+ topLayout.addWidget(self.renderAreas[i], i / 3, i % 3)
+ """
+
+ self.fillRuleChanged()
+ self.fillGradientChanged()
+ self.penColorChanged()
+ self.penWidthSpinBox.setValue(2)
+
+ self.setWindowTitle("Painter Paths")
+
+ def fillRuleChanged(self):
+ rule = QtCore.Qt.FillRule(self.currentItemData(self.fillRuleComboBox))
+
+ for i in range(Window.NumRenderAreas):
+ self.renderAreas[i].setFillRule(rule)
+
+ def fillGradientChanged(self):
+ color1 = QtGui.QColor(self.currentItemData(self.fillColor1ComboBox))
+ color2 = QtGui.QColor(self.currentItemData(self.fillColor2ComboBox))
+
+ for i in range(Window.NumRenderAreas):
+ self.renderAreas[i].setFillGradient(color1, color2)
+
+ def penColorChanged(self):
+ color = QtGui.QColor(self.currentItemData(self.penColorComboBox))
+
+ for i in range(Window.NumRenderAreas):
+ self.renderAreas[i].setPenColor(color)
+
+ def populateWithColors(self, comboBox):
+ colorNames = QtGui.QColor.colorNames()
+ for name in colorNames:
+ comboBox.addItem(name, name)
+
+ def currentItemData(self, comboBox):
+ return comboBox.itemData(comboBox.currentIndex())
+
+ def __del__(self):
+ self.renderAreas = None
+
+
+if __name__ == '__main__':
+
+ import sys
+
+ app = QtGui.QApplication(sys.argv)
+ window = Window()
+ window.show()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/painting/svgviewer/files/bubbles.svg b/examples/widgets/painting/svgviewer/files/bubbles.svg
new file mode 100644
index 0000000..65867da
--- /dev/null
+++ b/examples/widgets/painting/svgviewer/files/bubbles.svg
@@ -0,0 +1,215 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg width="20cm" height="15cm" viewBox="0 0 800 600"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink/"
+ baseProfile="tiny" version="1.2">
+ <title>Spheres</title>
+ <desc>Semi-transparent bubbles on a colored background.</desc>
+ <defs>
+ <!-- Create radial gradients for each bubble. -->
+ <radialGradient id="blueBubble" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="25%" stop-color="#cdcdff" stop-opacity=".65" />
+ <stop offset="100%" stop-color="#cdaacd" stop-opacity=".75" />
+ </radialGradient>
+ <radialGradient id="redBubble" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="25%" stop-color="#ffcdcd" stop-opacity=".65" />
+ <stop offset="100%" stop-color="#bbbb99" stop-opacity=".75" />
+ </radialGradient>
+ <radialGradient id="greenBubble" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="25%" stop-color="#cdffcd" stop-opacity=".65" />
+ <stop offset="100%" stop-color="#99aaaa" stop-opacity=".75" />
+ </radialGradient>
+ <radialGradient id="yellowBubble" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" stop-opacity="1" />
+ <stop offset="25%" stop-color="#ffffcd" stop-opacity=".65" />
+ <stop offset="100%" stop-color="#bbbbaa" stop-opacity=".75" />
+ </radialGradient>
+ <radialGradient id="background" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="400" fx="250" fy="250">
+ <stop offset="0%" stop-color="#ffffee" />
+ <stop offset="100%" stop-color="#ccccaa" />
+ </radialGradient>
+ <linearGradient id="surface" gradientUnits="userSpaceOnUse"
+ x1="-100" y1="200" x2="400" y2="200">
+ <stop offset="0%" stop-color="#ffffcc" />
+ <stop offset="100%" stop-color="#bbbb88" />
+ </linearGradient>
+
+ <!-- Create radial gradients for each circle to make them look like
+ spheres. -->
+ <radialGradient id="blueSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="blue" />
+ <stop offset="100%" stop-color="#222244" />
+ </radialGradient>
+ <radialGradient id="redSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="red" />
+ <stop offset="100%" stop-color="#442222" />
+ </radialGradient>
+ <radialGradient id="greenSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="green" />
+ <stop offset="100%" stop-color="#113311" />
+ </radialGradient>
+ <radialGradient id="yellowSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="yellow" />
+ <stop offset="100%" stop-color="#444422" />
+ </radialGradient>
+ <radialGradient id="shadowGrad" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="50">
+ <stop offset="0%" stop-color="black" stop-opacity="1.0" />
+ <stop offset="100%" stop-color="white" stop-opacity="0.0" />
+ </radialGradient>
+
+ <!-- Define a shadow for each sphere. -->
+ <circle id="shadow" fill="url(#shadowGrad)" cx="0" cy="0" r="100" />
+ <g id="bubble">
+ <circle fill="black" cx="0" cy="0" r="50" />
+ <circle fill="#a6ce39" cx="0" cy="0" r="33" />
+ <path fill="black" d="M 37,50 L 50,37 L 12,-1 L 22,-11 L 10,-24 L -24,10
+ L -11,22 L -1,12 Z" />
+ <circle cx="0" cy="0" r="100" />
+ </g>
+ </defs>
+ <g>
+ <rect fill="url(#background)" x="0" y="0" width="800" height="600" />
+ </g>
+
+ <g transform="translate(200,700)">
+ <use xlink:href="#bubble" fill="url(#blueBubble)" />
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="1s" dur="10s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(315,700)">
+ <g transform="scale(0.5,0.5)">
+ <use xlink:href="#bubble" fill="url(#redBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="3s" dur="7s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(80,700)">
+ <g transform="scale(0.65,0.65)">
+ <use xlink:href="#bubble" fill="url(#greenBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="5s" dur="9s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(255,700)">
+ <g transform="scale(0.3,0.3)">
+ <use xlink:href="#bubble" fill="url(#yellowBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="2s" dur="6s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(565,700)">
+ <g transform="scale(0.4,0.4)">
+ <use xlink:href="#bubble" fill="url(#blueBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="4s" dur="8s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(715,700)">
+ <g transform="scale(0.6,0.6)">
+ <use xlink:href="#bubble" fill="url(#redBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="1s" dur="4s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(645,700)">
+ <g transform="scale(0.375,0.375)">
+ <use xlink:href="#bubble" fill="url(#greenBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="0s" dur="11s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(555,700)">
+ <g transform="scale(0.9,0.9)">
+ <use xlink:href="#bubble" fill="url(#yellowBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="3s" dur="7.5s" fill="freeze" repeatCount="indefinite" />
+ </g>
+
+ <g transform="translate(360,700)">
+ <g transform="scale(0.5,0.5)">
+ <use xlink:href="#bubble" fill="url(#blueBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="3s" dur="6s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(215,700)">
+ <g transform="scale(0.45,0.45)">
+ <use xlink:href="#bubble" fill="url(#redBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="5.5s" dur="7s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(420,700)">
+ <g transform="scale(0.75,0.75)">
+ <use xlink:href="#bubble" fill="url(#greenBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="1s" dur="9s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(815,700)">
+ <g transform="scale(0.6,0.6)">
+ <use xlink:href="#bubble" fill="url(#yellowBubble)" />
+ </g>
+ <animateTransform attributeName="transform" type="translate"
+ values="0,0; 0,-800" begin="2s" dur="9.5s" fill="freeze" repeatCount="indefinite" />
+ </g>
+
+ <g transform="translate(225,375)" >
+ <g transform="scale(1.0,0.5)" >
+ <path d="M 0 0 L 350 0 L 450 450 L -100 450 z"
+ fill="url(#surface)" stroke="none" />
+ </g>
+ </g>
+ <g transform="translate(200,0)" >
+ <g transform="translate(200,490) scale(2.0,1.0) rotate(45)" >
+ <rect fill="#a6ce39" x="-69" y="-69" width="138" height="138" />
+ <circle fill="black" cx="0" cy="0" r="50" />
+ <circle fill="#a6ce39" cx="0" cy="0" r="33" />
+ <path fill="black" d="M 37,50 L 50,37 L 12,-1 L 22,-11 L 10,-24 L -24,10
+ L -11,22 L -1,12 Z" />
+ <animateTransform attributeName="transform" type="rotate" values="0; 360"
+ begin="0s" dur="10s" fill="freeze" repeatCount="indefinite" />
+ </g>
+ <g transform="translate(200,375)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#blueSphere)" cx="0" cy="0" r="100" />
+ </g>
+ <g transform="translate(315,440)">
+ <g transform="scale(0.5,0.5)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#redSphere)" cx="0" cy="0" r="100" />
+ </g>
+ </g>
+ <g transform="translate(80,475)">
+ <g transform="scale(0.65,0.65)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#greenSphere)" cx="0" cy="0" r="100" />
+ </g>
+ </g>
+ <g transform="translate(255,525)">
+ <g transform="scale(0.3,0.3)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#yellowSphere)" cx="0" cy="0" r="100" />
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/examples/widgets/painting/svgviewer/files/cubic.svg b/examples/widgets/painting/svgviewer/files/cubic.svg
new file mode 100644
index 0000000..492bb72
--- /dev/null
+++ b/examples/widgets/painting/svgviewer/files/cubic.svg
@@ -0,0 +1,77 @@
+<?xml version="1.0" standalone="no"?>
+<svg width="10cm" height="10cm" viewBox="0 0 1000 1000"
+ xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny">
+ <title>Example cubic02 - cubic Bezier commands in path data</title>
+ <desc>Picture showing examples of "C" and "S" commands,
+ along with annotations showing the control points
+ and end points</desc>
+
+ <rect fill="none" stroke="blue" stroke-width="1" x="1" y="1" width="998" height="998" />
+
+ <!-- Path 1 -->
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="100,200 100,100" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="400,100 400,200" />
+ <path fill="none" stroke="red" stroke-width="5" d="M100,200 C100,100 400,100 400,200" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="100" cy="200" r="10" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="400" cy="200" r="10" />
+ <circle class="CtlPoint" cx="100" cy="100" r="10" />
+ <circle class="CtlPoint" cx="400" cy="100" r="10" />
+ <text text-anchor="middle" font-size="22" font-family="Verdana" x="250" y="275">M100,200 C100,100 400,100 400,200</text>
+
+ <!-- Path 2 -->
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="100,500 25,400" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="475,400 400,500" />
+ <path fill="none" stroke="red" stroke-width="5" d="M100,500 C25,400 475,400 400,500" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="100" cy="500" r="10" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="400" cy="500" r="10" />
+ <circle fill="#888888" stroke="none" cx="25" cy="400" r="10" />
+ <circle fill="#888888" stroke="none" cx="475" cy="400" r="10" />
+ <text text-anchor="middle" font-size="22" font-family="Verdana" x="250" y="575">M100,500 C25,400 475,400 400,500</text>
+
+ <!-- Path 3 -->
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="100,800 175,700" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="325,700 400,800" />
+ <path fill="none" stroke="red" stroke-width="5" d="M100,800 C175,700 325,700 400,800" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="100" cy="800" r="10" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="400" cy="800" r="10" />
+ <circle fill="#888888" stroke="none" cx="175" cy="700" r="10" />
+ <circle fill="#888888" stroke="none" cx="325" cy="700" r="10" />
+ <text text-anchor="middle" font-size="22" font-family="Verdana" x="250" y="875">M100,800 C175,700 325,700 400,800</text>
+
+ <!-- Path 4 -->
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="600,200 675,100" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="975,100 900,200" />
+ <path fill="none" stroke="red" stroke-width="5" d="M600,200 C675,100 975,100 900,200" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="600" cy="200" r="10" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="900" cy="200" r="10" />
+ <circle fill="#888888" stroke="none" cx="675" cy="100" r="10" />
+ <circle fill="#888888" stroke="none" cx="975" cy="100" r="10" />
+ <text text-anchor="middle" font-size="22" font-family="Verdana" x="750" y="275">M600,200 C675,100 975,100 900,200</text>
+
+ <!-- Path 5 -->
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="600,500 600,350" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="900,650 900,500" />
+ <path fill="none" stroke="red" stroke-width="5" d="M600,500 C600,350 900,650 900,500" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="600" cy="500" r="10" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="900" cy="500" r="10" />
+ <circle fill="#888888" stroke="none" cx="600" cy="350" r="10" />
+ <circle fill="#888888" stroke="none" cx="900" cy="650" r="10" />
+ <text text-anchor="middle" font-size="22" font-family="Verdana" x="750" y="575">M600,500 C600,350 900,650 900,500</text>
+
+ <!-- Path 6 (C and S command) -->
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="600,800 625,700" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="725,700 750,800" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="750,800 775,900" />
+ <polyline fill="none" stroke="#888888" stroke-width="2" points="875,900 900,800" />
+ <path fill="none" stroke="red" stroke-width="5" d="M600,800 C625,700 725,700 750,800
+ S875,900 900,800" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="600" cy="800" r="10" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="750" cy="800" r="10" />
+ <circle fill="none" stroke="#888888" stroke-width="2" cx="900" cy="800" r="10" />
+ <circle fill="#888888" stroke="none" cx="625" cy="700" r="10" />
+ <circle fill="#888888" stroke="none" cx="725" cy="700" r="10" />
+ <circle fill="#888888" stroke="none" cx="875" cy="900" r="10" />
+ <circle fill="none" stroke="blue" stroke-width="4" cx="775" cy="900" r="9" />
+ <text text-anchor="middle" font-size="22" font-family="Verdana" x="750" y="945">M600,800 C625,700 725,700 750,800</text>
+ <text text-anchor="middle" font-size="22" font-family="Verdana" x="750" y="975">S875,900 900,800</text>
+</svg>
diff --git a/examples/widgets/painting/svgviewer/files/spheres.svg b/examples/widgets/painting/svgviewer/files/spheres.svg
new file mode 100644
index 0000000..1deabb5
--- /dev/null
+++ b/examples/widgets/painting/svgviewer/files/spheres.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" standalone="no"?>
+<svg width="8cm" height="8cm" viewBox="0 0 400 400"
+ xmlns="http://www.w3.org/2000/svg" baseProfile="tiny" version="1.2">
+ <title>Spheres</title>
+ <desc>Gradient filled spheres with different colors.</desc>
+ <defs>
+ <!-- Create radial gradients for each circle to make them look like
+ spheres. -->
+ <radialGradient id="blueSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="blue" />
+ <stop offset="100%" stop-color="#222244" />
+ </radialGradient>
+ <radialGradient id="redSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="red" />
+ <stop offset="100%" stop-color="#442222" />
+ </radialGradient>
+ <radialGradient id="greenSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="green" />
+ <stop offset="100%" stop-color="#113311" />
+ </radialGradient>
+ <radialGradient id="yellowSphere" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="-50">
+ <stop offset="0%" stop-color="white" />
+ <stop offset="75%" stop-color="yellow" />
+ <stop offset="100%" stop-color="#444422" />
+ </radialGradient>
+ <radialGradient id="shadow" gradientUnits="userSpaceOnUse"
+ cx="0" cy="0" r="100" fx="-50" fy="50">
+ <stop offset="0%" stop-color="black" stop-opacity="1.0" />
+ <stop offset="100%" stop-color="white" stop-opacity="0.0" />
+ </radialGradient>
+
+ <!-- Define a shadow for each sphere. -->
+ <circle id="shadow" fill="url(#shadow)" cx="0" cy="0" r="100" />
+ </defs>
+ <g fill="#ffee99" stroke="none" >
+ <rect x="0" y="0" width="400" height="400" />
+ </g>
+ <g fill="white" stroke="none" >
+ <rect x="0" y="175" width="400" height="225" />
+ </g>
+ <g transform="translate(200,290) scale(2.0,1.0) rotate(45)" >
+ <rect fill="#a6ce39" x="-69" y="-69" width="138" height="138" />
+ <circle fill="black" cx="0" cy="0" r="50" />
+ <circle fill="#a6ce39" cx="0" cy="0" r="33" />
+ <path fill="black" d="M 37,50 L 50,37 L 12,-1 L 22,-11 L 10,-24 L -24,10
+ L -11,22 L -1,12 Z" />
+ <animateTransform attributeName="transform" type="rotate" values="0; 360"
+ begin="0s" dur="10s" fill="freeze" />
+ </g>
+ <g transform="translate(200,175)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#blueSphere)" cx="0" cy="0" r="100" />
+ </g>
+ <g transform="translate(315,240)">
+ <g transform="scale(0.5,0.5)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#redSphere)" cx="0" cy="0" r="100" />
+ </g>
+ </g>
+ <g transform="translate(80,275)">
+ <g transform="scale(0.65,0.65)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#greenSphere)" cx="0" cy="0" r="100" />
+ </g>
+ </g>
+ <g transform="translate(255,325)">
+ <g transform="scale(0.3,0.3)">
+ <use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" />
+ <circle fill="url(#yellowSphere)" cx="0" cy="0" r="100" />
+ </g>
+ </g>
+</svg>
diff --git a/examples/widgets/painting/svgviewer/svgviewer.py b/examples/widgets/painting/svgviewer/svgviewer.py
new file mode 100755
index 0000000..e16f8f4
--- /dev/null
+++ b/examples/widgets/painting/svgviewer/svgviewer.py
@@ -0,0 +1,254 @@
+#!/usr/bin/env python
+
+"""PySide port of the painting/svgviewer example from Qt v4.x"""
+
+import sys
+from PySide2 import QtCore, QtGui, QtOpenGL, QtSvg
+
+import svgviewer_rc
+
+
+class MainWindow(QtGui.QMainWindow):
+ def __init__(self):
+ QtGui.QMainWindow.__init__(self)
+
+ self.currentPath = ""
+
+ self.area = SvgWindow()
+
+ fileMenu = QtGui.QMenu(self.tr("&File"), self)
+ self.openAction = fileMenu.addAction(self.tr("&Open..."))
+ self.openAction.setShortcut(QtGui.QKeySequence(self.tr("Ctrl+O")))
+ self.quitAction = fileMenu.addAction(self.tr("E&xit"))
+ self.quitAction.setShortcut(QtGui.QKeySequence(self.tr("Ctrl+Q")))
+
+ self.menuBar().addMenu(fileMenu)
+
+ rendererMenu = QtGui.QMenu(self.tr("&Renderer"), self)
+ self.nativeAction = rendererMenu.addAction(self.tr("&Native"))
+ self.nativeAction.setCheckable(True)
+
+ if QtOpenGL.QGLFormat.hasOpenGL():
+ self.glAction = rendererMenu.addAction(self.tr("&OpenGL"))
+ self.glAction.setCheckable(True)
+
+ self.imageAction = rendererMenu.addAction(self.tr("&Image"))
+ self.imageAction.setCheckable(True)
+ self.imageAction.setChecked(True)
+
+ rendererGroup = QtGui.QActionGroup(self)
+ rendererGroup.addAction(self.nativeAction)
+
+ if QtOpenGL.QGLFormat.hasOpenGL():
+ rendererGroup.addAction(self.glAction)
+
+ rendererGroup.addAction(self.imageAction)
+
+ self.menuBar().addMenu(rendererMenu)
+
+ self.connect(self.openAction, QtCore.SIGNAL("triggered()"), self.openFile)
+ self.connect(self.quitAction, QtCore.SIGNAL("triggered()"), QtGui.qApp, QtCore.SLOT("quit()"))
+ self.connect(rendererGroup, QtCore.SIGNAL("triggered(QAction *)"), self.setRenderer)
+
+ self.setCentralWidget(self.area)
+ self.setWindowTitle(self.tr("SVG Viewer"))
+
+ def openFile(self, path=""):
+ if path=="":
+ fileName = QtGui.QFileDialog.getOpenFileName(self, self.tr("Open SVG File"),
+ self.currentPath, "*.svg")[0]
+ else:
+ fileName = path
+
+ if fileName!="":
+ self.area.openFile(fileName)
+ if not fileName.startswith(":/"):
+ self.currentPath = fileName
+ self.setWindowTitle(self.tr("%s - SVGViewer") % self.currentPath)
+
+ def setRenderer(self, action):
+ if action == self.nativeAction:
+ self.area.setRenderer(SvgWindow.Native)
+ elif action == self.glAction:
+ if QtOpenGL.QGLFormat.hasOpenGL():
+ self.area.setRenderer(SvgWindow.OpenGL)
+ elif action == self.imageAction:
+ self.area.setRenderer(SvgWindow.Image)
+
+
+class SvgWindow(QtGui.QScrollArea):
+ Native, OpenGL, Image = range(3)
+
+ def __init__(self):
+ QtGui.QScrollArea.__init__(self)
+
+ self.mousePressPos = QtCore.QPoint()
+ self.scrollBarValuesOnMousePress = QtCore.QPoint()
+ self.currentPath = ""
+
+ self.view = QtGui.QWidget(self)
+ self.renderer = SvgWindow.Image
+ self.setWidget(self.view)
+
+ def openFile(self, path):
+ self.currentPath = path
+ self.setRenderer(self.renderer)
+
+ def setRenderer(self, renderer):
+ self.renderer = renderer
+
+ if self.renderer == SvgWindow.OpenGL:
+ if QtOpenGL.QGLFormat.hasOpenGL():
+ view = SvgGLView(self.currentPath, self)
+ else:
+ view = QtGui.QWidget()
+ elif self.renderer == SvgWindow.Image:
+ view = SvgRasterView(self.currentPath, self)
+ else:
+ view = SvgNativeView(self.currentPath, self)
+
+ self.setWidget(view)
+ view.show()
+
+ def mousePressEvent(self, event):
+ self.mousePressPos = QtCore.QPoint(event.pos())
+ self.scrollBarValuesOnMousePress.setX(self.horizontalScrollBar().value())
+ self.scrollBarValuesOnMousePress.setY(self.verticalScrollBar().value())
+ event.accept()
+
+ def mouseMoveEvent(self, event):
+ if self.mousePressPos.isNull():
+ event.ignore()
+ return
+
+ self.horizontalScrollBar().setValue(self.scrollBarValuesOnMousePress.x() - event.pos().x() + self.mousePressPos.x())
+ self.verticalScrollBar().setValue(self.scrollBarValuesOnMousePress.y() - event.pos().y() + self.mousePressPos.y())
+ self.horizontalScrollBar().update()
+ self.verticalScrollBar().update()
+ event.accept()
+
+ def mouseReleaseEvent(self, event):
+ self.mousePressPos = QtCore.QPoint()
+ event.accept()
+
+
+class SvgGLView(QtOpenGL.QGLWidget):
+ def __init__(self, path, parent):
+ QtOpenGL.QGLWidget.__init__(self, QtOpenGL.QGLFormat(QtOpenGL.QGL.SampleBuffers))
+
+ self.doc = QtSvg.QSvgRenderer(path, self)
+ self.connect(self.doc, QtCore.SIGNAL("repaintNeeded()"),
+ self, QtCore.SLOT("update()"))
+
+ def paintEvent(self, e):
+ p = QtGui.QPainter(self)
+ self.doc.render(p)
+
+ def sizeHint(self):
+ if self.doc:
+ return self.doc.defaultSize()
+ return QtOpenGL.QGLWidget.sizeHint(self)
+
+ def wheelEvent(self, e):
+ diff = 0.1
+ size = QtCore.QSize(self.doc.defaultSize())
+ width = size.width()
+ height = size.height()
+ if e.delta() > 0:
+ width = int(self.width() + self.width() * diff)
+ height = int(self.height() + self.height() * diff)
+ else:
+ width = int(self.width() - self.width() * diff)
+ height = int(self.height() - self.height() * diff)
+
+ self.resize(width, height)
+
+
+class SvgRasterView(QtGui.QWidget):
+ def __init__(self, path, parent):
+ QtGui.QWidget.__init__(self, parent)
+
+ self.buffer = QtGui.QImage()
+ self.m_dirty = False
+
+ self.doc = QtSvg.QSvgRenderer(path, self)
+ self.connect(self.doc, QtCore.SIGNAL("repaintNeeded()"), self.poluteImage)
+
+ def paintEvent(self, e):
+ if self.buffer.size() != self.size() or self.m_dirty:
+ self.buffer = QtGui.QImage(self.size(), QtGui.QImage.Format_ARGB32_Premultiplied)
+ p = QtGui.QPainter(self.buffer)
+ p.setViewport(0, 0, self.width(), self.height())
+ p.eraseRect(0, 0, self.width(), self.height())
+ self.doc.render(p)
+
+ pt = QtGui.QPainter(self)
+ pt.drawImage(0, 0, self.buffer)
+
+ def sizeHint(self):
+ if self.doc:
+ return self.doc.defaultSize()
+ return QtGui.QWidget.sizeHint(self)
+
+ def poluteImage(self):
+ self.m_dirty = True
+ self.update()
+
+ def wheelEvent(self, e):
+ diff = 0.1
+ size = QtCore.QSize(self.doc.defaultSize())
+ width = size.width()
+ height = size.height()
+ if e.delta() > 0:
+ width = int(self.width() + self.width() * diff)
+ height = int(self.height() + self.height() * diff)
+ else:
+ width = int(self.width() - self.width() * diff)
+ height = int(self.height() - self.height() * diff)
+
+ self.resize(width, height)
+
+
+class SvgNativeView(QtGui.QWidget):
+ def __init__(self, path, parent):
+ QtGui.QWidget.__init__(self, parent)
+
+ self.doc = QtSvg.QSvgRenderer(path, self)
+ self.connect(self.doc, QtCore.SIGNAL("repaintNeeded()"),
+ self, QtCore.SLOT("update()"))
+
+ def paintEvent(self, e):
+ p = QtGui.QPainter(self)
+ p.setViewport(0, 0, self.width(), self.height())
+ self.doc.render(p)
+
+ def sizeHint(self):
+ if self.doc:
+ return self.doc.defaultSize()
+ return QtGui.QWidget.sizeHint(self)
+
+ def wheelEvent(self, e):
+ diff = 0.1
+ size = QtCore.QSize(self.doc.defaultSize())
+ width = size.width()
+ height = size.height()
+ if e.delta() > 0:
+ width = int(self.width() + self.width() * diff)
+ height = int(self.height() + self.height() * diff)
+ else:
+ width = int(self.width() - self.width() * diff)
+ height = int(self.height() - self.height() * diff)
+
+ self.resize(width, height)
+
+
+if __name__ == '__main__':
+ app = QtGui.QApplication(sys.argv)
+
+ window = MainWindow()
+ if len(sys.argv) == 2:
+ window.openFile(sys.argv[1])
+ else:
+ window.openFile(":/files/cubic.svg")
+ window.show()
+ sys.exit(app.exec_())
diff --git a/examples/widgets/painting/svgviewer/svgviewer.qrc b/examples/widgets/painting/svgviewer/svgviewer.qrc
new file mode 100644
index 0000000..77238d6
--- /dev/null
+++ b/examples/widgets/painting/svgviewer/svgviewer.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/">
+ <file>files/cubic.svg</file>
+ <file>files/spheres.svg</file>
+</qresource>
+</RCC>
+
diff --git a/examples/widgets/painting/svgviewer/svgviewer_rc.py b/examples/widgets/painting/svgviewer/svgviewer_rc.py
new file mode 100644
index 0000000..14a5ee6
--- /dev/null
+++ b/examples/widgets/painting/svgviewer/svgviewer_rc.py
@@ -0,0 +1,639 @@
+#############################################################################
+##
+## Copyright (C) 2013 Riverbank Computing Limited.
+## Copyright (C) 2016 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the PySide examples of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:BSD$
+## You may use this file under the terms of the BSD license as follows:
+##
+## "Redistribution and use in source and binary forms, with or without
+## modification, are permitted provided that the following conditions are
+## met:
+## * Redistributions of source code must retain the above copyright
+## notice, this list of conditions and the following disclaimer.
+## * Redistributions in binary form must reproduce the above copyright
+## notice, this list of conditions and the following disclaimer in
+## the documentation and/or other materials provided with the
+## distribution.
+## * Neither the name of The Qt Company Ltd nor the names of its
+## contributors may be used to endorse or promote products derived
+## from this software without specific prior written permission.
+##
+##
+## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# Resource object code
+#
+# Created: Tue Jan 10 14:08:21 2006
+# by: The Resource Compiler for PyQt (Qt v4.1.0)
+#
+# WARNING! All changes made in this file will be lost!
+
+from PySide2 import QtCore
+
+qt_resource_data = b"\
+\x00\x00\x14\xa0\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\x6e\
+\x6f\x22\x3f\x3e\x0a\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\
+\x22\x31\x30\x63\x6d\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x31\
+\x30\x63\x6d\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\
+\x30\x20\x31\x30\x30\x30\x20\x31\x30\x30\x30\x22\x0a\x20\x20\x20\
+\x20\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\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x32\x22\x20\x62\x61\x73\x65\x50\x72\x6f\x66\x69\x6c\x65\x3d\x22\
+\x74\x69\x6e\x79\x22\x3e\x0a\x20\x20\x3c\x74\x69\x74\x6c\x65\x3e\
+\x45\x78\x61\x6d\x70\x6c\x65\x20\x63\x75\x62\x69\x63\x30\x32\x20\
+\x2d\x20\x63\x75\x62\x69\x63\x20\x42\x65\x7a\x69\x65\x72\x20\x63\
+\x6f\x6d\x6d\x61\x6e\x64\x73\x20\x69\x6e\x20\x70\x61\x74\x68\x20\
+\x64\x61\x74\x61\x3c\x2f\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x3c\
+\x64\x65\x73\x63\x3e\x50\x69\x63\x74\x75\x72\x65\x20\x73\x68\x6f\
+\x77\x69\x6e\x67\x20\x65\x78\x61\x6d\x70\x6c\x65\x73\x20\x6f\x66\
+\x20\x22\x43\x22\x20\x61\x6e\x64\x20\x22\x53\x22\x20\x63\x6f\x6d\
+\x6d\x61\x6e\x64\x73\x2c\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\
+\x6c\x6f\x6e\x67\x20\x77\x69\x74\x68\x20\x61\x6e\x6e\x6f\x74\x61\
+\x74\x69\x6f\x6e\x73\x20\x73\x68\x6f\x77\x69\x6e\x67\x20\x74\x68\
+\x65\x20\x63\x6f\x6e\x74\x72\x6f\x6c\x20\x70\x6f\x69\x6e\x74\x73\
+\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x61\x6e\x64\x20\x65\x6e\x64\
+\x20\x70\x6f\x69\x6e\x74\x73\x3c\x2f\x64\x65\x73\x63\x3e\x0a\x0a\
+\x20\x20\x3c\x72\x65\x63\x74\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\
+\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x62\x6c\x75\x65\
+\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\
+\x31\x22\x20\x78\x3d\x22\x31\x22\x20\x79\x3d\x22\x31\x22\x20\x77\
+\x69\x64\x74\x68\x3d\x22\x39\x39\x38\x22\x20\x68\x65\x69\x67\x68\
+\x74\x3d\x22\x39\x39\x38\x22\x20\x2f\x3e\x0a\x0a\x20\x20\x3c\x21\
+\x2d\x2d\x20\x50\x61\x74\x68\x20\x31\x20\x2d\x2d\x3e\x0a\x20\x20\
+\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\
+\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\
+\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\
+\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\
+\x31\x30\x30\x2c\x32\x30\x30\x20\x31\x30\x30\x2c\x31\x30\x30\x22\
+\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\
+\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\
+\x69\x6e\x74\x73\x3d\x22\x34\x30\x30\x2c\x31\x30\x30\x20\x34\x30\
+\x30\x2c\x32\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x61\x74\
+\x68\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\
+\x72\x6f\x6b\x65\x3d\x22\x72\x65\x64\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x35\x22\x20\x64\x3d\x22\x4d\
+\x31\x30\x30\x2c\x32\x30\x30\x20\x43\x31\x30\x30\x2c\x31\x30\x30\
+\x20\x34\x30\x30\x2c\x31\x30\x30\x20\x34\x30\x30\x2c\x32\x30\x30\
+\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\
+\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\
+\x22\x31\x30\x30\x22\x20\x63\x79\x3d\x22\x32\x30\x30\x22\x20\x72\
+\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\
+\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\
+\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\
+\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\
+\x20\x63\x78\x3d\x22\x34\x30\x30\x22\x20\x63\x79\x3d\x22\x32\x30\
+\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\
+\x63\x69\x72\x63\x6c\x65\x20\x63\x6c\x61\x73\x73\x3d\x22\x43\x74\
+\x6c\x50\x6f\x69\x6e\x74\x22\x20\x63\x78\x3d\x22\x31\x30\x30\x22\
+\x20\x63\x79\x3d\x22\x31\x30\x30\x22\x20\x72\x3d\x22\x31\x30\x22\
+\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x63\x6c\
+\x61\x73\x73\x3d\x22\x43\x74\x6c\x50\x6f\x69\x6e\x74\x22\x20\x63\
+\x78\x3d\x22\x34\x30\x30\x22\x20\x63\x79\x3d\x22\x31\x30\x30\x22\
+\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x74\x65\
+\x78\x74\x20\x74\x65\x78\x74\x2d\x61\x6e\x63\x68\x6f\x72\x3d\x22\
+\x6d\x69\x64\x64\x6c\x65\x22\x20\x66\x6f\x6e\x74\x2d\x73\x69\x7a\
+\x65\x3d\x22\x32\x32\x22\x20\x66\x6f\x6e\x74\x2d\x66\x61\x6d\x69\
+\x6c\x79\x3d\x22\x56\x65\x72\x64\x61\x6e\x61\x22\x20\x78\x3d\x22\
+\x32\x35\x30\x22\x20\x79\x3d\x22\x32\x37\x35\x22\x3e\x4d\x31\x30\
+\x30\x2c\x32\x30\x30\x20\x43\x31\x30\x30\x2c\x31\x30\x30\x20\x34\
+\x30\x30\x2c\x31\x30\x30\x20\x34\x30\x30\x2c\x32\x30\x30\x3c\x2f\
+\x74\x65\x78\x74\x3e\x0a\x0a\x20\x20\x3c\x21\x2d\x2d\x20\x50\x61\
+\x74\x68\x20\x32\x20\x2d\x2d\x3e\x0a\x20\x20\x3c\x70\x6f\x6c\x79\
+\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\
+\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\
+\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\
+\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\x31\x30\x30\x2c\x35\
+\x30\x30\x20\x32\x35\x2c\x34\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\
+\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\
+\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\
+\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\
+\x34\x37\x35\x2c\x34\x30\x30\x20\x34\x30\x30\x2c\x35\x30\x30\x22\
+\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\
+\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\
+\x72\x65\x64\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x22\x20\x64\x3d\x22\x4d\x31\x30\x30\x2c\x35\x30\
+\x30\x20\x43\x32\x35\x2c\x34\x30\x30\x20\x34\x37\x35\x2c\x34\x30\
+\x30\x20\x34\x30\x30\x2c\x35\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\
+\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\
+\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\x22\x31\x30\x30\x22\x20\x63\
+\x79\x3d\x22\x35\x30\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\
+\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\
+\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\
+\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\x22\x34\x30\
+\x30\x22\x20\x63\x79\x3d\x22\x35\x30\x30\x22\x20\x72\x3d\x22\x31\
+\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\
+\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\
+\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x63\x78\x3d\
+\x22\x32\x35\x22\x20\x63\x79\x3d\x22\x34\x30\x30\x22\x20\x72\x3d\
+\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\
+\x65\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\
+\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x63\
+\x78\x3d\x22\x34\x37\x35\x22\x20\x63\x79\x3d\x22\x34\x30\x30\x22\
+\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x74\x65\
+\x78\x74\x20\x74\x65\x78\x74\x2d\x61\x6e\x63\x68\x6f\x72\x3d\x22\
+\x6d\x69\x64\x64\x6c\x65\x22\x20\x66\x6f\x6e\x74\x2d\x73\x69\x7a\
+\x65\x3d\x22\x32\x32\x22\x20\x66\x6f\x6e\x74\x2d\x66\x61\x6d\x69\
+\x6c\x79\x3d\x22\x56\x65\x72\x64\x61\x6e\x61\x22\x20\x78\x3d\x22\
+\x32\x35\x30\x22\x20\x79\x3d\x22\x35\x37\x35\x22\x3e\x4d\x31\x30\
+\x30\x2c\x35\x30\x30\x20\x43\x32\x35\x2c\x34\x30\x30\x20\x34\x37\
+\x35\x2c\x34\x30\x30\x20\x34\x30\x30\x2c\x35\x30\x30\x3c\x2f\x74\
+\x65\x78\x74\x3e\x0a\x0a\x20\x20\x3c\x21\x2d\x2d\x20\x50\x61\x74\
+\x68\x20\x33\x20\x2d\x2d\x3e\x0a\x20\x20\x3c\x70\x6f\x6c\x79\x6c\
+\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\
+\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\
+\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\
+\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\x31\x30\x30\x2c\x38\x30\
+\x30\x20\x31\x37\x35\x2c\x37\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\
+\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\
+\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\
+\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\
+\x33\x32\x35\x2c\x37\x30\x30\x20\x34\x30\x30\x2c\x38\x30\x30\x22\
+\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\
+\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\
+\x72\x65\x64\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3d\x22\x35\x22\x20\x64\x3d\x22\x4d\x31\x30\x30\x2c\x38\x30\
+\x30\x20\x43\x31\x37\x35\x2c\x37\x30\x30\x20\x33\x32\x35\x2c\x37\
+\x30\x30\x20\x34\x30\x30\x2c\x38\x30\x30\x22\x20\x2f\x3e\x0a\x20\
+\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\
+\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\
+\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\
+\x74\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\x22\x31\x30\x30\x22\x20\
+\x63\x79\x3d\x22\x38\x30\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\
+\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\
+\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\
+\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\x22\x34\
+\x30\x30\x22\x20\x63\x79\x3d\x22\x38\x30\x30\x22\x20\x72\x3d\x22\
+\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\
+\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\
+\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x63\x78\
+\x3d\x22\x31\x37\x35\x22\x20\x63\x79\x3d\x22\x37\x30\x30\x22\x20\
+\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\x38\x38\x38\
+\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\
+\x20\x63\x78\x3d\x22\x33\x32\x35\x22\x20\x63\x79\x3d\x22\x37\x30\
+\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\
+\x74\x65\x78\x74\x20\x74\x65\x78\x74\x2d\x61\x6e\x63\x68\x6f\x72\
+\x3d\x22\x6d\x69\x64\x64\x6c\x65\x22\x20\x66\x6f\x6e\x74\x2d\x73\
+\x69\x7a\x65\x3d\x22\x32\x32\x22\x20\x66\x6f\x6e\x74\x2d\x66\x61\
+\x6d\x69\x6c\x79\x3d\x22\x56\x65\x72\x64\x61\x6e\x61\x22\x20\x78\
+\x3d\x22\x32\x35\x30\x22\x20\x79\x3d\x22\x38\x37\x35\x22\x3e\x4d\
+\x31\x30\x30\x2c\x38\x30\x30\x20\x43\x31\x37\x35\x2c\x37\x30\x30\
+\x20\x33\x32\x35\x2c\x37\x30\x30\x20\x34\x30\x30\x2c\x38\x30\x30\
+\x3c\x2f\x74\x65\x78\x74\x3e\x0a\x0a\x20\x20\x3c\x21\x2d\x2d\x20\
+\x50\x61\x74\x68\x20\x34\x20\x2d\x2d\x3e\x0a\x20\x20\x3c\x70\x6f\
+\x6c\x79\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\
+\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\
+\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\
+\x3d\x22\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\x36\x30\x30\
+\x2c\x32\x30\x30\x20\x36\x37\x35\x2c\x31\x30\x30\x22\x20\x2f\x3e\
+\x0a\x20\x20\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\x66\x69\x6c\
+\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\
+\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\
+\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\x69\x6e\x74\
+\x73\x3d\x22\x39\x37\x35\x2c\x31\x30\x30\x20\x39\x30\x30\x2c\x32\
+\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x61\x74\x68\x20\x66\
+\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x22\x72\x65\x64\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\
+\x69\x64\x74\x68\x3d\x22\x35\x22\x20\x64\x3d\x22\x4d\x36\x30\x30\
+\x2c\x32\x30\x30\x20\x43\x36\x37\x35\x2c\x31\x30\x30\x20\x39\x37\
+\x35\x2c\x31\x30\x30\x20\x39\x30\x30\x2c\x32\x30\x30\x22\x20\x2f\
+\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\
+\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\
+\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\x22\x36\x30\
+\x30\x22\x20\x63\x79\x3d\x22\x32\x30\x30\x22\x20\x72\x3d\x22\x31\
+\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\
+\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\
+\x3d\x22\x39\x30\x30\x22\x20\x63\x79\x3d\x22\x32\x30\x30\x22\x20\
+\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\x38\x38\x38\
+\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\
+\x20\x63\x78\x3d\x22\x36\x37\x35\x22\x20\x63\x79\x3d\x22\x31\x30\
+\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\
+\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\
+\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\
+\x6e\x65\x22\x20\x63\x78\x3d\x22\x39\x37\x35\x22\x20\x63\x79\x3d\
+\x22\x31\x30\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\
+\x20\x20\x3c\x74\x65\x78\x74\x20\x74\x65\x78\x74\x2d\x61\x6e\x63\
+\x68\x6f\x72\x3d\x22\x6d\x69\x64\x64\x6c\x65\x22\x20\x66\x6f\x6e\
+\x74\x2d\x73\x69\x7a\x65\x3d\x22\x32\x32\x22\x20\x66\x6f\x6e\x74\
+\x2d\x66\x61\x6d\x69\x6c\x79\x3d\x22\x56\x65\x72\x64\x61\x6e\x61\
+\x22\x20\x78\x3d\x22\x37\x35\x30\x22\x20\x79\x3d\x22\x32\x37\x35\
+\x22\x3e\x4d\x36\x30\x30\x2c\x32\x30\x30\x20\x43\x36\x37\x35\x2c\
+\x31\x30\x30\x20\x39\x37\x35\x2c\x31\x30\x30\x20\x39\x30\x30\x2c\
+\x32\x30\x30\x3c\x2f\x74\x65\x78\x74\x3e\x0a\x0a\x20\x20\x3c\x21\
+\x2d\x2d\x20\x50\x61\x74\x68\x20\x35\x20\x2d\x2d\x3e\x0a\x20\x20\
+\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\
+\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\
+\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\
+\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\
+\x36\x30\x30\x2c\x35\x30\x30\x20\x36\x30\x30\x2c\x33\x35\x30\x22\
+\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\
+\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\
+\x69\x6e\x74\x73\x3d\x22\x39\x30\x30\x2c\x36\x35\x30\x20\x39\x30\
+\x30\x2c\x35\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x61\x74\
+\x68\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\
+\x72\x6f\x6b\x65\x3d\x22\x72\x65\x64\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x35\x22\x20\x64\x3d\x22\x4d\
+\x36\x30\x30\x2c\x35\x30\x30\x20\x43\x36\x30\x30\x2c\x33\x35\x30\
+\x20\x39\x30\x30\x2c\x36\x35\x30\x20\x39\x30\x30\x2c\x35\x30\x30\
+\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\
+\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\
+\x22\x36\x30\x30\x22\x20\x63\x79\x3d\x22\x35\x30\x30\x22\x20\x72\
+\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\
+\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\
+\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\
+\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\
+\x20\x63\x78\x3d\x22\x39\x30\x30\x22\x20\x63\x79\x3d\x22\x35\x30\
+\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\
+\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\
+\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\
+\x6e\x65\x22\x20\x63\x78\x3d\x22\x36\x30\x30\x22\x20\x63\x79\x3d\
+\x22\x33\x35\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\
+\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\
+\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\
+\x22\x6e\x6f\x6e\x65\x22\x20\x63\x78\x3d\x22\x39\x30\x30\x22\x20\
+\x63\x79\x3d\x22\x36\x35\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\
+\x2f\x3e\x0a\x20\x20\x3c\x74\x65\x78\x74\x20\x74\x65\x78\x74\x2d\
+\x61\x6e\x63\x68\x6f\x72\x3d\x22\x6d\x69\x64\x64\x6c\x65\x22\x20\
+\x66\x6f\x6e\x74\x2d\x73\x69\x7a\x65\x3d\x22\x32\x32\x22\x20\x66\
+\x6f\x6e\x74\x2d\x66\x61\x6d\x69\x6c\x79\x3d\x22\x56\x65\x72\x64\
+\x61\x6e\x61\x22\x20\x78\x3d\x22\x37\x35\x30\x22\x20\x79\x3d\x22\
+\x35\x37\x35\x22\x3e\x4d\x36\x30\x30\x2c\x35\x30\x30\x20\x43\x36\
+\x30\x30\x2c\x33\x35\x30\x20\x39\x30\x30\x2c\x36\x35\x30\x20\x39\
+\x30\x30\x2c\x35\x30\x30\x3c\x2f\x74\x65\x78\x74\x3e\x0a\x0a\x20\
+\x20\x3c\x21\x2d\x2d\x20\x50\x61\x74\x68\x20\x36\x20\x28\x43\x20\
+\x61\x6e\x64\x20\x53\x20\x63\x6f\x6d\x6d\x61\x6e\x64\x29\x20\x2d\
+\x2d\x3e\x0a\x20\x20\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\x66\
+\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\
+\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\x69\
+\x6e\x74\x73\x3d\x22\x36\x30\x30\x2c\x38\x30\x30\x20\x36\x32\x35\
+\x2c\x37\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x6f\x6c\x79\
+\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\
+\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\
+\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\
+\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\x22\x37\x32\x35\x2c\x37\
+\x30\x30\x20\x37\x35\x30\x2c\x38\x30\x30\x22\x20\x2f\x3e\x0a\x20\
+\x20\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\x20\x66\x69\x6c\x6c\x3d\
+\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\
+\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\
+\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x70\x6f\x69\x6e\x74\x73\x3d\
+\x22\x37\x35\x30\x2c\x38\x30\x30\x20\x37\x37\x35\x2c\x39\x30\x30\
+\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x6f\x6c\x79\x6c\x69\x6e\x65\
+\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\
+\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\
+\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x70\
+\x6f\x69\x6e\x74\x73\x3d\x22\x38\x37\x35\x2c\x39\x30\x30\x20\x39\
+\x30\x30\x2c\x38\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x70\x61\
+\x74\x68\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\
+\x74\x72\x6f\x6b\x65\x3d\x22\x72\x65\x64\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x35\x22\x20\x64\x3d\x22\
+\x4d\x36\x30\x30\x2c\x38\x30\x30\x20\x43\x36\x32\x35\x2c\x37\x30\
+\x30\x20\x37\x32\x35\x2c\x37\x30\x30\x20\x37\x35\x30\x2c\x38\x30\
+\x30\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x53\x38\x37\x35\x2c\x39\x30\
+\x30\x20\x39\x30\x30\x2c\x38\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\
+\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x23\x38\x38\x38\
+\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\x64\x74\
+\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\x22\x36\x30\x30\x22\x20\x63\
+\x79\x3d\x22\x38\x30\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\
+\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\
+\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\
+\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\
+\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\x3d\x22\x37\x35\
+\x30\x22\x20\x63\x79\x3d\x22\x38\x30\x30\x22\x20\x72\x3d\x22\x31\
+\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\
+\x66\x69\x6c\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\
+\x6b\x65\x3d\x22\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\
+\x6f\x6b\x65\x2d\x77\x69\x64\x74\x68\x3d\x22\x32\x22\x20\x63\x78\
+\x3d\x22\x39\x30\x30\x22\x20\x63\x79\x3d\x22\x38\x30\x30\x22\x20\
+\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\x38\x38\x38\
+\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\
+\x20\x63\x78\x3d\x22\x36\x32\x35\x22\x20\x63\x79\x3d\x22\x37\x30\
+\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\x20\x20\x3c\
+\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x23\x38\x38\
+\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\
+\x6e\x65\x22\x20\x63\x78\x3d\x22\x37\x32\x35\x22\x20\x63\x79\x3d\
+\x22\x37\x30\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\x2f\x3e\x0a\
+\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\
+\x23\x38\x38\x38\x38\x38\x38\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\
+\x22\x6e\x6f\x6e\x65\x22\x20\x63\x78\x3d\x22\x38\x37\x35\x22\x20\
+\x63\x79\x3d\x22\x39\x30\x30\x22\x20\x72\x3d\x22\x31\x30\x22\x20\
+\x2f\x3e\x0a\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\
+\x6c\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\
+\x22\x62\x6c\x75\x65\x22\x20\x73\x74\x72\x6f\x6b\x65\x2d\x77\x69\
+\x64\x74\x68\x3d\x22\x34\x22\x20\x63\x78\x3d\x22\x37\x37\x35\x22\
+\x20\x63\x79\x3d\x22\x39\x30\x30\x22\x20\x72\x3d\x22\x39\x22\x20\
+\x2f\x3e\x0a\x20\x20\x3c\x74\x65\x78\x74\x20\x74\x65\x78\x74\x2d\
+\x61\x6e\x63\x68\x6f\x72\x3d\x22\x6d\x69\x64\x64\x6c\x65\x22\x20\
+\x66\x6f\x6e\x74\x2d\x73\x69\x7a\x65\x3d\x22\x32\x32\x22\x20\x66\
+\x6f\x6e\x74\x2d\x66\x61\x6d\x69\x6c\x79\x3d\x22\x56\x65\x72\x64\
+\x61\x6e\x61\x22\x20\x78\x3d\x22\x37\x35\x30\x22\x20\x79\x3d\x22\
+\x39\x34\x35\x22\x3e\x4d\x36\x30\x30\x2c\x38\x30\x30\x20\x43\x36\
+\x32\x35\x2c\x37\x30\x30\x20\x37\x32\x35\x2c\x37\x30\x30\x20\x37\
+\x35\x30\x2c\x38\x30\x30\x3c\x2f\x74\x65\x78\x74\x3e\x0a\x20\x20\
+\x3c\x74\x65\x78\x74\x20\x74\x65\x78\x74\x2d\x61\x6e\x63\x68\x6f\
+\x72\x3d\x22\x6d\x69\x64\x64\x6c\x65\x22\x20\x66\x6f\x6e\x74\x2d\
+\x73\x69\x7a\x65\x3d\x22\x32\x32\x22\x20\x66\x6f\x6e\x74\x2d\x66\
+\x61\x6d\x69\x6c\x79\x3d\x22\x56\x65\x72\x64\x61\x6e\x61\x22\x20\
+\x78\x3d\x22\x37\x35\x30\x22\x20\x79\x3d\x22\x39\x37\x35\x22\x3e\
+\x53\x38\x37\x35\x2c\x39\x30\x30\x20\x39\x30\x30\x2c\x38\x30\x30\
+\x3c\x2f\x74\x65\x78\x74\x3e\x0a\x3c\x2f\x73\x76\x67\x3e\x0a\
+\x00\x00\x0d\xe6\
+\x3c\
+\x3f\x78\x6d\x6c\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\
+\x30\x22\x20\x73\x74\x61\x6e\x64\x61\x6c\x6f\x6e\x65\x3d\x22\x6e\
+\x6f\x22\x3f\x3e\x0a\x3c\x73\x76\x67\x20\x77\x69\x64\x74\x68\x3d\
+\x22\x38\x63\x6d\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x38\x63\
+\x6d\x22\x20\x76\x69\x65\x77\x42\x6f\x78\x3d\x22\x30\x20\x30\x20\
+\x34\x30\x30\x20\x34\x30\x30\x22\x0a\x20\x20\x20\x20\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\x62\x61\x73\x65\x50\x72\x6f\x66\x69\x6c\x65\x3d\x22\x74\x69\
+\x6e\x79\x22\x20\x76\x65\x72\x73\x69\x6f\x6e\x3d\x22\x31\x2e\x32\
+\x22\x3e\x0a\x20\x20\x3c\x74\x69\x74\x6c\x65\x3e\x53\x70\x68\x65\
+\x72\x65\x73\x3c\x2f\x74\x69\x74\x6c\x65\x3e\x0a\x20\x20\x3c\x64\
+\x65\x73\x63\x3e\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x66\x69\x6c\
+\x6c\x65\x64\x20\x73\x70\x68\x65\x72\x65\x73\x20\x77\x69\x74\x68\
+\x20\x64\x69\x66\x66\x65\x72\x65\x6e\x74\x20\x63\x6f\x6c\x6f\x72\
+\x73\x2e\x3c\x2f\x64\x65\x73\x63\x3e\x0a\x20\x20\x20\x20\x3c\x64\
+\x65\x66\x73\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x21\x2d\x2d\x20\
+\x43\x72\x65\x61\x74\x65\x20\x72\x61\x64\x69\x61\x6c\x20\x67\x72\
+\x61\x64\x69\x65\x6e\x74\x73\x20\x66\x6f\x72\x20\x65\x61\x63\x68\
+\x20\x63\x69\x72\x63\x6c\x65\x20\x74\x6f\x20\x6d\x61\x6b\x65\x20\
+\x74\x68\x65\x6d\x20\x6c\x6f\x6f\x6b\x20\x6c\x69\x6b\x65\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x73\x70\x68\x65\x72\x65\
+\x73\x2e\x20\x2d\x2d\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x61\
+\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x69\x64\x3d\
+\x22\x62\x6c\x75\x65\x53\x70\x68\x65\x72\x65\x22\x20\x67\x72\x61\
+\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\
+\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\x22\x30\x22\x20\
+\x72\x3d\x22\x31\x30\x30\x22\x20\x66\x78\x3d\x22\x2d\x35\x30\x22\
+\x20\x66\x79\x3d\x22\x2d\x35\x30\x22\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\
+\x22\x77\x68\x69\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x37\x35\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\
+\x3d\x22\x62\x6c\x75\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x31\x30\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\
+\x72\x3d\x22\x23\x32\x32\x32\x32\x34\x34\x22\x20\x2f\x3e\x0a\x20\
+\x20\x20\x20\x20\x20\x3c\x2f\x72\x61\x64\x69\x61\x6c\x47\x72\x61\
+\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x61\
+\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x69\x64\x3d\
+\x22\x72\x65\x64\x53\x70\x68\x65\x72\x65\x22\x20\x67\x72\x61\x64\
+\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\
+\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\x22\x30\x22\x20\x72\
+\x3d\x22\x31\x30\x30\x22\x20\x66\x78\x3d\x22\x2d\x35\x30\x22\x20\
+\x66\x79\x3d\x22\x2d\x35\x30\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\
+\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\
+\x77\x68\x69\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\
+\x37\x35\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\
+\x22\x72\x65\x64\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x20\
+\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\x31\
+\x30\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\
+\x22\x23\x34\x34\x32\x32\x32\x32\x22\x20\x2f\x3e\x0a\x20\x20\x20\
+\x20\x20\x20\x3c\x2f\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\
+\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x61\x64\x69\
+\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x69\x64\x3d\x22\x67\
+\x72\x65\x65\x6e\x53\x70\x68\x65\x72\x65\x22\x20\x67\x72\x61\x64\
+\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\x53\
+\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\x22\x30\x22\x20\x72\
+\x3d\x22\x31\x30\x30\x22\x20\x66\x78\x3d\x22\x2d\x35\x30\x22\x20\
+\x66\x79\x3d\x22\x2d\x35\x30\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\
+\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\
+\x77\x68\x69\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\
+\x37\x35\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\
+\x22\x67\x72\x65\x65\x6e\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\
+\x22\x31\x30\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\
+\x72\x3d\x22\x23\x31\x31\x33\x33\x31\x31\x22\x20\x2f\x3e\x0a\x20\
+\x20\x20\x20\x20\x20\x3c\x2f\x72\x61\x64\x69\x61\x6c\x47\x72\x61\
+\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x72\x61\
+\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x20\x69\x64\x3d\
+\x22\x79\x65\x6c\x6c\x6f\x77\x53\x70\x68\x65\x72\x65\x22\x20\x67\
+\x72\x61\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\
+\x65\x72\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\x22\x30\
+\x22\x20\x72\x3d\x22\x31\x30\x30\x22\x20\x66\x78\x3d\x22\x2d\x35\
+\x30\x22\x20\x66\x79\x3d\x22\x2d\x35\x30\x22\x3e\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\
+\x74\x3d\x22\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\
+\x72\x3d\x22\x77\x68\x69\x74\x65\x22\x20\x2f\x3e\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\
+\x74\x3d\x22\x37\x35\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\
+\x6f\x72\x3d\x22\x79\x65\x6c\x6c\x6f\x77\x22\x20\x2f\x3e\x0a\x20\
+\x20\x20\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\
+\x73\x65\x74\x3d\x22\x31\x30\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\
+\x63\x6f\x6c\x6f\x72\x3d\x22\x23\x34\x34\x34\x34\x32\x32\x22\x20\
+\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x72\x61\x64\x69\x61\
+\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x3c\x72\x61\x64\x69\x61\x6c\x47\x72\x61\x64\x69\x65\x6e\x74\
+\x20\x69\x64\x3d\x22\x73\x68\x61\x64\x6f\x77\x22\x20\x67\x72\x61\
+\x64\x69\x65\x6e\x74\x55\x6e\x69\x74\x73\x3d\x22\x75\x73\x65\x72\
+\x53\x70\x61\x63\x65\x4f\x6e\x55\x73\x65\x22\x0a\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\x22\x30\x22\x20\
+\x72\x3d\x22\x31\x30\x30\x22\x20\x66\x78\x3d\x22\x2d\x35\x30\x22\
+\x20\x66\x79\x3d\x22\x35\x30\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\
+\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\x74\x3d\x22\
+\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\x6c\x6f\x72\x3d\x22\
+\x62\x6c\x61\x63\x6b\x22\x20\x73\x74\x6f\x70\x2d\x6f\x70\x61\x63\
+\x69\x74\x79\x3d\x22\x31\x2e\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\
+\x20\x20\x20\x20\x20\x3c\x73\x74\x6f\x70\x20\x6f\x66\x66\x73\x65\
+\x74\x3d\x22\x31\x30\x30\x25\x22\x20\x73\x74\x6f\x70\x2d\x63\x6f\
+\x6c\x6f\x72\x3d\x22\x77\x68\x69\x74\x65\x22\x20\x73\x74\x6f\x70\
+\x2d\x6f\x70\x61\x63\x69\x74\x79\x3d\x22\x30\x2e\x30\x22\x20\x2f\
+\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x2f\x72\x61\x64\x69\x61\x6c\
+\x47\x72\x61\x64\x69\x65\x6e\x74\x3e\x0a\x0a\x20\x20\x20\x20\x20\
+\x20\x3c\x21\x2d\x2d\x20\x44\x65\x66\x69\x6e\x65\x20\x61\x20\x73\
+\x68\x61\x64\x6f\x77\x20\x66\x6f\x72\x20\x65\x61\x63\x68\x20\x73\
+\x70\x68\x65\x72\x65\x2e\x20\x2d\x2d\x3e\x0a\x20\x20\x20\x20\x20\
+\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x69\x64\x3d\x22\x73\x68\x61\
+\x64\x6f\x77\x22\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\
+\x73\x68\x61\x64\x6f\x77\x29\x22\x20\x63\x78\x3d\x22\x30\x22\x20\
+\x63\x79\x3d\x22\x30\x22\x20\x72\x3d\x22\x31\x30\x30\x22\x20\x2f\
+\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x64\x65\x66\x73\x3e\x0a\x20\x20\
+\x3c\x67\x20\x66\x69\x6c\x6c\x3d\x22\x23\x66\x66\x65\x65\x39\x39\
+\x22\x20\x73\x74\x72\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\x20\
+\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x30\
+\x22\x20\x79\x3d\x22\x30\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x34\
+\x30\x30\x22\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x34\x30\x30\x22\
+\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x67\x20\
+\x66\x69\x6c\x6c\x3d\x22\x77\x68\x69\x74\x65\x22\x20\x73\x74\x72\
+\x6f\x6b\x65\x3d\x22\x6e\x6f\x6e\x65\x22\x20\x3e\x0a\x20\x20\x20\
+\x20\x3c\x72\x65\x63\x74\x20\x78\x3d\x22\x30\x22\x20\x79\x3d\x22\
+\x31\x37\x35\x22\x20\x77\x69\x64\x74\x68\x3d\x22\x34\x30\x30\x22\
+\x20\x68\x65\x69\x67\x68\x74\x3d\x22\x32\x32\x35\x22\x20\x2f\x3e\
+\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x67\x20\x74\x72\x61\
+\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\
+\x65\x28\x32\x30\x30\x2c\x32\x39\x30\x29\x20\x73\x63\x61\x6c\x65\
+\x28\x32\x2e\x30\x2c\x31\x2e\x30\x29\x20\x72\x6f\x74\x61\x74\x65\
+\x28\x34\x35\x29\x22\x20\x3e\x0a\x20\x20\x20\x20\x3c\x72\x65\x63\
+\x74\x20\x66\x69\x6c\x6c\x3d\x22\x23\x61\x36\x63\x65\x33\x39\x22\
+\x20\x78\x3d\x22\x2d\x36\x39\x22\x20\x79\x3d\x22\x2d\x36\x39\x22\
+\x20\x77\x69\x64\x74\x68\x3d\x22\x31\x33\x38\x22\x20\x68\x65\x69\
+\x67\x68\x74\x3d\x22\x31\x33\x38\x22\x20\x2f\x3e\x0a\x20\x20\x20\
+\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x62\
+\x6c\x61\x63\x6b\x22\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\
+\x22\x30\x22\x20\x72\x3d\x22\x35\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\
+\x23\x61\x36\x63\x65\x33\x39\x22\x20\x63\x78\x3d\x22\x30\x22\x20\
+\x63\x79\x3d\x22\x30\x22\x20\x72\x3d\x22\x33\x33\x22\x20\x2f\x3e\
+\x0a\x20\x20\x20\x20\x3c\x70\x61\x74\x68\x20\x66\x69\x6c\x6c\x3d\
+\x22\x62\x6c\x61\x63\x6b\x22\x20\x64\x3d\x22\x4d\x20\x33\x37\x2c\
+\x35\x30\x20\x4c\x20\x35\x30\x2c\x33\x37\x20\x4c\x20\x31\x32\x2c\
+\x2d\x31\x20\x4c\x20\x32\x32\x2c\x2d\x31\x31\x20\x4c\x20\x31\x30\
+\x2c\x2d\x32\x34\x20\x4c\x20\x2d\x32\x34\x2c\x31\x30\x0a\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
+\x20\x20\x20\x20\x20\x20\x20\x20\x4c\x20\x2d\x31\x31\x2c\x32\x32\
+\x20\x4c\x20\x2d\x31\x2c\x31\x32\x20\x5a\x22\x20\x2f\x3e\x0a\x20\
+\x20\x20\x20\x3c\x61\x6e\x69\x6d\x61\x74\x65\x54\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x20\x61\x74\x74\x72\x69\x62\x75\x74\x65\x4e\x61\
+\x6d\x65\x3d\x22\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x22\x20\x20\
+\x74\x79\x70\x65\x3d\x22\x72\x6f\x74\x61\x74\x65\x22\x20\x76\x61\
+\x6c\x75\x65\x73\x3d\x22\x30\x3b\x20\x33\x36\x30\x22\x0a\x09\x20\
+\x20\x20\x20\x20\x20\x20\x62\x65\x67\x69\x6e\x3d\x22\x30\x73\x22\
+\x20\x64\x75\x72\x3d\x22\x31\x30\x73\x22\x20\x66\x69\x6c\x6c\x3d\
+\x22\x66\x72\x65\x65\x7a\x65\x22\x20\x2f\x3e\x0a\x20\x20\x3c\x2f\
+\x67\x3e\x0a\x20\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\
+\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x32\x30\x30\
+\x2c\x31\x37\x35\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\x75\x73\x65\
+\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x73\x68\
+\x61\x64\x6f\x77\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\
+\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x32\x35\x2c\x35\x35\
+\x29\x20\x73\x63\x61\x6c\x65\x28\x31\x2e\x30\x2c\x30\x2e\x35\x29\
+\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\
+\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x62\x6c\x75\x65\
+\x53\x70\x68\x65\x72\x65\x29\x22\x20\x63\x78\x3d\x22\x30\x22\x20\
+\x63\x79\x3d\x22\x30\x22\x20\x72\x3d\x22\x31\x30\x30\x22\x20\x2f\
+\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x67\x20\x74\x72\
+\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\
+\x74\x65\x28\x33\x31\x35\x2c\x32\x34\x30\x29\x22\x3e\x0a\x20\x20\
+\x20\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\
+\x73\x63\x61\x6c\x65\x28\x30\x2e\x35\x2c\x30\x2e\x35\x29\x22\x3e\
+\x0a\x20\x20\x20\x20\x20\x20\x3c\x75\x73\x65\x20\x78\x6c\x69\x6e\
+\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x73\x68\x61\x64\x6f\x77\x22\
+\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\
+\x73\x6c\x61\x74\x65\x28\x32\x35\x2c\x35\x35\x29\x20\x73\x63\x61\
+\x6c\x65\x28\x31\x2e\x30\x2c\x30\x2e\x35\x29\x22\x20\x2f\x3e\x0a\
+\x20\x20\x20\x20\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\
+\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x72\x65\x64\x53\x70\x68\x65\
+\x72\x65\x29\x22\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\x22\
+\x30\x22\x20\x72\x3d\x22\x31\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\
+\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\
+\x61\x6e\x73\x6c\x61\x74\x65\x28\x38\x30\x2c\x32\x37\x35\x29\x22\
+\x3e\x0a\x20\x20\x20\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\
+\x72\x6d\x3d\x22\x73\x63\x61\x6c\x65\x28\x30\x2e\x36\x35\x2c\x30\
+\x2e\x36\x35\x29\x22\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x75\x73\
+\x65\x20\x78\x6c\x69\x6e\x6b\x3a\x68\x72\x65\x66\x3d\x22\x23\x73\
+\x68\x61\x64\x6f\x77\x22\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\
+\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\x32\x35\x2c\x35\
+\x35\x29\x20\x73\x63\x61\x6c\x65\x28\x31\x2e\x30\x2c\x30\x2e\x35\
+\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x20\x20\x3c\x63\x69\x72\
+\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\x22\x75\x72\x6c\x28\x23\x67\
+\x72\x65\x65\x6e\x53\x70\x68\x65\x72\x65\x29\x22\x20\x63\x78\x3d\
+\x22\x30\x22\x20\x63\x79\x3d\x22\x30\x22\x20\x72\x3d\x22\x31\x30\
+\x30\x22\x20\x2f\x3e\x0a\x20\x20\x20\x20\x3c\x2f\x67\x3e\x0a\x20\
+\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x67\x20\x74\x72\x61\x6e\x73\
+\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\x74\x65\x28\
+\x32\x35\x35\x2c\x33\x32\x35\x29\x22\x3e\x0a\x20\x20\x20\x20\x3c\
+\x67\x20\x74\x72\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x73\x63\x61\
+\x6c\x65\x28\x30\x2e\x33\x2c\x30\x2e\x33\x29\x22\x3e\x0a\x20\x20\
+\x20\x20\x20\x20\x3c\x75\x73\x65\x20\x78\x6c\x69\x6e\x6b\x3a\x68\
+\x72\x65\x66\x3d\x22\x23\x73\x68\x61\x64\x6f\x77\x22\x20\x74\x72\
+\x61\x6e\x73\x66\x6f\x72\x6d\x3d\x22\x74\x72\x61\x6e\x73\x6c\x61\
+\x74\x65\x28\x32\x35\x2c\x35\x35\x29\x20\x73\x63\x61\x6c\x65\x28\
+\x31\x2e\x30\x2c\x30\x2e\x35\x29\x22\x20\x2f\x3e\x0a\x20\x20\x20\
+\x20\x20\x20\x3c\x63\x69\x72\x63\x6c\x65\x20\x66\x69\x6c\x6c\x3d\
+\x22\x75\x72\x6c\x28\x23\x79\x65\x6c\x6c\x6f\x77\x53\x70\x68\x65\
+\x72\x65\x29\x22\x20\x63\x78\x3d\x22\x30\x22\x20\x63\x79\x3d\x22\
+\x30\x22\x20\x72\x3d\x22\x31\x30\x30\x22\x20\x2f\x3e\x0a\x20\x20\
+\x20\x20\x3c\x2f\x67\x3e\x0a\x20\x20\x3c\x2f\x67\x3e\x0a\x3c\x2f\
+\x73\x76\x67\x3e\x0a\
+"
+
+qt_resource_name = b"\
+\x00\x05\
+\x00\x6d\x02\xc3\
+\x00\x66\
+\x00\x69\x00\x6c\x00\x65\x00\x73\
+\x00\x09\
+\x08\xf6\x8f\xa7\
+\x00\x63\
+\x00\x75\x00\x62\x00\x69\x00\x63\x00\x2e\x00\x73\x00\x76\x00\x67\
+\x00\x0b\
+\x08\x32\x87\x47\
+\x00\x73\
+\x00\x70\x00\x68\x00\x65\x00\x72\x00\x65\x00\x73\x00\x2e\x00\x73\x00\x76\x00\x67\
+"
+
+qt_resource_struct = b"\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00\x01\
+\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x02\
+\x00\x00\x00\x28\x00\x00\x00\x00\x00\x01\x00\x00\x14\xa4\
+\x00\x00\x00\x10\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
+"
+
+def qInitResources():
+ QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+def qCleanupResources():
+ QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)
+
+qInitResources()
diff --git a/examples/widgets/painting/transformations.py b/examples/widgets/painting/transformations.py
new file mode 100755
index 0000000..1bc7ecb
--- /dev/null
+++ b/examples/widgets/painting/transformations.py
@@ -0,0 +1,232 @@
+#!/usr/bin/env python
+
+"""***************************************************************************
+**
+** Copyright (C) 2005-2005 Trolltech AS. All rights reserved.
+**
+** This file is part of the example classes of the Qt Toolkit.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
+**
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales@trolltech.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+***************************************************************************"""
+
+import sys
+from PySide2 import QtCore, QtGui
+
+
+NoTransformation, Translate, Rotate, Scale = range(4)
+
+class RenderArea(QtGui.QWidget):
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+
+ newFont = self.font()
+ newFont.setPixelSize(12)
+ self.setFont(newFont)
+
+ fontMetrics = QtGui.QFontMetrics(newFont)
+ self.xBoundingRect = fontMetrics.boundingRect(self.tr("x"))
+ self.yBoundingRect = fontMetrics.boundingRect(self.tr("y"))
+ self.shape = QtGui.QPainterPath()
+ self.operations = []
+
+ def setOperations(self, operations):
+ self.operations = operations
+ self.update()
+
+ def setShape(self, shape):
+ self.shape = shape
+ self.update()
+
+ def minimumSizeHint(self):
+ return QtCore.QSize(182, 182)
+
+ def sizeHint(self):
+ return QtCore.QSize(232, 182)
+
+ def paintEvent(self, event):
+ painter = QtGui.QPainter()
+ painter.begin(self)
+ painter.setRenderHint(QtGui.QPainter.Antialiasing)
+ painter.fillRect(event.rect(), QtGui.QBrush(QtCore.Qt.white))
+
+ painter.translate(66, 66)
+
+ painter.save()
+ self.transformPainter(painter)
+ self.drawShape(painter)
+ painter.restore()
+
+ self.drawOutline(painter)
+
+ painter.save()
+ self.transformPainter(painter)
+ self.drawCoordinates(painter)
+ painter.restore()
+ painter.end()
+
+ def drawCoordinates(self, painter):
+ painter.setPen(QtCore.Qt.red)
+
+ painter.drawLine(0, 0, 50, 0)
+ painter.drawLine(48, -2, 50, 0)
+ painter.drawLine(48, 2, 50, 0)
+ painter.drawText(60 - self.xBoundingRect.width() / 2,
+ 0 + self.xBoundingRect.height() / 2, self.tr("x"))
+
+ painter.drawLine(0, 0, 0, 50)
+ painter.drawLine(-2, 48, 0, 50)
+ painter.drawLine(2, 48, 0, 50)
+ painter.drawText(0 - self.yBoundingRect.width() / 2,
+ 60 + self.yBoundingRect.height() / 2, self.tr("y"))
+
+ def drawOutline(self, painter):
+ painter.setPen(QtCore.Qt.darkGreen)
+ painter.setPen(QtCore.Qt.DashLine)
+ painter.setBrush(QtCore.Qt.NoBrush)
+ painter.drawRect(0, 0, 100, 100)
+
+ def drawShape(self, painter):
+ painter.fillPath(self.shape, QtCore.Qt.blue)
+
+ def transformPainter(self, painter):
+ for operation in self.operations:
+ if operation == Translate:
+ painter.translate(50, 50)
+
+ elif operation == Scale:
+ painter.scale(0.75, 0.75)
+
+ elif operation == Rotate:
+ painter.rotate(60)
+
+
+class Window(QtGui.QWidget):
+
+ operationTable = (NoTransformation, Rotate, Scale, Translate)
+ NumTransformedAreas = 3
+
+ def __init__(self, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+
+ self.originalRenderArea = RenderArea()
+
+ self.shapeComboBox = QtGui.QComboBox()
+ self.shapeComboBox.addItem(self.tr("Clock"))
+ self.shapeComboBox.addItem(self.tr("House"))
+ self.shapeComboBox.addItem(self.tr("Text"))
+ self.shapeComboBox.addItem(self.tr("Truck"))
+
+ layout = QtGui.QGridLayout()
+ layout.addWidget(self.originalRenderArea, 0, 0)
+ layout.addWidget(self.shapeComboBox, 1, 0)
+
+ self.transformedRenderAreas = range(Window.NumTransformedAreas)
+ self.operationComboBoxes = range(Window.NumTransformedAreas)
+
+ for i in range(Window.NumTransformedAreas):
+ self.transformedRenderAreas[i] = RenderArea()
+
+ self.operationComboBoxes[i] = QtGui.QComboBox()
+ self.operationComboBoxes[i].addItem(self.tr("No transformation"))
+ self.operationComboBoxes[i].addItem(self.tr("Rotate by 60\xB0"))
+ self.operationComboBoxes[i].addItem(self.tr("Scale to 75%"))
+ self.operationComboBoxes[i].addItem(self.tr("Translate by (50, 50)"))
+
+ self.connect(self.operationComboBoxes[i], QtCore.SIGNAL("activated(int)"),
+ self.operationChanged)
+
+ layout.addWidget(self.transformedRenderAreas[i], 0, i + 1)
+ layout.addWidget(self.operationComboBoxes[i], 1, i + 1)
+
+ self.setLayout(layout)
+ self.setupShapes()
+ self.shapeSelected(0)
+
+ self.setWindowTitle(self.tr("Transformations"))
+
+ def setupShapes(self):
+ truck = QtGui.QPainterPath()
+ truck.setFillRule(QtCore.Qt.WindingFill)
+ truck.moveTo(0.0, 87.0)
+ truck.lineTo(0.0, 60.0)
+ truck.lineTo(10.0, 60.0)
+ truck.lineTo(35.0, 35.0)
+ truck.lineTo(100.0, 35.0)
+ truck.lineTo(100.0, 87.0)
+ truck.lineTo(0.0, 87.0)
+ truck.moveTo(17.0, 60.0)
+ truck.lineTo(55.0, 60.0)
+ truck.lineTo(55.0, 40.0)
+ truck.lineTo(37.0, 40.0)
+ truck.lineTo(17.0, 60.0)
+ truck.addEllipse(17.0, 75.0, 25.0, 25.0)
+ truck.addEllipse(63.0, 75.0, 25.0, 25.0)
+
+ clock = QtGui.QPainterPath()
+ clock.addEllipse(-50.0, -50.0, 100.0, 100.0)
+ clock.addEllipse(-48.0, -48.0, 96.0, 96.0)
+ clock.moveTo(0.0, 0.0)
+ clock.lineTo(-2.0, -2.0)
+ clock.lineTo(0.0, -42.0)
+ clock.lineTo(2.0, -2.0)
+ clock.lineTo(0.0, 0.0)
+ clock.moveTo(0.0, 0.0)
+ clock.lineTo(2.732, -0.732)
+ clock.lineTo(24.495, 14.142)
+ clock.lineTo(0.732, 2.732)
+ clock.lineTo(0.0, 0.0)
+
+ house = QtGui.QPainterPath()
+ house.moveTo(-45.0, -20.0)
+ house.lineTo(0.0, -45.0)
+ house.lineTo(45.0, -20.0)
+ house.lineTo(45.0, 45.0)
+ house.lineTo(-45.0, 45.0)
+ house.lineTo(-45.0, -20.0)
+ house.addRect(15.0, 5.0, 20.0, 35.0)
+ house.addRect(-35.0, -15.0, 25.0, 25.0)
+
+ text = QtGui.QPainterPath()
+ font = QtGui.QFont()
+ font.setPixelSize(50)
+ fontBoundingRect = QtGui.QFontMetrics(font).boundingRect(self.tr("Qt"))
+ text.addText(-QtCore.QPointF(fontBoundingRect.center()), font, self.tr("Qt"))
+
+ self.shapes = (clock, house, text, truck)
+
+ self.connect(self.shapeComboBox, QtCore.SIGNAL("activated(int)"),
+ self.shapeSelected)
+
+ def operationChanged(self):
+ operations = []
+ for i in range(Window.NumTransformedAreas):
+ index = self.operationComboBoxes[i].currentIndex()
+ operations.append(Window.operationTable[index])
+ self.transformedRenderAreas[i].setOperations(operations[:])
+
+ def shapeSelected(self, index):
+ shape = self.shapes[index]
+ self.originalRenderArea.setShape(shape)
+ for i in range(Window.NumTransformedAreas):
+ self.transformedRenderAreas[i].setShape(shape)
+
+
+if __name__ == "__main__":
+ app = QtGui.QApplication(sys.argv)
+ window = Window()
+ window.show()
+ sys.exit(app.exec_())