Beispiel #1
0
def _render_qwebpage_full(web_page, logger, viewport_size, image_size):
    image = QImage(image_size, QImage.Format_ARGB32)
    image.fill(0)
    painter = QPainter(image)
    try:
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.TextAntialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
        painter.setWindow(QRect(QPoint(0, 0), web_page.viewportSize()))
        painter.setViewport(QRect(QPoint(0, 0), viewport_size))
        if image_size != viewport_size:
            # Try not to draw stuff that won't fit into the image.  Clipping
            # must be specified in input (aka logical) coordinates, but we know
            # it in output (aka physical) coordinates, so we have to do an
            # inverse transformation.  If, for some reason, we cannot, skip the
            # clipping altogether.
            clip_rect = QRect(QPoint(0, 0), viewport_size)
            inv_transform, invertible = painter.combinedTransform().inverted()
            if invertible:
                painter.setClipRect(inv_transform.mapRect(clip_rect))
        web_page.mainFrame().render(painter)
    finally:
        # It is important to end painter explicitly in python code, because
        # Python finalizer invocation order, unlike C++ destructors, is not
        # deterministic and there is a possibility of image's finalizer running
        # before painter's which may break tests and kill your cat.
        painter.end()
    return qimage_to_pil_image(image)
Beispiel #2
0
 def _render_qwebpage_full(self, web_rect, render_rect, canvas_size):
     """Render web page in one step."""
     if self._qpainter_needs_tiling(render_rect, canvas_size):
         # If this condition is true, this function may get stuck.
         raise ValueError("Rendering region is too large to be drawn"
                          " in one step, use tile-by-tile renderer instead")
     canvas = QImage(canvas_size, self.qt_image_format)
     if self.is_jpeg():
         # White background for JPEG images, same as we have in all browsers.
         canvas.fill(Qt.white)
     else:
         # Preserve old behaviour for PNG format.
         canvas.fill(0)
     painter = QPainter(canvas)
     try:
         painter.setRenderHint(QPainter.Antialiasing, True)
         painter.setRenderHint(QPainter.TextAntialiasing, True)
         painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
         painter.setWindow(web_rect)
         painter.setViewport(render_rect)
         painter.setClipRect(web_rect)
         self.web_page.mainFrame().render(painter)
     finally:
         painter.end()
     return WrappedQImage(canvas)
Beispiel #3
0
    def print_photo(self):
        print_dialog = QPrintDialog(self._printer,self)

        if print_dialog.exec_() == QDialog.Accepted:
            painter = QPainter(self._printer)
            rect = painter.viewport()
            size = self._lbl_photo.pixmap().size()
            size.scale(rect.size(), Qt.KeepAspectRatio)
            painter.setViewport(rect.x(), rect.y(), size.width(), size.height())
            painter.setWindow(self._lbl_photo.pixmap().rect())
            painter.drawPixmap(0, 0, self._lbl_photo.pixmap())
Beispiel #4
0
    def paintEvent(self, event):

        painter = QPainter()
        painter.begin(self)
        painter.fillRect(event.rect(), QBrush(Qt.white))
        size = min(self.width(), self.height())
        painter.setViewport(self.width() / 2 - size / 2,
                            self.height() / 2 - size / 2, size, size)
        painter.setWindow(0, 0, 100, 100)
        painter.drawText(10, 10, 80, 80, Qt.AlignCenter, "Python")
        painter.end()
Beispiel #5
0
 def on_actionPrint_triggered(self):
     if self.printer is None:
         self.printer = QPrinter(QPrinter.HighResolution)
         self.printer.setPageSize(QPrinter.Letter)
     form = QPrintDialog(self.printer, self)
     if form.exec_():
         painter = QPainter(self.printer)
         rect = painter.viewport()
         size = self.image.size()
         size.scale(rect.size(), Qt.KeepAspectRatio)
         painter.setViewport(rect.x(), rect.y(), size.width(),
                             size.height())
         painter.drawImage(0, 0, self.image)
 def filePrint(self):
     if self.image.isNull():
         return
     if self.printer is None:
         self.printer = QPrinter(QPrinter.HighResolution)
         self.printer.setPageSize(QPrinter.Letter)
     form = QPrintDialog(self.printer, self)
     if form.exec_():
         painter = QPainter(self.printer)
         rect = painter.viewport()
         size = self.image.size()
         size.scale(rect.size(), Qt.KeepAspectRatio)
         painter.setViewport(rect.x(), rect.y(), size.width(),
                             size.height())
         painter.drawImage(0, 0, self.image)
Beispiel #7
0
def _render_qwebpage_full(web_page, logger,
                          web_rect, render_rect, canvas_size):
    """Render web page in one step."""
    if _qpainter_needs_tiling(render_rect, canvas_size):
        # If this condition is true, this function may get stuck.
        raise ValueError("Rendering region is too large to be drawn"
                         " in one step, use tile-by-tile renderer instead")
    canvas = QImage(canvas_size, QImage.Format_ARGB32)
    canvas.fill(0)
    painter = QPainter(canvas)
    try:
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.TextAntialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
        painter.setWindow(web_rect)
        painter.setViewport(render_rect)
        painter.setClipRect(web_rect)
        web_page.mainFrame().render(painter)
    finally:
        painter.end()
    return WrappedQImage(canvas)
	def paintEvent(self, event = None):
		
		LogicalSize = 100.0

		def logicalFromPhysical(length, side):
			return (length / side) * LogicalSize

		fm = QFontMetricsF(self.font())
		ymargin = ((LogicalSize / 30.0) + logicalFromPhysical(self.leftSpinBox.height(), self.height()))
		ymax = (LogicalSize - logicalFromPhysical(fm.height() * 2, self.height()))
		width = LogicalSize / 4.0
		
		cx, cy = LogicalSize / 2.0, LogicalSize / 3.0
		ax, ay = cx - (2 * width), ymargin
		bx, by = cx - width, ay
		dx, dy = cx + width, ay
		ex, ey = cx + (2 * width), ymargin
		fx, fy = cx + (width / 2), cx + (LogicalSize / 24.0)
		gx, gy = fx, ymax
		hx, hy = cx - (width / 2), ymax
		ix, iy = hx, fy

		painter = QPainter(self)
		painter.setRenderHint(QPainter.Antialiasing)
		side = min(self.width(), self.height())
		painter.setViewport((self.width() - side) / 2, (self.height() - side) / 2, side, side)
		painter.setWindow(0, 0, LogicalSize, LogicalSize)

		painter.setPen(Qt.NoPen)

		gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100))
		gradient.setColorAt(0, Qt.white)
		a = self.leftSpinBox.value()
		gradient.setColorAt(1, (Qt.red if a != 0 else Qt.white))
		painter.setBrush(QBrush(gradient))
		painter.drawPolygon(QPolygon([ax, ay, bx, by, cx, cy, ix, iy]))

		gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100))
		gradient.setColorAt(0, Qt.white)
		b = self.rightSpinBox.value()
		gradient.setColorAt(1, (Qt.blue if b != 0 else Qt.white))
		painter.setBrush(QBrush(gradient))
		painter.drawPolygon(QPolygon([cx, cy, dx, dy, ex, ey, fx, fy]))

		if (a + b) == 0:
			color = QColor(Qt.white)
		else:
			ashare = (a / (a + b)) * 255.0
			bshare = 255.0 - ashare
			color = QColor(ashare, 0, bshare)

		gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100))
		gradient.setColorAt(0, Qt.white)
		gradient.setColorAt(1, color)
		painter.setBrush(QBrush(gradient))
		painter.drawPolygon(QPolygon([cx, cy, fx, fy, gx, gy, hx, hy, ix, iy]))

		painter.setPen(Qt.black)
		painter.drawPolyline(QPolygon([ax, ay, ix, iy, hx, hy]))
		painter.drawPolyline(QPolygon([gx, gy, fx, fy, ex, ey]))
		painter.drawPolyline(QPolygon([bx, by, cx, cy, dx, dy]))
Beispiel #9
0
    def paintEvent(self, event=None):
        LogicalSize = 100.0

        def logicalFromPhysical(length, side):
            return (length / side) * LogicalSize

        fm = QFontMetricsF(self.font())
        ymargin = (
            (LogicalSize / 30.0) +
            logicalFromPhysical(self.leftSpinBox.height(), self.height()))
        ymax = (LogicalSize -
                logicalFromPhysical(fm.height() * 2, self.height()))
        width = LogicalSize / 4.0
        cx, cy = LogicalSize / 2.0, LogicalSize / 3.0
        ax, ay = cx - (2 * width), ymargin
        bx, by = cx - width, ay
        dx, dy = cx + width, ay
        ex, ey = cx + (2 * width), ymargin
        fx, fy = cx + (width / 2), cx + (LogicalSize / 24.0)
        gx, gy = fx, ymax
        hx, hy = cx - (width / 2), ymax
        ix, iy = hx, fy

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        side = min(self.width(), self.height())
        painter.setViewport((self.width() - side) / 2,
                            (self.height() - side) / 2, side, side)
        painter.setWindow(0, 0, LogicalSize, LogicalSize)

        painter.setPen(Qt.NoPen)

        gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100))
        gradient.setColorAt(0, Qt.white)
        a = self.leftSpinBox.value()
        gradient.setColorAt(1, (Qt.red if a != 0 else Qt.white))
        painter.setBrush(QBrush(gradient))
        painter.drawPolygon(QPolygon([ax, ay, bx, by, cx, cy, ix, iy]))

        gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100))
        gradient.setColorAt(0, Qt.white)
        b = self.rightSpinBox.value()
        gradient.setColorAt(1, (Qt.blue if b != 0 else Qt.white))
        painter.setBrush(QBrush(gradient))
        painter.drawPolygon(QPolygon([cx, cy, dx, dy, ex, ey, fx, fy]))

        if (a + b) == 0:
            color = QColor(Qt.white)
        else:
            ashare = (a / (a + b)) * 255.0
            bshare = 255.0 - ashare
            color = QColor(ashare, 0, bshare)
        gradient = QLinearGradient(QPointF(0, 0), QPointF(0, 100))
        gradient.setColorAt(0, Qt.white)
        gradient.setColorAt(1, color)
        painter.setBrush(QBrush(gradient))
        painter.drawPolygon(QPolygon([cx, cy, fx, fy, gx, gy, hx, hy, ix, iy]))

        painter.setPen(Qt.black)
        painter.drawPolyline(QPolygon([ax, ay, ix, iy, hx, hy]))
        painter.drawPolyline(QPolygon([gx, gy, fx, fy, ex, ey]))
        painter.drawPolyline(QPolygon([bx, by, cx, cy, dx, dy]))
Beispiel #10
0
def _render_qwebpage_tiled(web_page, logger, viewport_size, image_size):
    tile_maxsize = defaults.TILE_MAXSIZE

    draw_width = viewport_size.width()
    draw_height = min(viewport_size.height(), image_size.height())

    # One bug is worked around by rendering the page one tile at a time onto a
    # small-ish temporary image.  The magic happens in viewport-window
    # transformation:
    #
    # - Sizes of tile painter viewport and tile painter window match
    #   webpage viewport size to avoid rescaling.
    # - Tile painter window is moved appropriately so that tile region is
    #   overlayed onto the temporary image.
    tile_hsize = min(tile_maxsize, draw_width)
    tile_vsize = min(tile_maxsize, draw_height)
    htiles = 1 + (draw_width - 1) // tile_hsize
    vtiles = 1 + (draw_height - 1) // tile_vsize
    tile_image = QImage(QSize(tile_hsize, tile_vsize), QImage.Format_ARGB32)
    ratio = viewport_size.width() / float(web_page.viewportSize().width())

    # The other bug manifests itself when you do painter.drawImage trying to
    # concatenate tiles onto a single image and once you reach 32'768 along
    # either dimension all of a sudden drawImage simply stops drawing anything.
    # The simplest workaround that comes to mind is to use pillow for pasting
    # images.
    pil_image = Image.new(mode='RGBA',
                          size=(image_size.width(), image_size.height()))

    painter = QPainter(tile_image)
    try:
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.TextAntialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
        painter.setWindow(QRect(QPoint(0, 0), web_page.viewportSize()))
        painter_viewport = QRect(QPoint(0, 0), viewport_size)
        for i in xrange(htiles):
            for j in xrange(vtiles):
                left, top = i * tile_hsize, j * tile_vsize
                painter.setViewport(painter_viewport.translated(-left, -top))
                logger.log("Rendering with viewport=%s" % painter.viewport(),
                           min_level=2)

                clip_rect = QRect(
                    QPoint(floor(left / ratio), floor(top / ratio)),
                    QPoint(ceil((left + tile_hsize) / ratio),
                           ceil((top + tile_vsize) / ratio)))
                web_page.mainFrame().render(painter, QRegion(clip_rect))
                pil_tile_image = qimage_to_pil_image(tile_image)
                if viewport_size.height() - top < tile_vsize:
                    # If this is the last tile, make sure that the bottom of
                    # the image is not garbled: the last tile's bottom may be
                    # clipped and will then have stuff left over from rendering
                    # the previous tile.  Crop it, because the image can be
                    # taller than the viewport because of "height=" option.
                    box = (0, 0, tile_hsize, viewport_size.height() - top)
                    pil_tile_image = pil_tile_image.crop(box)

                if logger:
                    logger.log("Pasting rendered tile to coords: %s" %
                               ((left, top), ),
                               min_level=2)
                pil_image.paste(pil_tile_image, (left, top))
        # Make sure that painter.end() is invoked before destroying the
        # underlying image.
    finally:
        painter.end()
    return pil_image
Beispiel #11
0
def _render_qwebpage_tiled(web_page, logger,
                           web_rect, render_rect, canvas_size):
    """
    Render web page tile-by-tile.

    This function works around bugs in QPaintEngine that occur when render_rect
    is larger than 32k pixels in either dimension.

    """
    # One bug is worked around by rendering the page one tile at a time onto a
    # small-ish temporary image.  The magic happens in viewport-window
    # transformation: painter viewport is moved appropriately so that rendering
    # region is overlayed onto a temporary "render" image which is then pasted
    # into the resulting one.
    #
    # The other bug manifests itself when you do painter.drawImage when pasting
    # the rendered tiles.  Once you reach 32'768 along either dimension all of
    # a sudden drawImage simply stops drawing anything.  This is a known
    # limitation of Qt painting system where coordinates are signed short ints.
    # The simplest workaround that comes to mind is to use pillow for pasting.
    tile_conf = _calculate_tiling(
        to_paint=render_rect.intersected(QRect(QPoint(0, 0), canvas_size)))

    canvas = Image.new('RGBA', _qsize_to_tuple(canvas_size))
    ratio = render_rect.width() / float(web_rect.width())
    tile_qimage = QImage(tile_conf['tile_size'], QImage.Format_ARGB32)
    painter = QPainter(tile_qimage)
    try:
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.TextAntialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
        painter.setWindow(web_rect)
        # painter.setViewport here seems superfluous (actual viewport is being
        # set inside the loop below), but it is not.  For some reason, if
        # viewport is reset after setClipRect, clipping rectangle is adjusted,
        # which is not what we want.
        painter.setViewport(render_rect)
        # painter.setClipRect(web_rect)
        for i in xrange(tile_conf['horizontal_count']):
            left = i * tile_qimage.width()
            for j in xrange(tile_conf['vertical_count']):
                top = j * tile_qimage.height()
                painter.setViewport(render_rect.translated(-left, -top))
                logger.log("Rendering with viewport=%s"
                           % painter.viewport(), min_level=2)

                clip_rect = QRect(
                    QPoint(floor(left / ratio),
                           floor(top / ratio)),
                    QPoint(ceil((left + tile_qimage.width()) / ratio),
                           ceil((top + tile_qimage.height()) / ratio)))
                web_page.mainFrame().render(painter, QRegion(clip_rect))
                tile_image = qimage_to_pil_image(tile_qimage)

                # If this is the bottommost tile, its bottom may have stuff
                # left over from rendering the previous tile.  Make sure these
                # leftovers don't garble the bottom of the canvas which can be
                # larger than render_rect because of "height=" option.
                rendered_vsize = min(render_rect.height() - top,
                                     tile_qimage.height())
                if rendered_vsize < tile_qimage.height():
                    box = (0, 0, tile_qimage.width(), rendered_vsize)
                    tile_image = tile_image.crop(box)

                logger.log("Pasting rendered tile to coords: %s" %
                           ((left, top),), min_level=2)
                canvas.paste(tile_image, (left, top))
    finally:
        # It is important to end painter explicitly in python code, because
        # Python finalizer invocation order, unlike C++ destructors, is not
        # deterministic and there is a possibility of image's finalizer running
        # before painter's which may break tests and kill your cat.
        painter.end()
    return WrappedPillowImage(canvas)
    def paintEvent(self, event):
        painter = QPainter(self)

        painter.setViewport(self.centeredViewport(self.size()))
        self.renderer().render(painter)