diff options
author | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-04 18:21:12 +0000 |
---|---|---|
committer | shess@chromium.org <shess@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-04 18:21:12 +0000 |
commit | d60655b86f1d6a15e88ca51a77ccb7d3a3945612 (patch) | |
tree | ef45576279e8b904b3ffb50a25df5401d9098ec4 /chrome | |
parent | e9b084c2af3b8831f1d872691184da32e7df5b92 (diff) | |
download | chromium_src-d60655b86f1d6a15e88ca51a77ccb7d3a3945612.zip chromium_src-d60655b86f1d6a15e88ca51a77ccb7d3a3945612.tar.gz chromium_src-d60655b86f1d6a15e88ca51a77ccb7d3a3945612.tar.bz2 |
[Mac] Image-drawing which doesn't require image-flipping.
Snow Leopard deprecated -[NSImage setFlipped:] for good reasons. This
implements a method similar to the new
-[NSImage drawInRect:*:respectFlipped:] method, which allows images to
be drawn so that they always look right visually regardless of the
-isFlipped status of the view being drawn.
BUG=38943
TEST=Autocomplete, download, and reload button look right.
Review URL: http://codereview.chromium.org/2587003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48954 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_popup_view_mac.mm | 5 | ||||
-rw-r--r-- | chrome/browser/cocoa/autocomplete_text_field_cell.mm | 9 | ||||
-rw-r--r-- | chrome/browser/cocoa/bookmark_bar_folder_window.mm | 9 | ||||
-rw-r--r-- | chrome/browser/cocoa/bookmark_button_cell.mm | 5 | ||||
-rw-r--r-- | chrome/browser/cocoa/download_item_cell.mm | 5 | ||||
-rw-r--r-- | chrome/browser/cocoa/gradient_button_cell.mm | 5 | ||||
-rw-r--r-- | chrome/browser/cocoa/image_utils.h | 25 | ||||
-rw-r--r-- | chrome/browser/cocoa/image_utils.mm | 37 | ||||
-rw-r--r-- | chrome/browser/cocoa/image_utils_unittest.mm | 142 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
11 files changed, 229 insertions, 16 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm index c0e4f93..5d31764 100644 --- a/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm +++ b/chrome/browser/autocomplete/autocomplete_popup_view_mac.mm @@ -11,6 +11,7 @@ #include "chrome/browser/autocomplete/autocomplete_edit_view_mac.h" #include "chrome/browser/autocomplete/autocomplete_popup_model.h" #include "chrome/browser/cocoa/event_utils.h" +#include "chrome/browser/cocoa/image_utils.h" #include "gfx/rect.h" #include "grit/theme_resources.h" #import "third_party/GTM/AppKit/GTMNSAnimation+Duration.h" @@ -484,11 +485,11 @@ void AutocompletePopupViewMac::OpenURLForRow(int row, bool force_background) { imageRect.origin.y += floor((NSHeight(cellFrame) - NSHeight(imageRect)) / 2); imageRect.origin.x += kLeftRightMargin; - [image setFlipped:[controlView isFlipped]]; [image drawInRect:imageRect fromRect:NSZeroRect // Entire image operation:NSCompositeSourceOver - fraction:1.0]; + fraction:1.0 + neverFlipped:YES]; } // Adjust the title position to be lined up under the field's text. diff --git a/chrome/browser/cocoa/autocomplete_text_field_cell.mm b/chrome/browser/cocoa/autocomplete_text_field_cell.mm index 9801892..7558c70 100644 --- a/chrome/browser/cocoa/autocomplete_text_field_cell.mm +++ b/chrome/browser/cocoa/autocomplete_text_field_cell.mm @@ -6,6 +6,7 @@ #include "app/resource_bundle.h" #include "base/logging.h" +#import "chrome/browser/cocoa/image_utils.h" #include "gfx/font.h" #include "grit/theme_resources.h" @@ -17,7 +18,7 @@ // down relative to the containing text's baseline. // Draw the image using |DrawImageInRect()| helper function for -// |-setFlipped:| consistency with other image drawing. +// flipped consistency with other image drawing. - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)aView; @end @@ -85,11 +86,11 @@ void DrawImageInRect(NSImage* image, NSView* view, const NSRect& rect) { // If there is an image, make sure we calculated the target size // correctly. DCHECK(!image || NSEqualSizes([image size], rect.size)); - [image setFlipped:[view isFlipped]]; [image drawInRect:rect fromRect:NSZeroRect // Entire image operation:NSCompositeSourceOver - fraction:1.0]; + fraction:1.0 + neverFlipped:YES]; } // Helper function to generate an attributed string containing @@ -120,7 +121,7 @@ NSAttributedString* AttributedStringForImage(NSImage* anImage, - (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)aView { // Draw image with |DrawImageInRect()| to get consistent - // |-setFlipped:| treatment. + // flipped treatment. DrawImageInRect([self image], aView, cellFrame); } diff --git a/chrome/browser/cocoa/bookmark_bar_folder_window.mm b/chrome/browser/cocoa/bookmark_bar_folder_window.mm index da0455e..1d0e863 100644 --- a/chrome/browser/cocoa/bookmark_bar_folder_window.mm +++ b/chrome/browser/cocoa/bookmark_bar_folder_window.mm @@ -8,6 +8,7 @@ #include "base/nsimage_cache_mac.h" #import "base/scoped_nsobject.h" #import "chrome/browser/cocoa/bookmark_bar_folder_controller.h" +#import "chrome/browser/cocoa/image_utils.h" #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" #import "third_party/GTM/AppKit/GTMNSBezierPath+RoundRect.h" @@ -54,7 +55,6 @@ const CGFloat kViewCornerRadius = 4.0; NSRect visibleRect = [self bounds]; // On top - [arrowUpImage_ setFlipped:[self isFlipped]]; NSRect imageRect = NSZeroRect; imageRect.size = [arrowUpImage_ size]; NSRect drawRect = NSOffsetRect( @@ -64,10 +64,10 @@ const CGFloat kViewCornerRadius = 4.0; [arrowUpImage_ drawInRect:drawRect fromRect:imageRect operation:NSCompositeSourceOver - fraction:1.0]; + fraction:1.0 + neverFlipped:YES]; // On bottom - [arrowDownImage_ setFlipped:[self isFlipped]]; imageRect = NSZeroRect; imageRect.size = [arrowDownImage_ size]; drawRect = NSOffsetRect(imageRect, @@ -76,7 +76,8 @@ const CGFloat kViewCornerRadius = 4.0; [arrowDownImage_ drawInRect:drawRect fromRect:imageRect operation:NSCompositeSourceOver - fraction:1.0]; + fraction:1.0 + neverFlipped:YES]; } - (void)drawRect:(NSRect)rect { diff --git a/chrome/browser/cocoa/bookmark_button_cell.mm b/chrome/browser/cocoa/bookmark_button_cell.mm index d2a30b9..f8d0ffc 100644 --- a/chrome/browser/cocoa/bookmark_button_cell.mm +++ b/chrome/browser/cocoa/bookmark_button_cell.mm @@ -11,6 +11,7 @@ #import "chrome/browser/bookmarks/bookmark_model.h" #import "chrome/browser/cocoa/bookmark_menu.h" #import "chrome/browser/cocoa/bookmark_button.h" +#import "chrome/browser/cocoa/image_utils.h" #include "grit/generated_resources.h" @@ -225,11 +226,11 @@ NSWidth(cellFrame) - NSWidth(imageRect), (NSHeight(cellFrame) / 2.0) - (NSHeight(imageRect) / 2.0)); - [arrowImage_ setFlipped:[controlView isFlipped]]; [arrowImage_ drawInRect:drawRect fromRect:imageRect operation:NSCompositeSourceOver - fraction:[self isEnabled] ? 1.0 : 0.5]; + fraction:[self isEnabled] ? 1.0 : 0.5 + neverFlipped:YES]; } } diff --git a/chrome/browser/cocoa/download_item_cell.mm b/chrome/browser/cocoa/download_item_cell.mm index cabde16..84d4421 100644 --- a/chrome/browser/cocoa/download_item_cell.mm +++ b/chrome/browser/cocoa/download_item_cell.mm @@ -10,6 +10,7 @@ #include "base/sys_string_conversions.h" #import "chrome/browser/browser_theme_provider.h" #import "chrome/browser/cocoa/download_item_cell.h" +#import "chrome/browser/cocoa/image_utils.h" #import "chrome/browser/cocoa/themed_window.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_manager.h" @@ -587,11 +588,11 @@ NSGradient* BackgroundTheme::GetNSGradient(int id) const { // Draw icon NSRect imageRect = NSZeroRect; imageRect.size = [[self image] size]; - [[self image] setFlipped:[controlView isFlipped]]; [[self image] drawInRect:[self imageRectForBounds:cellFrame] fromRect:imageRect operation:NSCompositeSourceOver - fraction:[self isEnabled] ? 1.0 : 0.5]; + fraction:[self isEnabled] ? 1.0 : 0.5 + neverFlipped:YES]; // Separator between button and popup parts CGFloat lx = NSMaxX(cellFrame) - kDropdownAreaWidth + 0.5; diff --git a/chrome/browser/cocoa/gradient_button_cell.mm b/chrome/browser/cocoa/gradient_button_cell.mm index 002116d..ac71474 100644 --- a/chrome/browser/cocoa/gradient_button_cell.mm +++ b/chrome/browser/cocoa/gradient_button_cell.mm @@ -7,6 +7,7 @@ #include "base/logging.h" #import "base/scoped_nsobject.h" #import "chrome/browser/browser_theme_provider.h" +#import "chrome/browser/cocoa/image_utils.h" #import "chrome/browser/cocoa/themed_window.h" #include "grit/theme_resources.h" #import "third_party/GTM/AppKit/GTMNSColor+Luminance.h" @@ -415,11 +416,11 @@ static const NSTimeInterval kAnimationHideDuration = 0.4; NSRect imageRect = NSZeroRect; imageRect.size = [[self image] size]; NSRect drawRect = [self imageRectForBounds:cellFrame]; - [[self image] setFlipped:[controlView isFlipped]]; [[self image] drawInRect:drawRect fromRect:imageRect operation:NSCompositeSourceOver - fraction:[self isEnabled] ? 1.0 : 0.5]; + fraction:[self isEnabled] ? 1.0 : 0.5 + neverFlipped:YES]; if (isTemplate) { if (color) { [color set]; diff --git a/chrome/browser/cocoa/image_utils.h b/chrome/browser/cocoa/image_utils.h new file mode 100644 index 0000000..36a3bb45 --- /dev/null +++ b/chrome/browser/cocoa/image_utils.h @@ -0,0 +1,25 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_COCOA_IMAGE_UTILS_H_ +#define CHROME_BROWSER_COCOA_IMAGE_UTILS_H_ + +#import <Cocoa/Cocoa.h> + +@interface NSImage (FlippedAdditions) + +// Works like |-drawInRect:fromRect:operation:fraction:|, except that +// if |neverFlipped| is |YES|, and the context is flipped, the a +// transform is applied to flip it again before drawing the image. +// +// Compare to the 10.6 method +// |-drawInRect:fromRect:operation:fraction:respectFlipped:hints:|. +- (void)drawInRect:(NSRect)dstRect + fromRect:(NSRect)srcRect + operation:(NSCompositingOperation)op + fraction:(CGFloat)requestedAlpha + neverFlipped:(BOOL)neverFlipped; +@end + +#endif // CHROME_BROWSER_COCOA_IMAGE_UTILS_H_ diff --git a/chrome/browser/cocoa/image_utils.mm b/chrome/browser/cocoa/image_utils.mm new file mode 100644 index 0000000..80188e5 --- /dev/null +++ b/chrome/browser/cocoa/image_utils.mm @@ -0,0 +1,37 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/image_utils.h" + +@implementation NSImage (FlippedAdditions) + +- (void)drawInRect:(NSRect)dstRect + fromRect:(NSRect)srcRect + operation:(NSCompositingOperation)op + fraction:(CGFloat)requestedAlpha + neverFlipped:(BOOL)neverFlipped { + NSAffineTransform *transform = nil; + + // Flip drawing and adjust the origin to make the image come out + // right. + if (neverFlipped && [[NSGraphicsContext currentContext] isFlipped]) { + transform = [NSAffineTransform transform]; + [transform scaleXBy:1.0 yBy:-1.0]; + [transform concat]; + + // The lower edge of the image is as far from the origin as the + // upper edge was, plus it's on the other side of the origin. + dstRect.origin.y -= NSMaxY(dstRect) + NSMinY(dstRect); + } + + [self drawInRect:dstRect + fromRect:srcRect + operation:op + fraction:requestedAlpha]; + + // Flip drawing back, if needed. + [transform concat]; +} + +@end diff --git a/chrome/browser/cocoa/image_utils_unittest.mm b/chrome/browser/cocoa/image_utils_unittest.mm new file mode 100644 index 0000000..4398371 --- /dev/null +++ b/chrome/browser/cocoa/image_utils_unittest.mm @@ -0,0 +1,142 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#include "chrome/browser/cocoa/image_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +@interface ImageUtilsTestView : NSView { + @private + // Determine whether the view is flipped. + BOOL isFlipped_; + + // Determines whether to draw using the new method with + // |neverFlipped:|. + BOOL useNeverFlipped_; + + // Passed to |neverFlipped:| when drawing |image_|. + BOOL neverFlipped_; + + scoped_nsobject<NSImage> image_; +} +@property(assign, nonatomic) BOOL isFlipped; +@property(assign, nonatomic) BOOL useNeverFlipped; +@property(assign, nonatomic) BOOL neverFlipped; +@end + +@implementation ImageUtilsTestView +@synthesize isFlipped = isFlipped_; +@synthesize useNeverFlipped = useNeverFlipped_; +@synthesize neverFlipped = neverFlipped_; + +- (id)initWithFrame:(NSRect)rect { + self = [super initWithFrame:rect]; + if (self) { + rect = NSInsetRect(rect, 5.0, 5.0); + rect.origin = NSZeroPoint; + const NSSize imageSize = NSInsetRect(rect, 5.0, 5.0).size; + image_.reset([[NSImage alloc] initWithSize:imageSize]); + + NSBezierPath* path = [NSBezierPath bezierPath]; + [path moveToPoint:NSMakePoint(NSMinX(rect), NSMinY(rect))]; + [path lineToPoint:NSMakePoint(NSMinX(rect), NSMaxY(rect))]; + [path lineToPoint:NSMakePoint(NSMaxX(rect), NSMinY(rect))]; + [path closePath]; + + [image_ lockFocus]; + [[NSColor blueColor] setFill]; + [path fill]; + [image_ unlockFocus]; + } + return self; +} + +- (void)drawRect:(NSRect)rect { + NSBezierPath* path = [NSBezierPath bezierPath]; + [path moveToPoint:NSMakePoint(NSMinX(rect), NSMinY(rect))]; + [path lineToPoint:NSMakePoint(NSMinX(rect), NSMaxY(rect))]; + [path lineToPoint:NSMakePoint(NSMaxX(rect), NSMinY(rect))]; + [path closePath]; + + [[NSColor redColor] setFill]; + [path fill]; + + rect = NSInsetRect(rect, 5.0, 5.0); + rect = NSOffsetRect(rect, 2.0, 2.0); + + if (useNeverFlipped_) { + [image_ drawInRect:rect + fromRect:NSZeroRect + operation:NSCompositeCopy + fraction:1.0 + neverFlipped:neverFlipped_]; + } else { + [image_ drawInRect:rect + fromRect:NSZeroRect + operation:NSCompositeCopy + fraction:1.0]; + } +} + +@end + +namespace { + +class ImageUtilTest : public CocoaTest { + public: + ImageUtilTest() { + const NSRect frame = NSMakeRect(0, 0, 300, 100); + scoped_nsobject<ImageUtilsTestView> view( + [[ImageUtilsTestView alloc] initWithFrame: frame]); + view_ = view.get(); + [[test_window() contentView] addSubview:view_]; + } + + NSData* SnapshotView() { + [view_ display]; + + const NSRect bounds = [view_ bounds]; + + [view_ lockFocus]; + scoped_nsobject<NSBitmapImageRep> bitmap( + [[NSBitmapImageRep alloc] initWithFocusedViewRect:bounds]); + [view_ unlockFocus]; + + scoped_nsobject<NSImage> image( + [[NSImage alloc] initWithSize:bounds.size]); + [image addRepresentation:bitmap]; + + return [image TIFFRepresentation]; + } + + NSData* SnapshotViewBase() { + [view_ setUseNeverFlipped:NO]; + return SnapshotView(); + } + + NSData* SnapshotViewNeverFlipped(BOOL neverFlipped) { + [view_ setUseNeverFlipped:YES]; + [view_ setNeverFlipped:neverFlipped]; + return SnapshotView(); + } + + ImageUtilsTestView* view_; +}; + +TEST_F(ImageUtilTest, Test) { + // When not flipped, both drawing methods return the same data. + [view_ setIsFlipped:NO]; + NSData* baseSnapshotData = SnapshotViewBase(); + EXPECT_TRUE([baseSnapshotData isEqualToData:SnapshotViewNeverFlipped(YES)]); + EXPECT_TRUE([baseSnapshotData isEqualToData:SnapshotViewNeverFlipped(NO)]); + + // When flipped, there's only a difference when the context flip is + // not being respected. + [view_ setIsFlipped:YES]; + baseSnapshotData = SnapshotViewBase(); + EXPECT_FALSE([baseSnapshotData isEqualToData:SnapshotViewNeverFlipped(YES)]); + EXPECT_TRUE([baseSnapshotData isEqualToData:SnapshotViewNeverFlipped(NO)]); +} + +} // namespace diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 2f163e8..9b50d5b 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -753,6 +753,8 @@ 'browser/cocoa/hyperlink_button_cell.mm', 'browser/cocoa/hung_renderer_controller.h', 'browser/cocoa/hung_renderer_controller.mm', + 'browser/cocoa/image_utils.h', + 'browser/cocoa/image_utils.mm', 'browser/cocoa/import_progress_dialog.h', 'browser/cocoa/import_progress_dialog.mm', 'browser/cocoa/import_settings_dialog.h', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index ab39a51..4aad2dc 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -697,6 +697,7 @@ 'browser/cocoa/html_dialog_window_controller_unittest.mm', 'browser/cocoa/hung_renderer_controller_unittest.mm', 'browser/cocoa/hyperlink_button_cell_unittest.mm', + 'browser/cocoa/image_utils_unittest.mm', 'browser/cocoa/import_settings_dialog_unittest.mm', 'browser/cocoa/info_bubble_view_unittest.mm', 'browser/cocoa/info_bubble_window_unittest.mm', |