Creating pattern on-the-fly?

2019-07-06 16:52发布

问题:

Is there a way to create a colored fill pattern dynamically in Cocoa?

In particular instead of using a fixed pattern from an image file via

NSColor *fillPattern = [NSColor colorWithPatternImage:patternImage];

I'd like to create a pattern by dynamically choosing the appropriate colors at runtime. Background is highlighting a colored object by rendering stripes or squares in the ''opposite'' color on top of it - whatever opposite might mean in this context, but that's a different story..

Being applied to potentially hundreds of objects in a drawing app it needs to be a rather fast method so I suppose just swapping colors in patternImage won't be good enough.

(It did work just fine back in QuickDraw..!)

回答1:

Why not just draw to an in-memory image and use that for your pattern?

NSImage* patternImage = [[NSImage alloc] initWithSize:someSize];
[patternImage lockFocus];
//draw your pattern
[patternImage unlockFocus];
NSColor* patternColor = [NSColor colorWithPatternImage:patternImage];
//do something with the pattern color
//remember to release patternImage if you're not using ARC

Performance-wise, you generally should be looking at optimising drawing by paying attention to the rect passed in to drawRect: and making sure you only draw what is necessary. If you do that then I can't see the pattern drawing performance being a major problem.



回答2:

Background is highlighting a colored object by rendering stripes or squares in the ''opposite'' color on top of it - whatever opposite might mean in this context, but that's a different story..

You'll want to use one of Quartz's blend modes (most of them are present in Photoshop, Pixelmator, and Opacity, so you can experiment in one of those apps to determine which one you need).

You should then be able to fill with a static image—or a dynamic pattern, if it's really necessary—and Quartz will blend it in appropriately.

There's no way to do this in AppKit alone; you'll need to get a CGContext from the current NSGraphicsContext and do it in Quartz.