def draw_circle(context: cairo.Context, circle: symbols.Circle) -> None: """draw a circle""" context.set_line_width(circle.thickness) _set_color(context, circle.color) # TODO: it's still a bit unclear whether I should use arc or arc_negative # to match opencv behavior if circle.start_angle > circle.end_angle: context.arc_negative(circle.center[0], circle.center[1], circle.radius, circle.start_angle, circle.end_angle) else: context.arc(circle.center[0], circle.center[1], circle.radius, circle.start_angle, circle.end_angle) context.stroke()
def draw_star_band( ctx: cairo.Context, rng: Generator, pos_x: float, pos_y: float, radius_outer: float, radius_inner: float, ): band_center = (radius_outer + radius_inner) / 2 star_size = 0.2 * (radius_outer - radius_inner) n_stars = rng.integers(20, 50) ctx.arc(pos_x, pos_y, radius_outer, 0, tau) ctx.arc_negative(pos_x, pos_y, radius_inner, 0, -tau) ctx.stroke_preserve() ctx.clip_preserve() grad_offset_x = rng.uniform(radius_inner / 3.0, radius_inner) grad_offset_y = rng.uniform(radius_inner / 3.0, radius_inner) grad = PointLinearGradient( [Color(0, 0, 0), Color(1, 1, 1, 0.0)], Pattern.PACKED) grad.fill( ctx, rng, pos_x - grad_offset_x, pos_y - grad_offset_y, pos_x + grad_offset_x, pos_y + grad_offset_y, ) for x, y in jitter_points( points_along_arc(pos_x, pos_y, band_center, 0, tau, n_stars), rng, star_size): draw_star(ctx, rng, x, y, star_size) ctx.reset_clip()
def draw(self, cr: cairo.Context) -> None: start_angle = self._start_angle delta_angle = self._delta_angle clockwise = self._clockwise arc_radius = self._arc_radius start_line_radius = self._start_line_radius end_line_radius = self._end_line_radius x = self._x y = self._y stroke_color = self._stroke_color stroke_width = self._stroke_width text_radius = self._text_radius font_size = self._font_size text_color = self._text_color scale_radii = self._scale_radii scale_text = self._scale_text scale_strokes = self._scale_strokes if not (math.isfinite(start_angle) and math.isfinite(delta_angle)): return end_angle = start_angle + delta_angle matrix = cr.get_matrix() if scale_radii: radius_scale = 1/(0.5 * (matrix.xx + matrix.yy)) else: radius_scale = 1.0 self._show_hand(cr, x, y, -start_angle, radius_scale*start_line_radius) self._show_hand(cr, x, y, -end_angle, radius_scale*end_line_radius) if clockwise: cr.arc(x, y, radius_scale*arc_radius, -start_angle, -end_angle) else: cr.arc_negative(x, y, radius_scale*arc_radius, -start_angle, -end_angle) cr.save() if scale_strokes: cr.identity_matrix() cr.set_source_rgba(*stroke_color) cr.set_line_width(stroke_width) cr.stroke() cr.restore() half_angle = (start_angle + end_angle) / 2 cr.move_to(x, y) cr.rel_move_to( radius_scale*text_radius * math.cos(half_angle), radius_scale*text_radius * -math.sin(half_angle), ) cr.save() cr.set_source_rgba(*text_color) cr.set_font_size(font_size) if scale_text: cr.identity_matrix() text = '{:.1f}°'.format(math.degrees(math.fabs(delta_angle))) text_extents = cr.text_extents(text) cr.rel_move_to(-text_extents.x_bearing, -text_extents.y_bearing) cr.rel_move_to(-text_extents.width/2, -text_extents.height/2) cr.show_text(text) cr.fill() cr.restore()
def draw_with_hint(self, ctx: cairo.Context, x, y, layout, hint=''): if self.is_roomazi(): hint = self.roomazi.hyphenize(hint) ctx.move_to(x, y) ctx.set_line_width(1) ctx.set_line_join(cairo.LineJoin.ROUND) scale = 0.4 orig_x = x orig_y = y h = Keyboard.L * scale r = Keyboard.R * scale s = Keyboard.S * scale shift = list() shift_left = False shift_right = False alt = list() index_raw = 0 fingers = list() for raw in layout: index_column = 0 for column in raw: if column[1] == '⇧': shift.append((x, y, column)) if column[1] == '⌥': alt.append((x, y, column)) w = column[0] * scale color = self.get_key_color(index_column) if index_raw <= 0 or 4 <= index_raw: color = (0x99, 0x99, 0x99) ctx.set_source_rgb(*[c / 255 for c in color]) if self._is_uk_enter(column): self.uk_enter(ctx, x, y, w, h, s, r) else: self.round_rect(ctx, x + s, y + s, w - 2 * s, h - 2 * s, r) ctx.stroke() for c in hint: if c in column[1]: if index_raw < 4: fingers.append(index_column) if c == '\u3000': c = "空白" self._draw_key(ctx, x, y, w, h, s, r, c) elif c in column[2]: if index_raw < 4: fingers.append(index_column) self._draw_key(ctx, x, y, w, h, s, r, c) if index_column <= 5: shift_right = True else: shift_left = True x += w index_column += 1 index_raw += 1 x = orig_x y += h if shift_right: if 2 <= len(shift): self._draw_key(ctx, shift[1][0], shift[1][1], shift[1][2][0] * scale, h, s, r, 'シフト') else: self._draw_key(ctx, shift[0][0], shift[0][1], shift[0][2][0] * scale, h, s, r, 'シフト') if shift_left: self._draw_key(ctx, shift[0][0], shift[0][1], shift[0][2][0] * scale, h, s, r, 'シフト') # draw fingers if 5 in fingers: fingers.append(4) if 6 in fingers: fingers.append(7) metrics = [(1, 25, 8), (2, 45, 10), (3, 60, 10), (4, 45, 10), (7, 45, 10), (8, 60, 10), (9, 45, 10), (10, 25, 8)] x = orig_x - 100 y = orig_y + 4.5 * Keyboard.L * scale for m in metrics: r = m[2] ctx.set_source_rgb(*[c / 255 for c in (0x99, 0x99, 0x99)]) ctx.move_to(x, y) y -= m[1] ctx.line_to(x, y) ctx.arc(x + r, y, r, -180 * Keyboard.DEG, 0 * Keyboard.DEG) y += m[1] x += 2 * r ctx.line_to(x, y) ctx.stroke() if m[0] in fingers: color = self.get_key_color(m[0]) ctx.set_source_rgb(*[c / 255 for c in color]) ctx.arc(x - r, y - m[1] + 1, r * 0.8, 0 * Keyboard.DEG, 360 * Keyboard.DEG) ctx.fill() if m[0] != 4: x += 5 else: ctx.set_source_rgb(*[c / 255 for c in (0x99, 0x99, 0x99)]) # draw thumbs ctx.move_to(x, y) y += 30 ctx.line_to(x, y) x += 20 y -= 5 ctx.line_to(x, y) ctx.arc(x, y + r, r, -90 * Keyboard.DEG, 90 * Keyboard.DEG) y += 2 * r x -= 20 y += 5 ctx.line_to(x, y) x = orig_x + 1500 * scale + 7 y = orig_y + 4.5 * Keyboard.L * scale ctx.move_to(x, y) y += 30 ctx.line_to(x, y) x -= 20 y -= 5 ctx.line_to(x, y) ctx.arc_negative(x, y + r, r, -90 * Keyboard.DEG, 90 * Keyboard.DEG) y += 2 * r x += 20 y += 5 ctx.line_to(x, y) x = orig_x + 1500 * scale + 7 y = orig_y + 4.5 * Keyboard.L * scale