Esempio n. 1
0
def render_round_floating_button(cr,
                                 x,
                                 y,
                                 color,
                                 pixbuf,
                                 z=2,
                                 radius=gui.style.FLOATING_BUTTON_RADIUS):
    """Draw a round floating button with a standard size.

    :param cairo.Context cr: Context in which to draw.
    :param float x: X coordinate of the center pixel.
    :param float y: Y coordinate of the center pixel.
    :param lib.color.UIColor color: Color for the button base.
    :param GdkPixbuf.Pixbuf pixbuf: Icon to render.
    :param int z: Simulated height of the button above the canvas.
    :param float radius: Button radius, in pixels.

    These are used within certain overlays tightly associated with
    particular interaction modes for manipulating things on the canvas.

    """
    x = round(float(x))
    y = round(float(y))
    render_round_floating_color_chip(cr, x, y, color, radius=radius, z=z)
    cr.save()
    w = pixbuf.get_width()
    h = pixbuf.get_height()
    x -= w / 2
    y -= h / 2
    Gdk.cairo_set_source_pixbuf(cr, pixbuf, x, y)
    cr.rectangle(x, y, w, h)
    cr.clip()
    cr.paint()
    cr.restore()
Esempio n. 2
0
    def _draw_cb(self, da, cr):
        """Paint a preview of the current brush to the view."""
        if not self._brush_preview:
            cr.set_source_rgb(1, 0, 1)
            cr.paint()
            return
        aw = da.get_allocated_width()
        ah = da.get_allocated_height()

        # Work in a temporary group so that
        # the result can be masked with a gradient later.
        cr.push_group()

        # Paint a shadow line around the edge of
        # where the the brush preview will go.
        # There's an additional top border of one pixel
        # for alignment with the color preview widget
        # in the other corner.
        cr.rectangle(1.5, 2.5, aw - 3, ah)
        cr.set_line_join(cairo.LINE_JOIN_ROUND)
        cr.set_source_rgba(*self._OUTLINE_RGBA)
        cr.set_line_width(3)
        cr.stroke()

        # Scale and align the brush preview in its own saved context
        cr.save()
        # Clip rectangle for the bit in the middle of the shadow.
        # Note that the bottom edge isn't shadowed.
        cr.rectangle(1, 2, aw - 2, ah)
        cr.clip()
        # Scale and align the preview to the top of that clip rect.
        preview = self._brush_preview
        pw = preview.get_width()
        ph = preview.get_height()
        area_size = float(max(aw, ah)) - 2
        preview_size = float(max(pw, ph))
        x = math.floor(-pw / 2.0)
        y = 0
        cr.translate(aw / 2.0, 2)
        scale = area_size / preview_size
        cr.scale(scale, scale)
        Gdk.cairo_set_source_pixbuf(cr, preview, x, y)
        cr.paint()
        cr.restore()

        # Finally a highlight around the edge in the house style
        # Note that the bottom edge isn't highlighted.
        cr.rectangle(1.5, 2.5, aw - 3, ah)
        cr.set_line_width(1)
        cr.set_source_rgba(*self._EDGE_HIGHLIGHT_RGBA)
        cr.stroke()

        # Paint the group within a gradient mask
        cr.pop_group_to_source()
        mask = cairo.LinearGradient(0, 0, 0, ah)
        mask.add_color_stop_rgba(0.0, 1, 1, 1, 1.0)
        mask.add_color_stop_rgba(0.8, 1, 1, 1, 1.0)
        mask.add_color_stop_rgba(0.95, 1, 1, 1, 0.5)
        mask.add_color_stop_rgba(1.0, 1, 1, 1, 0.1)
        cr.mask(mask)
Esempio n. 3
0
    def draw_cb(self, widget, cr):
        # Paint the base color, and the list's pixbuf.
        state_flags = widget.get_state_flags()
        style_context = widget.get_style_context()
        style_context.save()
        bg_color_gdk = style_context.get_background_color(state_flags)
        bg_color = uicolor.from_gdk_rgba(bg_color_gdk)
        cr.set_source_rgb(*bg_color.get_rgb())
        cr.paint()
        Gdk.cairo_set_source_pixbuf(cr, self.pixbuf, 0, 0)
        cr.paint()
        # border colors
        gdkrgba = style_context.get_background_color(state_flags
                                                     | Gtk.StateFlags.SELECTED)
        selected_color = uicolor.from_gdk_rgba(gdkrgba)
        gdkrgba = style_context.get_background_color(state_flags
                                                     | Gtk.StateFlags.NORMAL)
        insertion_color = uicolor.from_gdk_rgba(gdkrgba)
        style_context.restore()
        # Draw borders
        last_i = len(self.itemlist) - 1
        for i, b in enumerate(self.itemlist):
            rect_color = None
            if b is self.selected:
                rect_color = selected_color
            elif self.drag_insertion_index is not None:
                if i == self.drag_insertion_index \
                        or (i == last_i and self.drag_insertion_index > i):
                    rect_color = insertion_color
            if rect_color is None:
                continue
            x = (i % self.tiles_w) * self.total_w
            y = (i // self.tiles_w) * self.total_h
            w = self.total_w
            h = self.total_h

            def shrink(pixels, x, y, w, h):
                x += pixels
                y += pixels
                w -= 2 * pixels
                h -= 2 * pixels
                return (x, y, w, h)

            x, y, w, h = shrink(self.spacing_outside, x, y, w, h)
            for j in xrange(self.border_visible_outside_cell):
                x, y, w, h = shrink(-1, x, y, w, h)
            max_j = self.border_visible + self.border_visible_outside_cell
            for j in xrange(max_j):
                cr.set_source_rgb(*rect_color.get_rgb())
                cr.rectangle(x, y, w - 1,
                             h - 1)  # FIXME: check pixel alignment
                cr.stroke()
                x, y, w, h = shrink(1, x, y, w, h)
        return True
Esempio n. 4
0
 def render_background_cb(self, cr, wd, ht, icon_border=None):
     self._backend.set_brush_color(*self._hsv)
     size = self._backend.get_size()
     pixbuf = GdkPixbuf.Pixbuf.new(
         GdkPixbuf.Colorspace.RGB,
         True,
         8,
         size,
         size,
     )
     arr = gdkpixbuf2numpy(pixbuf)
     self._backend.render(arr)
     self._dx = (wd - size) // 2
     self._dy = (ht - size) // 2
     cr.translate(self._dx, self._dy)
     Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0)
     cr.paint()
Esempio n. 5
0
    def cairo_request(self):
        """Access via a temporary Cairo context.

        Modifications are copied back into the backing pixbuf when the
        context manager finishes.

        """
        # Make a Cairo surface copy of the subpixbuf
        surf = cairo.ImageSurface(
            cairo.FORMAT_ARGB32,
            self.pixbuf.get_width(), self.pixbuf.get_height(),
        )
        cr = cairo.Context(surf)
        Gdk.cairo_set_source_pixbuf(cr, self.pixbuf, 0, 0)
        cr.paint()

        # User can modify its content with Cairo operations
        yield cr

        # Put the modified data back into the tile-aligned pixbuf.
        dx = self.x - self.ex
        dy = self.y - self.ey
        pixbuf = Gdk.pixbuf_get_from_surface(surf, 0, 0, self.w, self.h)
        pixbuf.copy_area(0, 0, self.w, self.h, self.epixbuf, dx, dy)
Esempio n. 6
0
def render_brush_preview_pixbuf(brushinfo, max_edge_tiles=4):
    """Renders brush preview images

    :param BrushInfo brushinfo: settings to render
    :param int max_edge_tiles: Use at most this many tiles along an edge
    :returns: Preview image, at 128x128 pixels
    :rtype: GdkPixbuf

    This generates the preview image (128px icon) used for brushes which
    don't have saved ones. These include brushes picked from .ORA files
    where the parent_brush_name doesn't correspond to a brush in the
    user's MyPaint brushes - they're used as the default, and for the
    Auto button in the Brush Icon editor.

    Brushstrokes are inherently unpredictable in size, so the allowable
    area is grown until the brush fits or until the rendering becomes
    too big. `max_edge_tiles` limits this growth.
    """
    assert max_edge_tiles >= 1
    brushinfo = brushinfo.clone()  # avoid capturing a ref
    brush = Brush(brushinfo)
    surface = lib.tiledsurface.Surface()
    n = lib.tiledsurface.N
    for size_in_tiles in range(1, max_edge_tiles):
        width = n * size_in_tiles
        height = n * size_in_tiles
        surface.clear()
        fg, spiral = _brush_preview_bg_fg(surface, size_in_tiles, brushinfo)
        brushinfo.set_color_rgb(fg)
        brush.reset()
        # Curve
        shape = _variable_pressure_scribble(width, height, size_in_tiles)
        surface.begin_atomic()
        for dt, x, y, p, xt, yt in shape:
            brush.stroke_to(surface.backend, x, y, p, xt, yt, dt, 1.0, 0.0,
                            0.0)
        surface.end_atomic()
        # Check rendered size
        tposs = surface.tiledict.keys()

        outside = min({tx for tx, ty in tposs}) < 0
        outside = outside or (min({ty for tx, ty in tposs}) < 0)
        outside = outside or (max({tx for tx, ty in tposs}) >= size_in_tiles)
        outside = outside or (max({ty for tx, ty in tposs}) >= size_in_tiles)

        if not outside:
            break
    # Convert to pixbuf at the right scale
    rect = (0, 0, width, height)
    pixbuf = render_as_pixbuf(surface, *rect, alpha=True)
    if max(width, height) != 128:
        interp = (GdkPixbuf.InterpType.NEAREST if max(width, height) < 128 else
                  GdkPixbuf.InterpType.BILINEAR)
        pixbuf = pixbuf.scale_simple(128, 128, interp)
    # Composite over a checquered bg via Cairo: shows erases
    size = gui.style.ALPHA_CHECK_SIZE
    nchecks = int(128 // size)
    cairo_surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, 128, 128)
    cr = cairo.Context(cairo_surf)
    render_checks(cr, size, nchecks)
    Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0)
    cr.paint()
    cairo_surf.flush()
    return Gdk.pixbuf_get_from_surface(cairo_surf, 0, 0, 128, 128)
def make_preview(thumb, preview_size):
    """Convert a layer's thumbnail into a nice preview image."""

    # Check size
    check_size = 2
    while check_size < (preview_size / 6) and check_size < 16:
        check_size *= 2

    blank = GdkPixbuf.Pixbuf.new(
        GdkPixbuf.Colorspace.RGB,
        True,
        8,
        preview_size,
        preview_size,
    )
    blank.fill(0x00000000)

    if thumb is None:
        thumb = blank

    # Make a square of chex
    preview = blank.composite_color_simple(
        dest_width=preview_size,
        dest_height=preview_size,
        interp_type=GdkPixbuf.InterpType.NEAREST,
        overall_alpha=255,
        check_size=check_size,
        color1=0xff707070,
        color2=0xff808080,
    )

    w = thumb.get_width()
    h = thumb.get_height()
    scale = preview_size / max(w, h)
    w *= scale
    h *= scale
    x = (preview_size - w) // 2
    y = (preview_size - h) // 2

    thumb.composite(
        dest=preview,
        dest_x=x,
        dest_y=y,
        dest_width=w,
        dest_height=h,
        offset_x=x,
        offset_y=y,
        scale_x=scale,
        scale_y=scale,
        interp_type=GdkPixbuf.InterpType.BILINEAR,
        overall_alpha=255,
    )

    # Add some very minor decorations..
    surf = cairo.ImageSurface(cairo.FORMAT_ARGB32, preview_size, preview_size)
    cr = cairo.Context(surf)
    Gdk.cairo_set_source_pixbuf(cr, preview, 0, 0)
    cr.paint()

    cr.set_source_rgba(1, 1, 1, 0.1)
    cr.rectangle(0.5, 0.5, preview_size - 1, preview_size - 1)
    cr.set_line_width(1.0)
    cr.stroke()

    surf.flush()

    preview = Gdk.pixbuf_get_from_surface(
        surf,
        0,
        0,
        preview_size,
        preview_size,
    )

    return preview