def snapshot(self, snapshot: Gtk.Snapshot, bounds: Graphene.Rect, fgcolor: Gdk.RGBA, scale: float): # Drawing cached textures is in large scale faster than rendering # the svg over and over if self._cached_texture_scale < scale: scaled_w = int(WIDTH * scale) scaled_h = int(HEIGHT * scale) cr = cairo.ImageSurface( cairo.Format.ARGB32, scaled_w, scaled_h) ctx = cairo.Context(cr) rect = Rsvg.Rectangle() rect.x = 0 rect.y = 0 rect.width = scaled_w rect.height = scaled_h self._handle.render_document(ctx, rect) pixbuf = Gdk.pixbuf_get_from_surface(cr, 0, 0, scaled_w, scaled_h) self._cached_texture = Gdk.Texture.new_for_pixbuf(pixbuf) self._cached_texture_scale = scale snapshot.append_texture(self._cached_texture, bounds)
def append_to_snapshot(cmd: lib.Command, snapshot: Gtk.Snapshot, x, y, widget: Gtk.Widget, colors: lib.icon.CommandColorScheme, code: lib.CodeBuffer = None) -> int: defin: lib.CommandDefinition = cmd.definition bg, fg = colors[defin.color] # Extend the width of the icon for icons with data data_layout, icon_width = _create_data_layout(cmd, widget) area = Graphene.Rect.init( Graphene.Rect(), x, y, icon_width * icon.WIDTH, icon.HEIGHT) # Background snapshot.append_color(bg, area) # Foreground icon if not (defin.data_only and cmd.data): if icon_width > 1: icon_area = Graphene.Rect.init( Graphene.Rect(), x + (icon_width - 1) * icon.WIDTH / 2, y, icon.WIDTH, icon.HEIGHT) else: icon_area = area defin.icon.snapshot(snapshot, icon_area, fg, widget.get_scale_factor()) # Data if cmd.data and defin.show_data: if defin.id == 'img' and code is not None: texture = code.get_command_data_preview(cmd) if texture is not None: t_scale = max( 1, texture.get_width() / area.get_width(), texture.get_height() / area.get_height()) ta_width = texture.get_width() / t_scale ta_height = texture.get_height() / t_scale t_area = Graphene.Rect.init( Graphene.Rect(), area.get_x() + area.get_width() / 2 - ta_width / 2, area.get_y() + area.get_height() / 2 - ta_height / 2, ta_width, ta_height) snapshot.append_texture(texture, t_area) if defin.id == 'color': data_color = utils.rgba(f'rgb({cmd.data})') layout = widget.create_pango_layout('⬤') _append_layout( snapshot, layout, icon.FONT_NORMAL, data_color, area) if data_layout: _append_layout( snapshot, data_layout, None, fg, area, 0 if defin.data_only else 5) return icon_width
def do_snapshot(self, snapshot: Gtk.Snapshot): if not self._colors: return # Scroll tx = -int(self.props.hadjustment.props.value) ty = -int(self.props.vadjustment.props.value) area = Graphene.Rect().init(0, 0, self.get_width(), self.get_height()) snapshot.append_color(self._colors[icon.CommandColor.INDENTATION][0], area) if not self._codebuffer: return # Content snapshot.push_clip(area) end_x = math.ceil( (self.props.hadjustment.props.value + self.get_width()) / icon.WIDTH) start_y = int(self.props.vadjustment.props.value / icon.HEIGHT) end_y = math.ceil( (self.props.vadjustment.props.value + self.get_height()) / icon.HEIGHT) icon.append_block_to_snapshot(self._codebuffer.lines, snapshot, tx, ty, self, self._colors, self._codebuffer, end_x, start_y, end_y) # Selection if self.props.selection: start_y = self.props.selection.start_y end_y = self.props.selection.end_y for y in range(start_y, end_y + 1): start_x = (0 if y > start_y else self._line_x_to_render_x( self.props.selection.start_x, y)) end_x = self._line_x_to_render_x( len(self._codebuffer.lines[y]) - 1 if y < end_y else self.props.selection.end_x, y, True) selection_rect = Graphene.Rect().init( tx + start_x * icon.WIDTH, ty + y * icon.HEIGHT, (end_x - start_x + 1) * icon.WIDTH, icon.HEIGHT) snapshot.append_color( self._colors[icon.CommandColor.OVERLAY_SELECTION][0], selection_rect) snapshot.pop() snapshot.render_focus(self.get_style_context(), 0, 0, self.get_width(), self.get_height())
def snapshot(self, snapshot: Gtk.Snapshot, bounds: Graphene.Rect, fgcolor: Gdk.RGBA, scale: float): if (self._cached_texture_scale < scale or not self._fgcolor.equal(fgcolor)): PangoCairo.context_set_resolution( _text_texture_pango_ctx, 96 * scale) layout = Pango.Layout.new(_text_texture_pango_ctx) layout.set_text(self._text) layout.set_font_description(FONT_NORMAL) layout_width, layout_height = layout.get_pixel_size() scaled_w = int(WIDTH * scale) scaled_h = int(HEIGHT * scale) cr = cairo.ImageSurface( cairo.Format.ARGB32, scaled_w, scaled_h) ctx = cairo.Context(cr) Gdk.cairo_set_source_rgba(ctx, fgcolor) x = int(scaled_w / 2 - layout_width / 2) y = int(scaled_h / 2 - layout_height / 2) ctx.move_to(x, y) PangoCairo.show_layout(ctx, layout) pixbuf = Gdk.pixbuf_get_from_surface( cr, 0, 0, scaled_w, scaled_h) del self._cached_texture self._cached_texture = Gdk.Texture.new_for_pixbuf(pixbuf) self._cached_texture_scale = scale self._fgcolor = fgcolor snapshot.append_texture(self._cached_texture, bounds)
def append_block_to_snapshot(commands: lib.CodePiece, snapshot: Gtk.Snapshot, tx: int, ty: int, widget: Gtk.Widget, colors: lib.icon.CommandColorScheme, code: lib.CodeBuffer = None, end_x=None, start_y=0, end_y=None) -> tuple[int, int]: width = 0 height = 0 end_y = end_y if end_y else len(commands) for y, line in enumerate(commands[start_y:end_y], start_y): height += 1 render_x = 0 comment_overlay = False # Darken icons that follows blank comment (#) for command in line: xp = tx + render_x * icon.WIDTH yp = ty + y * icon.HEIGHT render_x += append_to_snapshot( command, snapshot, xp, yp, widget, colors, code) if comment_overlay: ovrly = Graphene.Rect.init( Graphene.Rect(), xp, yp, tx + render_x * icon.WIDTH, yp + icon.HEIGHT) snapshot.append_color( colors[icon.CommandColor.OVERLAY_COMMENT][0], ovrly) if command.definition.id == '#' and not command.data: comment_overlay = True if render_x > width: width = render_x if end_x is not None and render_x >= end_x: break return (width * icon.WIDTH, height * icon.HEIGHT)
def _append_layout(snapshot: Gtk.Snapshot, layout: Pango.Layout, font, color: Gdk.RGBA, area: Graphene.Rect, y=0): if font: layout.set_font_description(font) layout.set_alignment(Pango.Alignment.CENTER) layout.set_width(area.size.width * Pango.SCALE) x = area.get_x() y = (area.get_y() + y + area.size.height / 2 - layout.get_pixel_size()[1] / 2) translate_required = x != 0 or y != 0 if translate_required: snapshot.save() snapshot.translate(Graphene.Point.init(Graphene.Point(), x, y)) snapshot.append_layout(layout, color) if translate_required: snapshot.restore()
def do_snapshot(self, snapshot: Gtk.Snapshot): # Scroll tx = -int(self.props.hadjustment.props.value) ty = -int(self.props.vadjustment.props.value) if self.scenebuffer is None or self.scenebuffer.scene_name is None: snapshot.render_background(self.get_style_context(), 0, 0, self.get_width(), self.get_height()) return area = Graphene.Rect().init(0, 0, self.get_width(), self.get_height()) snapshot.append_color(self.BACKGROUND_COLOR, area) snapshot.push_clip(area) # Background scene_area = Graphene.Rect().init(tx, ty, self.scenebuffer.props.scene_width, self.scenebuffer.props.scene_height) snapshot.append_color(self.SCENE_COLOR, scene_area) # Sprites for s in self.scenebuffer.scene_sprites: sprite_area, texture = self.get_sprite_info(s) if texture is not None: snapshot.append_texture(texture, sprite_area) else: snapshot.append_color(self.MISSING_TEXTURE_COLOR, sprite_area) # Selection if self.props.selection is not None: selection_area = self.get_sprite_info(self.props.selection)[0] snapshot.append_color(self.SELECTION_COLOR, selection_area) snapshot.pop() snapshot.render_focus(self.get_style_context(), 0, 0, self.get_width(), self.get_height())