Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# You should have received a copy of the GNU General Public License
# along with CairoSVG. If not, see .
"""
Cairo surface types.
"""
import abc
import cairo
import os
from . import surface
class MultipageSurface(surface.Surface):
"""Cairo abstract surface managing multi-page outputs.
Classes overriding :class:`MultipageSurface` must have a ``surface_class``
class attribute corresponding to the cairo surface class.
"""
__metaclass__ = abc.ABCMeta
surface_class = NotImplementedError
def _create_surface(self, tree):
width, height, viewbox = surface.node_format(tree)
if "svg" in tuple(child.tag for child in tree.children):
# Real svg pages are in this root svg tag, create a fake surface
self.context = cairo.Context(
self.surface_class(os.devnull, width, height))
else:
self.context.save()
self._set_context_size(width, height, viewbox)
self.cairo.set_size(width, height)
class PDFSurface(MultipageSurface):
"""Cairo PDF surface."""
surface_class = cairo.PDFSurface
class PSSurface(MultipageSurface):
"""Cairo PostScript surface."""
surface_class = cairo.PSSurface
class OnepageSurface(surface.Surface):
"""Cairo abstract surface managing one page outputs.
Classes overriding :class:`OnepageSurface` must have a ``self._width`` and
a ``self._height`` set in ``self._create_surface``.
"""
__metaclass__ = abc.ABCMeta
_width = NotImplementedError
_height = NotImplementedError
@property
def width(self):
"""Surface width."""
return self._width
@property
write_to=None, output_width=None, output_height=None):
return surface.PSSurface.convert(
bytestring=bytestring, file_obj=file_obj, url=url, dpi=dpi,
parent_width=parent_width, parent_height=parent_height, scale=scale,
background_color=background_color, negate_colors=negate_colors,
invert_images=invert_images, unsafe=unsafe, write_to=write_to,
output_width=output_width, output_height=output_height)
svg2svg.__doc__ = surface.Surface.convert.__doc__.replace(
'the format for this class', 'SVG')
svg2png.__doc__ = surface.Surface.convert.__doc__.replace(
'the format for this class', 'PNG')
svg2pdf.__doc__ = surface.Surface.convert.__doc__.replace(
'the format for this class', 'PDF')
svg2ps.__doc__ = surface.Surface.convert.__doc__.replace(
'the format for this class', 'PS')
self.cursor_position = [0, 0]
self.cursor_d_position = [0, 0]
self.text_path_width = 0
self.context.restore()
self.parent_node = old_parent_node
self.font_size = old_font_size
self.context_width, self.context_height = old_context_size
class PDFSurface(Surface):
"""A surface that writes in PDF format."""
surface_class = cairo.PDFSurface
class PSSurface(Surface):
"""A surface that writes in PostScript format."""
surface_class = cairo.PSSurface
class PNGSurface(Surface):
"""A surface that writes in PNG format."""
device_units_per_user_units = 1
def _create_surface(self, width, height):
"""Create and return ``(cairo_surface, width, height)``."""
width = int(width)
height = int(height)
cairo_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
return cairo_surface, width, height
def finish(self):
self.parent_node = old_parent_node
self.font_size = old_font_size
self.context_width, self.context_height = old_context_size
class PDFSurface(Surface):
"""A surface that writes in PDF format."""
surface_class = cairo.PDFSurface
class PSSurface(Surface):
"""A surface that writes in PostScript format."""
surface_class = cairo.PSSurface
class PNGSurface(Surface):
"""A surface that writes in PNG format."""
device_units_per_user_units = 1
def _create_surface(self, width, height):
"""Create and return ``(cairo_surface, width, height)``."""
width = int(width)
height = int(height)
cairo_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
return cairo_surface, width, height
def finish(self):
"""Read the PNG surface content."""
if self.output is not None:
self.cairo.write_to_png(self.output)
return super().finish()
if "x" in node:
del node["x"]
if "y" in node:
del node["y"]
if "viewBox" in node:
del node["viewBox"]
href = node.get("{http://www.w3.org/1999/xlink}href")
tree = Tree(href, node)
self._set_context_size(*node_format(tree))
self.draw(tree)
self.context.restore()
# Restore twice, because draw does not restore at the end of svg tags
self.context.restore()
class DummySurface(Surface):
"""Dummy surface used as source for the pattern's images."""
def _create_surface(self, tree):
self._width, self._height, viewbox = node_format(tree)
self.cairo = cairo.SVGSurface(None, self._width, self._height)
self.context = cairo.Context(self.cairo)
self._set_context_size(self._width, self._height, viewbox)
self.context.move_to(0, 0)
def _create_surface(self, width, height):
"""Create and return ``(cairo_surface, width, height)``."""
width = int(width)
height = int(height)
cairo_surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
return cairo_surface, width, height
def finish(self):
"""Read the PNG surface content."""
if self.output is not None:
self.cairo.write_to_png(self.output)
return super().finish()
class SVGSurface(Surface):
"""A surface that writes in SVG format.
It may seem pointless to render SVG to SVG, but this can be used
with ``output=None`` to get a vector-based single page cairo surface.
"""
surface_class = cairo.SVGSurface
def parse_font(value):
ret = {"font-family": "", "font-size": "", "font-style": "normal",
"font-variant": "normal", "font-weight": "normal",
"line-height": "normal"}
font_styles = ["italic", "oblique"]
font_variants = ["small-caps"]
if filter_:
apply_filter_after_painting(self, node, filter_)
# Clean cursor's position after 'text' tags
if node.tag == 'text':
self.cursor_position = [0, 0]
self.cursor_d_position = [0, 0]
self.text_path_width = 0
self.context.restore()
self.parent_node = old_parent_node
self.font_size = old_font_size
self.context_width, self.context_height = old_context_size
class PDFSurface(Surface):
"""A surface that writes in PDF format."""
surface_class = cairo.PDFSurface
class PSSurface(Surface):
"""A surface that writes in PostScript format."""
surface_class = cairo.PSSurface
class PNGSurface(Surface):
"""A surface that writes in PNG format."""
device_units_per_user_units = 1
def _create_surface(self, width, height):
"""Create and return ``(cairo_surface, width, height)``."""
width = int(width)