Question

So, I have this odd issue in my Cocoa app. A toolbar item, and some NSImageViews just render their image upside-down for no apparent reason. The toolbar item actually comes that way when I launch the App for some reason (the icon is assigned in code), and then, when I open my HUD with a finder zoom effect, the imageViews contained in it are upside down.

alt text

That image above is a screensot of this odd phenomenon. AS you can see, the "Show Trash" item is rotated oddly, every NSImageView in the HUD, but the NSImageView in the NSBrowser is fine.

How would I go about tracking down what is causing this, and then fixing it?

Was it helpful?

Solution

See Mac OS X Developer Release Note - AppKit Release Notes (Snow Leopard):

Flipped images in toolbars (New since January 2009 seed)

A common but incorrect practice is to call setFlipped:YES on an image that you plan to draw into a flipped graphics context. This is incorrect because if the image is later drawn into a normal unflipped context, the image will appear upside down. However, Leopard and earlier contained a bug in which images set on NSToolbarItem (via setImage:) would ignore their isFlipped property. SnowLeopard fixes this bug for apps compiled on SnowLeopard with the 10.6 SDK; as a result, some images which should have drawn upside down in Leopard, will begin doing so when your app is recompiled.

If you recompile your app on SnowLeopard and discover that your toolbar item images are drawing upside down, then it indicates that you are calling setFlipped:YES somewhere within your code. You should remove those calls and replace the image drawing with methods that correctly handle flipped contexts. See the discussion of setFlipped: in these Release Notes for more discussion.

Re: setFlipped:

NSImage: deprecating -[NSImage setFlipped:], adding a drawing method that respects context flippedness (New since WWDC 2008)

The flipped attribute of NSImage is widely misunderstood. We are deprecating it for SnowLeopard, and replacing its typical uses with less error-prone API.

The property describes the orientation of the internal coordinate system of the NSImage. Just as a superview never cares about the flippedness of its subviews, a user of an NSImage should not care about its flippedness.

The typical (flawed) use case is to try to call [image setFlipped:[[NSGraphicsContext currentContext] isFlipped]] just prior to drawing, but this does not accomplish the intended goal. If called before caching, then representations end up caching upside down, and the flip is absorbed into the cache. If called after caching, it has no effect-the cached representation is already supposed to incorporate any necessary flipping. In the former case, if the NSImage is drawn anywhere else later, it ends up upside down in that place, which is also confusing because the bug and the expression of the bug are far apart. Lack of understanding regarding flippedness is also frequently the source of poorly performing code, in which people make unnecessary intermediate buffers to work around perceived framework bugs. The framework behaves according to design, but contrary to expectation, and the semantics are not all that useful. It's also difficult to change the semantics of -[NSImage isFlipped], because a lot of code is very closely dependent on the current behavior. Rather than attempt this, we have deprecated the property.

We are providing a simple and correct way to draw images in a flipped or unflipped context, which is a draw method that can account for context flippedness. We are also adding a hints parameter matching the hints in -bestRepresentationForRect:context:hints:.

- (void)drawInRect:(NSRect)dstRect fromRect:(NSRect)srcRect operation:(NSCompositingOperation)op fraction:(CGFloat)alpha respectFlipped:(BOOL)respectContextIsFlipped hints:(NSDictionary *)hints;

Pass YES for respectFlipped to get the fancy new behavior. One note for those that understand the CTM and worry that this method has an odd interaction, where modifying the CTM could fail to have any effect on image drawing: This is not the case. This method branches behavior based on [[NSGraphicsContext currentContext] isFlipped]. Modifying the CTM might turn your axes upside down, but it will not alter the result of -[NSGraphicsContext isFlipped]. They're completely orthogonal.

A second valid use of -[NSImage setFlipped:] was to specify the flippedness of the context obtained via -[NSImage lockFocus]. There are cases, for example drawing directly via NSLayoutManager, that require a flipped context. To cover this case, we add

- (void)lockFocusFlipped:(BOOL)flipped;

This doesn't alter the state of the image itself, only the context on which focus is locked. It means that (0,0) is at the top left and positive along the Y-axis is down in the locked context.

OTHER TIPS

My off-the-top-of-my-head guess is that the image has mistakenly had -setFlipped:YES called on it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top