/* gcc -framework Cocoa -lobjc `pkg-config --cflags --libs cairo` cairo.m -o cairo * Draws a ring using a surface with a data buffer, and then using as * a source for a translated cr, which exposes what I believe is a * bug. At least the same code works for X11. */ #import #include static void paint_ring (cairo_t *cr, int x, int y, int width, int height) { int xx, yy; double size, ring_width; double dx, dy, dist; double cx, cy; double inner, outer; uint32 *buf, *p; cairo_surface_t *source; size = MIN (width, height) / 2.0; ring_width = 20; cx = width / 2.0; cy = height / 2.0; outer = size / 2.0; inner = outer - ring_width; buf = calloc (width * height, sizeof (uint32)); for (yy = 0; yy < height; yy++) { p = buf + yy * width; dy = -(yy + y - cy); for (xx = 0; xx < width; xx++) { dx = xx + x - cx; dist = dx * dx + dy * dy; if (dist < ((inner-1) * (inner-1)) || dist > ((outer+1) * (outer+1))) { *p++ = 0; continue; } *p++ = (255 << 16) | (65 << 8) | 24; } } source = cairo_image_surface_create_for_data ((unsigned char *) buf, CAIRO_FORMAT_RGB24, width, height, 4 * width); cairo_save (cr); cairo_set_source_surface (cr, source, x, y); cairo_surface_destroy (source); cairo_set_line_width (cr, ring_width); cairo_new_path (cr); cairo_arc (cr, cx, cy, size / 2.0 - ring_width / 2.0, 0, 2 * M_PI); cairo_stroke (cr); cairo_restore (cr); free (buf); } @interface TestView: NSView { } @end @implementation TestView - (id)initWithFrame:(NSRect)frameRect { self = [super initWithFrame:frameRect]; return self; } - (BOOL)isOpaque { return NO; } - (void)drawRect:(NSRect)rect { NSRect bounds = [self bounds]; int width = bounds.size.width; int height = bounds.size.height; CGContextRef ctx = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort]; CGContextTranslateCTM (ctx, 0.0, height); CGContextScaleCTM (ctx, 1.0, -1.0); cairo_surface_t *surface = cairo_quartz_surface_create_for_cg_context (ctx, width, height); cairo_t *cr = cairo_create (surface); /* Commenting this will make the ring look as intented. */ //cairo_translate (cr, 10, 10); paint_ring (cr, 0, 0, width, height); cairo_destroy (cr); cairo_surface_destroy (surface); } @end int main (int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [NSApplication sharedApplication]; int style = NSClosableWindowMask | NSResizableWindowMask | NSTitledWindowMask | NSMiniaturizableWindowMask; NSWindow *win = [[NSWindow alloc] initWithContentRect:NSMakeRect(50, 50, 600, 400) styleMask:style backing:NSBackingStoreBuffered defer:NO]; NSView *view = [[TestView alloc] init]; [win setContentView: view]; [win makeKeyAndOrderFront:win]; [NSApp run]; [pool release]; return 0; }