roundedrectangles

## Method A

From the cairo samples, modified. Gives a very nice shape but takes width and height only as guides, however width and height do not render properly and are affected by radius.

``````def roundedrecA(self,cr,x,y,width,height,radius=5):
#/* a custom shape, that could be wrapped in a function */
x0       = x+radius/2.0   #/*< parameters like cairo_rectangle */

cr.save()
#cr.set_line_width (0.04)
#self.snippet_normalize (cr, width, height)

x1=x0+rect_width
y1=y0+rect_height
#if (!rect_width || !rect_height)
#    return
cr.move_to  (x0, (y0 + y1)/2)
cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
else:
cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
cr.line_to (x1 , y1 - radius)
cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
cr.curve_to (x0, y1, x0, y1, x0, y1- radius)

else:
cr.move_to  (x0, (y0 + y1)/2)
cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
else:
cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
cr.line_to (x1 , y1 - radius)
cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
cr.curve_to (x0, y1, x0, y1, x0, y1- radius)

cr.close_path ()

cr.restore()
``````

## Method B

From mono moonlight aka mono silverlight. Works very well on larger shapes.

``````def roundedrecMoonlight(self,cr,x,y,w,h,radius_x=5,radius_y=5):
#from mono moonlight aka mono silverlight
#test limits (without using multiplications)
# http://graphics.stanford.edu/courses/cs248-98-fall/Final/q1.html
ARC_TO_BEZIER = 0.55228475

#approximate (quite close) the arc using a bezier curve

cr.new_path();
cr.move_to ( x + radius_x, y)
cr.rel_line_to ( w - 2 * radius_x, 0.0)
cr.rel_line_to ( 0, h - 2 * radius_y)
cr.rel_line_to ( -w + 2 * radius_x, 0)
cr.rel_line_to (0, -h + 2 * radius_y)
cr.close_path ()
``````

## Method C

I can't remember where I got this. If you are the author please add your name. Works well on smaller shapes.

``````def roundedrec(self,context,x,y,w,h,r = 10):
"Draw a rounded rectangle"
#   A****BQ
#  H      C
#  *      *
#  G      D
#   F****E

context.move_to(x+r,y)                      # Move to A
context.line_to(x+w-r,y)                    # Straight line to B
context.curve_to(x+w,y,x+w,y,x+w,y+r)       # Curve to C, Control points are both at Q
context.line_to(x+w,y+h-r)                  # Move to D
context.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h) # Curve to E
context.line_to(x+r,y+h)                    # Line to F
context.curve_to(x,y+h,x,y+h,x,y+h-r)       # Curve to G
context.line_to(x,y+r)                      # Line to H
context.curve_to(x,y,x,y,x+r,y)             # Curve to A
return
``````

## Method D

Created by Helton Moraes (heltonbiker at gmail dot com). Uses round arcs and takes advantage of the segment-creation property of cairo.arc() - just draw the arcs, no need to draw straight segments in between.

``````def draw_rounded(cr, area, radius):
""" draws rectangles with rounded (circular arc) corners """
from math import pi
a,b,c,d=area
cr.close_path()
cr.stroke()

################################################################

### EXAMPLE
import cairo, Image

w,h = 800, 600
offset = 100
fig_size = (w,h)

# an area with coordinates of
# (top, bottom, left, right) edges in absolute coordinates:
inside_area = (offset, w-offset, offset, h-offset)

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *fig_size)
cr = cairo.Context(surface)
cr.set_line_width(3)
cr.set_source_rgb(1,1,1)

draw_rounded(cr, inside_area, 150)

im = Image.frombuffer("RGBA",
fig_size,
surface.get_data(),
"raw",
"BGRA",
0,1)
im.show()
``````