def draw(self, wdg, ctx: cairo.Context, *args): if self.surface: ctx.fill() ctx.set_source_surface(self.surface, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() return True
def _draw_cell(self, context: cairo.Context, cell_value: CrucipixelCellValue, area: Rectangle): r, g, b = self.crucipixel_cell_value_to_color[cell_value] context.set_source_rgb(r, g, b) context.rectangle(area.start.x, area.start.y, area.width, area.height) context.fill() if not self.victory_screen and cell_value == CrucipixelCellValue.EMPTY: # draw the X r, g, b = self.crucipixel_cell_value_to_color[ CrucipixelCellValue.SELECTED ] context.set_source_rgb(r, g, b) context.set_line_cap(cairo.LINE_CAP_ROUND) delta_x = self.cell_width // 2.8 delta_y = self.cell_height // 2.8 context.move_to(area.start.x + area.width - delta_x, area.start.y + delta_y) context.line_to(area.start.x + delta_x, area.start.y + area.height - delta_y) context.move_to(area.start.x + area.width - delta_x, area.start.y + area.width - delta_y) context.line_to(area.start.x + delta_x, area.start.y + delta_y) context.stroke()
def render_picture(ctx: cairo.Context, picture: Picture) -> None: """ Render a picture at (0, 0) onto the supplied context (which should use mm units). """ ctx.save() # Load the picture image_surface = cairo.ImageSurface.create_for_data( picture.get_image_bytes(), cairo.FORMAT_ARGB32, picture.image_width, picture.image_height, ) # Scale and translate the picture according to the scale/crop mode in use. # # NB: Pattern matrix maps from page space to pixel space, hence the # apparently inverted transformation described here. ctx.set_source_surface(image_surface) pattern = ctx.get_source() m = pattern.get_matrix() m.scale(1 / picture.scale, 1 / picture.scale) m.translate(-picture.x_offset, -picture.y_offset) pattern.set_matrix(m) # Draw the picture (clipped) ctx.rectangle(0, 0, picture.width, picture.height) ctx.fill() ctx.restore()
def draw(self, cr: cairo.Context) -> None: xc = self._xc yc = self._yc radius = self._radius scale_radius = self._scale_radius fill_color = self._fill_color if radius == 0.0: return matrix = cr.get_matrix() dx = 1 / matrix.xx dy = 1 / matrix.yy if scale_radius: radius_scale = 1 / (0.5 * (matrix.xx + matrix.yy)) else: radius_scale = 1.0 cr.arc(xc, yc, radius_scale * radius, 0, 2 * math.pi) cr.set_source_rgba(*fill_color) cr.fill() self._last_drawn_region = circle_region( xc, yc, radius_scale * radius + max(dx, dy)) self._last_drawn_radius_scale = radius_scale
def draw_stats(self, context: cairo.Context): # Draw sunrise, sunset, AQI icon and values self.draw_icon(context, "rise-set-aqi", (450, 300)) self.draw_text( context, position=(505, 337), text=self.weather.sunrise().astimezone(self.timezone).strftime("%H:%M"), color=BLACK, size=32, ) self.draw_text( context, position=(505, 385), text=self.weather.sunset().astimezone(self.timezone).strftime("%H:%M"), color=BLACK, size=32, ) # Pick AQI text and color aqi = self.weather.aqi() if aqi < 50: color = GREEN elif aqi < 150: color = ORANGE else: color = RED text_width = self.draw_text(context, aqi, size=30, weight="bold", noop=True) self.draw_roundrect(context, 505, 402, text_width + 13, 36, 3) context.set_source_rgb(*color) context.fill() self.draw_text( context, position=(510, 430), text=aqi, color=WHITE, size=30, weight="bold" )
def fill( self, ctx: cairo.Context, rng: Generator, x1: float, y1: float, x2: float, y2: float, ): with source(ctx, self.stops[-1].to_pattern()): ctx.fill_preserve() # Orient the canvas so that our gradient goes straight in direction of +Y. gradient_angle = angle((x1, y1), (x2, y2)) - (pi / 2) with translation(ctx, x1, y1), rotation(ctx, gradient_angle), source( ctx, self.stops[0].to_pattern()): # We translated and rotated the canvas, so our gradient control # vector is now from (0, 0) straight up: grad_control_y = distance((x1, y1), (x2, y2)) # Get a bounding box of what needs to be filled: start_x, start_y, end_x, end_y = ctx.fill_extents() ctx.new_path() for cx, cy, cr in self.pattern.func( rng, (start_x, start_y), (end_x, end_y), (0, 0), (0, grad_control_y), self.dot_radius, ): ctx.arc(cx, cy, cr, 0, tau) ctx.fill()
def create_surface(self): bw, bh = self.size old_backing = self._backing #should we honour self.depth here? self._backing = None if bw==0 or bh==0: #this can happen during cleanup return None backing = ImageSurface(FORMAT_ARGB32, bw, bh) self._backing = backing cr = Context(backing) if self._alpha_enabled: cr.set_operator(OPERATOR_CLEAR) cr.set_source_rgba(1, 1, 1, 0) else: cr.set_operator(OPERATOR_SOURCE) cr.set_source_rgba(1, 1, 1, 1) cr.rectangle(0, 0, bw, bh) cr.fill() if COPY_OLD_BACKING and old_backing is not None: oldw, oldh = old_backing.get_width(), old_backing.get_height() sx, sy, dx, dy, w, h = self.gravity_copy_coords(oldw, oldh, bw, bh) cr.translate(dx-sx, dy-sy) cr.rectangle(sx, sy, w, h) cr.clip() cr.set_operator(OPERATOR_SOURCE) cr.set_source_surface(old_backing, 0, 0) cr.paint() backing.flush() return cr
def draw_base(self, cr: cairo.Context): cr.identity_matrix() cr.set_matrix(self.matrix) cr.rectangle(-1, -1, 2, 2) cr.set_source_rgb(*colors[0]) cr.fill() if self.gtk_mode: cr.rectangle(-1, .65, .15, .35) cr.set_source_rgb(*colors[1]) cr.fill() cr.set_source_rgb(*colors[1]) cr.set_line_width(9e-3) cr.arc(0, 0, self.radius, 0, 2 * PI) # cr.stroke() for theta in np.linspace(0, 2 * PI, self.radio_button + 1): cr.move_to(0, 0) x, y = self.radius * np.cos(theta), self.radius * np.sin(theta) cr.line_to(x, y) if (x, y) not in self.inter_sections: self.inter_sections.append((x, y)) cr.stroke()
def draw(self, wdg, ctx: cairo.Context, *args): if self.surface: ctx.fill() ctx.set_source_surface(self.surface, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() # Draw rectangles on the WTE image representing the selected WTU entries # Allows multiple selections active_rows: List[Gtk.TreePath] = self.builder.get_object( 'wtu_tree').get_selection().get_selected_rows()[ 1] # type: ignore store: Gtk.ListStore = self.builder.get_object( 'wtu_store') # type: ignore for x in active_rows: row = store[x.get_indices()[0]] ctx.set_line_width(4) ctx.set_source_rgba(1, 1, 1, 1) ctx.rectangle(int(row[0]), int(row[1]), int(row[2]), int(row[3])) ctx.stroke() ctx.set_line_width(2) ctx.set_source_rgba(0, 0, 0, 1) ctx.rectangle(int(row[0]), int(row[1]), int(row[2]), int(row[3])) ctx.stroke() return True
def draw_highlight_layer(self, layout: Layout, cr: Context): if isinstance(self.highlight_item, Piece): self.draw_piece(self.highlight_item, cr, self.highlight_drawing_options) if isinstance(self.selected_item, Piece): self.draw_piece(self.selected_item, cr, self.selection_drawing_options) elif isinstance(self.selected_item, Anchor) and self.selected_item.position: cr.arc( self.selected_item.position.x, self.selected_item.position.y, 3 if any( piece.placement and anchor_name == piece.anchor_names[0] for piece, anchor_name in self.selected_item.items() ) else 1, 0, math.tau, ) cr.set_source_rgb(0.2, 0.2, 1) cr.fill() elif ( isinstance(self.selected_item, TracksideItem) and self.selected_item.position ): self.draw_sensor( self.selected_item, layout, cr, self.selection_drawing_options )
def _highlight_border(self, context: cairo.Context, row: int, col: int): width = self._total_width height = self._total_height line_width = 3 row_rectangles = [ Rectangle(Point(1, row * self.cell_height - line_width / 2), width - 2, line_width), Rectangle(Point(1, (row + 1) * self.cell_height - line_width / 2), width - 2, line_width) ] col_rectangles = [ Rectangle(Point(col * self.cell_width - line_width / 2, 1), line_width, height - 2), Rectangle(Point((col + 1) * self.cell_width - line_width / 2, 1), line_width, height - 2) ] context.save() r, g, b = self.highlight_color context.set_source_rgba(r, g, b, .6) for row_rectangle in row_rectangles: context.rectangle(row_rectangle.start.x, row_rectangle.start.y, row_rectangle.width, row_rectangle.height) context.fill() for col_rectangle in col_rectangles: context.rectangle(col_rectangle.start.x, col_rectangle.start.y, col_rectangle.width, col_rectangle.height) context.fill() context.restore()
def draw(self, wdg, ctx: cairo.Context): ctx.set_antialias(cairo.Antialias.NONE) ctx.scale(self.scale, self.scale) # Background ctx.set_source_rgb(0, 0, 0) ctx.rectangle(0, 0, self.width, self.height) ctx.fill() matrix_x_flip = cairo.Matrix(-1, 0, 0, 1, BPC_TILE_DIM, 0) matrix_y_flip = cairo.Matrix(1, 0, 0, -1, 0, BPC_TILE_DIM) tiles_for_pals = self.animation_context.current() for i, mapping in enumerate(self.tile_mappings): tiles_for_frame = tiles_for_pals[mapping.pal_idx] tile_at_pos = mapping.idx if 0 < tile_at_pos < len(tiles_for_frame): tile = tiles_for_frame[tile_at_pos] if mapping.flip_x: ctx.transform(matrix_x_flip) if mapping.flip_y: ctx.transform(matrix_y_flip) ctx.set_source_surface(tile, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() if mapping.flip_x: ctx.transform(matrix_x_flip) if mapping.flip_y: ctx.transform(matrix_y_flip) if (i + 1) % self.tiling_width == 0: # Move to beginning of next line ctx.translate(-BPC_TILE_DIM * (self.tiling_width - 1), BPC_TILE_DIM) else: # Move to next tile in line ctx.translate(BPC_TILE_DIM, 0)
def draw(self, wdg, ctx: cairo.Context, *args): if self.surface: wdg.set_size_request(self.surface.get_width(), self.surface.get_height()) ctx.fill() ctx.set_source_surface(self.surface, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() entry_tree: Gtk.TreeView = self.builder.get_object('entry_tree') active_rows: List[Gtk.TreePath] = entry_tree.get_selection( ).get_selected_rows()[1] for x in active_rows: prop = self.entries[x.get_indices()[0]].get_properties() if self.font.get_entry_image_size() > 12: ctx.set_line_width(4) ctx.set_source_rgba(0, 0, 0, 1) ctx.rectangle((prop["char"]%16)*self.font.get_entry_image_size()*IMAGE_ZOOM, \ (prop["char"]//16)*self.font.get_entry_image_size()*IMAGE_ZOOM, prop["width"]*IMAGE_ZOOM, self.font.get_entry_image_size()*IMAGE_ZOOM) ctx.stroke() ctx.set_line_width(2) if self.font.get_entry_image_size() > 12: ctx.set_source_rgba(1, 1, 1, 1) else: ctx.set_source_rgba(1, 0, 0, 1) ctx.rectangle((prop["char"]%16)*self.font.get_entry_image_size()*IMAGE_ZOOM, \ (prop["char"]//16)*self.font.get_entry_image_size()*IMAGE_ZOOM, prop["width"]*IMAGE_ZOOM, self.font.get_entry_image_size()*IMAGE_ZOOM) ctx.stroke() return True
def selection_draw_callback(self, ctx: cairo.Context, x: int, y: int): if self.interaction_mode == DrawerInteraction.CHUNKS: # Draw a chunk chunks_at_frame = self.animation_context.current()[self.edited_layer] ctx.set_source_surface( chunks_at_frame[self.interaction_chunks_selected_id], x, y ) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() elif self.interaction_mode == DrawerInteraction.COL: # Draw collision if self.interaction_col_solid: ctx.set_source_rgba(1, 0, 0, 1) ctx.rectangle( x, y, BPC_TILE_DIM, BPC_TILE_DIM ) ctx.fill() elif self.interaction_mode == DrawerInteraction.DAT: # Draw data if self.interaction_dat_value > 0: ctx.select_font_face("monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(6) ctx.set_source_rgb(1, 1, 1) ctx.move_to(x, y + BPC_TILE_DIM - 2) ctx.show_text(f"{self.interaction_dat_value:02x}")
def on_draw(self, wd, cr: cairo.Context, sc=None, lw=None, al=None): # setup scale if sc is None: sc = self.sc lw = self.lw al = self.al cr.identity_matrix() cr.scale(self.width * sc, self.height * sc) tx = (sc - 1) / (sc * 2) cr.translate(-tx, 0) self.background(cr) # triangle p = [0.0, 1.0] for r0, r1 in self.reverse_line(): # iterate thought rows pc = p.copy() for n, _ in enumerate(r0): if n % 2: continue if (r0[n] and r1[n]) and (r0[n + 1] and r1[n]): self.draw_triag(cr, pc) pc[0] += 2 * self.dx p = [p[0] + self.dx, p[1] - self.dy] cr.set_line_width(lw) cr.set_source_rgb(0, 0, 0) cr.stroke_preserve() cr.set_source_rgba(*colors[4], al) cr.fill()
def draw(self, ctx: cairo.Context, relative_to=(0, 0)): x, y = self.pos - relative_to pat = self.color.to_pattern(x, y, self.size) with source(ctx, pat): ctx.arc(x, y, self.size, 0, math.tau) ctx.fill()
def draw_precip_curve( self, context: cairo.Context, points: List[Tuple[int, int]], bottom: int, color, curviness: float = 7, ): # Draw the top curves for i, point in enumerate(points): if i == 0: context.move_to(*point) else: last_point = points[i - 1] context.curve_to( last_point[0] + curviness, last_point[1], point[0] - curviness, point[1], point[0], point[1], ) # Draw the rest and fill context.line_to(points[-1][0], bottom) context.line_to(points[0][0], bottom) context.close_path() context.set_source_rgb(*color) context.fill()
def draw_pieces(self): if not self.num_pieces: # Nothing to draw. return if (self.resized() or self.pieces != self.prev_pieces or self.pieces_overlay is None): # Need to recreate the cache drawing self.pieces_overlay = ImageSurface(FORMAT_ARGB32, self.width, self.height) ctx = Context(self.pieces_overlay) if self.pieces: pieces = self.pieces elif self.num_pieces: # Completed torrents do not send any pieces so create list using 'completed' state. pieces = [COLOR_STATES.index('completed')] * self.num_pieces start_pos = 0 piece_width = self.width / len(pieces) pieces_colors = [[ color / 65535 for color in self.gtkui_config['pieces_color_%s' % state] ] for state in COLOR_STATES] for state in pieces: ctx.set_source_rgb(*pieces_colors[state]) ctx.rectangle(start_pos, 0, piece_width, self.height) ctx.fill() start_pos += piece_width self.cr.set_source_surface(self.pieces_overlay) self.cr.paint()
def cairo_paint_from_source(self, set_source_fn, source, x: int, y: int, iw: int, ih: int, width: int, height: int, options): """ must be called from UI thread """ backing = self._backing log("cairo_paint_surface%s backing=%s, paint box line width=%i", (set_source_fn, source, x, y, iw, ih, width, height, options), backing, self.paint_box_line_width) if not backing: return gc = Context(backing) if self.paint_box_line_width: gc.save() gc.rectangle(x, y, width, height) gc.clip() gc.set_operator(OPERATOR_CLEAR) gc.rectangle(x, y, width, height) gc.fill() gc.set_operator(OPERATOR_SOURCE) gc.translate(x, y) if iw != width or ih != height: gc.scale(width / iw, height / ih) gc.rectangle(0, 0, width, height) set_source_fn(gc, source, 0, 0) gc.paint() if self.paint_box_line_width: gc.restore() encoding = options.get("encoding") self.cairo_paint_box(gc, encoding, x, y, width, height)
def _draw(self, widget: Gtk.Widget, ctx: Context): height = widget.get_allocated_height() ctx.scale(20, height) ctx.rectangle(0, 0, 1, 1) set_rgb(ctx, self.color) ctx.fill()
def draw(self, wdg, ctx: cairo.Context, *args): if self.surface: wdg.set_size_request(self.surface.get_width(), self.surface.get_height()) ctx.fill() ctx.set_source_surface(self.surface, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() return True
def draw_dot(context: cairo.Context, dot: symbols.Dot) -> None: """draw a filled circle""" context.set_line_width(dot.thickness) _set_color(context, dot.color) context.arc(dot.center[0], dot.center[1], dot.radius, 0.0, 2.0 * np.pi) context.stroke_preserve() context.fill()
def on_draw(self, index: int, widget: Gtk.DrawingArea, ctx: cairo.Context): w16 = self._surfaces[index] ctx.set_source_rgb(0, 0, 0) ctx.rectangle(0, 0, *widget.get_size_request()) ctx.fill() ctx.set_source_surface(w16) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint()
def do_render(self, model: Dazzle.GraphModel, x_begin: int, x_end: int, y_begin: float, y_end: float, cairo_context: cairo.Context, area: cairo.RectangleInt) -> None: model_iter = Dazzle.GraphModelIter() cairo_context.save() if model.get_iter_first(model_iter): chunk = area.width / (model.props.max_samples - 1) / 2.0 last_x = self._calc_x(model_iter, x_begin, x_end, area.width) last_y = float(area.height) cairo_context.move_to(last_x, area.height) while Dazzle.GraphModel.iter_next(model_iter): x = self._calc_x(model_iter, x_begin, x_end, area.width) y = self._calc_y(model_iter, y_begin, y_end, area.height, self._column) cairo_context.curve_to(last_x + chunk, last_y, last_x + chunk, y, x, y) last_x = x last_y = y cairo_context.set_line_width(self._line_width) cairo_context.set_source_rgba(self._stacked_color_rgba.red, self._stacked_color_rgba.green, self._stacked_color_rgba.blue, self._stacked_color_rgba.alpha) cairo_context.rel_line_to(0, area.height) cairo_context.stroke_preserve() cairo_context.close_path() cairo_context.fill() if model.get_iter_first(model_iter): chunk = area.width / (model.props.max_samples - 1) / 2.0 last_x = self._calc_x(model_iter, x_begin, x_end, area.width) last_y = float(area.height) cairo_context.move_to(last_x, last_y) while Dazzle.GraphModel.iter_next(model_iter): x = self._calc_x(model_iter, x_begin, x_end, area.width) y = self._calc_y(model_iter, y_begin, y_end, area.height, self._column) cairo_context.curve_to(last_x + chunk, last_y, last_x + chunk, y, x, y) last_x = x last_y = y cairo_context.set_source_rgba(self._stroke_color_rgba.red, self._stroke_color_rgba.green, self._stroke_color_rgba.blue, self._stacked_color_rgba.alpha) cairo_context.stroke() cairo_context.restore()
def draw_trains(self, layout: Layout, cr: Context): for train in layout.trains.values(): car_start = train.position annotation = train.meta.get("annotation") for i, car in enumerate(train.cars): front_bogey_offset, rear_bogey_offset = car.bogey_offsets bogey_spacing = rear_bogey_offset - front_bogey_offset front_bogey_position = car_start - front_bogey_offset front_bogey_xy = self.transform_track_point(front_bogey_position) rear_bogey_position, rear_bogey_xy = self.point_back( front_bogey_position, bogey_spacing ) cr.save() cr.translate(front_bogey_xy[0], front_bogey_xy[1]) cr.rotate( math.pi + math.atan2( front_bogey_xy[1] - rear_bogey_xy[1], front_bogey_xy[0] - rear_bogey_xy[0], ) ) cr.set_source_rgb(*hex_to_rgb(train.meta.get("color", "#a0a0ff"))) if i == 0 and annotation: cr.move_to(0, -10) cr.set_font_size(5) cr.show_text(annotation) cr.set_line_width(4) cr.move_to(-front_bogey_offset, 0) cr.line_to(car.length - front_bogey_offset, 0) cr.stroke() cr.set_line_width(6) cr.move_to(1 - front_bogey_offset, 0) cr.line_to(car.length - front_bogey_offset - 1, 0) cr.stroke() if i == 0 and train.lights_on: cr.set_source_rgba(1, 1, 0.2, 0.5) for y in (-2.5, 2.5): cr.move_to(-front_bogey_offset - 1, y) cr.arc( -front_bogey_offset - 1, y, 10, 6 / 7 * math.pi, math.pi * 8 / 7, ) cr.close_path() cr.fill() cr.restore() car_start = rear_bogey_position - (car.length - rear_bogey_offset + 1)
def draw(self, wdg, ctx: cairo.Context, do_translates=True): ctx.set_antialias(cairo.Antialias.NONE) ctx.scale(self.scale, self.scale) chunk_width = self.tiling_width * DPCI_TILE_DIM chunk_height = self.tiling_height * DPCI_TILE_DIM # Background if not self.use_pink_bg: ctx.set_source_rgb(0, 0, 0) else: ctx.set_source_rgb(1.0, 0, 1.0) ctx.rectangle( 0, 0, self.width_in_chunks * self.tiling_width * DPCI_TILE_DIM, self.height_in_chunks * self.tiling_height * DPCI_TILE_DIM) ctx.fill() # Layers for chunks_at_frame in self.animation_context.current(): for i, chunk_at_pos in enumerate(self.mappings): if 0 < chunk_at_pos < len(chunks_at_frame): chunk = chunks_at_frame[chunk_at_pos] ctx.set_source_surface(chunk, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() if (i + 1) % self.width_in_chunks == 0: # Move to beginning of next line if do_translates: ctx.translate( -chunk_width * (self.width_in_chunks - 1), chunk_height) else: # Move to next tile in line if do_translates: ctx.translate(chunk_width, 0) # Move back to beginning if do_translates: ctx.translate(0, -chunk_height * self.height_in_chunks) break size_w, size_h = self.draw_area.get_size_request() size_w /= self.scale size_h /= self.scale # Selection self.selection_plugin.set_size(self.tiling_width * DPCI_TILE_DIM, self.tiling_height * DPCI_TILE_DIM) self.selection_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) # Tile Grid if self.draw_tile_grid: self.tile_grid_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) # Chunk Grid if self.draw_chunk_grid: self.chunk_grid_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) return True
def create_image(context: cairo.Context, cells: CellBlock, cell_sizes: Dict[CellBlock, float]) -> None: context.rectangle(0, 0, WIDTH, HEIGHT) context.set_source_rgb(1, 1, 1) context.fill() context.set_source_rgb(0, 0, 0) for (x, y), cell_state in cells.items(): context.arc(x * 16, y * 16, cell_sizes[cell_state], 0, 2 * pi) context.fill()
def draw(self, cr: Context, drawing_options: DrawingOptions): cr.set_source_rgb(*drawing_options.rail_color) cr.rectangle(-1, -1, 2, 2) cr.fill() cr.set_source_rgb( *(SENSOR_ACTIVATED if self.activated else SENSOR_NORMAL)) cr.arc(0, 0, 0.8, 0, math.tau) cr.fill()
def draw_squares(self, cr: cairo.Context, color=colors[2]): cr.set_line_width(self.lw) cr.set_source_rgba(*self.lc) nx, ny = self.normalize_coord(*np.where(self.M)) for x, y in zip(nx, ny): nx, ny = self.normalize_coord(x, y) cr.rectangle(x, y, self.norm_box_size[0], self.norm_box_size[1]) cr.stroke_preserve() cr.set_source_rgba(*color) cr.fill()
def draw_one_rect(ctx: cairo.Context, rect: PColoredRectangle) -> None: ctx.move_to(rect.x, rect.y) x2 = rect.x + rect.width y2 = rect.y + rect.height ctx.line_to(x2, rect.y) ctx.line_to(x2, y2) ctx.line_to(rect.x, y2) ctx.close_path() ctx.set_source_rgba(rect.r, rect.g, rect.b, rect.a) ctx.fill()
class Canvas: def __init__(self, width, height): self.xform = lambda x, y: (x, y) self.img = ImageSurface(FORMAT_RGB24, width, height) self.ctx = Context(self.img) self.ctx.move_to(0, 0) self.ctx.line_to(width, 0) self.ctx.line_to(width, height) self.ctx.line_to(0, height) self.ctx.line_to(0, 0) self.ctx.set_source_rgb(1, 1, 1) self.ctx.fill() self.width = width self.height = height def fit(self, left, top, right, bottom): xoff = left yoff = top xscale = self.width / float(right - left) yscale = self.height / float(bottom - top) if abs(xscale) > abs(yscale): xscale *= abs(yscale) / abs(xscale) elif abs(xscale) < abs(yscale): yscale *= abs(xscale) / abs(yscale) self.xform = lambda x, y: ((x - xoff) * xscale, (y - yoff) * yscale) def dot(self, x, y, size=4, fill=(.5, .5, .5)): x, y = self.xform(x, y) self.ctx.arc(x, y, size/2., 0, 2*pi) self.ctx.set_source_rgb(*fill) self.ctx.fill() def line(self, points, stroke=(.5, .5, .5), width=1): self.ctx.move_to(*self.xform(*points[0])) for (x, y) in points[1:]: self.ctx.line_to(*self.xform(x, y)) self.ctx.set_source_rgb(*stroke) self.ctx.set_line_cap(LINE_CAP_ROUND) self.ctx.set_line_width(width) self.ctx.stroke() def save(self, filename): self.img.write_to_png(filename)
def draw_alerts(self, context: cairo.Context): # Load weather alerts alerts = self.weather.active_alerts() for alert in alerts: alert["color"] = RED # Add holidays for holiday_date, holiday_name in holidays.items(): days_until = (holiday_date - datetime.date.today()).days if 0 <= days_until <= 14: alerts.append( { "text": holiday_name, "subtext": ( "in %i days" % days_until if days_until != 1 else "tomorrow" ), "color": BLUE, } ) # Add no alert pill if there weren't any if not alerts: alerts = [{"text": "No Alerts", "color": BLACK}] top = 265 left = 5 for alert in alerts: text = alert["text"].upper() text_width = self.draw_text( context, text, position=(0, 0), size=20, weight="bold", noop=True, ) self.draw_roundrect(context, left, top, text_width + 15, 30, 4) context.set_source_rgb(*alert["color"]) context.fill() left += self.draw_text( context, text, position=(left + 8, top + 23), size=20, color=WHITE, weight="bold", ) if alert.get("subtext"): subtext_width = self.draw_text( context, alert["subtext"], position=(left + 20, top + 26), size=15, color=BLACK, ) else: subtext_width = 0 left += 30 + subtext_width
def on_draw(self, widget: Widget, context: cairo.Context): self.guide_line.set_shape_from_context(context) shape = self.guide_line.shape self.guide_line.set_translate(shape.width + 10, shape.height + 10) context.save() context.set_source_rgb(1, 1, 1) if self.guide_line.orientation == Orientation.HORIZONTAL: context.rectangle(10, shape.height + 10, shape.width, 20) else: context.rectangle(shape.width + 10, 10, 20, shape.height) context.fill() context.restore() super().on_draw(widget, context)
def _highlight_border(self, context: cairo.Context, row: int, col: int): width = self._total_width height = self._total_height line_width = 3 row_rectangles = [ Rectangle( Point(1, row * self.cell_height - line_width / 2), width - 2, line_width ), Rectangle( Point(1, (row + 1) * self.cell_height - line_width / 2), width - 2, line_width ) ] col_rectangles = [ Rectangle( Point(col * self.cell_width - line_width / 2, 1), line_width, height - 2 ), Rectangle( Point((col + 1) * self.cell_width - line_width / 2, 1), line_width, height - 2 ) ] context.save() r, g, b = self.highlight_color context.set_source_rgba(r, g, b, .6) for row_rectangle in row_rectangles: context.rectangle(row_rectangle.start.x, row_rectangle.start.y, row_rectangle.width, row_rectangle.height) context.fill() for col_rectangle in col_rectangles: context.rectangle(col_rectangle.start.x, col_rectangle.start.y, col_rectangle.width, col_rectangle.height) context.fill() context.restore()
def on_draw(self, widget: Widget, context: cairo.Context): start_x, start_y = context.get_current_point() context.set_font_size(self.font_size) context.move_to(0, 0) if not self.is_shape_set: self.set_shape_from_context(context) shape = self.shape start = shape.start padding = self.padding h = shape.height - 2 * padding label = self.label context.set_source_rgb(*self.background_color) shape.draw_on_context(context) context.fill_preserve() context.set_line_width(1) context.set_source_rgb(*self.label_color) context.stroke() if self.disabled: context.set_source_rgba(1, 1, 1, .7) context.move_to(start.x + padding-1, start.y + padding + h+1) context.show_text(label) context.set_source_rgba(*self.label_color, .9) else: context.set_source_rgb(*self.label_color) context.move_to(start.x + padding, start.y + padding + h) context.show_text(label) if self.disabled: context.set_source_rgba(1, 1, 1, .7) context.move_to(0, 0) shape.draw_on_context(context) context.fill()
def renderText(self, surface, text, y_offset, size, shade, w=(2,3), wrap=True): if len(text) < 1: return def setdesc(l, size): l.set_font_description( FontDescription( self.font + " " + str(size))) origin = Context(surface) origin.translate(self.w * (w[1] - w[0]) / (w[1] * 2), y_offset) box = CairoContext(origin) # Start laying out text layout = box.create_layout() setdesc(layout, size) width = self.w * w[0] / w[1] if wrap: layout.set_width(width * pango.SCALE) else: layout.set_width(-1) layout.set_alignment(pango.ALIGN_CENTER) layout.set_text(text) # Resize text to make sure it doesn't exceed width. wi, n = layout.get_pixel_size() if wi > width: s = size * width / wi setdesc(layout, s) layout.set_width(width * pango.SCALE) # Draw a transparent pane behind the text origin.set_source_rgba(1, 1, 1, 0.7) origin.rectangle(*layout.get_pixel_extents()[1]) origin.fill() # Draw text origin.set_source_rgb(shade, shade, shade) box.update_layout(layout) box.show_layout(layout)
pen.y += face.glyph.advance.y L.flush() return L if __name__ == '__main__': from PIL import Image n_words = 200 H, W, dpi = 600, 800, 72.0 I = ImageSurface(FORMAT_A8, W, H) ctxI = Context(I) ctxI.rectangle(0,0,800,600) ctxI.set_source_rgba (0.9, 0.9, 0.9, 0) ctxI.fill() S = random.normal(0,1,n_words) S = (S-S.min())/(S.max()-S.min()) S = sort(1-sqrt(S))[::-1] sizes = (12 + S*48).astype(int).tolist() def spiral(): eccentricity = 1.5 radius = 8 step = 0.1 t = 0 while True: t += step yield eccentricity*radius*t*cos(t), radius*t*sin(t) drawn_regions = Region()
def _paint_panel(self, key, width, height, panel_h): self.db.IUD("update web_stat_panels set HEIGHT = %s where ID = %s" % (panel_h, key)) self.db.commit() color_x_line = (0.7, 0.7, 0.7) color_x_line_2 = (0.9, 0.9, 0.9) color_y_line = (0.9, 0.9, 0.9) color_y_line_date = (0.7, 0.7, 0.7) color_border = (0.5, 0.5, 0.5) left = 40 right = 10 bottom = 15 var_ids = "0" series = [0, 0, 0, 0] typ = 0 for row in self.db.select( "select SERIES_1, SERIES_2, SERIES_3, SERIES_4, TYP " " from web_stat_panels " " where ID = " + str(key) ): series = row var_ids = "%s, %s, %s, %s" % row[0:4] typ = row[4] width, height = int(width), int(height) if width <= 0: width = 300 if height <= 0: height = 150 interval = self.param("range") delta_x = 1 if interval == "-6 hour": delta_x = 6 * 3600 elif interval == "-12 hour": delta_x = 12 * 3600 elif interval == "-1 day": delta_x = 24 * 3600 elif interval == "-3 day": delta_x = 3 * 24 * 3600 elif interval == "-7 day": delta_x = 7 * 24 * 3600 elif interval == "-14 day": delta_x = 14 * 24 * 3600 elif interval == "-30 day": delta_x = 30 * 24 * 3600 elif interval == "-90 day": delta_x = 3 * 30 * 24 * 3600 elif interval == "-180 day": delta_x = 6 * 30 * 24 * 3600 elif interval == "-360 day": delta_x = 12 * 30 * 24 * 3600 min_x = int(self.param("start")) - delta_x // 2 max_x = min_x + delta_x min_x_q = min_x - delta_x # // 100 max_x_q = max_x + delta_x # // 100 max_y = -9999 min_y = 9999 # Делаем полную выборку данных. Выкидываем подозрительные точки и # собираем статистику. prev_vals = [-9999] * 4 chart_data = [[], [], [], []] zoom_step = delta_x / (width * 5) if zoom_step < 1 or typ != 0: zoom_step = 1 x_min_max_values = [] mi_x = max_x_q ma_x = min_x_q tt = -100 for row in self.db.select( "select UNIX_TIMESTAMP(CHANGE_DATE) D, MIN(VALUE) + (MAX(VALUE) - MIN(VALUE)) VALUE, VARIABLE_ID " " from core_variable_changes " " where VARIABLE_ID in (%s) " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " " group by 3, ROUND(UNIX_TIMESTAMP(CHANGE_DATE) / %s)" " order by 3, 1 " % (var_ids, min_x_q, max_x_q, zoom_step) ): ind = series.index(row[2]) chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) if tt == -100: tt = row[2] if tt != row[2]: v = [tt, mi_x, ma_x] x_min_max_values += [v] mi_x = max_x_q ma_x = min_x_q tt = row[2] if row[0] < mi_x: mi_x = row[0] if row[0] > ma_x: ma_x = row[0] if tt != -1: v = [tt, mi_x, ma_x] x_min_max_values += [v] # print(x_min_max_values) # print(series) """ for row in self.db.select("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)): """ """ try: self.db.IUD("set @rn := 0") sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "order by CHANGE_DATE " % (min_x_q, max_x_q)) for c in self.db.select("select count(*) c " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " % (min_x_q, max_x_q)): cou = c[0] ccc = 1000 * 4 if cou > ccc: sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, @rn := @rn + 1 rownum " " from core_variable_changes " " where VARIABLE_ID in (" + var_ids + ") " " and CHANGE_DATE >= FROM_UNIXTIME(%s) " " and CHANGE_DATE <= FROM_UNIXTIME(%s) " "having mod(rownum, %s) = 0 " "order by VARIABLE_ID, CHANGE_DATE " % (min_x_q, max_x_q, math.ceil(cou / ccc))) for row in self.db.select(sql): ind = series.index(row[2]) prev_vals[ind] = row[1] if abs(prev_vals[ind] - row[1]) < 10: chart_data[ind] += [row] if row[0] > min_x and row[0] < max_x: max_y = max(max_y, row[1]) min_y = min(min_y, row[1]) prev_vals[ind] = row[1] except: pass """ if min_y is None or max_y is None or min_y == 9999 or max_y == -9999 or min_y == max_y: max_y = 1 min_y = 0 min_y = math.floor(min_y) max_y = math.ceil(max_y) if typ == 2: if min_y < 0 and max_y < 0: max_y = 0 elif min_y > 0 and max_y > 0: min_y = 0 # Определяем цвета colors = [[1, 0, 0], [0, 0.65, 0.31], [0, 0, 1], [1, 0, 1]] off_y = (max_y - min_y) / 10 min_y -= off_y max_y += off_y try: kx = (max_x - min_x) / (width - left - right) ky = (max_y - min_y) / (height - bottom) if ky == 0: ky = 1 except: kx, ky = 1, 1 img = ImageSurface(FORMAT_ARGB32, width, height) ctx = Context(img) width -= right ctx.set_line_width(1) # Рисуем сетку ctx.set_font_size(12) try: b_w, b_h = ctx.text_extents("00-00-0000")[2:4] # Метки на оси Y count = math.ceil(max_y) - math.ceil(min_y) space_count = math.ceil(count / ((height - bottom) / (b_h * 1.5))) sc = 0 for i in range(math.ceil(min_y), math.ceil(max_y)): if sc == 0: y = height - bottom + (min_y - i) / ky ctx.set_source_rgb(*(color_x_line)) ctx.move_to(left, y) ctx.line_to(width, y) ctx.stroke() ctx.set_source_rgb(0, 0, 0) num = str(i) tw, th = ctx.text_extents(num)[2:4] ctx.move_to(left - 5 - tw, y + th // 2) ctx.show_text(num) sc = space_count sc -= 1 # Метки на оси Х x_step = 3600 if interval == "-6 hour" or interval == "-12 hour" or interval == "-1 day": # Дополнительно метки часов x_step = 3600 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step)): x = (i * x_step - min_x) / kx + left ctx.set_source_rgb(*(color_x_line_2)) ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() num = datetime.datetime.fromtimestamp(i * x_step).strftime("%H") tw, th = ctx.text_extents(num)[2:4] ctx.move_to(x + 2, height - bottom - 3) ctx.set_source_rgb(*(color_x_line)) ctx.show_text(num) x_step = 3600 * 24 space_count = 1 count = math.ceil(max_x / x_step) - math.ceil(min_x / x_step) try: if (width / count) < b_w: space_count = 2 except: pass sc = 0 tz = 3600 * 2 tx_prev = -100 for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step) + 1): if sc == 0: d_i = datetime.datetime.fromtimestamp(i * x_step) x = (i * x_step - min_x - tz) / kx + left ctx.set_source_rgb(0, 0, 0) num = d_i.strftime("%d-%m-%Y %H") x -= (int(d_i.strftime("%H")) * 3600 - tz) / kx tw, th = ctx.text_extents(num)[2:4] tx = x - tw // 2 ctx.move_to(tx, height - bottom + th + 5) if tx - tx_prev > tw: ctx.show_text(num) tx_prev = tx ctx.set_source_rgb(*(color_y_line_date)) else: ctx.set_source_rgb(*(color_y_line)) if x >= left and x < width: ctx.move_to(x, 0) ctx.line_to(x, height - bottom) ctx.stroke() sc = space_count sc -= 1 except Exception as e: pass # Рисуем верхний и правый бордер ctx.set_source_rgb(*color_border) ctx.move_to(left, 0) ctx.line_to(width, 0) ctx.line_to(width, height - bottom) ctx.stroke() # Рисуем сами графики ctx.rectangle(left, 0, width - left, height) ctx.clip() is_first = True currVarID = -1 prevX = -1 if typ == 0: # Линейная for ind in range(4): """ if len(chart_data[ind]) > 0: for i in range(len(chart_data[ind]) - 1): chart_data[ind][i] = list(chart_data[ind][i]) r1 = chart_data[ind][i] r2 = chart_data[ind][i + 1] chart_data[ind][i][0] += (r2[0] - r1[0]) / 2 chart_data[ind][i][1] += (r2[1] - r1[1]) / 2 """ ctx.set_source_rgb(*colors[ind]) is_first = True for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: ctx.move_to(x, y) else: if row[0] - prevX > 10000: ctx.move_to(x, y) else: ctx.line_to(x, y) prevX = row[0] is_first = False ctx.stroke() elif typ == 1: # Точечная for ind in range(4): if chart_data[ind]: ctx.set_source_rgb(*colors[ind]) for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 3, y - 3, 6, 6) ctx.fill() elif typ == 2: # Столбчатая cy = height - bottom - (-min_y) / ky for ind in range(4): for row in chart_data[ind]: if currVarID != row[2]: ctx.fill() for i in range(4): if series[i] == row[2]: ctx.set_source_rgb(*colors[i]) x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky ctx.rectangle(x - 5, y, 10, cy - y) currVarID = row[2] ctx.fill() else: # Линейчастая # one_vals = self._get_one_val(series, min_x_q, max_x_q) one_vals = self._get_one_val(series, x_min_max_values, min_x_q, max_x_q) for ind in range(4): if series[ind]: is_now = True for r in one_vals[ind]: if r[4] == 1: chart_data[ind].insert(0, r) else: chart_data[ind] += [r] is_now = False if is_now: if len(chart_data[ind]) > 0: r = list(chart_data[ind][len(chart_data[ind]) - 1]) r[0] = datetime.datetime.now().timestamp() chart_data[ind] += [r] color = colors[ind] color_fill = color.copy() color_fill += [0.3] is_first = True y0 = height - bottom + min_y / ky for row in chart_data[ind]: x = (row[0] - min_x) / kx + left y = height - bottom - (row[1] - min_y) / ky if is_first: is_first = False else: ctx.set_source_rgb(*color) ctx.move_to(prevX, prevY) ctx.line_to(x, prevY) ctx.line_to(x, y) ctx.stroke() ctx.set_source_rgba(*color_fill) rx, ry, rw, rh = prevX, y0, x - prevX, prevY - y0 ctx.rectangle(rx, ry, rw, rh) ctx.fill() prevX, prevY = x, y # Рисуем оси ctx.set_source_rgb(0, 0, 0) ctx.move_to(left, 0) ctx.line_to(left, height - bottom) ctx.line_to(width, height - bottom) ctx.stroke() # --------------------------- del ctx byt = BytesIO() img.write_to_png(byt) byt.seek(0) return byt.read()
def on_draw(self, widget: Widget, context: cairo.Context): self.min_size = 200, 150 super().on_draw(widget, context) context.save() context.set_font_size(self.font_size) if self._table_extents is None: self._update_table_extents(context) skip = max(self.skip, 0) how_many = self.how_many table_extents = self._table_extents title_extents = self._table_extents.title_extents expected_height = title_extents.total_height + self.margin entries = self.entries base = skip up_to = skip over = False while up_to < len(entries) and not over: expected_height += table_extents[up_to].total_height over = expected_height >= self._max_height if not over: up_to += 1 while base > 0 and not over: expected_height += table_extents[base-1].total_height over = expected_height >= self._max_height if not over: base -= 1 how_many = up_to - base skip = base self.base = base entries = self.entries[skip:skip + how_many] def table_extents_iterator(): return table_extents.iter_over( skip, how_many ) start_x, start_y = context.get_current_point() start_y += title_extents.total_height h = title_extents.total_height self.title_height = h for (index, cell), data in zip(enumerate(title_extents), self.title): context.save() offset = title_extents.get_cell_data_left(index) context.rectangle(start_x + offset, start_y - h, cell.width, 2*h) context.clip() context.move_to( start_x + offset, start_y ) context.show_text(data) context.restore() # start_y += self.margin curr_x, curr_y = start_x, start_y# + title_extents.total_height for line_index, (line_extent, entry) in enumerate(zip(table_extents_iterator(), entries)): h = line_extent.total_height curr_y += h if curr_y + self.margin >= self._max_height: break for (cell_index, cell), data in zip(enumerate(line_extent), entry): context.save() offset = line_extent.get_cell_data_left(cell_index) context.rectangle(curr_x + offset, curr_y - h, cell.width, 2*h) context.clip() context.move_to( curr_x + offset, curr_y ) context.show_text(data) context.restore() curr_x = start_x end_x = table_extents.entries_width curr_y = start_y + self.margin end_y = table_extents.get_height_up_to(skip, how_many) + start_y + self.margin + 1 self.table_height = end_y self.table_width = end_x for line in table_extents_iterator(): context.move_to(curr_x, curr_y) context.line_to(end_x, curr_y) context.stroke() curr_y += line.total_height context.move_to(curr_x, curr_y) context.line_to(end_x, curr_y) context.stroke() curr_x = start_x curr_y = start_y - 1 + self.margin if self._how_many > 0: line = table_extents[0] for cell in line: context.move_to(curr_x, curr_y) context.line_to(curr_x, end_y) context.stroke() curr_x += cell.total_width + 2 * self.margin context.move_to(curr_x, curr_y) context.line_to(curr_x, end_y) context.stroke() if self._to_highlight is not None: r, g, b = global_constants.highlight context.set_source_rgba(r, g, b, .6) index = self._to_highlight base = start_y + table_extents.get_height_up_to(skip, index) + self.margin h = table_extents.get_height_of(skip, how_many, index) context.rectangle(start_x, base, table_extents.entries_width, h) context.fill() context.restore() self._shown = how_many
ctx.fill_preserve() ctx.set_source_rgb(0,1,0) ctx.stroke() start, end = 0, 0 for i in range(len(outline.contours)): end = outline.contours[i] ctx.new_path() ctx.set_source_rgb(0,0,1) for j in range(start, end+1): if ( Curve_Tag[j] == FT_Curve_Tag_On ): point = outline.points[j] ctx.move_to(point[0],point[1]) ctx.arc(point[0], point[1], 40, 0, 2 * math.pi) ctx.fill() ctx.new_path() ctx.set_source_rgb(1,0,0) for j in range(start, end+1): if ( Curve_Tag[j] != FT_Curve_Tag_On ): point = outline.points[j] ctx.move_to(point[0],point[1]) ctx.arc(point[0], point[1], 10, 0, 2 * math.pi) ctx.fill() points = outline.points[start:end+1] points.append(points[0]) tags = outline.tags[start:end+1] tags.append(tags[0])