def on_draw(self, widget: Widget, context: cairo.Context): self.shape.draw_on_context(context) context.set_source_rgb(*global_constants.background) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() super().on_draw(widget, context)
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 on_draw(self, widget: Widget, context: cairo.Context): if not self.is_shape_set: self.layout(context) context.set_font_size(self.font_size) self.shape.draw_on_context(context) context.set_source_rgb(1, 1, 1) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() shape = self.shape label = self.label if len(label) > 0 and label[-1] == ' ': label += '.' xb, yb, w, h, xa, ya = context.text_extents(label) context.rectangle(shape.start.x + self.padding, shape.start.y, shape.width - self.padding, shape.height) context.clip() context.move_to(shape.start.x + (shape.width - self.padding - w)/2, shape.start.y + shape.height - self.padding) context.show_text(self.label)
def on_draw(self, widget: Widget, context: cairo.Context): context.save() self.shape.draw_on_context(context) context.set_source_rgb(1, 1, 1) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() context.restore() super().on_draw(widget, context)
def on_draw(self, widget: Widget, context: cairo.Context): context.save() context.set_source_rgb(*self.background_color) self.shape.draw_on_context(context) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.set_line_width(1) context.stroke() context.restore() super().on_draw(widget, context)
def on_draw(self, widget: Widget, context: cairo.Context): context.save() context.set_source_rgb(*self.background_color) self.shape.draw_on_context(context) context.fill_preserve() context.set_source_rgb(0,0,0) context.set_line_width(1) context.stroke() context.restore() super().on_draw(widget, context)
def _polygon(self, ctx: cairo.Context, points, color, outline=None): ctx.new_path() for point in points: ctx.line_to(*point) ctx.close_path() ctx.set_source_rgba(*color) if outline is not None: ctx.fill_preserve() ctx.set_source_rgba(*outline) ctx.set_line_width(1) ctx.stroke() else: ctx.fill()
def on_draw(self, widget: Widget, context: cairo.Context): super().on_draw(widget, context) if self.shape is not None: self.__wrapper_shape.draw_on_context(context) context.stroke() context.set_source_rgb(*global_constants.background) self.__outer_font_box.draw_on_context(context) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() context.move_to(self.__title_start_point.x, self.__title_start_point.y) context.set_font_size(self.font_size) context.show_text(self.title)
def func_wrapper(self, ctx: cairo.Context): func(self, ctx) if self.fill: ctx.set_source_rgb(*self.fill_color) if self.stroke: ctx.fill_preserve() else: ctx.fill() if self.stroke: ctx.set_line_width(self.stroke_width) ctx.set_source_rgb(*self.stroke_color) ctx.stroke()
def on_draw(self, widget: Widget, context: cairo.Context): shape = self.shape if shape is None: self.layout(context) shape = self.shape shape.draw_on_context(context) context.set_source_rgb(1, 1, 1) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() text = str(self.value) context.set_font_size(self.font_size) xb, yb, w, h, xa, ya = context.text_extents(text) context.move_to(shape.start.x + shape.width - w - self.padding, shape.start.y + shape.height - self.padding) context.show_text(text)
def on_draw(self, widget: Widget, context: cairo.Context): context.set_source_rgba(*self.background_color, self.background_alpha) self.__background_rectangle.draw_on_context(context) context.fill() context.set_font_size(self.font_size) self.__overlay_shape.draw_on_context(context) context.set_source_rgb(.3, .3, .3) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() context.move_to(self.__label_start.x, self.__label_start.y) context.show_text(self.label) super().on_draw(widget, context)
def on_draw(self, widget: Widget, context: cairo.Context): context.set_source_rgba(*self.background_color, self.background_alpha) self.__background_rectangle.draw_on_context(context) context.fill() context.set_font_size(self.font_size) self.__label_rectangle.draw_on_context(context) context.set_source_rgb(.3, .3, .3) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() rectangle = self.__label_rectangle start = rectangle.start context.move_to(start.x + self.padding, start.y + rectangle.height - self.padding/2) context.show_text(self.label)
def draw_points_labels(self, layout: Layout, cr: Context): for i, piece in enumerate(layout.points): if not piece.position: continue cr.save() cr.set_font_size(4) cr.translate( *piece.position.as_matrix().transform_point( 4, -10 if piece.direction == "left" else 10 ) ) cr.rectangle(-4, -4, 8, 8) cr.set_source_rgb(1, 1, 1) cr.fill_preserve() cr.set_source_rgb(0, 0, 0) cr.set_line_width(1) cr.stroke() cr.move_to(-2, 2) cr.show_text(str(i)) cr.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 draw_speed_limit(ctx: Context, surface_marking: SurfaceMarking, limit: int, start_zone: bool): """Draw a speed limit on the road. Add a cross if it is the end of a speed limit zone. Args: start_zone: Is this speed limit the start or end? """ ctx.translate(surface_marking.center.x, surface_marking.center.y ) # Translate to the center point of the surface marking ctx.rotate(surface_marking.orientation) ctx.translate(0, surface_marking.width / 2) # Translate to the middle # Position text and scale it ctx.rotate(-math.pi / 2) # rotate by 90deg ctx.scale(1, -1) # mirror y-axis to display text correctly ctx.scale(0.7245, 1.8506) # scale text to match rule book # Set font options ctx.select_font_face("OpenDinSchriftenEngshrift", cairo.FONT_SLANT_NORMAL) ctx.set_font_size(0.4) ctx.text_path(str(limit)) ctx.set_line_width(0.01) # Draw text _, _, text_width, text_height, _, _ = ctx.text_extents(str(limit)) ctx.fill_preserve() ctx.stroke() if not start_zone: # Draw cross padding = 0.025 ctx.set_line_width(0.03) ctx.move_to(-padding, padding) ctx.line_to(text_width + padding, -text_height - padding) ctx.stroke() ctx.move_to(-padding, -text_height - padding) ctx.line_to(text_width + padding, padding) ctx.stroke()
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 on_draw(self, widget: Widget, context: cairo.Context): if not self.is_shape_set: self.layout(context) context.set_font_size(self.font_size) self.shape.draw_on_context(context) context.set_source_rgb(1, 1, 1) context.fill_preserve() context.set_source_rgb(0, 0, 0) context.stroke() shape = self.shape label = self.label if len(label) > 0 and label[-1] == ' ': label += '.' xb, yb, w, h, xa, ya = context.text_extents(label) context.rectangle(shape.start.x + self.padding, shape.start.y, shape.width - self.padding, shape.height) context.clip() context.move_to(shape.start.x + (shape.width - self.padding - w) / 2, shape.start.y + shape.height - self.padding) context.show_text(self.label)
def hypotrochoid(self, cr: cairo.Context, r, R, d, theta=4 * np.pi, n=1000, c=(0, 4), alpha=1.0): # t = self.theta th = np.linspace(0, theta, n) for t in th: ph = ((R - r) * np.cos(t) + d * np.cos( (R - r) * t / r), (R - r) * np.sin(t) - d * np.sin( (R - r) * t / r)) if t == 0: cr.move_to(*ph) continue cr.line_to(*ph) cr.set_source_rgba(*colors[c[0]], alpha) cr.fill_preserve() cr.set_source_rgba(*colors[c[1]], alpha) cr.stroke()
def draw_moon( ctx: cairo.Context, pos_x: float, pos_y: float, radius: float, eclipse_pct: float = -1.0, ): moon_color = Color(0.9, 0.9, 0.9) ctx.arc(pos_x, pos_y, radius, 0, tau) ctx.stroke_preserve() with source( ctx, moon_color.to_pattern(), ): ctx.fill_preserve() ctx.clip() with source(ctx, Color(0.0, 0.0, 0.0).to_pattern()): eclipse_cx = pos_x + eclipse_pct * 2.0 * radius ctx.arc(eclipse_cx, pos_y, radius, 0, tau) ctx.fill() ctx.reset_clip()
class Canvas: def __init__(self, width: int, height: Optional[int] = None, *, normalise: bool = True): if height is None: height = width self._width = width self._height = height self._surface = ImageSurface(FORMAT_ARGB32, width, height) self._context = Context(self._surface) self._normalise = normalise if self._normalise: self.scale(self._width, self._height) @property def width(self) -> int: return self._width if not self._normalise else 1 @property def height(self) -> int: return self._height if not self._normalise else 1 # TODO depreciate @property def context(self) -> Context: # pragma: no cover return self._context def save(self) -> None: self._context.save() def restore(self) -> None: self._context.restore() # Transformation def rotate(self, angle: float) -> None: self._context.rotate(angle) def translate(self, x: float, y: float) -> None: self._context.translate(x, y) def scale(self, width: int, height: int) -> None: self._context.scale(width, height) def set_line_width(self, width: float) -> None: self._context.set_line_width(width) # Colour functionality def set_colour(self, colour: Colour) -> None: self._context.set_source_rgba(colour.red, colour.blue, colour.green, colour.alpha) def set_grey(self, colour_value: float, alpha: float = 1) -> None: colour = Colour(*(colour_value, ) * 3, alpha) self.set_colour(colour) def set_black(self) -> None: self.set_colour(BLACK) def set_white(self) -> None: self.set_colour(WHITE) def set_background(self, colour: Colour) -> None: self._context.rectangle(0, 0, self.width, self.height) self.set_colour(colour) self._context.fill() def set_line_cap(self, line_cap: LineCap) -> None: self._context.set_line_cap(line_cap.value) def set_line_join(self, line_join: LineJoin) -> None: self._context.set_line_join(line_join.value) def set_fill_rule(self, file_rule: FillRule) -> None: self._context.set_fill_rule(file_rule.value) # Render methods def fill(self, preserve: bool = False) -> None: if not preserve: self._context.fill() else: self._context.fill_preserve() def stroke(self, preserve: bool = False) -> None: if not preserve: self._context.stroke() else: self._context.stroke_preserve() def clip(self) -> None: self._context.clip() def _draw_path(self, path: Iterable[Point], close_path: bool) -> None: self._context.new_sub_path() for p in path: self._context.line_to(*p) if close_path: self._context.close_path() def draw_path(self, path: Iterable[PointType], close_path: bool = False) -> None: points = (p if isinstance(p, Point) else Point(*p) for p in path) self._draw_path(points, close_path) def draw_polygon(self, polygon: Polygon) -> None: self._draw_path(polygon.points, close_path=True) def draw_circle(self, circle: Circle, fill: bool = False, stroke: bool = True) -> None: self._context.new_sub_path() self._context.arc(*circle.centre, circle.radius, 0, 2 * pi) def write_to_png(self, file_name: str) -> None: self._surface.write_to_png(file_name)
def draw(self, ctx: cairo.Context, display_id: int): if self._boost: self._draw_boost(ctx, display_id) return # TODO: Support other display drawing. if display_id == 1 and self.enabled and self.debugger: if self._refresh_cache and not self._cache_redrawing_registered: self._cache_redrawing_registered = True threadsafe_emu_nonblocking_coro(self.debugger.emu_thread, self._update_cache()) if self._cache_running: # Draw for bbox in self._actor_bbox_cache: ctx.set_source_rgba(*COLOR_ACTOR) ctx.rectangle(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]) ctx.fill() for bbox in self._object_bbox_cache: ctx.set_source_rgba(*COLOR_OBJECTS) ctx.rectangle(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]) ctx.fill() for bbox in self._perf_bbox_cache: ctx.set_source_rgba(*COLOR_PERFORMER) ctx.rectangle(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]) ctx.fill() for bbox in self._event_bbox_cache: ctx.set_source_rgba(*COLOR_EVENTS) ctx.rectangle(bbox[0], bbox[1], bbox[2] - bbox[0], bbox[3] - bbox[1]) ctx.fill() if self.debugger.ground_engine_state: ground_state = self.debugger.ground_engine_state for ssb in ground_state.loaded_ssb_files: if ssb is not None: for mark in ground_state.ssb_file_manager.get( ssb.file_name ).position_markers: # type: ignore x_absolute = (mark.x_with_offset * TILE_SIZE ) - self._camera_pos_cache[0] y_absolute = (mark.y_with_offset * TILE_SIZE ) - self._camera_pos_cache[1] ctx.set_source_rgba(*COLOR_POS_MARKERS) ctx.rectangle( # They are centered. x_absolute - 4, y_absolute - 4, TILE_SIZE, TILE_SIZE) ctx.fill_preserve() ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(1) ctx.stroke() ctx.set_source_rgba(*COLOR_POS_MARKERS) ctx.move_to(x_absolute, y_absolute + 18) ctx.select_font_face("cairo:monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(8) ctx.text_path(mark.name) ctx.fill_preserve() ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(0.3) ctx.stroke()
def do_draw(self, context: cairo.Context) -> bool: if not self.adjustment or self.adjustment.get_upper() <= 0: return False height = self.get_allocated_height() width = self.get_allocated_width() if width <= 0 or height <= 0: return False base_bg, base_outline, handle_overdraw, handle_outline = ( self.get_map_base_colors()) x0 = self.overdraw_padding + 0.5 x1 = width - 2 * x0 height_scale = height * self.get_height_scale() if self._cached_map is None: surface = cairo.Surface.create_similar( context.get_target(), cairo.CONTENT_COLOR_ALPHA, width, height) cache_ctx = cairo.Context(surface) cache_ctx.set_line_width(1) cache_ctx.rectangle(x0, -0.5, x1, height_scale + 0.5) cache_ctx.set_source_rgba(*base_bg) cache_ctx.fill() # We get drawing coordinates by tag to minimise our source # colour setting, and make this loop slightly cleaner. tagged_diffs = self.chunk_coords_by_tag() for tag, diffs in tagged_diffs.items(): cache_ctx.set_source_rgba(*self.fill_colors[tag]) for y0, y1 in diffs: y0 = round(y0 * height_scale) + 0.5 y1 = round(y1 * height_scale) - 0.5 cache_ctx.rectangle(x0, y0, x1, y1 - y0) cache_ctx.fill_preserve() cache_ctx.set_source_rgba(*self.line_colors[tag]) cache_ctx.stroke() cache_ctx.rectangle(x0, -0.5, x1, height_scale + 0.5) cache_ctx.set_source_rgba(*base_outline) cache_ctx.stroke() self._cached_map = surface context.set_source_surface(self._cached_map, 0, 0) context.paint() # Draw our scroll position indicator context.set_line_width(1) context.set_source_rgba(*handle_overdraw) adj_y = self.adjustment.get_value() / self.adjustment.get_upper() adj_h = self.adjustment.get_page_size() / self.adjustment.get_upper() context.rectangle( x0 - self.overdraw_padding, round(height_scale * adj_y) + 0.5, x1 + 2 * self.overdraw_padding, round(height_scale * adj_h) - 1, ) context.fill_preserve() context.set_source_rgba(*handle_outline) context.stroke() return True
start, end = 0, 0 VERTS, CODES = [], [] # Iterate over each contour ctx.set_source_rgb(0.5,0.5,0.5) for i in range(len(outline.contours)): end = outline.contours[i] ctx.move_to(outline.points[start][0],outline.points[start][1]) for j in range(start, end+1): point = outline.points[j] ctx.line_to(point[0],point[1]) #back to origin ctx.line_to(outline.points[start][0], outline.points[start][1]) start = end+1 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()
def draw(self, wdg, ctx: cairo.Context): ctx.set_antialias(cairo.Antialias.NONE) ctx.scale(self.scale, self.scale) # Background if self.map_bg is not None: ctx.set_source_surface(self.map_bg, 0, 0) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() size_w, size_h = self.draw_area.get_size_request() size_w /= self.scale size_h /= self.scale # Black out bg a bit if not self._edit_pos_marks: ctx.set_source_rgba(0, 0, 0, 0.5) ctx.rectangle(0, 0, size_w, size_h) ctx.fill() # Tile Grid if self.draw_tile_grid: self.tile_grid_plugin.draw(ctx, size_w, size_h, self.mouse_x, self.mouse_y) # RENDER ENTITIES for layer_i, layer in enumerate(self.ssa.layer_list): if not self._is_layer_visible(layer_i): continue for actor in layer.actors: if not self._is_dragged(actor): bb = self.get_bb_actor(actor) if actor != self._selected: self._handle_layer_highlight(ctx, layer_i, *bb) self._draw_actor(ctx, actor, *bb) self._draw_hitbox_actor(ctx, actor) for obj in layer.objects: if not self._is_dragged(obj): bb = self.get_bb_object(obj) if obj != self._selected: self._handle_layer_highlight(ctx, layer_i, *bb) self._draw_object(ctx, obj, *bb) self._draw_hitbox_object(ctx, obj) for trigger in layer.events: if not self._is_dragged(trigger): bb = self.get_bb_trigger(trigger) if trigger != self._selected: self._handle_layer_highlight(ctx, layer_i, *bb) self._draw_trigger(ctx, trigger, *bb) for performer in layer.performers: if not self._is_dragged(performer): bb = self.get_bb_performer(performer) if performer != self._selected: self._handle_layer_highlight(ctx, layer_i, *bb) self._draw_hitbox_performer(ctx, performer) self._draw_performer(ctx, performer, *bb) # Black out bg a bit if self._edit_pos_marks: ctx.set_source_rgba(0, 0, 0, 0.5) ctx.rectangle(0, 0, size_w, size_h) ctx.fill() # RENDER POSITION MARKS for pos_mark in self.position_marks: bb = self.get_bb_pos_mark(pos_mark) self._draw_pos_mark(ctx, pos_mark, *bb) # Cursor / Active selected / Place mode self._handle_selection(ctx) x, y, w, h = self._handle_drag_and_place_modes() self.selection_plugin.set_size(w, h) self.selection_plugin.draw(ctx, size_w, size_h, x, y, ignore_obb=True) # Position ctx.scale(1 / self.scale, 1 / self.scale) ctx.select_font_face("monospace", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_source_rgb(*COLOR_WHITE) ctx.set_font_size(18) try: sw: Gtk.ScrolledWindow = self.draw_area.get_parent().get_parent( ).get_parent() s = sw.get_allocated_size() ctx.move_to(sw.get_hadjustment().get_value() + 30, s[0].height + sw.get_vadjustment().get_value() - 30) if self._selected__drag is not None: sx, sy = self.get_current_drag_entity_pos() else: sx, sy = self._snap_pos(self.mouse_x, self.mouse_y) sx /= BPC_TILE_DIM sy /= BPC_TILE_DIM ctx.text_path(f"X: {sx}, Y: {sy}") ctx.set_source_rgb(*COLOR_BLACK) ctx.set_line_width(0.3) ctx.set_source_rgb(*COLOR_WHITE) ctx.fill_preserve() ctx.stroke() except BaseException: pass return True
def draw_ticks(self, ctx: cairo.Context): # green = (0, 0.4, 0.2) # red = (0.55, 0.15, 0) green = (92 / 256, 214 / 256, 92 / 256) red = (1, 102 / 256, 102 / 256) bars = self.data ylim = (bars.low.min(), bars.high.max()) axis_x_0 = self.transform_plot @ np.array([-0.03, -0.06, 1]) axis_x_1 = self.transform_plot @ np.array([1.03, -0.06, 1]) axis_y_0 = self.transform_plot @ np.array([1.03, 1, 1]) ctx.set_line_width(self.grid_line_width) ctx.set_source_rgb(0, 0, 0) ctx.move_to(*axis_x_0[:2]) ctx.line_to(*axis_x_1[:2]) ctx.line_to(*axis_y_0[:2]) ctx.stroke() # Draw x ticks. ctx.set_font_size(self.tick_font_size) x_ticks = [ -0.5, ] + list(range(7)) x_tick_labels = [ '9:30', ] + list(f'{10+i}:00' for i in x_ticks[1:]) for idx, tick in enumerate(x_ticks): grid_0 = self.transform_plot @ np.array( [tick / 6.5 + 0.5 / 6.5, -0.06, 1]) grid_1 = self.transform_plot @ np.array( [tick / 6.5 + 0.5 / 6.5, -0.08, 1]) ctx.set_line_width(self.grid_line_width) ctx.move_to(*grid_0[:2]) ctx.line_to(*grid_1[:2]) ctx.set_source_rgb(0, 0, 0) ctx.stroke() ctx.set_source_rgb(0, 0, 0) tick_label = x_tick_labels[idx] (x, y, w, h, dx, dy) = ctx.text_extents(tick_label) ctx.move_to(grid_0[0] - w / 2, grid_0[1] + h / 2 + 0.9 * self.y_axis_space) ctx.show_text(tick_label) # Draw y ticks. y_tick_min = np.ceil(ylim[0]) + 0 y_tick_max = np.ceil(ylim[1]) num_y_ticks = 6 tick_int = int((y_tick_max - y_tick_min) / num_y_ticks) y_ticks = list(y_tick_min + i * tick_int for i in range(num_y_ticks)) y_tick_labels = list('{:.0f}.00'.format(i) for i in y_ticks) for idx in range(num_y_ticks): tick = y_ticks[idx] label = y_tick_labels[idx] grid_0 = self.transform_plot @ np.array( [1.03, (tick - ylim[0]) / (ylim[1] - ylim[0]), 1]) grid_1 = self.transform_plot @ np.array( [1.04, (tick - ylim[0]) / (ylim[1] - ylim[0]), 1]) ctx.move_to(*grid_0[:2]) ctx.line_to(*grid_1[:2]) ctx.stroke() (x, y, w, h, dx, dy) = ctx.text_extents(tick_label) ctx.move_to(grid_0[0] + w / 2 - 4, grid_0[1] + h / 2) ctx.show_text(label) ctx.set_font_size(self.axis_label_size) p = self.transform_plot @ np.array([1.22, -0.98, 0]) _text(ctx, 'Price', p[:2], -np.pi / 2) for idx in range(len(bars)): x0 = bars.t_open.iloc[idx] / ((16 - 9.5) * 60 * 60) x1 = bars.t_close.iloc[idx] / ((16 - 9.5) * 60 * 60) h = bars.high.iloc[idx] l = bars.low.iloc[idx] o = bars.open.iloc[idx] c = bars.close.iloc[idx] y0 = (l - ylim[0]) / (ylim[1] - ylim[0]) y1 = (h - ylim[0]) / (ylim[1] - ylim[0]) y2 = (o - ylim[0]) / (ylim[1] - ylim[0]) y3 = (c - ylim[0]) / (ylim[1] - ylim[0]) if y2 < y3: c = green else: c = red ctx.set_source_rgb(*c) y2, y3 = min(y2, y3), max(y2, y3) x_mid = 0.5 * (x0 + x1) line_0 = np.array([x_mid, y0, 1.0]) line_1 = np.array([x_mid, y1, 1.0]) line_0 = self.transform_plot @ line_0 line_1 = self.transform_plot @ line_1 ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(self.stick_line_width) ctx.move_to(*line_0[:2]) ctx.line_to(*line_1[:2]) ctx.stroke() w, h = x1 - x0, y3 - y2 ctx.set_source_rgb(*c) candle_0 = self.transform_plot @ np.array( [x_mid - 0.5 * self.candle_width_scale * w, y2, 1]) candle_1 = self.transform_plot @ np.array( [x_mid + 0.5 * self.candle_width_scale * w, y3, 1]) candle_sc = candle_1 - candle_0 ctx.rectangle(*candle_0[:2], *candle_sc[:2]) ctx.fill_preserve() ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(0.5) ctx.stroke()
def draw_action(self, ctx: cairo.Context, action: FixedFloorActionRule, sx: int, sy: int): if isinstance(action, EntityRule): assert self.parent.entity_rule_container is not None item, monster, tile, stats = self.parent.entity_rule_container.get( action.entity_rule_id) # Has trap? if tile.trap_id < 25: self._draw_trap(ctx, tile.trap_id, sx, sy) # Has item? if item.item_id > 0: try: self._draw_item(ctx, item.item_id, sx, sy) except IndexError: ctx.arc(sx + DPCI_TILE_DIM * DPC_TILING_DIM / 2, sy + DPCI_TILE_DIM * DPC_TILING_DIM / 2, DPCI_TILE_DIM * DPC_TILING_DIM / 2, 0, 2 * math.pi) ctx.set_source_rgba(*COLOR_ITEM) ctx.fill_preserve() ctx.set_source_rgba(*COLOR_OUTLINE) ctx.set_line_width(1) ctx.stroke() # Has Pokémon? if monster.md_idx > 0: self._draw_pokemon(ctx, monster.md_idx, action.direction, sx, sy) elif isinstance(action, TileRule): # Leader spawn tile if action.tr_type == TileRuleType.LEADER_SPAWN: self.parent.draw_placeholder(0, sx, sy, action.direction, ctx) # Attendant1 spawn tile if action.tr_type == TileRuleType.ATTENDANT1_SPAWN: self.parent.draw_placeholder(10, sx, sy, action.direction, ctx) # Attendant2 spawn tile if action.tr_type == TileRuleType.ATTENDANT2_SPAWN: self.parent.draw_placeholder(11, sx, sy, action.direction, ctx) # Attendant3 spawn tile if action.tr_type == TileRuleType.ATTENDANT3_SPAWN: self.parent.draw_placeholder(15, sx, sy, action.direction, ctx) # Key walls if action.tr_type == TileRuleType.FL_WA_ROOM_FLAG_0C or action.tr_type == TileRuleType.FL_WA_ROOM_FLAG_0D: sprite, x, y, w, h = self.parent.sprite_provider.get_for_trap( 31, lambda: GLib.idle_add(self.parent.redraw)) ctx.translate(sx, sy) ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.translate(-sx, -sy) # Warp zone if action.tr_type == TileRuleType.WARP_ZONE or action.tr_type == TileRuleType.WARP_ZONE_2: self._draw_stairs(ctx, sx, sy) elif isinstance(action, DirectRule): if action.tile.room_type == RoomType.KECLEON_SHOP: sprite, x, y, w, h = self.parent.sprite_provider.get_for_trap( 30, lambda: GLib.idle_add(self.parent.redraw)) ctx.translate(sx, sy) ctx.set_source_surface(sprite) ctx.get_source().set_filter(cairo.Filter.NEAREST) ctx.paint() ctx.translate(-sx, -sy) if action.tile.typ == TileType.PLAYER_SPAWN or action.tile.typ == TileType.ENEMY: self._draw_pokemon(ctx, action.itmtpmon_id, action.direction, sx, sy) if action.tile.typ == TileType.STAIRS: self._draw_stairs(ctx, sx, sy) if action.tile.typ == TileType.TRAP: self._draw_trap(ctx, action.itmtpmon_id, sx, sy) if action.tile.typ == TileType.BURIED_ITEM: self._draw_item(ctx, action.itmtpmon_id, sx, sy, buried=True) if action.tile.typ == TileType.ITEM: self._draw_item(ctx, action.itmtpmon_id, sx, sy) if action.tile.room_type == RoomType.MONSTER_HOUSE: ctx.set_source_rgba(230, 0, 0, 0.2) ctx.rectangle(sx, sy, DPCI_TILE_DIM * DPC_TILING_DIM, DPCI_TILE_DIM * DPC_TILING_DIM) ctx.fill()
def draw(widget: Gtk.Widget, cr: cairo.Context): if not world.map: return player_x = world.player.x player_y = world.player.y allocation = widget.get_allocation() tile_width = allocation.width / world.map_width tile_height = allocation.height / world.map_height # clear drawing cr.set_source_rgb(1, 1, 1) cr.paint() # draw shadow shadow_surface = cairo.ImageSurface(cairo.Format.ARGB32, allocation.width, allocation.height) scr = cairo.Context(shadow_surface) scr.set_line_width(1) scr.set_source_rgb(0, 0, 0) for y, row in enumerate(world.map): for x, tile in enumerate(row): if tile == "#": left = x * tile_width top = y * tile_height right = left + tile_width bottom = top + tile_height shadow_points = [] for dest_x, dest_y in itertools.product([left, right], [top, bottom]): other_x = {left: right, right: left}[dest_x] other_y = {top: bottom, bottom: top}[dest_y] if line_goes_through_border(player_x, player_y, dest_x, dest_y, other_x, top, bottom) \ or line_goes_through_border(player_y, player_x, dest_y, dest_x, other_y, left, right): continue shadow_points.append((dest_x, dest_y)) if len(shadow_points) == 3: for i in range(len(shadow_points)): if shadow_points[i] == (shadow_points[(i - 1) % 3][0], shadow_points[(i + 1) % 3][1]) \ or shadow_points[i] == (shadow_points[(i + 1) % 3][0], shadow_points[(i - 1) % 3][1]): del shadow_points[i] break elif len(shadow_points) == 4: continue for i, shadow_point in enumerate( extend_shadow_points(shadow_points, allocation)): if i == 0: scr.move_to(*shadow_point) else: scr.line_to(*shadow_point) scr.fill() cr.set_source_surface(shadow_surface) cr.mask(cairo.SolidPattern(0, 0, 0, .6)) cr.fill() # draw tiles cr.set_line_width(1) for y, row in enumerate(world.map): for x, tile in enumerate(row): if tile == "#": cr.set_source_rgb(.9, 0, 0) cr.rectangle(x * tile_width, y * tile_height, tile_width, tile_height) cr.fill_preserve() cr.set_source_rgba(0, 0, 0) cr.stroke() for player in world.players.values(): collides = False for y, row in enumerate(world.map): for x, tile in enumerate(row): if tile == "#": left = x * tile_width top = y * tile_height right = left + tile_width bottom = top + tile_height if collision_rect_line(Rectangle(left, right, top, bottom), player_x, player_y, player.x, player.y): collides = True break if collides: break if not collides: draw_player(cr, player) draw_player( cr, Player(player_x, player_y, world.player.rotation, world.player.health)) for bullet in world.bullets: draw_bullet(cr, bullet)
def do_draw(self, context: cairo.Context) -> bool: if not self.adjustment or self.adjustment.get_upper() <= 0: return False height = self.get_allocated_height() width = self.get_allocated_width() if width <= 0 or height <= 0: return False base_bg, base_outline, handle_overdraw, handle_outline = ( self.get_map_base_colors()) x0 = self.overdraw_padding + 0.5 x1 = width - 2 * x0 height_scale = height * self.get_height_scale() if self._cached_map is None: surface = cairo.Surface.create_similar(context.get_target(), cairo.CONTENT_COLOR_ALPHA, width, height) cache_ctx = cairo.Context(surface) cache_ctx.set_line_width(1) cache_ctx.rectangle(x0, -0.5, x1, height_scale + 0.5) cache_ctx.set_source_rgba(*base_bg) cache_ctx.fill() # We get drawing coordinates by tag to minimise our source # colour setting, and make this loop slightly cleaner. tagged_diffs = self.chunk_coords_by_tag() for tag, diffs in tagged_diffs.items(): cache_ctx.set_source_rgba(*self.fill_colors[tag]) for y0, y1 in diffs: y0 = round(y0 * height_scale) + 0.5 y1 = round(y1 * height_scale) - 0.5 cache_ctx.rectangle(x0, y0, x1, y1 - y0) cache_ctx.fill_preserve() cache_ctx.set_source_rgba(*self.line_colors[tag]) cache_ctx.stroke() cache_ctx.rectangle(x0, -0.5, x1, height_scale + 0.5) cache_ctx.set_source_rgba(*base_outline) cache_ctx.stroke() self._cached_map = surface context.set_source_surface(self._cached_map, 0, 0) context.paint() # Draw our scroll position indicator context.set_line_width(1) context.set_source_rgba(*handle_overdraw) adj_y = self.adjustment.get_value() / self.adjustment.get_upper() adj_h = self.adjustment.get_page_size() / self.adjustment.get_upper() context.rectangle( x0 - self.overdraw_padding, round(height_scale * adj_y) + 0.5, x1 + 2 * self.overdraw_padding, round(height_scale * adj_h) - 1, ) context.fill_preserve() context.set_source_rgba(*handle_outline) context.stroke() return True
def draw_volumes(self, ctx: cairo.Context): green = (92 / 256, 214 / 256, 92 / 256) red = (1, 102 / 256, 102 / 256) bars = self.data ylim = (bars.volume.min(), bars.volume.max()) axis_x_0 = self.transform_plot @ np.array([-0.03, -0.06, 1]) axis_x_1 = self.transform_plot @ np.array([1.03, -0.06, 1]) axis_y_0 = self.transform_plot @ np.array([1.03, 1, 1]) ctx.set_line_width(self.grid_line_width) ctx.set_source_rgb(0, 0, 0) ctx.move_to(*axis_x_0[:2]) ctx.line_to(*axis_x_1[:2]) ctx.line_to(*axis_y_0[:2]) ctx.stroke() ctx.set_font_size(self.tick_label_size) x_ticks = [ -0.5, ] + list(range(7)) x_tick_labels = [ '9:30', ] + list(f'{10+i}:00' for i in x_ticks[1:]) for idx, tick in enumerate(x_ticks): grid_0 = self.transform_plot @ np.array( [tick / 6.5 + 0.5 / 6.5, -0.06, 1]) grid_1 = self.transform_plot @ np.array( [tick / 6.5 + 0.5 / 6.5, -0.08, 1]) ctx.set_line_width(self.grid_line_width) ctx.move_to(*grid_0[:2]) ctx.line_to(*grid_1[:2]) ctx.set_source_rgb(0, 0, 0) ctx.stroke() ctx.set_source_rgb(0, 0, 0) tick_label = x_tick_labels[idx] (x, y, w, h, dx, dy) = ctx.text_extents(tick_label) ctx.move_to(grid_0[0] - w / 2, grid_0[1] + h / 2 + 0.9 * self.y_axis_space) ctx.show_text(tick_label) y_tick_min = np.ceil(ylim[0]) + 0 y_tick_max = np.ceil(ylim[1]) num_y_ticks = 6 tick_int = int((y_tick_max - y_tick_min) / num_y_ticks) y_ticks = list(y_tick_min + i * tick_int for i in range(num_y_ticks)) y_tick_labels = list('{:.0f}'.format(i) for i in y_ticks) for idx in range(num_y_ticks): tick = y_ticks[idx] label = y_tick_labels[idx] grid_0 = self.transform_plot @ np.array( [1.03, (tick - ylim[0]) / (ylim[1] - ylim[0]), 1]) grid_1 = self.transform_plot @ np.array( [1.04, (tick - ylim[0]) / (ylim[1] - ylim[0]), 1]) ctx.move_to(*grid_0[:2]) ctx.line_to(*grid_1[:2]) ctx.stroke() (x, y, w, h, dx, dy) = ctx.text_extents(tick_label) ctx.move_to(grid_0[0] + w / 2 - 4, grid_0[1] + h / 2) ctx.show_text(label) ctx.set_font_size(self.axis_label_size) p = self.transform_plot @ np.array([1.22, -0.5, 0]) p += np.array([0, self.rect_inner.position.y, 1]) _text(ctx, 'Volume', p[:2], -np.pi / 2) for idx in range(len(bars)): x0 = bars.t_open.iloc[idx] / ((16 - 9.5) * 60 * 60) x1 = bars.t_close.iloc[idx] / ((16 - 9.5) * 60 * 60) h = bars.high.iloc[idx] l = bars.low.iloc[idx] o = bars.open.iloc[idx] c = bars.close.iloc[idx] v = bars.volume.iloc[idx] y0 = 0 y1 = (v - ylim[0]) / (ylim[1] - ylim[0]) if o < c: c = green else: c = red ctx.set_source_rgb(*c) x_mid = 0.5 * (x0 + x1) w, h = x1 - x0, y1 - y0 ctx.set_source_rgb(*c) vol_bar_0 = self.transform_plot @ np.array( [x_mid - 0.5 * self.candle_width_scale * w, y0, 1]) vol_bar_1 = self.transform_plot @ np.array( [x_mid + 0.5 * self.candle_width_scale * w, y1, 1]) vol_bar_sc = vol_bar_1 - vol_bar_0 ctx.rectangle(*vol_bar_0[:2], *vol_bar_sc[:2]) ctx.fill_preserve() ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(0.5) ctx.stroke()