Beispiel #1
0
def fileformat(filename, width, height):
    ''' figure out the output image format
    
    Args:
        filename: output filename, which will raise an error if it does not end
            in one of '.pdf', '.png', '.ps', or '.svg'
        width: width of the output image, in pixels
        height: height of the output image, in pixels
    
    Returns:
        tuple of cairo.Surface and filetype string e.g. 'pdf' or 'png'
    '''
    
    if filename is not None:
        _, ext = os.path.splitext(filename)
        if not ext:
            ext = '.png'
        ext = ext[1:].lower()
    else:
        ext = None
    
    assert ext in ['png', 'pdf', 'ps', 'svg', None], 'unknown format: .{}'.format(ext)
    
    if ext == 'pdf':
        surface = cairo.PDFSurface(filename, width, height)
    elif ext == 'svg':
        surface = cairo.SVGSurface(filename, width, height)
    elif ext == 'ps':
        surface = cairo.PSSurface(filename, width, height)
    else:
        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width,  height)
    
    return ext, surface
def create_new_surface(file_format, target=None, width=1024, height=768):
    """
    Create a new surface of the specified `file_format`:
        "png" for :class:`ImageSurface`
        "svg" for :class:`SVGSurface`
        "pdf" for :class:`PDFSurface`
        "ps" for :class:`PSSurface`
    The surface will be written to the `target` parameter , which can be a
    path to save the surface to, or file-like object with a `write()` method.
    You can also optionally specify the `width` and `height` of the generated
    surface if you know what it is; otherwise a default size of 1024 by 768 is
    used.
    """
    file_format = file_format.lower()
    if file_format == 'png':
        surface = cairo.ImageSurface(
            cairo.FORMAT_ARGB32, int(width), int(height))
    elif file_format == 'svg':
        surface = cairo.SVGSurface(target, width, height)
    elif file_format == 'pdf':
        surface = cairo.PDFSurface(target, width, height)
    elif file_format == 'ps':
        surface = cairo.PSSurface(target, width, height)
    else:
        raise ValueError(
            'Invalid value "{0}" for type parameter; valid values are "png", "svg", "pdf", and "ps".'.format(type))
    return surface
Beispiel #3
0
        def output_file(ctx):
            root, extension = os.path.splitext(target)
            if file_number:
                filename = '%s_%04d%s' % (root, file_number, extension)
            else:
                filename = target

            extension = extension.lower()
            if extension == '.png':
                surface = ctx.get_target()
                surface.write_to_png(target)
            elif extension == '.pdf':
                target_ctx = cairo.Context(
                    cairo.PDFSurface(filename, *self.size_or_default()))
                target_ctx.set_source_surface(ctx.get_target())
                target_ctx.paint()
            elif extension in ('.ps', '.eps'):
                target_ctx = cairo.Context(
                    cairo.PSSurface(filename, *self.size_or_default()))
                if extension == '.eps':
                    target_ctx.set_eps(extension='.eps')
                target_ctx.set_source_surface(ctx.get_target())
                target_ctx.paint()
            elif extension == '.svg':
                target_ctx = cairo.Context(
                    cairo.SVGSurface(filename, *self.size_or_default()))
                target_ctx.set_source_surface(ctx.get_target())
                target_ctx.paint()
            return filename
Beispiel #4
0
    def __init__(
            self,
            image=None,  # PIL image
            size=None,
            ctx=None,
            imageType=None,  # determines file type
            fileName=None,  # if set determines output file name
    ):
        """
    Canvas can be used in four modes:
    1) using the supplied PIL image
    2) using the supplied cairo context ctx
    3) writing to a file fileName with image type imageType
    4) creating a cairo surface and context within the constructor
    """
        self.image = None
        self.imageType = imageType
        if image is not None:
            try:
                imgd = getattr(image, 'tobytes', image.tostring)("raw", "BGRA")
            except SystemError:
                r, g, b, a = image.split()
                mrg = Image.merge("RGBA", (b, g, r, a))
                imgd = getattr(mrg, 'tobytes', mrg.tostring)("raw", "RGBA")

            a = array.array('B', imgd)
            stride = image.size[0] * 4
            surface = cairo.ImageSurface.create_for_data(
                a, cairo.FORMAT_ARGB32, image.size[0], image.size[1], stride)
            ctx = cairo.Context(surface)
            size = image.size[0], image.size[1]
            self.image = image
        elif ctx is None and size is not None:
            if hasattr(cairo, "PDFSurface") and imageType == "pdf":
                surface = cairo.PDFSurface(fileName, size[0], size[1])
            elif hasattr(cairo, "SVGSurface") and imageType == "svg":
                surface = cairo.SVGSurface(fileName, size[0], size[1])
            elif hasattr(cairo, "PSSurface") and imageType == "ps":
                surface = cairo.PSSurface(fileName, size[0], size[1])
            elif imageType == "png":
                surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, size[0],
                                             size[1])
            else:
                raise ValueError(
                    "Unrecognized file type. Valid choices are pdf, svg, ps, and png"
                )
            ctx = cairo.Context(surface)
            ctx.set_source_rgb(1, 1, 1)
            ctx.paint()
        else:
            surface = ctx.get_target()
            if size is None:
                try:
                    size = surface.get_width(), surface.get_height()
                except AttributeError:
                    size = None
        self.ctx = ctx
        self.size = size
        self.surface = surface
        self.fileName = fileName
Beispiel #5
0
 def _make_vector_surface(self, output_path, image_format, image_width, crop_margin):
     """
     Make a vector surface in the appropriate format and with the
     appropriate size depending on whether or not there is a crop margin.
     In a vector image, 1 screen pixel is scaled to a certain number of
     points, such that the figure as a whole will conform to a certain
     physical size.
     """
     if crop_margin is None:
         scale = image_width / self.screen_width
         image_height = self.screen_height * scale
     else:
         crop_margin = _mm_to_pts(crop_margin)
         if crop_margin > image_width / 3:
             raise ValueError(
                 "The crop margin set on this image is too large for the image width. Increase the image width or decrease the crop margin."
             )
         scale = (image_width - crop_margin * 2) / (
             self._block_extents[2] - self._block_extents[0]
         )
         image_height = (
             self._block_extents[3] - self._block_extents[1]
         ) * scale + crop_margin * 2
     if image_format == "PDF":
         surface = _cairo.PDFSurface(output_path, image_width, image_height)
         surface.set_metadata(_cairo.PDF_METADATA_CREATOR, f"eyekit {__version__}")
     elif image_format == "EPS":
         surface = _cairo.PSSurface(output_path, image_width, image_height)
         surface.set_eps(True)
     elif image_format == "SVG":
         surface = _cairo.SVGSurface(output_path, image_width, image_height)
     surface.set_device_scale(scale, scale)
     return surface, scale, crop_margin
Beispiel #6
0
    def _save(self, fo, fmt, **kwargs):
        # save PDF/PS/SVG
        orientation = kwargs.get('orientation', 'portrait')

        dpi = 72
        self.figure.dpi = dpi
        w_in, h_in = self.figure.get_size_inches()
        width_in_points, height_in_points = w_in * dpi, h_in * dpi

        if orientation == 'landscape':
            width_in_points, height_in_points = (
                height_in_points, width_in_points)

        if fmt == 'ps':
            if not hasattr(cairo, 'PSSurface'):
                raise RuntimeError('cairo has not been compiled with PS '
                                   'support enabled')
            surface = cairo.PSSurface(fo, width_in_points, height_in_points)
        elif fmt == 'pdf':
            if not hasattr(cairo, 'PDFSurface'):
                raise RuntimeError('cairo has not been compiled with PDF '
                                   'support enabled')
            surface = cairo.PDFSurface(fo, width_in_points, height_in_points)
        elif fmt in ('svg', 'svgz'):
            if not hasattr(cairo, 'SVGSurface'):
                raise RuntimeError('cairo has not been compiled with SVG '
                                   'support enabled')
            if fmt == 'svgz':
                if isinstance(fo, six.string_types):
                    fo = gzip.GzipFile(fo, 'wb')
                else:
                    fo = gzip.GzipFile(None, 'wb', fileobj=fo)
            surface = cairo.SVGSurface(fo, width_in_points, height_in_points)
        else:
            warnings.warn("unknown format: %s" % fmt)
            return

        # surface.set_dpi() can be used
        renderer = RendererCairo(self.figure.dpi)
        renderer.set_width_height(width_in_points, height_in_points)
        renderer.set_ctx_from_surface(surface)
        ctx = renderer.gc.ctx

        if orientation == 'landscape':
            ctx.rotate(np.pi/2)
            ctx.translate(0, -height_in_points)
            # cairo/src/cairo_ps_surface.c
            # '%%Orientation: Portrait' is always written to the file header
            # '%%Orientation: Landscape' would possibly cause problems
            # since some printers would rotate again ?
            # TODO:
            # add portrait/landscape checkbox to FileChooser

        self.figure.draw(renderer)

        ctx.show_page()
        surface.finish()
        if fmt == 'svgz':
            fo.close()
Beispiel #7
0
    def __init__(self, filename, entity, options):
        self.color = (0, 0, 0)
        self.factor = 1
        self.background_color = (0, 0, 0)
        self.analyse_options(options)

        self.surface = cairo.SVGSurface(filename, 10, 10)
        self.context = cairo.Context(self.surface)

        self.factor = 1
        self.height = self.compute_height(entity)
        self.width = self.compute_width(entity)
        self.line_length = default_line_length

        self.surface = cairo.PDFSurface(
            filename, self.width + self.line_length * 2 + bbox_w_margin * 2, self.height + bbox_h_margin * 2)

        self.context = cairo.Context(self.surface)
        self.compute_wire_length(entity)

        if options.format.lower() == "svg":
            self.factor = 1
            self.surface = cairo.SVGSurface(
                filename, self.width + self.line_length * 2 + bbox_w_margin * 2, self.height + bbox_h_margin * 2)

        if options.format.lower() == "pdf":
            self.factor = 1
            self.surface = cairo.PDFSurface(
                filename, self.width + self.line_length * 2 + bbox_w_margin * 2, self.height + bbox_h_margin * 2)

        if options.format.lower() == "ps":
            self.factor = 1
            self.surface = cairo.PSSurface(
                filename, self.width + self.line_length * 2 + bbox_w_margin * 2, self.height + bbox_h_margin * 2)

        if options.format.lower() == "png":
            self.factor = float(
                options.width / (self.width + self.factor * self.line_length * 2 + self.factor * bbox_w_margin * 2))

            stride = cairo.ImageSurface.format_stride_for_width(
                cairo.FORMAT_ARGB32, 10000)
            data = bytearray(stride * 10000)
            # stride = cairo.ImageSurface.format_stride_for_width(cairo.FORMAT_ARGB32, int(self.width)+1)
            # data = bytearray(stride * int(self.height))

            self.surface = cairo.ImageSurface(
                cairo.FORMAT_ARGB32,
                int(self.factor * self.width + self.factor *
                    self.line_length * 2 + self.factor * bbox_w_margin * 2),
                int(self.factor * self.height + self.factor * bbox_h_margin * 2), data, stride)

        self.context = cairo.Context(self.surface)
        self.draw_background(self.context)
        self.draw_entity(entity)

        self.surface.write_to_png(options.filename)
Beispiel #8
0
    def _save(self, fo, fmt, **kwargs):
        # save PDF/PS/SVG
        orientation = kwargs.get('orientation', 'portrait')

        dpi = 72
        self.figure.dpi = dpi
        w_in, h_in = self.figure.get_size_inches()
        width_in_points, height_in_points = w_in * dpi, h_in * dpi

        if orientation == 'landscape':
            width_in_points, height_in_points = (height_in_points,
                                                 width_in_points)

        if fmt == 'ps':
            if not hasattr(cairo, 'PSSurface'):
                raise RuntimeError('cairo has not been compiled with PS '
                                   'support enabled')
            surface = cairo.PSSurface(fo, width_in_points, height_in_points)
        elif fmt == 'pdf':
            if not hasattr(cairo, 'PDFSurface'):
                raise RuntimeError('cairo has not been compiled with PDF '
                                   'support enabled')
            surface = cairo.PDFSurface(fo, width_in_points, height_in_points)
        elif fmt in ('svg', 'svgz'):
            if not hasattr(cairo, 'SVGSurface'):
                raise RuntimeError('cairo has not been compiled with SVG '
                                   'support enabled')
            if fmt == 'svgz':
                if isinstance(fo, str):
                    fo = gzip.GzipFile(fo, 'wb')
                else:
                    fo = gzip.GzipFile(None, 'wb', fileobj=fo)
            surface = cairo.SVGSurface(fo, width_in_points, height_in_points)
        else:
            warnings.warn("unknown format: %s" % fmt, stacklevel=2)
            return

        # surface.set_dpi() can be used
        renderer = RendererCairo(self.figure.dpi)
        renderer.set_width_height(width_in_points, height_in_points)
        renderer.set_ctx_from_surface(surface)
        ctx = renderer.gc.ctx

        if orientation == 'landscape':
            ctx.rotate(np.pi / 2)
            ctx.translate(0, -height_in_points)
            # Perhaps add an '%%Orientation: Landscape' comment?

        self.figure.draw(renderer)

        ctx.show_page()
        surface.finish()
        if fmt == 'svgz':
            fo.close()
Beispiel #9
0
 def create_rcontext(self, size, frame):
     """
     Called when CairoCanvas needs a cairo context to draw on
     """
     if self.format == 'pdf':
         surface = cairo.PDFSurface(self._output_file(frame), *size)
     elif self.format in ('ps', 'eps'):
         surface = cairo.PSSurface(self._output_file(frame), *size)
     elif self.format == 'svg':
         surface = cairo.SVGSurface(self._output_file(frame), *size)
     else:
         surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *size)
     return cairo.Context(surface)
Beispiel #10
0
 def _make_surface(self, output_path, figure_format, figure_width, figure_height):
     """
     Make the relevant Cairo surface and context with appropriate sizing.
     """
     if figure_format == "PDF":
         surface = _cairo.PDFSurface(output_path, figure_width, figure_height)
         surface.set_metadata(_cairo.PDF_METADATA_CREATOR, f"eyekit {__version__}")
     elif figure_format == "EPS":
         surface = _cairo.PSSurface(output_path, figure_width, figure_height)
         surface.set_eps(True)
     elif figure_format == "SVG":
         surface = _cairo.SVGSurface(output_path, figure_width, figure_height)
     context = _cairo.Context(surface)
     return surface, context
Beispiel #11
0
def main():
    import argparse

    parser = argparse.ArgumentParser(description='A tool to generate mazes')

    def maze_size(s):
        result = int(s)
        if result < 1:
            raise argparse.ArgumentTypeError(
                'The maze size must be greater than 0')
        else:
            return result

    parser.add_argument('--maze-size',
                        type=maze_size,
                        nargs=2,
                        metavar=('WIDTH', 'HEIGHT'),
                        default=(15, 10),
                        help='The size of the maze.')

    maze_classes = dict(
        (len(mc.Wall.WALLS), mc) for mc in (Maze, TriMaze, HexMaze))
    parser.add_argument('--walls',
                        type=int,
                        choices=maze_classes.keys(),
                        default=4,
                        help='The number of walls for every room.')

    def char(s):
        if len(s) != 1:
            raise argparse.ArgumentTypeError('%s is not a valid character' % s)
        else:
            return s

    parser.add_argument(
        '--print-wall-char',
        type=char,
        default='@',
        help='The character used for walls when printing the maze.')
    parser.add_argument(
        '--print-path-char',
        type=char,
        default='.',
        help='The character used for the path when printing the maze.')
    parser.add_argument(
        '--print-floor-char',
        type=char,
        default=' ',
        help='The character used for the floor when printing the maze.')

    def print_room_size(s):
        result = int(s)
        if result < 3:
            raise argparse.ArgumentTypeError(
                'The room size must be greater than or equal to 3')
        else:
            return result

    parser.add_argument(
        '--print-room-size',
        type=print_room_size,
        nargs=2,
        default=(5, 4),
        help='The size of each room in characters when printing the maze.')

    def image_room_size(s):
        result = int(s)
        if result < 1:
            raise argparse.ArgumentTypeError(
                'The maze room size in the image must be greater than 0')
        else:
            return int(0.5 * math.sqrt(2.0) * result)

    parser.add_argument('--image-room-size',
                        type=image_room_size,
                        nargs=2,
                        metavar=('WIDTH', 'HEIGHT'),
                        default=(30, 30),
                        help='The size of the rooms in the maze image.')

    surface_types = {
        'pdf':
        (lambda f, w, h: cairo.PDFSurface(f, w, h), lambda f, surface: None),
        'png': (lambda f, w, h: cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h),
                lambda f, surface: surface.write_to_png(f)),
        'ps':
        (lambda f, w, h: cairo.PSSurface(f, w, h), lambda f, surface: None),
        'svg':
        (lambda f, w, h: cairo.SVGSurface(f, w, h), lambda f, surface: None)
    }

    def surface(s):
        try:
            ext = s.rsplit(os.path.extsep, 1)[1]
            return (lambda w, h: surface_types[ext][0]
                    (s, w, h), lambda surface: surface_types[ext][1]
                    (s, surface))
        except KeyError as e:
            argparse.ArgumentTypeError('"%s" is not a valid file extension' %
                                       e.args[0])
        except IndexError:
            argparse.ArgumentTypeError(
                'The image file must have a valid extension')

    class default:
        def write(*args, **kwargs):
            pass

    parser.add_argument(
        '--image-output',
        type=surface,
        metavar='FILENAME',
        required=True,
        help=('The name of the image file to create. Valid types are %s.') %
        (', '.join(surface_types.keys())))

    def color(allow_rgba):
        def rgb(s):
            result = None
            m = re.match(
                r'''(?x)
                \#(?P<red>[0-9A-Fa-f]{2})
                 (?P<green>[0-9A-Fa-f]{2})
                 (?P<blue>[0-9A-Fa-f]{2})''', s)
            if not m is None:
                result = tuple(float(int(d, 16)) / 255 for d in m.groups())
            else:
                m = re.match(
                    r'''(?x)
                    rgb\(
                        \s*(?P<red>\d{1,3}%?)\s*,
                        \s*(?P<green>\d{1,3}%?)\s*,
                        \s*(?P<blue>\d{1,3}%?)\s*\)''', s)
                if not m is None:
                    result = tuple(
                        float(d) / 255 if d[-1].isdigit() else float(d[:-1]) /
                        100 for d in m.groups())
            if result is None or any(r < 0 or r > 1.0 for r in result):
                raise argparse.ArgumentTypeError(
                    '"%s" is not a valid colour.' % s)
            return result + (1.0, )

        def rgba(s):
            result = None
            m = re.match(
                r'''(?x)
                \#(?P<alpha>[0-9A-Fa-f]{2})
                 (?P<red>[0-9A-Fa-f]{2})
                 (?P<green>[0-9A-Fa-f]{2})
                 (?P<blue>[0-9A-Fa-f]{2})''', s)
            if not m is None:
                result = tuple(
                    float(int(d, 16)) / 255
                    for d in m.groups()[1:] + (m.group(1), ))
            else:
                m = re.match(
                    r'''(?x)
                    rgba\(
                        \s*(?P<red>\d{1,3}%?)\s*,
                        \s*(?P<green>\d{1,3}%?)\s*,
                        \s*(?P<blue>\d{1,3}%?)\s*\,
                        \s*(?P<alpha>\d{1,3}%?)\s*\)''', s)
                if not m is None:
                    result = tuple(
                        float(d) / 255 if d[-1].isdigit() else float(d[:-1]) /
                        100 for d in m.groups())
            if result is None:
                return rgb(s)
            elif any(r < 0 or r > 1.0 for r in result):
                raise argparse.ArgumentTypeError(
                    '"%s" is not a valid colour.' % s)
            return result

        if allow_rgba:
            return rgba
        else:
            return rgb

    parser.add_argument(
        '--image-background-color',
        type=color(True),
        metavar='COLOUR',
        default=(0.0, 0.0, 0.0),
        help='The background colour of the image. This must be specified as '
        'an HTML colour on the form #RRGGBB or rgb(r, g, b), or #AARRGGBB '
        'or rgba(r, g, b, a).')
    parser.add_argument(
        '--image-wall-color',
        type=color(False),
        metavar='COLOUR',
        default=(1.0, 1.0, 1.0),
        help='The colour of the wall in the image. This must be specified as '
        'an HTML colour on the form #RRGGBB or rgb(r, g, b).')
    parser.add_argument(
        '--image-path-color',
        type=color(True),
        metavar='COLOUR',
        default=(0.8, 0.4, 0.2),
        help='The colour of the path in the image. This must be specified as '
        'an HTML colour on the form #RRGGBB or rgb(r, g, b), or #AARRGGBB '
        'or rgba(r, g, b, a).')

    def line_width(s):
        result = int(s)
        if result < 2:
            raise argparse.ArgumentTypeError(
                'Line widths must be greater than 1')
        elif result & 1:
            raise argparse.ArgumentTypeError(
                'Line widths must be an even number')
        else:
            return result

    parser.add_argument('--image-wall-width',
                        type=line_width,
                        metavar='WIDTH',
                        default=2,
                        help='The width of the maze wall lines.')
    parser.add_argument('--image-path-width',
                        type=line_width,
                        metavar='WIDTH',
                        default=2,
                        help='The width of the maze path lines.')

    parser.add_argument(
        '--image-path-smooth',
        action='store_true',
        default=False,
        help='Whether the path should be painted as a smooth curve instead '
        'of a sharp line.')

    namespace = parser.parse_args()

    # Create and initialise the maze
    maze = maze_classes[namespace.walls](*namespace.maze_size)
    initialize(maze, lambda max: random.randint(0, max - 1))
    solution = list(maze.walk_path((0, 0), (maze.width - 1, maze.height - 1)))

    print_maze(
        maze, solution,
        **dict((name.split('_', 1)[1], value)
               for name, value in vars(namespace).items()
               if name.startswith('print_')))
    make_image(
        maze, solution,
        **dict((name.split('_', 1)[1], value)
               for name, value in vars(namespace).items()
               if name.startswith('image_')))
    def _save(self, fo, format, **kwargs):
        # save PDF/PS/SVG
        orientation = kwargs.get('orientation', 'portrait')

        dpi = 72
        self.figure.dpi = dpi
        w_in, h_in = self.figure.get_size_inches()
        width_in_points, height_in_points = w_in * dpi, h_in * dpi

        if orientation == 'landscape':
            width_in_points, height_in_points = (height_in_points,
                                                 width_in_points)

        if format == 'ps':
            if not hasattr(cairo, 'PSSurface'):
                raise RuntimeError('cairo has not been compiled with PS '
                                   'support enabled')
            surface = cairo.PSSurface(fo, width_in_points, height_in_points)
        elif format == 'pdf':
            if not hasattr(cairo, 'PDFSurface'):
                raise RuntimeError('cairo has not been compiled with PDF '
                                   'support enabled')
            surface = cairo.PDFSurface(fo, width_in_points, height_in_points)
        elif format in ('svg', 'svgz'):
            if not hasattr(cairo, 'SVGSurface'):
                raise RuntimeError('cairo has not been compiled with SVG '
                                   'support enabled')
            if format == 'svgz':
                filename = fo
                if is_string_like(fo):
                    fo = open(fo, 'wb')
                    close = True
                else:
                    close = False
                try:
                    fo = gzip.GzipFile(None, 'wb', fileobj=fo)
                finally:
                    if close:
                        fo.close()
            surface = cairo.SVGSurface(fo, width_in_points, height_in_points)
        else:
            warnings.warn("unknown format: %s" % format)
            return

        # surface.set_dpi() can be used
        renderer = RendererCairo(self.figure.dpi)
        renderer.set_width_height(width_in_points, height_in_points)
        renderer.set_ctx_from_surface(surface)
        ctx = renderer.gc.ctx

        if orientation == 'landscape':
            ctx.rotate(np.pi / 2)
            ctx.translate(0, -height_in_points)
            # cairo/src/cairo_ps_surface.c
            # '%%Orientation: Portrait' is always written to the file header
            # '%%Orientation: Landscape' would possibly cause problems
            # since some printers would rotate again ?
            # TODO:
            # add portrait/landscape checkbox to FileChooser

        self.figure.draw(renderer)

        show_fig_border = False  # for testing figure orientation and scaling
        if show_fig_border:
            ctx.new_path()
            ctx.rectangle(0, 0, width_in_points, height_in_points)
            ctx.set_line_width(4.0)
            ctx.set_source_rgb(1, 0, 0)
            ctx.stroke()
            ctx.move_to(30, 30)
            ctx.select_font_face('sans-serif')
            ctx.set_font_size(20)
            ctx.show_text('Origin corner')

        ctx.show_page()
        surface.finish()
Beispiel #13
0
 def _create_surface(self, width, height):
     """Create and return ``(cairo_surface, width, height)``."""
     cairo_surface = cairo.PSSurface(self.output, width, height)
     cairo_surface.set_eps(True)
     return cairo_surface, width, height