On Thu, Apr 17, 2008 at 8:41 PM, Graham Cox <[EMAIL PROTECTED]> wrote: > If only life were that simple... > > The requirement is to hit-test a stroked or filled path to pixel-perfect > accuracy. Yes there is containsPoint: and that other one in CG for > hit-testing a stroke, but these are blunt instruments when it comes to all > the possible stylistic variations that can be applied to a path, including > shadows, images arranged along the path, text and so forth. (I use these > methods as a first "weed out" of the hit). There is also no built-in way to > test whether a rect intersects the pixels in a path. > > So, each graphic object currently caches an offscreen image of itself > (created lazily when an accurate hit test is needed) and tests the pixel at > the given point (or scans within a given rect) for pixels that are turned > on. This only *needs* to be a 1-bit image, because either a point hits or it > doesn't. But because the pixels themselves are drawn using Quartz, the > offscreen context needs to be writable by Quartz, which a 1-bit rep isn't, > as I have discovered. Thus the smallest supported bit depth is 8 bits, > leading to the eightfold overkill in terms of memory storage - and given > that there can be thousands of graphic objects this does add up. > > Heinrich's suggestion would work, but each time the offscreen cache needs > to be updated (which can be often in an interactive editing situation) a > temporary 8-bit image needs to be made then hand-copied and thresholded down > to the 1-bit version. While this is going to save the memory in the long run > the penalty is likely to be much more sluggish interaction - the classic > trade-off. That said I might try it and see if the performance is > acceptable. > > If I'm missing anything obvious, I hope someone will point it out!
There is an easy, although deeply non-obvious, way to do 100% correct hit testing with any stylistic variations, and even to hit test with fill versus stroke. In fact, you're almost there, and just need to take it a little bit further. The answer is, instead of drawing into a big context and then checking the pixel value of the location in question, you draw into a very teeny context with a proper transform set up. Create a 1x1 context, set up the proper affine transform to make that pixel be the one you're hit testing, then draw whatever it is you're drawing. Afterwards, check your one pixel: if it's dark, you hit, if it's light, you missed. You're still wasting the memory for an 8-bit context, but at least it's only 7 bits wasted. :) Mike _______________________________________________ Cocoa-dev mailing list ([email protected]) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to [EMAIL PROTECTED]
