"""Painting primitives using Skia.""" import skia from .fonts import get_font class PaintCommand: """Base class for paint commands.""" def __init__(self, rect): self.rect = rect # (x1, y1, x2, y2) bounding box def execute(self, canvas: skia.Canvas): """Execute this paint command on the canvas.""" raise NotImplementedError class DrawText(PaintCommand): """Command to draw text.""" def __init__(self, x: float, y: float, text: str, font_size: int, color=None): self.x = x self.y = y self.text = text self.font_size = font_size self.color = color or skia.ColorBLACK self._font = get_font(font_size) width = self._font.measureText(text) super().__init__((x, y - font_size, x + width, y)) def execute(self, canvas: skia.Canvas, paint: skia.Paint = None): """Draw the text on the canvas.""" if paint is None: paint = skia.Paint() paint.setAntiAlias(True) paint.setColor(self.color) canvas.drawString(self.text, self.x, self.y, self._font, paint) class DrawRect(PaintCommand): """Command to draw a rectangle.""" def __init__(self, x1: float, y1: float, x2: float, y2: float, color, fill: bool = True): super().__init__((x1, y1, x2, y2)) self.color = color self.fill = fill def execute(self, canvas: skia.Canvas, paint: skia.Paint = None): """Draw the rectangle on the canvas.""" if paint is None: paint = skia.Paint() paint.setColor(self.color) paint.setStyle(skia.Paint.kFill_Style if self.fill else skia.Paint.kStroke_Style) rect = skia.Rect.MakeLTRB(*self.rect) canvas.drawRect(rect, paint) class DisplayList: """A list of paint commands to execute.""" def __init__(self): self.commands = [] def append(self, command: PaintCommand): """Add a paint command.""" self.commands.append(command) def execute(self, canvas: skia.Canvas, paint: skia.Paint = None): """Execute all commands on the canvas.""" for cmd in self.commands: cmd.execute(canvas, paint) def __len__(self): return len(self.commands) def __iter__(self): return iter(self.commands)