Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw image in tile pattern in Cocoa

I would like to draw an NSImage in a NSView drawRect in a simple tile pattern in my Cocoa mac app. One method to do this is simply write a loop to draw this image multiple times using drawInRect:fromRect:operation:fraction:

Is there a more direct method?

like image 230
AmaltasCoder Avatar asked Dec 01 '22 06:12

AmaltasCoder


2 Answers

NSColor* myColor = [NSColor colorWithPatternImage:myImage];
[myColor set];
// then treat it like you would any other color, e.g.:
NSRectFill(myRect);
like image 41
Kurt Revis Avatar answered Dec 04 '22 07:12

Kurt Revis


You need to use a pattern image as Kurt pointed out, but it's not as simple as that. Pattern images use the window's origin as their origin point, so if you resize the window the pattern will move.

You need to adjust the pattern phase in the current graphics context depending on where the view sits in the window. I use this category on NSView:

@implementation NSView (RKAdditions)
- (void)rk_drawPatternImage:(NSColor*)patternColor inRect:(NSRect)rect
{
    [self rk_drawPatternImage:patternColor inBezierPath:[NSBezierPath bezierPathWithRect:rect]];
}

- (void)rk_drawPatternImage:(NSColor*)patternColor inBezierPath:(NSBezierPath*)path
{
    [NSGraphicsContext saveGraphicsState];

    CGFloat yOffset = NSMaxY([self convertRect:self.bounds toView:nil]);
    CGFloat xOffset = NSMinX([self convertRect:self.bounds toView:nil]);
    [[NSGraphicsContext currentContext] setPatternPhase:NSMakePoint(xOffset, yOffset)];

    [patternColor set];
    [path fill];
    [NSGraphicsContext restoreGraphicsState];
}

@end

You'd use it like this:

-(void) drawRect: (NSRect)dirtyRect
{
    [self rk_drawPatternImage:[NSColor colorWithPatternImage:yourImage] inRect:self.bounds];
}
like image 72
Rob Keniger Avatar answered Dec 04 '22 06:12

Rob Keniger