def fitRect(rect, targetrect): size = rect.size().boundedTo(targetgeom.size()) newrect = QRect(rect.topLeft(), size) dx, dy = 0, 0 if newrect.left() < targetrect.left(): dx = targetrect.left() - newrect.left() if newrect.top() < targetrect.top(): dy = targetrect.top() - newrect.top() if newrect.right() > targetrect.right(): dx = targetrect.right() - newrect.right() if newrect.bottom() > targetrect.bottom(): dy = targetrect.bottom() - newrect.bottom() return newrect.translated(dx, dy)
def __layoutActions(self): left, right = self.__actions contents = self.contentsRect() buttonSize = QSize(contents.height(), contents.height()) margins = self.textMargins() if left: geom = QRect(contents.topLeft(), buttonSize) left.button.setGeometry(geom) margins.setLeft(buttonSize.width()) if right: geom = QRect(contents.topRight(), buttonSize) right.button.setGeometry(geom.translated(-buttonSize.width(), 0)) margins.setLeft(buttonSize.width()) self.setTextMargins(margins)
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