"""Icon renderer: Claude starburst logo + circular usage arc.""" import math from PIL import Image, ImageDraw SIZE = 256 CENTER = SIZE // 2 ARC_WIDTH = 28 # Claude brand orange _CLAUDE_ORANGE = (224, 123, 83) # #E07B53 # Color thresholds for the usage arc (10% increments) _COLORS = [ (10, "#4CAF50"), # green (20, "#43A047"), # green (darker) (30, "#7CB342"), # light green (40, "#C0CA33"), # lime (50, "#FDD835"), # yellow (60, "#FFC107"), # amber (70, "#FFB300"), # amber (darker) (80, "#FF9800"), # orange (90, "#FF5722"), # deep orange (100, "#F44336"), # red ] def _hex_to_rgba(hex_color, alpha=255): h = hex_color.lstrip("#") return (int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16), alpha) def _arc_color(pct): for threshold, color in _COLORS: if pct <= threshold: return color return _COLORS[-1][1] def _draw_starburst(img): """Draw 8-petal starburst logo in Claude orange, full opacity.""" layer = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0)) draw = ImageDraw.Draw(layer) color = (*_CLAUDE_ORANGE, 255) num_petals = 8 petal_length = SIZE * 0.38 # fill most of the icon petal_width = SIZE * 0.10 for i in range(num_petals): angle = math.radians(i * (360 / num_petals)) # Tip of petal (far from center) tip_x = CENTER + math.cos(angle) * petal_length tip_y = CENTER + math.sin(angle) * petal_length # Base points (perpendicular to petal direction, near center) perp = angle + math.pi / 2 base_offset = SIZE * 0.05 bx = CENTER + math.cos(angle) * base_offset by = CENTER + math.sin(angle) * base_offset left_x = bx + math.cos(perp) * (petal_width / 2) left_y = by + math.sin(perp) * (petal_width / 2) right_x = bx - math.cos(perp) * (petal_width / 2) right_y = by - math.sin(perp) * (petal_width / 2) # Inner point (towards center, slight taper) inner_x = CENTER - math.cos(angle) * (SIZE * 0.02) inner_y = CENTER - math.sin(angle) * (SIZE * 0.02) polygon = [(inner_x, inner_y), (left_x, left_y), (tip_x, tip_y), (right_x, right_y)] draw.polygon(polygon, fill=color) # Center dot dot_r = SIZE * 0.04 draw.ellipse( [CENTER - dot_r, CENTER - dot_r, CENTER + dot_r, CENTER + dot_r], fill=color, ) img = Image.alpha_composite(img, layer) return img def _draw_arc(img, pct): """Draw circular progress arc from 12 o'clock, clockwise.""" if pct <= 0: return img layer = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0)) draw = ImageDraw.Draw(layer) color = _hex_to_rgba(_arc_color(pct)) pct = min(pct, 100) start_angle = -90 end_angle = -90 + (pct / 100) * 360 margin = ARC_WIDTH // 2 bbox = [margin, margin, SIZE - margin, SIZE - margin] draw.arc(bbox, start_angle, end_angle, fill=color, width=ARC_WIDTH) img = Image.alpha_composite(img, layer) return img def render_icon(pct): """Render a 256x256 RGBA icon with starburst + usage arc. Args: pct: Usage percentage (0-100). Arc is invisible at 0. Returns: PIL.Image.Image (RGBA) """ img = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0)) img = _draw_starburst(img) img = _draw_arc(img, pct) return img