コード例 #1
0
    def __init__(self,
                 tree,
                 surface,
                 context,
                 dpi,
                 parent_surface=None,
                 parent_width=None,
                 parent_height=None,
                 scale=1):
        """Create the surface from a filename or a file-like object.

        The rendered content is written to ``output`` which can be a filename,
        a file-like object, ``None`` (render in memory but do not write
        anything) or the built-in ``bytes`` as a marker.

        Call the ``.finish()`` method to make sure that the output is
        actually written.

        """
        self.cairo = None
        self.context_width, self.context_height = parent_width, parent_height
        self.cursor_position = [0, 0]
        self.cursor_d_position = [0, 0]
        self.text_path_width = 0
        self.tree_cache = {(tree.url, tree.get('id')): tree}
        if parent_surface:
            self.markers = parent_surface.markers
            self.gradients = parent_surface.gradients
            self.patterns = parent_surface.patterns
            self.masks = parent_surface.masks
            self.paths = parent_surface.paths
            self.filters = parent_surface.filters
        else:
            self.markers = {}
            self.gradients = {}
            self.patterns = {}
            self.masks = {}
            self.paths = {}
            self.filters = {}
        self._old_parent_node = self.parent_node = None
        self.dpi = dpi
        self.font_size = size(self, '12pt')
        self.stroke_and_fill = True
        width, height, viewbox = node_format(self, tree)
        width *= scale
        height *= scale
        # Actual surface dimensions: may be rounded on raster surfaces types
        self.cairo = surface
        self.width = width
        self.height = height
        self.context = context
        # We must scale the context as the surface size is using physical units
        self.context.scale(self.device_units_per_user_units,
                           self.device_units_per_user_units)
        # Initial, non-rounded dimensions
        self.set_context_size(width, height, viewbox, scale,
                              preserved_ratio(tree))
        self.context.move_to(0, 0)
        self.draw(tree)
コード例 #2
0
 def read_dimensions_from_svg(self, tree):
     """
     :param tree:
     :return: Returns the size of the image in pixels. If the image is
              measured in points, it will error.
     """
     svg_width_px, svg_height_px, _ = node_format(self, tree)
     self.svg_width = CanvasUnit.from_px(svg_width_px).pt
     self.svg_height = CanvasUnit.from_px(svg_height_px).pt
コード例 #3
0
ファイル: _cairosvg.py プロジェクト: betatim/conx
def image(surface, node):
    """Draw an image ``node``."""
    base_url = node.get('{http://www.w3.org/XML/1998/namespace}base')
    if not base_url and node.url:
        base_url = os.path.dirname(node.url) + '/'
    url = parse_url(node.get('{http://www.w3.org/1999/xlink}href'), base_url)
    if "href" in node and node["href"].startswith("data:image/"):  # gif, etc
        image_bytes = uri2image_bytes(node["href"])
    else:
        image_bytes = node.fetch_url(url, 'image/*')

    if len(image_bytes) < 5:
        return

    x, y = size(surface, node.get('x'), 'x'), size(surface, node.get('y'), 'y')
    width = size(surface, node.get('width'), 'x')
    height = size(surface, node.get('height'), 'y')

    if image_bytes[:4] == b'\x89PNG':
        png_file = BytesIO(image_bytes)
    elif (image_bytes[:5] in (b'<svg ', b'<?xml', b'<!DOC')
          or image_bytes[:2] == b'\x1f\x8b'):
        if 'x' in node:
            del node['x']
        if 'y' in node:
            del node['y']
        tree = Tree(url=url.geturl(),
                    url_fetcher=node.url_fetcher,
                    bytestring=image_bytes,
                    tree_cache=surface.tree_cache,
                    unsafe=node.unsafe)
        tree_width, tree_height, viewbox = node_format(surface,
                                                       tree,
                                                       reference=False)
        if not viewbox:
            tree_width = tree['width'] = width
            tree_height = tree['height'] = height
        node.image_width = tree_width or width
        node.image_height = tree_height or height
        scale_x, scale_y, translate_x, translate_y = preserve_ratio(
            surface, node)

        # Clip image region
        surface.context.rectangle(x, y, width, height)
        surface.context.clip()

        # Draw image
        surface.context.save()
        surface.context.translate(x, y)
        surface.set_context_size(*node_format(surface, tree, reference=False),
                                 scale=1,
                                 preserved_ratio=preserved_ratio(tree))
        surface.context.translate(*surface.context.get_current_point())
        surface.context.scale(scale_x, scale_y)
        surface.context.translate(translate_x, translate_y)
        surface.draw(tree)
        surface.context.restore()
        return
    else:
        png_file = BytesIO()
        Image.open(BytesIO(image_bytes)).save(png_file, 'PNG')
        png_file.seek(0)

    image_surface = cairo.ImageSurface.create_from_png(png_file)

    ### DSB
    ## Added:
    image_surface.pattern = cairo.SurfacePattern(image_surface)
    image_surface.pattern.set_filter(cairo.FILTER_NEAREST)
    ### DSB

    node.image_width = image_surface.get_width()
    node.image_height = image_surface.get_height()
    scale_x, scale_y, translate_x, translate_y = preserve_ratio(surface, node)

    # Clip image region (if necessary)
    if not (translate_x == 0 and translate_y == 0
            and width == scale_x * node.image_width
            and height == scale_y * node.image_height):
        surface.context.rectangle(x, y, width, height)
        surface.context.clip()

    # Paint raster image
    surface.context.save()
    surface.context.translate(x, y)
    surface.context.scale(scale_x, scale_y)
    surface.context.translate(translate_x, translate_y)
    ### DSB
    ## Removed:
    #surface.context.set_source_surface(image_surface)
    ## Added:
    surface.context.set_source(image_surface.pattern)
    ### DSB
    surface.context.paint()
    surface.context.restore()
コード例 #4
0
    def __init__(self,
                 tree,
                 output,
                 dpi,
                 parent_surface=None,
                 parent_width=None,
                 parent_height=None,
                 scale=1,
                 output_width=None,
                 output_height=None,
                 background_color=None,
                 map_rgba=None,
                 map_image=None,
                 output_cairo=None,
                 output_cairo_context=None):
        # ## END OF FORK ## #
        """Create the surface from a filename or a file-like object.

        The rendered content is written to ``output`` which can be a filename,
        a file-like object, ``None`` (render in memory but do not write
        anything) or the built-in ``bytes`` as a marker.

        Call the ``.finish()`` method to make sure that the output is
        actually written.

        """
        self.cairo = None
        self.context_width, self.context_height = parent_width, parent_height
        self.cursor_position = [0, 0]
        self.cursor_d_position = [0, 0]
        self.text_path_width = 0
        self.tree_cache = {(tree.url, tree.get('id')): tree}
        if parent_surface:
            self.markers = parent_surface.markers
            self.gradients = parent_surface.gradients
            self.patterns = parent_surface.patterns
            self.masks = parent_surface.masks
            self.paths = parent_surface.paths
            self.filters = parent_surface.filters
            self.images = parent_surface.images
        else:
            self.markers = {}
            self.gradients = {}
            self.patterns = {}
            self.masks = {}
            self.paths = {}
            self.filters = {}
            self.images = {}
        self._old_parent_node = self.parent_node = None
        self.output = output
        self.dpi = dpi
        self.font_size = size(self, '12pt')
        self.stroke_and_fill = True
        width, height, viewbox = node_format(self, tree)
        if viewbox is None:
            viewbox = (0, 0, width, height)

        if output_width and output_height:
            width, height = output_width, output_height
        elif output_width:
            if width:
                # Keep the aspect ratio
                height *= output_width / width
            width = output_width
        elif output_height:
            if height:
                # Keep the aspect ratio
                width *= output_height / height
            height = output_height
        else:
            width *= scale
            height *= scale

        # ## START OF FORK ## #
        # Actual surface dimensions: may be rounded on raster surfaces types
        self.width = width * self.device_units_per_user_units
        self.height = height * self.device_units_per_user_units
        if output_cairo is not None:
            self.cairo = output_cairo
        else:
            self.cairo = self._create_surface(self.width, self.height)
        # ## END OF FORK ## #

        if 0 in (self.width, self.height):
            raise ValueError('The SVG size is undefined')

        # ## START OF FORK ## #
        if output_cairo_context is not None:
            self.context = output_cairo_context
        else:
            self.context = cairo.Context(self.cairo)
        # ## END OF FORK ## #

        # We must scale the context as the surface size is using physical units
        self.context.scale(self.device_units_per_user_units,
                           self.device_units_per_user_units)
        # Initial, non-rounded dimensions
        self.set_context_size(width, height, viewbox, tree)
        self.context.move_to(0, 0)

        if background_color:
            self.context.set_source_rgba(*color(background_color))
            self.context.paint()

        self.map_rgba = map_rgba
        self.map_image = map_image
        self.draw(tree)
コード例 #5
0
 def read_dimensions_from_svg(self, tree):
     self.svg_width, self.svg_height, _ = node_format(self, tree)
コード例 #6
0
    def __init__(
        self,
        surface,
        x,
        y,
        tree,
        dpi,
        output=None,
        parent_surface=None,
        parent_width=None,
        parent_height=None,
        scale=1,
        output_width=None,
        output_height=None,
        background_color=None,
        map_rgba=None,
        map_image=None,
        rotation=None,
    ):
        self.surface = surface
        self.cairo = None
        self.context_width, self.context_height = parent_width, parent_height
        self.cursor_position = [0, 0]
        self.cursor_d_position = [0, 0]
        self.text_path_width = 0
        self.tree_cache = {(tree.url, tree.get("id")): tree}
        if parent_surface:
            self.markers = parent_surface.markers
            self.gradients = parent_surface.gradients
            self.patterns = parent_surface.patterns
            self.masks = parent_surface.masks
            self.paths = parent_surface.paths
            self.filters = parent_surface.filters
            self.images = parent_surface.images
        else:
            self.markers = {}
            self.gradients = {}
            self.patterns = {}
            self.masks = {}
            self.paths = {}
            self.filters = {}
            self.images = {}
        self._old_parent_node = self.parent_node = None
        self.output = output
        self.dpi = dpi
        self.font_size = size(self, "12pt")
        self.stroke_and_fill = True
        width, height, viewbox = node_format(self, tree)
        if viewbox is None:
            viewbox = (0, 0, width, height)

        if output_width and output_height:
            width, height = output_width, output_height
        elif output_width:
            if width:
                # Keep the aspect ratio
                height *= output_width / width
            width = output_width
        elif output_height:
            if height:
                # Keep the aspect ratio
                width *= output_height / height
            height = output_height
        else:
            width *= scale
            height *= scale

        # Actual surface dimensions: may be rounded on raster surfaces types
        self.cairo, self.width, self.height = self._create_surface(
            width * self.device_units_per_user_units,
            height * self.device_units_per_user_units,
        )

        if 0 in (self.width, self.height):
            raise ValueError("The SVG size is undefined")

        self.context = cairo.Context(self.cairo)
        # We must scale the context as the surface size is using physical units
        self.context.scale(self.device_units_per_user_units,
                           self.device_units_per_user_units)
        center = (x + width / 2, y + height / 2)
        transform(self.context, center, rotation=rotation)
        self.context.translate(x, y)

        # Initial, non-rounded dimensions
        self.set_context_size(width, height, viewbox, tree)

        if background_color:
            self.context.set_source_rgba(*color(background_color))
            self.context.paint()

        self.map_rgba = map_rgba
        self.map_image = map_image