Exemple #1
0
    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 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()
Exemple #3
0
def draw_background(ctx: cairo.Context, width: int, height: int):
    # TODO: Add noise/cracks/stains
    bg_color = RadialGradient([Color(0.84, 0.81, 0.74), Color(0.55, 0.50, 0.36)])
    center_x = width / 2
    center_y = height / 2
    with source(ctx, bg_color.to_pattern(center_x, center_y, center_x)), operator(
        ctx, cairo.Operator.DARKEN
    ):
        ctx.paint()
 def triangle(self, color: Color):
     """
     Draws a single triangle with the point down.
     """
     with cairoctx.source(self.ctx, color.to_pattern()):
         self.ctx.rel_line_to(-self.scale / 2, -self.diag_offset)
         self.ctx.rel_line_to(self.scale, 0)
         self.ctx.rel_line_to(-self.scale / 2, self.diag_offset)
         self.ctx.fill()
Exemple #5
0
 def rectangle(self, color: Color):
     """
     Draws a single rectangle starting at the bottom left.
     """
     with cairoctx.source(self.ctx, color.to_pattern()):
         self.ctx.rel_line_to(0, -self.rect_height)
         self.ctx.rel_line_to(self.scale, 0)
         self.ctx.rel_line_to(0, -self.rect_height)
         self.ctx.rel_line_to(-self.scale, 0)
         self.ctx.fill()
    def draw(self, ctx: cairo.Context, eye_radius: float, relative_to=(0, 0)):
        pos = self.pos - relative_to

        top_intersection = pos + np.array([0, self.opening / 2])
        bottom_intersection = pos - np.array([0, self.opening / 2])
        right_point = pos + np.array([self.size, 0])
        left_point = pos - np.array([self.size, 0])

        center_1, rad_1 = circle_from_3_points(left_point, top_intersection,
                                               right_point)
        center_2, rad_2 = circle_from_3_points(left_point, bottom_intersection,
                                               right_point)

        # Eyelid 1:
        ctx.push_group()
        with source(ctx, self.color.to_pattern()):
            # Restrict drawing area to eyeball:
            ctx.arc(pos[0], pos[1], eye_radius + 1, 0, math.tau)
            ctx.clip()
            ctx.paint()
            # Sub circle 1:
            with operator(ctx, cairo.Operator.CLEAR):
                ctx.arc(center_1[0], center_1[1], rad_1, 0, math.tau)
                ctx.fill()
            ctx.reset_clip()
        with source(ctx, ctx.pop_group()):
            ctx.paint()

        # Eyelid 2:
        ctx.push_group()
        with source(ctx, self.color.to_pattern()):
            # Restrict drawing area to eyeball:
            ctx.arc(pos[0], pos[1], eye_radius + 1, 0, math.tau)
            ctx.clip()
            ctx.paint()
            # Sub circle 2:
            with operator(ctx, cairo.Operator.CLEAR):
                ctx.arc(center_2[0], center_2[1], rad_2, 0, math.tau)
                ctx.fill()
            ctx.reset_clip()
        with source(ctx, ctx.pop_group()):
            ctx.paint()
    def finalize(self, sim: Simulation):
        for id, p in self.trails.items():
            props = self.particle_props[id]

            if self.line_width is LineWidth.MASS:
                lw = log(props.mass) + 0.1
                self.ctx.set_line_width(lw)
            elif self.line_width is LineWidth.CHARGE:
                lw = log(abs(props.total_charge))
                self.ctx.set_line_width(lw)
            elif self.line_width is LineWidth.DEPTH:
                lw = 2.0 + 0.01 * props.position[2]
                self.ctx.set_line_width(lw)

            if self.color_scheme is ColorScheme.BW:
                color = Color(0.0, 0.0, 0.0)
            else:
                color = self.color_scheme.gen_color(self.rng, props)

            self.ctx.move_to(*p[0])
            for control_point, destination in zip(p[1::2], p[2::2]):
                self.ctx.curve_to(*control_point, *control_point, *destination)

            with cairoctx.source(self.ctx, color.to_pattern()):
                self.ctx.stroke()

        if self.color_scheme is ColorScheme.COMIC:
            # Overlay a lightening radial gradient to create a "bang".
            grad = RadialGradient((Color(1.0, 1.0, 1.0,
                                         0.9), Color(1.0, 1.0, 1.0, 0.0)))
            mid_x = self.width / 2.0
            mid_y = self.height / 2.0
            radius = min(self.width, self.height) / 4.0
            with cairoctx.operator(self.ctx,
                                   cairo.Operator.ATOP), cairoctx.source(
                                       self.ctx,
                                       grad.to_pattern(mid_x, mid_y, radius)):
                self.ctx.arc(mid_x, mid_y, radius, 0.0, pi * 2)
                self.ctx.fill()
    def draw(self, ctx: cairo.Context):
        with translation(ctx, self.pos[0], self.pos[1]):
            with rotation(ctx, self.rotation):
                with source(ctx, self.color.to_pattern()):
                    ctx.arc(0, 0, self.size, 0, math.tau)
                    ctx.fill()

                if self.iris:
                    self.iris.draw(ctx, relative_to=self.pos)

                self.pupil.draw(ctx, relative_to=self.pos)

                if self.eyelids:
                    self.eyelids.draw(ctx, self.size, relative_to=self.pos)
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()
    def add_grid(self, width: float, height: float, rows: int, cols: int):
        rowheight = height // rows
        colwidth = width // cols

        with cairoctx.source(self.ctx, Color(0.5, 0.5, 0.5).to_pattern()):
            for col in range(1, cols + 1):
                x = col * colwidth
                self.ctx.move_to(x, 0)
                self.ctx.line_to(x, height)
                self.ctx.stroke()

            for row in range(1, rows + 1):
                y = row * rowheight
                self.ctx.move_to(0, y)
                self.ctx.line_to(width, y)
                self.ctx.stroke()
Exemple #11
0
def draw_grid(ctx: cairo.Context, width: float, height: float, rows: int,
              cols: int):
    rowheight = height // rows
    colwidth = width // cols

    with cairoctx.source(ctx, Color(0.5, 0.5, 0.5).to_pattern()):
        for col in range(1, cols + 1):
            x = col * colwidth
            ctx.move_to(x, 0)
            ctx.line_to(x, height)
            ctx.stroke()

        for row in range(1, rows + 1):
            y = row * rowheight
            ctx.move_to(0, y)
            ctx.line_to(width, y)
            ctx.stroke()
Exemple #12
0
def draw_star(ctx: cairo.Context, rng: Generator, pos_x: float, pos_y: float,
              size: float):
    spikes = rng.integers(5, 8)
    outer_points = list(
        jitter_points(points_along_arc(pos_x, pos_y, size, 0, tau, spikes),
                      rng, 0.1 * size), )
    inner_offset = pi / spikes
    inner_points = list(
        jitter_points(
            points_along_arc(pos_x, pos_y, size / 2.0, inner_offset,
                             inner_offset + tau, spikes),
            rng,
            0.1 * size,
        ))

    ctx.move_to(*inner_points[-1])
    for (ax, ay), (bx, by) in zip(outer_points, inner_points):
        ctx.line_to(ax, ay)
        ctx.line_to(bx, by)
    ctx.stroke_preserve()
    with source(ctx, Color(1.0, 1.0, 1.0).to_pattern()):
        ctx.fill()
 def draw(self, ctx: cairo.Context):
     with source(ctx, self.color.to_pattern()):
         ctx.paint()