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)
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)
def __init__(self): self._cache = LRU(50)