import cairocffi as cairo import math def draw_cylinder_at_xy(ctx: cairo.Context, x: int, y: int, cyl_width:int, cyl_height: int, top_ellipse_height: int, top_ellipse_color=(1,1,1)): pat = cairo.LinearGradient(x, y, x + cyl_width, y) pat.add_color_stop_rgb(0, 1, 1, 1) # White top pat.add_color_stop_rgb(1, 0.2, 0.2, 1) # Blue bottom # 1. Draw Bottom Ellipse (White) ctx.set_line_width(1.0) ctx.save() ctx.translate(x + cyl_width / 2, y) ctx.scale(1, top_ellipse_height / cyl_width ) # Ellipse scale ctx.arc(0, 0, cyl_width / 2, 0, 2 * math.pi) ctx.restore() #ctx.set_source_rgb(1, 1, 1) # White ctx.set_line_width(0.0) ctx.set_source(pat) ctx.fill_preserve() #ctx.set_source_rgb(0, 0, 0) #ctx.set_line_width(1) ctx.stroke() # 2. Draw the rectangle body ctx.set_line_width(1.0) ctx.rectangle(x, y, cyl_width, -cyl_height) ctx.set_source(pat) ctx.fill() ctx.stroke() # 3. Draw top Ellipse (White) if True: ctx.set_line_width(1.0) ctx.save() ctx.translate(x + cyl_width / 2, y-cyl_height) ctx.scale(1, top_ellipse_height / (cyl_width / 2) * 0.5) # Ellipse scale ctx.arc(0, 0, cyl_width / 2, 0, 2 * math.pi) ctx.restore() ctx.set_source_rgb(top_ellipse_color[0], top_ellipse_color[1], top_ellipse_color[2]) ctx.fill_preserve() # Outline for better visibility ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(1) ctx.stroke() def draw_cylinders(width, height, filename): # Setup surface and context surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) ctx = cairo.Context(surface) # White background ctx.set_source_rgb(1, 1, 1) ctx.paint() # Cylinder dimensions cyl_width = 80 cyl_height = 200 top_ellipse_height = 30 spacing = 50 # Starting position start_x = 50 y = 50 for i in range(3): x = start_x + i * (cyl_width + spacing) # 1. Draw Side Gradient (Rect + Arc) # Create a horizontal linear gradient: White (top) to Blue (bottom) pat = cairo.LinearGradient(x, y, x+cyl_width, y) pat.add_color_stop_rgb(0, 1, 1, 1) # White top pat.add_color_stop_rgb(1, 0.2, 0.2, 1) # Blue bottom # Draw the rectangle body ctx.rectangle(x, y + top_ellipse_height / 2, cyl_width, cyl_height - top_ellipse_height / 2) ctx.set_source(pat) ctx.fill() # 2. Draw Top Ellipse (White) ctx.save() ctx.translate(x + cyl_width / 2, y + top_ellipse_height / 2) ctx.scale(1, top_ellipse_height / (cyl_width / 2) * 0.5) # Ellipse scale ctx.arc(0, 0, cyl_width / 2, 0, 2 * math.pi) ctx.restore() ctx.set_source_rgb(1, 1, 1) # White ctx.fill_preserve() # Outline for better visibility ctx.set_source_rgb(0, 0, 0) ctx.set_line_width(1) ctx.stroke() # Save to PNG surface.write_to_png(filename) print(f"Saved {filename}") if __name__ == "__main__": surface = cairo.SVGSurface("cylinder.svg", 800, 800) ctx = cairo.Context(surface) ctx.set_source_rgb(0, 1, 0) ctx.paint() draw_cylinder_at_xy(ctx, 100,300, 50,150,10) draw_cylinder_at_xy(ctx, 300,300, 60,110,10, top_ellipse_color=(0.9, 0.4, 0.7)) surface.write_to_png("cylinder.png") print("Saved cylinder.png") surface.finish()