Beispiel #1
0
    def setup_images(self):
        for key, name in self.icons.items():
            try:
                path = os.path.join(self.theme_path, name)
                img = cairocffi.ImageSurface.create_from_png(path)
            except (cairocffi.Error, FileNotFoundError):
                self.theme_path = None
                logger.warning('VolumeIcons wrong icons path')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            size = self.fontsize
            sp = input_height / size

            width = input_width / sp
            if width > self.length:
                # cast to `int` only after handling all potentially-float values
                self.length = int(width + self.actual_padding * 2)

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()
            scaler.scale(sp, sp)

            translate_y = (self.bar.height - size) // 2
            scaler.translate(self.actual_padding * -1, -translate_y)

            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[key] = imgpat
Beispiel #2
0
    def setup_images(self):
        for key, name in self.icons.items():
            try:
                path = os.path.join(self.theme_path, name)
                img = cairocffi.ImageSurface.create_from_png(path)
            except cairocffi.Error:
                self.theme_path = None
                self.qtile.log.warning('Battery Icon switching to text mode')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / float(self.bar.height - 1)

            width = input_width / sp
            if width > self.width:
                self.width = int(width) + self.actual_padding * 2

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()

            scaler.scale(sp, sp)
            scaler.translate(self.actual_padding * -1, 0)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[key] = imgpat
Beispiel #3
0
def get_cairo_pattern(surface, width=None, height=None, theta=0.0):
    """Return a SurfacePattern from an ImageSurface.

    if width and height are not None scale the pattern
    to be size width and height.

    theta is in degrees ccw
    """
    pattern = cairocffi.SurfacePattern(surface)
    pattern.set_filter(cairocffi.FILTER_BEST)
    matrix = cairocffi.Matrix()

    tr_width, tr_height = 1.0, 1.0
    surf_width, surf_height = surface.get_width(), surface.get_height()
    if (width is not None) and (width != surf_width):
        tr_width = surf_width / width
    if (height is not None) and (height != surf_height):
        tr_height = surf_height / height
    matrix.scale(tr_width, tr_height)

    epsilon = 1.0e-6
    pi = 3.141592653589793
    if abs(theta) > epsilon:
        theta_rad = pi / 180.0 * theta
        mat_rot = cairocffi.Matrix()
        # https://cairographics.org/cookbook/transform_about_point/
        xt = surf_width * tr_width * 0.5
        yt = surf_height * tr_height * 0.5
        mat_rot.translate(xt, yt)
        mat_rot.rotate(theta_rad)
        mat_rot.translate(-xt, -yt)
        matrix = mat_rot.multiply(matrix)

    pattern.set_matrix(matrix)
    return pattern
Beispiel #4
0
    def setup_images(self):
        """ Create image structures for each icon files. """
        for img_name, iconfile in self.icons_files.items():
            try:
                img = cairocffi.ImageSurface.create_from_png(iconfile)
            except cairocffi.Error:
                self.qtile.log.exception('No icon found for application ' +
                                         img_name + '(' + iconfile + ')')
                return

            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / float(self.bar.height - 4)

            width = input_width / sp
            if width > self.width:
                self.width = int(width) + self.padding * 2

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()

            scaler.scale(sp, sp)
            scaler.translate(self.padding * -1, -2)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[img_name] = imgpat
            self.icons_widths[img_name] = width
Beispiel #5
0
    def _configure(self, qtile, bar):
        base._Widget._configure(self, qtile, bar)

        if not self.filename:
            raise ValueError("Filename not set!")

        self.filename = os.path.expanduser(self.filename)

        try:
            self.image = cairocffi.ImageSurface.create_from_png(self.filename)
        except MemoryError:
            raise ValueError("The image '%s' doesn't seem to be a valid PNG" %
                             (self.filename))

        self.pattern = cairocffi.SurfacePattern(self.image)

        self.image_width = self.image.get_width()
        self.image_height = self.image.get_height()

        if self.scale:
            new_height = self.bar.height - (self.margin_y * 2)

            if new_height and self.image_height != new_height:
                scaler = cairocffi.Matrix()
                sp = self.image_height / float(new_height)
                self.image_height = new_height
                self.image_width = int(self.image_width / sp)
                scaler.scale(sp, sp)
                self.pattern.set_matrix(scaler)
Beispiel #6
0
    def get_window_icon(self, window):
        if not window.icons:
            return None

        wid = window.window.wid
        state = WindowState.from_window(
            window,
            current_window=self.bar.screen.group.current_window,
        )
        cache = self._icons_cache

        if wid in cache:
            if state in cache[wid]:
                return cache[wid][state]
        else:
            cache[wid] = {}

        surface = self._icon_render(window, self.icon_size, state=state)
        width, height = util.cairo.get_surface_size(surface)
        pattern = cairocffi.SurfacePattern(surface)

        size = max(width, height)
        if size != self.icon_size:
            pattern.set_matrix(self._icon_scale_matrix(
                self.icon_size,
                size,
            ))

        cache[wid][state] = pattern
        return pattern
Beispiel #7
0
def silt_pattern():
    p_surface = \
        cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (0, 0, 32, 8))
    ctx = cairo.Context(p_surface)
    ctx.set_line_width(.5)
    ctx.set_line_cap(cairo.LINE_CAP_ROUND)
    r = 0.5
    sc = 2
    yoffs = 1
    ctx.set_source_rgb(0, 0, 0)

    def dot(x, y):
        ctx.arc(x * sc, y * sc + yoffs, r, 0, 2 * pi)
        ctx.fill()

    def hz_line(x0, x1, y):
        ctx.move_to(x0 * sc, y * sc + yoffs)
        ctx.line_to(x1 * sc, y * sc + yoffs)
        ctx.stroke()

    hz_line(0.2, 7.8, 1)
    hz_line(8.2, 15.8, 3)
    for x in 10, 12, 14:
        dot(x, 1)
    for x in 2, 4, 6:
        dot(x, 3)
    pattern = cairo.SurfacePattern(p_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern
Beispiel #8
0
    def get_window_icon(self, window):
        if not window.icons:
            return None

        cache = self._icons_cache.get(window.wid)
        if cache:
            return cache

        icons = sorted(
            iter(window.icons.items()),
            key=lambda x: abs(self.icon_size - int(x[0].split("x")[0]))
        )
        icon = icons[0]
        width, height = map(int, icon[0].split("x"))

        img = cairocffi.ImageSurface.create_for_data(
            icon[1],
            cairocffi.FORMAT_ARGB32,
            width,
            height
        )

        surface = cairocffi.SurfacePattern(img)

        scaler = cairocffi.Matrix()

        if height != self.icon_size:
            sp = height / self.icon_size
            height = self.icon_size
            width /= sp
            scaler.scale(sp, sp)
        surface.set_matrix(scaler)
        self._icons_cache[window.wid] = surface
        return surface
Beispiel #9
0
    def setup_images(self):
        for img_name in ('audio-volume-high', 'audio-volume-low',
                         'audio-volume-medium', 'audio-volume-muted'):

            try:
                img = cairocffi.ImageSurface.create_from_png(
                    os.path.join(self.theme_path, '%s.png' % img_name))
            except cairocffi.Error:
                self.theme_path = None
                self.length_type = bar.CALCULATED
                logger.exception('Volume switching to text mode')
                return
            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / float(self.bar.height - 1)

            width = input_width / sp
            if width > self.length:
                self.length = int(width) + self.actual_padding * 2

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()

            scaler.scale(sp, sp)
            scaler.translate(self.actual_padding * -1, 0)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[img_name] = imgpat
Beispiel #10
0
def draw_background_image(context, layer, image_rendering):
    # Background image
    if layer.image is None:
        return

    painting_x, painting_y, painting_width, painting_height = (
        layer.painting_area)
    positioning_x, positioning_y, positioning_width, positioning_height = (
        layer.positioning_area)
    position_x, position_y = layer.position
    repeat_x, repeat_y = layer.repeat
    image_width, image_height = layer.size

    if repeat_x == 'no-repeat':
        repeat_width = painting_width * 2
    elif repeat_x in ('repeat', 'round'):
        repeat_width = image_width
    else:
        assert repeat_x == 'space'
        n_repeats = math.floor(positioning_width / image_width)
        if n_repeats >= 2:
            repeat_width = (positioning_width - image_width) / (n_repeats - 1)
            position_x = 0  # Ignore background-position for this dimension
        else:
            repeat_width = image_width

    if repeat_y == 'no-repeat':
        repeat_height = painting_height * 2
    elif repeat_y in ('repeat', 'round'):
        repeat_height = image_height
    else:
        assert repeat_y == 'space'
        n_repeats = math.floor(positioning_height / image_height)
        if n_repeats >= 2:
            repeat_height = (
                positioning_height - image_height) / (n_repeats - 1)
            position_y = 0  # Ignore background-position for this dimension
        else:
            repeat_height = image_height

    sub_surface = cairo.PDFSurface(None, repeat_width, repeat_height)
    sub_context = cairo.Context(sub_surface)
    sub_context.rectangle(0, 0, image_width, image_height)
    sub_context.clip()
    layer.image.draw(sub_context, image_width, image_height, image_rendering)
    pattern = cairo.SurfacePattern(sub_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)

    with stacked(context):
        if not layer.unbounded:
            context.rectangle(painting_x, painting_y,
                              painting_width, painting_height)
            context.clip()
        # else: unrestricted, whole page box

        context.translate(positioning_x + position_x,
                          positioning_y + position_y)
        context.set_source(pattern)
        context.paint()
Beispiel #11
0
def grayscale(surface):
    width, height = get_surface_size(surface)
    pattern = cairocffi.SurfacePattern(surface)
    ctx = cairocffi.Context(surface)
    ctx.rectangle(0, 0, width, height)
    ctx.set_source_rgb(0, 0, 0)
    ctx.set_operator(cairocffi.OPERATOR_HSL_SATURATION)
    ctx.mask(pattern)
Beispiel #12
0
 def _paint(self, color=None, alpha=None):
     color = color if color is not None else self.color
     alpha = alpha if alpha is not None else self.alpha
     ptn = cairo.SurfacePattern(self.active_layer)
     ptn.set_matrix(self.active_matrix)
     self.output_ctx.set_source_rgba(*color, alpha=alpha)
     self.output_ctx.mask(ptn)
     self.ctx = None
     self.active_layer = None
     self.active_matrix = None
Beispiel #13
0
def burrow_pattern():
    p_surface = \
        cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (0, 0, 36, 36))
    ctx = cairo.Context(p_surface)
    random.seed(17)
    ctx.set_source_rgb(0, 0, 0)
    for x in range(0, 4):
        for y in range(0, 2):
            burrow(ctx, 4.5 + x * 24 + random.random() * 8,
                   9 + y * 36 + random.random() * 8 + x * 8, 2)
    pattern = cairo.SurfacePattern(p_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern
Beispiel #14
0
    def setup_images(self):
        """Create image structures for each icon files."""
        for img_name, iconfile in self.icons_files.items():
            if iconfile is None:
                logger.warning(
                    'No icon found for application "%s" (%s) switch to text mode',
                    img_name,
                    iconfile,
                )
                # if no icon is found and no default icon was set, we just
                # print the name, based on a textbox.
                textbox = base._TextBox()
                textbox._configure(self.qtile, self.bar)
                textbox.layout = self.drawer.textlayout(
                    textbox.text,
                    self.foreground,
                    self.font,
                    self.fontsize,
                    self.fontshadow,
                    markup=textbox.markup,
                )
                # the name will be displayed
                textbox.text = img_name
                textbox.calculate_length()
                self.icons_widths[img_name] = textbox.width
                self.surfaces[img_name] = textbox
                continue
            else:
                try:
                    img = cairocffi.ImageSurface.create_from_png(iconfile)
                except cairocffi.Error:
                    logger.exception(
                        'Error loading icon for application "%s" (%s)',
                        img_name, iconfile)
                    return

            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / (self.bar.height - 4)
            width = int(input_width / sp)

            imgpat = cairocffi.SurfacePattern(img)
            scaler = cairocffi.Matrix()
            scaler.scale(sp, sp)
            scaler.translate(self.padding * -1, -2)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[img_name] = imgpat
            self.icons_widths[img_name] = width
Beispiel #15
0
    def _setup_images(self):
        """
        Loads layout icons.
        """
        for layout_name in self._get_layout_names():
            icon_file_path = self.find_icon_file_path(layout_name)
            if icon_file_path is None:
                logger.warning('No icon found for layout "{}"'.format(layout_name))
                icon_file_path = self.find_icon_file_path("unknown")

            try:
                img = cairocffi.ImageSurface.create_from_png(icon_file_path)
            except (cairocffi.Error, IOError) as e:
                # Icon file is guaranteed to exist at this point.
                # If this exception happens, it means the icon file contains
                # an invalid image or is not readable.
                self.icons_loaded = False
                logger.exception(
                    'Failed to load icon from file "{}", '
                    "error was: {}".format(icon_file_path, e.message)
                )
                return

            input_width = img.get_width()
            input_height = img.get_height()

            sp = input_height / (self.bar.height - 1)

            width = input_width / sp
            if width > self.length:
                self.length = int(width) + self.actual_padding * 2

            imgpat = cairocffi.SurfacePattern(img)

            scaler = cairocffi.Matrix()

            scaler.scale(sp, sp)
            scaler.scale(self.scale, self.scale)
            factor = (1 - 1 / self.scale) / 2
            scaler.translate(-width * factor, -width * factor)
            scaler.translate(self.actual_padding * -1, 0)
            imgpat.set_matrix(scaler)

            imgpat.set_filter(cairocffi.FILTER_BEST)
            self.surfaces[layout_name] = imgpat

        self.icons_loaded = True
Beispiel #16
0
    def make_cairo_pattern(self):
        pat = cairo.SurfacePattern(self._cairo_surface)
        pat.set_filter({"best": cairo.FILTER_BEST,
                        "nearest": cairo.FILTER_NEAREST,
                        "gaussian": cairo.FILTER_GAUSSIAN,
                        "good": cairo.FILTER_GOOD,
                        "bilinear": cairo.FILTER_BILINEAR,
                        "fast": cairo.FILTER_FAST}[self.filter])

        pat.set_extend({"none": cairo.EXTEND_NONE,
                        "repeat": cairo.EXTEND_REPEAT,
                        "reflect": cairo.EXTEND_REFLECT,
                        "pad": cairo.EXTEND_PAD}[self.extend])

        pat.set_matrix(self._cairo_matrix())

        return pat
Beispiel #17
0
def test_low_level_api():
    """Test the low-level Python API with various parameters."""
    expected_content = svg2png(SVG_SAMPLE)

    # Same as above, longer version
    tree = parser.Tree(bytestring=SVG_SAMPLE)
    file_like = io.BytesIO()
    png_surface = surface.PNGSurface(tree, file_like, 96)
    png_surface.finish()
    assert file_like.getvalue() == expected_content

    png_result = cairo.ImageSurface.create_from_png(
        io.BytesIO(expected_content))
    expected_width = png_result.get_width()
    expected_height = png_result.get_height()

    # Abstract surface
    png_surface = surface.PNGSurface(tree, None, 96)
    assert png_surface.width == expected_width
    assert png_surface.height == expected_height
    assert cairo.SurfacePattern(png_surface.cairo)
Beispiel #18
0
def sand_pattern():
    p_surface = \
        cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (0, 0, 36, 36))
    p_ctx = cairo.Context(p_surface)
    r = 0.5
    wiggle = 3
    sc = 3.6
    offs = 1.8
    random.seed(11)
    p_ctx.set_source_rgb(0, 0, 0)
    for x in range(0, 10):
        for y in range(0, 10):
            p_ctx.arc(offs + x * sc + random.random() * wiggle - wiggle / 2,
                      offs + y * sc + random.random() * wiggle - wiggle / 2,
                      r, 0, 2 * pi)
            p_ctx.fill()
    # for x in range(0,2):
    #     for y in range(0,2):
    #         burrow(p_ctx, 4.5+x*18+random.random()*8.-8./2.,
    #                   9+y*18+random.random()*8.-8./2., 2)
    pattern = cairo.SurfacePattern(p_surface)
    pattern.set_extend(cairo.EXTEND_REPEAT)
    return pattern
Beispiel #19
0
    def update_icons(self):
        w, h = self.icon_size
        sp = h / float(self.bar.height - 1)

        icons = []
        widths = []
        for gen in self.icon_gen:
            img = cairocffi.ImageSurface(cairocffi.FORMAT_ARGB32, w, h)
            ctx = cairocffi.Context(img)

            self.gen_icon(gen, ctx)

            scaler = cairocffi.Matrix()
            scaler.scale(sp, sp)

            imgpat = cairocffi.SurfacePattern(img)
            imgpat.set_matrix(scaler)
            imgpat.set_filter(cairocffi.FILTER_BEST)

            icons.append(imgpat)
            widths.append(w / sp)

        self.icon_current = icons
        self.icon_widths = widths
Beispiel #20
0
def draw_background_image(context, layer, image_rendering):
    if layer.image is None:
        return

    painting_x, painting_y, painting_width, painting_height = (
        layer.painting_area)
    positioning_x, positioning_y, positioning_width, positioning_height = (
        layer.positioning_area)
    position_x, position_y = layer.position
    repeat_x, repeat_y = layer.repeat
    image_width, image_height = layer.size

    if repeat_x == 'no-repeat':
        # We want at least the whole image_width drawn on sub_surface, but we
        # want to be sure it will not be repeated on the painting_width.
        repeat_width = max(image_width, painting_width)
    elif repeat_x in ('repeat', 'round'):
        # We repeat the image each image_width.
        repeat_width = image_width
    else:
        assert repeat_x == 'space'
        n_repeats = floor(positioning_width / image_width)
        if n_repeats >= 2:
            # The repeat width is the whole positioning width with one image
            # removed, divided by (the number of repeated images - 1). This
            # way, we get the width of one image + one space. We ignore
            # background-position for this dimension.
            repeat_width = (positioning_width - image_width) / (n_repeats - 1)
            position_x = 0
        else:
            # We don't repeat the image.
            repeat_width = image_width

    # Comments above apply here too.
    if repeat_y == 'no-repeat':
        repeat_height = max(image_height, painting_height)
    elif repeat_y in ('repeat', 'round'):
        repeat_height = image_height
    else:
        assert repeat_y == 'space'
        n_repeats = floor(positioning_height / image_height)
        if n_repeats >= 2:
            repeat_height = (positioning_height - image_height) / (n_repeats -
                                                                   1)
            position_y = 0
        else:
            repeat_height = image_height

    sub_surface = cairo.PDFSurface(None, repeat_width, repeat_height)
    sub_context = cairo.Context(sub_surface)
    sub_context.rectangle(0, 0, image_width, image_height)
    sub_context.clip()
    layer.image.draw(sub_context, image_width, image_height, image_rendering)
    pattern = cairo.SurfacePattern(sub_surface)

    if repeat_x == repeat_y == 'no-repeat':
        pattern.set_extend(cairo.EXTEND_NONE)
    else:
        pattern.set_extend(cairo.EXTEND_REPEAT)

    with stacked(context):
        if not layer.unbounded:
            context.rectangle(painting_x, painting_y, painting_width,
                              painting_height)
            context.clip()
        # else: unrestricted, whole page box

        context.translate(positioning_x + position_x,
                          positioning_y + position_y)
        context.set_source(pattern)
        context.paint()
Beispiel #21
0
 def _render_mask(self):
     self.ctx.set_operator(cairo.OPERATOR_OVER)
     ptn = cairo.SurfacePattern(self.mask)
     ptn.set_matrix(cairo.Matrix(xx=1.0, yy=-1.0, x0=-self.origin_in_pixels[0], y0=self.size_in_pixels[1] + self.origin_in_pixels[1]))
     self.ctx.set_source(ptn)
     self.ctx.paint()
Beispiel #22
0
def convert_page(path, note_name, notebook_path, directory, pdf_file,
                 page_number):
    page = papyrus_pb2.Page()
    # Open and parse papyrus page using protobuf
    page.ParseFromString(open(path, 'rb').read())
    # Create a new pdf surface for drawing

    if page.background.width == 0 and page.background.height == 0:
        print("\tInfinite page!")

        max_x = 0
        max_y = 0

        for item in page.layer.item:
            bounds = None
            if item.type == papyrus_pb2.Item.Type.Value('Stroke'):
                bounds = item.stroke.bounds
            elif item.type == papyrus_pb2.Item.Type.Value('Shape'):
                if item.shape.type == 'Ellipse':
                    bounds = item.shape.ellipse.bounds
            elif item.type == papyrus_pb2.Item.Type.Value('Text'):
                bounds = item.text.bounds
            else:
                print(item)

            if bounds is not None:
                if bounds.right > max_x:
                    max_x = bounds.right

                if bounds.bottom > max_y:
                    max_y = bounds.bottom

        page.background.width = max_x + 1
        page.background.height = max_y + 1

    note_name = titlesafe(note_name)
    print("\t%s" % note_name)

    note_path = directory + '/' + notebook_path + '/' + dirsafe(note_name)
    new_note_path = note_path
    num = 1

    #while os.path.exists(new_note_path):
    #    new_note_path = note_path + '(' + str(num) + ')'
    #    num += 1

    makedir(note_path)

    note_path = new_note_path

    pdfpath = note_path + '/pdf'
    makedir(pdfpath)

    pdffile = pdfpath + '/page' + str(page_number) + '.pdf'
    print("\tSource: %s\n\tOutput: %s" % (path, pdffile))

    pdf_out = open(pdffile, 'w')
    surface = cairocffi.PDFSurface(pdf_out, cm_to_point(page.background.width),
                                   cm_to_point(page.background.height))
    context = cairocffi.Context(surface)

    # Paint the page white
    context.set_source_rgba(0, 0, 0, 0)
    context.paint()

    for item in page.layer.item:
        if item.type == papyrus_pb2.Item.Type.Value('Stroke'):
            context.save()
            # Translate to reference_point (stroke origin)
            context.translate(cm_to_point(item.stroke.reference_point.x),
                              cm_to_point(item.stroke.reference_point.y))
            # Set source color
            argb = u32_to_4f(item.stroke.color)
            context.set_source_rgba(argb[1], argb[2], argb[3], argb[0])
            # Set line width
            width = cm_to_point(item.stroke.weight)
            # Other parameter
            context.set_line_join(cairocffi.LINE_JOIN_ROUND)
            context.set_line_cap(cairocffi.LINE_CAP_ROUND)
            context.move_to(0, 0)

            if item.stroke.stroke_type == papyrus_pb2.Stroke.Highlight:
                context.push_group()
                context.set_source_rgba(argb[1], argb[2], argb[3], 1)
                context.fill_preserve()
                context.set_line_cap(cairocffi.LINE_CAP_SQUARE)

            for point in item.stroke.point:
                context.line_to(cm_to_point(point.x), cm_to_point(point.y))
                if item.stroke.stroke_type == papyrus_pb2.Stroke.Highlight:
                    context.set_line_width(width)
                    #context.
                elif point.HasField('pressure'):
                    context.set_line_width(width * point.pressure)
                else:
                    context.set_line_width(width)
                context.stroke()
                context.move_to(cm_to_point(point.x), cm_to_point(point.y))
            if item.stroke.stroke_type == papyrus_pb2.Stroke.Highlight:
                context.pop_group_to_source()
                context.paint_with_alpha(argb[0])
            context.restore()
        elif item.type == papyrus_pb2.Item.Type.Value(
                'Shape') and item.shape.ellipse is not None:
            width = item.shape.ellipse.weight * 0.3

            context.save()
            context.new_sub_path()
            context.translate(cm_to_point(item.shape.ellipse.center_x),
                              cm_to_point(item.shape.ellipse.center_y))
            context.set_line_width(item.shape.ellipse.weight)
            argb = u32_to_4f(item.shape.ellipse.color)
            context.set_line_width(width)
            context.set_source_rgba(argb[1], argb[2], argb[3], argb[0])
            context.scale(cm_to_point(item.shape.ellipse.radius_x),
                          cm_to_point(item.shape.ellipse.radius_y))
            context.arc(0, 0, 1,
                        (item.shape.ellipse.start_angle / 360) * 2 * math.pi,
                        (item.shape.ellipse.sweep_angle / 360) * 2 * math.pi)
            context.close_path()
            context.stroke()
            context.restore()
        elif item.type == papyrus_pb2.Item.Type.Value('Text'):
            context.save()
            context.set_font_size(item.text.weight)

            # Color
            argb = u32_to_4f(item.text.color)
            context.set_source_rgba(argb[1], argb[2], argb[3], argb[0])

            context.move_to(cm_to_point(item.text.bounds.left),
                            cm_to_point(item.text.bounds.top))
            tw = int(item.text.weight)
            size_m = cairocffi.Matrix(tw, 0, 0, tw, 0, 0)
            scaledFont = cairocffi.ScaledFont(
                cairocffi.ToyFontFace("sans-serif"), size_m)
            glyphs = scaledFont.text_to_glyphs(
                cm_to_point(item.text.bounds.left),
                cm_to_point(item.text.bounds.bottom), item.text.text, False)
            context.show_glyphs(glyphs)
            context.restore()

        elif item.type == papyrus_pb2.Item.Type.Value('Image'):
            if (DEBUG):
                print("Got an image!")
                print(item.image.image_hash)

            # Convert JPEG image to PNG
            im = Image.open(base_directory + "data/imgs/" +
                            item.image.image_hash)
            im = im.crop(
                (item.image.crop_bounds.left, item.image.crop_bounds.top,
                 item.image.crop_bounds.right, item.image.crop_bounds.bottom))
            im.save(
                base_directory + "data/imgs/" + item.image.image_hash + ".png",
                "PNG")
            im.close()

            matrix = cairocffi.Matrix()

            scale_x = cm_to_point(item.image.bounds.right -
                                  item.image.bounds.left) / (
                                      item.image.crop_bounds.right -
                                      item.image.crop_bounds.left)
            scale_y = cm_to_point(item.image.bounds.bottom -
                                  item.image.bounds.top) / (
                                      item.image.crop_bounds.bottom -
                                      item.image.crop_bounds.top)

            if (DEBUG):
                print("Scale X: %d" % (1 / scale_x))
                print("Scale Y: %d" % (1 / scale_y))
                print("Translate: %d" % cm_to_point(item.image.bounds.left))
            matrix.scale(1 / scale_x, 1 / scale_y)
            matrix.translate(-cm_to_point(item.image.bounds.left),
                             -cm_to_point(item.image.bounds.top))

            im_surface = cairocffi.ImageSurface.create_from_png(
                base_directory + "./data/imgs/" + item.image.image_hash +
                ".png")
            im_surface_pattern = cairocffi.SurfacePattern(im_surface)

            im_surface_pattern.set_filter(cairocffi.FILTER_GOOD)
            im_surface_pattern.set_matrix(matrix)

            context.save()
            context.set_source(im_surface_pattern)
            context.rectangle(
                cm_to_point(item.image.bounds.left),
                cm_to_point(item.image.bounds.top),
                cm_to_point(item.image.bounds.right - item.image.bounds.left),
                cm_to_point(item.image.bounds.bottom - item.image.bounds.top))
            context.fill()
            context.restore()
        else:
            print(item)
            print("Item of type {} not supported".format(
                papyrus_pb2.Item.Type.Name(item.type)))
    surface.flush()
    surface.finish()
    pdf_out.close()

    if page.background.HasField("pdf_background"):

        try:
            output_file = PdfFileWriter()
            input_file = PdfFileReader(file(pdffile, "rb"))
            pdf_file = PdfFileReader(
                file(base_directory + "data/docs/" + pdf_file, "rb"))
            pdf_page = pdf_file.getPage(
                page.background.pdf_background.page_number)

            input_page = input_file.getPage(0)
            pdf_page.mergePage(input_page)

            output_file.addPage(pdf_page)

            with open(pdffile + ".tmp", "wb") as outputStream:
                output_file.write(outputStream)
            os.rename(pdffile + ".tmp", pdffile)
        except:
            print(
                "\t%sUnable to merge PDFs - maybe the PDF was malformed? Result was %s%s"
                % (color.RED, sys.exc_info()[0], color.END))
    print("")
    return pdffile