예제 #1
0
def draw_circular_roman(
    ctx: cairo.Context,
    rng: Generator,
    pos_x: float,
    pos_y: float,
    radius_outer: float,
    radius_inner: float,
):
    chunks = rng.integers(6, 16)
    _calendar_base(ctx, pos_x, pos_y, radius_outer, radius_inner, chunks)

    ctx.select_font_face("Noto Sans Symbols")
    font_size = 0.8 * (radius_outer - radius_inner)
    ctx.set_font_size(font_size)

    angle_offset = pi / chunks
    for i, (x, y) in enumerate(
            points_along_arc(
                pos_x,
                pos_y,
                (radius_inner + radius_outer) / 2.0,
                angle_offset,
                angle_offset + tau,
                chunks,
            ),
            1,
    ):
        with translation(ctx, x, y), rotation(ctx, (i * tau / chunks) +
                                              (pi / 2) - angle_offset):
            roman = int_to_roman(i)
            extents = ctx.text_extents(roman)

            ctx.move_to(-1 * extents.width / 2.0, extents.height / 2.0)
            ctx.show_text(roman)
            ctx.new_path()
예제 #2
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()
예제 #3
0
 def render(self, text: str):
     lines = text.splitlines()
     for i, line in enumerate(lines):
         y_offset = self.blockheight * i
         with cairoctx.translation(self.ctx, self.scale * 3,
                                   self.scale * 3 + y_offset):
             # self.debug_square()
             self.render_line(line)
예제 #4
0
    def letter(self, letter: str):
        color_top, color_bot = ALPHABET_PATTERN[letter.upper()]
        self.ctx.move_to(0, 0)
        self.rectangle(color_bot)

        with cairoctx.translation(self.ctx, 0,
                                  -(self.rect_height + self.margin)):
            self.ctx.move_to(0, 0)
            self.rectangle(color_top)
예제 #5
0
    def letter(self, letter: str):
        color_top, color_bot = ALPHABET_PATTERN[letter.upper()]
        self.ctx.move_to(0, 0)
        self.triangle(color_bot)

        # Move up 2x diag_offset and flip the canvas upside-down
        with cairoctx.translation(self.ctx, 0, -2 * self.diag_offset):
            self.ctx.move_to(0, 0)
            with cairoctx.rotation(self.ctx, pi):
                self.triangle(color_top)
예제 #6
0
    def render_line(self, line: str):
        for i, char in enumerate(line):
            if char == " ":
                continue

            orient_idx = i % 4
            block_offset = i // 4
            orient = self.orientations[orient_idx]

            x_offset = block_offset * self.blockwidth + orient[0][0]
            y_offset = orient[0][1]
            with cairoctx.translation(self.ctx, x_offset, y_offset):
                with cairoctx.rotation(self.ctx, orient[1]):
                    self.letter(char)
예제 #7
0
    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)
예제 #8
0
def _calendar_mapped(
    ctx: cairo.Context,
    rng: Generator,
    pos_x: float,
    pos_y: float,
    radius_outer: float,
    radius_inner: float,
    mapping: Sequence[str],
    font_family: str = "Noto Sans Symbols",
):
    chunks = rng.integers(6, min(len(mapping), 24))
    _calendar_base(ctx, pos_x, pos_y, radius_outer, radius_inner, chunks)

    ctx.select_font_face(font_family)
    font_size = 0.8 * (radius_outer - radius_inner)
    ctx.set_font_size(font_size)

    symbols = rng.choice(mapping, size=chunks, replace=False)

    angle_offset = pi / chunks
    for i, (x, y) in enumerate(
            points_along_arc(
                pos_x,
                pos_y,
                (radius_inner + radius_outer) / 2.0,
                angle_offset,
                angle_offset + tau,
                chunks,
            ),
            1,
    ):
        with translation(ctx, x, y), rotation(ctx, (i * tau / chunks) +
                                              (pi / 2) - angle_offset):
            symbol = symbols[i - 1]
            extents = ctx.text_extents(symbol)

            ctx.move_to(-1 * extents.width / 2.0, extents.height / 2.0)
            ctx.show_text(symbol)
            ctx.new_path()