File: svg.py

package info (click to toggle)
python-qpageview 1.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 788 kB
  • sloc: python: 5,125; makefile: 22
file content (118 lines) | stat: -rw-r--r-- 3,767 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# -*- coding: utf-8 -*-
#
# This file is part of the qpageview package.
#
# Copyright (c) 2016 - 2019 by Wilbert Berendsen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
# See http://www.gnu.org/licenses/ for more information.

"""
A page that can display a SVG document.

"""

from PyQt6.QtCore import QRect, QRectF, Qt
from PyQt6.QtGui import QColor, QPainter
from PyQt6.QtSvg import QSvgRenderer

from .constants import (
    Rotate_0,
    Rotate_90,
    Rotate_180,
    Rotate_270,
)

from . import document
from . import locking
from . import page
from . import render


class SvgPage(page.AbstractRenderedPage):
    """A page that can display a SVG document."""

    dpi = 90.0

    def __init__(self, svgrenderer, renderer=None):
        super().__init__(renderer)
        self._svg = svgrenderer
        self.pageWidth = svgrenderer.defaultSize().width()
        self.pageHeight = svgrenderer.defaultSize().height()
        self._viewBox = svgrenderer.viewBoxF()

    @classmethod
    def load(cls, filename, renderer=None):
        """Load a SVG document from filename, which may also be a QByteArray.

        Yields only one Page instance, as SVG currently supports one page per
        file. If the file can't be loaded by the underlying QSvgRenderer,
        no Page is yielded.

        """
        r = QSvgRenderer()
        if r.load(filename):
            yield cls(r, renderer)

    def mutex(self):
        return self._svg

    def group(self):
        return self._svg


class SvgDocument(document.MultiSourceDocument):
    """A Document representing a group of SVG files."""
    pageClass = SvgPage

    def createPages(self):
        return self.pageClass.loadFiles(self.sources(), self.renderer)


class SvgRenderer(render.AbstractRenderer):
    """Render SVG pages."""
    def setRenderHints(self, painter):
        """Sets the renderhints for the painter we want to use."""
        painter.setRenderHint(QPainter.RenderHint.Antialiasing, self.antialiasing)
        painter.setRenderHint(QPainter.RenderHint.TextAntialiasing, self.antialiasing)

    def draw(self, page, painter, key, tile, paperColor=None):
        """Draw the specified tile of the page (coordinates in key) on painter."""
        # determine the part to draw; convert tile to viewbox
        viewbox = self.map(key, page._viewBox).mapRect(QRectF(*tile))
        target = QRectF(0, 0, tile.w, tile.h)
        if key.rotation & 1:
            target.setSize(target.size().transposed())
        with locking.lock(page._svg):
            page._svg.setViewBox(viewbox)
            # we must specify the target otherwise QSvgRenderer scales to the
            # unrotated image
            painter.save()
            painter.setClipRect(target, Qt.ClipOperation.IntersectClip)
            # QSvgRenderer seems to set antialiasing always on anyway... :-)
            self.setRenderHints(painter)
            page._svg.render(painter, target)
            painter.restore()
            page._svg.setViewBox(page._viewBox)




# install a default renderer, so SvgPage can be used directly
SvgPage.renderer = SvgRenderer()