Ejemplo n.º 1
0
class _IconBuffer(object):

    _surface_cache = LRU(50)
    _loader = _SVGLoader()

    def __init__(self):
        self.icon_name = None
        self.icon_size = None
        self.file_name = None
        self.fill_color = None
        self.background_color = None
        self.stroke_color = None
        self.badge_name = None
        self.width = None
        self.height = None
        self.cache = False
        self.scale = 1.0

    def _get_cache_key(self, sensitive):
        if self.background_color is None:
            color = None
        else:
            color = (self.background_color.red, self.background_color.green,
                     self.background_color.blue)
        return (self.icon_name, self.file_name, self.fill_color,
                self.stroke_color, self.badge_name, self.width, self.height,
                color, sensitive)

    def _load_svg(self, file_name):
        entities = {}
        if self.fill_color:
            entities['fill_color'] = self.fill_color
        if self.stroke_color:
            entities['stroke_color'] = self.stroke_color

        return self._loader.load(file_name, entities, self.cache)

    def _get_attach_points(self, info, size_request):
        has_attach_points_, attach_points = info.get_attach_points()

        if attach_points:
            attach_x = float(attach_points[0].x) / size_request
            attach_y = float(attach_points[0].y) / size_request
        else:
            attach_x = attach_y = 0

        return attach_x, attach_y

    def _get_icon_info(self, file_name, icon_name):
        icon_info = _IconInfo()

        if file_name:
            icon_info.file_name = file_name
        elif icon_name:
            theme = Gtk.IconTheme.get_default()

            size = 50
            if self.width is not None:
                size = self.width

            info = theme.lookup_icon(icon_name, int(size), 0)
            if info:
                attach_x, attach_y = self._get_attach_points(info, size)

                icon_info.file_name = info.get_filename()
                icon_info.attach_x = attach_x
                icon_info.attach_y = attach_y

                del info
            else:
                logging.warning('No icon with the name %s was found in the '
                                'theme.', icon_name)

        return icon_info

    def _draw_badge(self, context, size, sensitive, widget):
        theme = Gtk.IconTheme.get_default()
        badge_info = theme.lookup_icon(self.badge_name, int(size), 0)
        if badge_info:
            badge_file_name = badge_info.get_filename()
            if badge_file_name.endswith('.svg'):
                handle = self._loader.load(badge_file_name, {}, self.cache)

                icon_width = handle.props.width
                icon_height = handle.props.height

                pixbuf = handle.get_pixbuf()
            else:
                pixbuf = GdkPixbuf.Pixbuf.new_from_file(badge_file_name)

                icon_width = pixbuf.get_width()
                icon_height = pixbuf.get_height()

            context.scale(float(size) / icon_width,
                          float(size) / icon_height)

            if not sensitive:
                pixbuf = self._get_insensitive_pixbuf(pixbuf, widget)
            Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0)
            context.paint()

    def _get_size(self, icon_width, icon_height, padding):
        if self.width is not None and self.height is not None:
            width = self.width + padding
            height = self.height + padding
        else:
            width = icon_width + padding
            height = icon_height + padding

        return width, height

    def _get_badge_info(self, icon_info, icon_width, icon_height):
        info = _BadgeInfo()
        if self.badge_name is None:
            return info

        info.size = int(_BADGE_SIZE * icon_width)
        info.attach_x = int(icon_info.attach_x * icon_width - info.size / 2)
        info.attach_y = int(icon_info.attach_y * icon_height - info.size / 2)

        if info.attach_x < 0 or info.attach_y < 0:
            info.icon_padding = max(-info.attach_x, -info.attach_y)
        elif info.attach_x + info.size > icon_width or \
                info.attach_y + info.size > icon_height:
            x_padding = info.attach_x + info.size - icon_width
            y_padding = info.attach_y + info.size - icon_height
            info.icon_padding = max(x_padding, y_padding)

        return info

    def _get_xo_color(self):
        if self.stroke_color and self.fill_color:
            return XoColor('%s,%s' % (self.stroke_color, self.fill_color))
        else:
            return None

    def _set_xo_color(self, xo_color):
        if xo_color:
            self.stroke_color = xo_color.get_stroke_color()
            self.fill_color = xo_color.get_fill_color()
        else:
            self.stroke_color = None
            self.fill_color = None

    def _get_insensitive_pixbuf(self, pixbuf, widget):
        if not (widget and widget.get_style()):
            return pixbuf

        icon_source = Gtk.IconSource()
        # Special size meaning "don't touch"
        icon_source.set_size(-1)
        icon_source.set_pixbuf(pixbuf)
        icon_source.set_state(Gtk.StateType.INSENSITIVE)
        icon_source.set_direction_wildcarded(False)
        icon_source.set_size_wildcarded(False)

        widget_style = widget.get_style()
        pixbuf = widget_style.render_icon(
            icon_source, widget.get_direction(),
            Gtk.StateType.INSENSITIVE, -1, widget,
            'sugar-icon')

        return pixbuf

    def get_surface(self, sensitive=True, widget=None):
        cache_key = self._get_cache_key(sensitive)
        if cache_key in self._surface_cache:
            return self._surface_cache[cache_key]

        # We run two attempts at finding the icon. First, we try the icon
        # requested by the user. If that fails, we fall back on
        # document-generic. If that doesn't work out, bail.
        icon_width = None
        for (file_name, icon_name) in ((self.file_name, self.icon_name),
                                      (None, 'document-generic')):
            icon_info = self._get_icon_info(file_name, icon_name)
            if icon_info.file_name is None:
                return None

            is_svg = icon_info.file_name.endswith('.svg')

            if is_svg:
                try:
                    handle = self._load_svg(icon_info.file_name)
                    icon_width = handle.props.width
                    icon_height = handle.props.height
                    break
                except IOError:
                    pass
            else:
                try:
                    path = icon_info.file_name
                    pixbuf = GdkPixbuf.Pixbuf.new_from_file(path)
                    icon_width = pixbuf.get_width()
                    icon_height = pixbuf.get_height()
                    break
                except GObject.GError:
                    pass

        if icon_width is None:
            # Neither attempt found an icon for us to use
            return None

        badge_info = self._get_badge_info(icon_info, icon_width, icon_height)

        padding = badge_info.icon_padding
        width, height = self._get_size(icon_width, icon_height, padding)
        if self.background_color is None:
            surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(width),
                                         int(height))
            context = cairo.Context(surface)
        else:
            surface = cairo.ImageSurface(cairo.FORMAT_RGB24, int(width),
                                         int(height))
            context = cairo.Context(surface)
            context.set_source_color(self.background_color)
            context.paint()

        context.scale(float(width) / (icon_width + padding * 2),
                      float(height) / (icon_height + padding * 2))
        context.save()

        context.translate(padding, padding)
        if is_svg:
            if sensitive:
                handle.render_cairo(context)
            else:
                pixbuf = handle.get_pixbuf()
                pixbuf = self._get_insensitive_pixbuf(pixbuf, widget)

                Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0)
                context.paint()
        else:
            if not sensitive:
                pixbuf = self._get_insensitive_pixbuf(pixbuf, widget)
            Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0)
            context.paint()

        if self.badge_name:
            context.restore()
            context.translate(badge_info.attach_x, badge_info.attach_y)
            self._draw_badge(context, badge_info.size, sensitive, widget)

        self._surface_cache[cache_key] = surface

        return surface

    xo_color = property(_get_xo_color, _set_xo_color)
Ejemplo n.º 2
0
        self.props['front_text']['card_text'] = newtext
        self._cached_surface[True] = None
        self.queue_draw()

    def get_text(self):
        return self.props['front_text'].get('card_text', '')

    def change_speak(self, value):
        self.props['front_text']['speak'] = value

    def get_speak(self):
        return self.props['front_text'].get('speak')

    def draw_round_rect(self, context, x, y, w, h, r):
        context.move_to(x + r, y)
        context.line_to(x + w - r, y)
        context.curve_to(x + w, y, x + w, y, x + w, y + r)
        context.line_to(x + w, y + h - r)
        context.curve_to(x + w, y + h, x + w, y + h, x + w - r, y + h)
        context.line_to(x + r, y + h)
        context.curve_to(x, y + h, x, y + h, x, y + h - r)
        context.line_to(x, y + r)
        context.curve_to(x, y, x, y, x + r, y)


def PIXELS_PANGO(x):
    return x * 1000


_text_layout_cache = LRU(50)
Ejemplo n.º 3
0
 def __init__(self):
     self._cache = LRU(50)