Skip to content

Instantly share code, notes, and snippets.

@jessearmand
Created January 23, 2011 02:47
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jessearmand/791761 to your computer and use it in GitHub Desktop.
Save jessearmand/791761 to your computer and use it in GitHub Desktop.
Using CG to draw a pointy rounded rect.
//
// From http://stackoverflow.com/questions/4442126/how-to-draw-a-speech-bubble-on-an-iphone
//
void DrawPopupShapeInRect(CGRect rect, CGColorRef borderColor, CGColorRef backgroundColor, CGFloat borderRadius, CGFloat strokeWidth, CGFloat pointerWidth, CGFloat pointerHeight)
{
CGRect currentFrame = self.bounds;
CGContextSetLineJoin(context, kCGLineJoinRound);
CGContextSetLineWidth(context, strokeWidth);
CGContextSetStrokeColorWithColor(context, borderColor);
CGContextSetFillColorWithColor(context, backgroundColor);
// Draw and fill the bubble
CGContextBeginPath(context);
// Move to the bottom left point
CGContextMoveToPoint(context, borderRadius + strokeWidth + 0.5f, strokeWidth + pointerHeight + 0.5f);
// Add the triangle lines starting from the top left point
CGContextAddLineToPoint(context, round(currentFrame.size.width / 2.0f - pointerWidth / 2.0f) + 0.5f, pointerHeight + strokeWidth + 0.5f);
CGContextAddLineToPoint(context, round(currentFrame.size.width / 2.0f) + 0.5f, strokeWidth + 0.5f);
CGContextAddLineToPoint(context, round(currentFrame.size.width / 2.0f + pointerWidth / 2.0f) + 0.5f, pointerHeight + strokeWidth + 0.5f);
// Continue drawing the rounded rect starting from the bottom right point
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, strokeWidth + pointerHeight + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, round(currentFrame.size.width / 2.0f + pointerWidth / 2.0f) - strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, strokeWidth + 0.5f, pointerHeight + strokeWidth + 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, strokeWidth + pointerHeight + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, pointerHeight + strokeWidth + 0.5f, borderRadius - strokeWidth);
CGContextClosePath(context);
CGContextDrawPath(context, kCGPathFillStroke);
// Draw a clipping path for the fill
CGContextBeginPath(context);
CGContextMoveToPoint(context, borderRadius + strokeWidth + 0.5f, round((currentFrame.size.height + pointerHeight) * 0.50f) + 0.5f);
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, round((currentFrame.size.height + pointerHeight) * 0.50f) + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, currentFrame.size.width - strokeWidth - 0.5f, currentFrame.size.height - strokeWidth - 0.5f, round(currentFrame.size.width / 2.0f + pointerWidth / 2.0f) - strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, currentFrame.size.height - strokeWidth - 0.5f, strokeWidth + 0.5f, pointerHeight + strokeWidth + 0.5f, borderRadius - strokeWidth);
CGContextAddArcToPoint(context, strokeWidth + 0.5f, round((currentFrame.size.height + pointerHeight) * 0.50f) + 0.5f, currentFrame.size.width - strokeWidth - 0.5f, round((currentFrame.size.height + pointerHeight) * 0.50f) + 0.5f, borderRadius - strokeWidth);
CGContextClosePath(context);
CGContextClip(context);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment