| Index: chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
|
| diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
|
| index c99c63fae6c0f9031e5aba28356c75398d822312..771a364021ee35453f665dc374b78e55a88663b6 100644
|
| --- a/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
|
| +++ b/chrome/browser/ui/cocoa/tabs/tab_strip_controller.mm
|
| @@ -30,6 +30,7 @@
|
| #include "chrome/browser/ui/browser_navigator.h"
|
| #include "chrome/browser/ui/browser_tabstrip.h"
|
| #import "chrome/browser/ui/cocoa/browser_window_controller.h"
|
| +#import "chrome/browser/ui/cocoa/browser_window_utils.h"
|
| #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h"
|
| #include "chrome/browser/ui/cocoa/drag_util.h"
|
| #import "chrome/browser/ui/cocoa/image_button_cell.h"
|
| @@ -191,33 +192,16 @@ NSImage* CreateImageWithSize(NSSize size,
|
| // Takes a normal bitmap and a mask image and returns an image the size of the
|
| // mask that has pixels from |image| but alpha information from |mask|.
|
| NSImage* ApplyMask(NSImage* image, NSImage* mask) {
|
| - return [CreateImageWithSize([mask size], ^(NSSize size) {
|
| - // Skip a few pixels from the top of the tab background gradient, because
|
| - // the new tab button is not drawn at the very top of the browser window.
|
| - const int kYOffset = 10;
|
| - CGFloat width = size.width;
|
| - CGFloat height = size.height;
|
| -
|
| - // In some themes, the tab background image is narrower than the
|
| - // new tab button, so tile the background image.
|
| - CGFloat x = 0;
|
| - // The floor() is to make sure images with odd widths don't draw to the
|
| - // same pixel twice on retina displays. (Using NSDrawThreePartImage()
|
| - // caused a startup perf regression, so that cannot be used.)
|
| - CGFloat tileWidth = floor(std::min(width, [image size].width));
|
| - while (x < width) {
|
| - [image drawAtPoint:NSMakePoint(x, 0)
|
| - fromRect:NSMakeRect(0,
|
| - [image size].height - height - kYOffset,
|
| - tileWidth,
|
| - height)
|
| - operation:NSCompositeCopy
|
| - fraction:1.0];
|
| - x += tileWidth;
|
| - }
|
| + DCHECK_EQ([image size].width, [mask size].width);
|
| + DCHECK_EQ([image size].height, [mask size].height);
|
|
|
| + return [CreateImageWithSize([mask size], ^(NSSize size) {
|
| + [image drawAtPoint:NSZeroPoint
|
| + fromRect:NSMakeRect(0, 0, size.width, size.height)
|
| + operation:NSCompositeCopy
|
| + fraction:1.0];
|
| [mask drawAtPoint:NSZeroPoint
|
| - fromRect:NSMakeRect(0, 0, width, height)
|
| + fromRect:NSMakeRect(0, 0, size.width, size.height)
|
| operation:NSCompositeDestinationIn
|
| fraction:1.0];
|
| }) autorelease];
|
| @@ -275,6 +259,51 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
|
| }) autorelease];
|
| }
|
|
|
| +// Tiles |image| horizontally into a new NSImage of |dest_size|. |dest_y_inset|
|
| +// refers to the position from the bottom of the returned image at which the top
|
| +// of |image| should be painted.
|
| +NSImage* TileHorizontally(NSImage* image,
|
| + CGFloat dest_y_inset,
|
| + NSSize dest_size) {
|
| + return [CreateImageWithSize(dest_size, ^(NSSize size) {
|
| + CGFloat width = size.width;
|
| + CGFloat height = size.height;
|
| +
|
| + CGFloat x = 0;
|
| + // The floor() is to make sure images with odd widths and height don't
|
| + // draw to the same pixel twice on retina displays. (Using
|
| + // NSDrawThreePartImage() caused a startup perf regression, so that
|
| + // cannot be used.)
|
| + CGFloat tile_width = floor(std::min(width, [image size].width));
|
| + while (x < width) {
|
| + [image drawAtPoint:NSMakePoint(x, 0)
|
| + fromRect:NSMakeRect(0,
|
| + [image size].height - dest_y_inset,
|
| + tile_width,
|
| + height)
|
| + operation:NSCompositeCopy
|
| + fraction:1.0];
|
| + x += tile_width;
|
| + }
|
| + }) autorelease];
|
| +}
|
| +
|
| +// Computes the y position that the top of a theme image with |alignment|
|
| +// should be painted at. The returned y position is in the coordinates of an
|
| +// NSImage of |dst_height| which is centered on the new tab button. This method
|
| +// is a helper for [TabStripController setNewTabImages].
|
| +int NewTabButtonThemeBackgroundYPosition(TabStripView* tabstrip,
|
| + ThemeImageAlignment alignment,
|
| + CGFloat dst_height) {
|
| + CGFloat y_position_in_tabstrip =
|
| + [BrowserWindowUtils themeImagePositionInTabStripCoords:tabstrip
|
| + alignment:alignment].y;
|
| + // The image is centered in the new tab button.
|
| + NSView* new_tab_button = [tabstrip getNewTabButton];
|
| + return y_position_in_tabstrip -
|
| + roundf((NSHeight([new_tab_button bounds]) - dst_height) / 2.0);
|
| +}
|
| +
|
| } // namespace
|
|
|
| @interface TabStripController (Private)
|
| @@ -2268,9 +2297,30 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
|
| NSImage* normal = rb.GetNativeImageNamed(IDR_NEWTAB_BUTTON).ToNSImage();
|
| NSImage* hover = rb.GetNativeImageNamed(IDR_NEWTAB_BUTTON_H).ToNSImage();
|
| NSImage* pressed = rb.GetNativeImageNamed(IDR_NEWTAB_BUTTON_P).ToNSImage();
|
| + NSImage* bgActive = theme->GetNSImageNamed(IDR_THEME_TAB_BACKGROUND);
|
| + NSImage* bgActiveOverlay = nil;
|
| + if (theme->HasCustomImage(IDR_THEME_TAB_BACKGROUND_OVERLAY)) {
|
| + bgActiveOverlay = theme->GetNSImageNamed(
|
| + IDR_THEME_TAB_BACKGROUND_OVERLAY);
|
| + }
|
|
|
| - NSImage* foreground = ApplyMask(
|
| - theme->GetNSImageNamed(IDR_THEME_TAB_BACKGROUND), mask);
|
| + int yPositionAlignWithFrame = NewTabButtonThemeBackgroundYPosition(
|
| + tabStripView_, THEME_IMAGE_ALIGN_WITH_FRAME, [mask size].height);
|
| + int yPositionAlignWithTabStrip = NewTabButtonThemeBackgroundYPosition(
|
| + tabStripView_, THEME_IMAGE_ALIGN_WITH_TAB_STRIP, [mask size].height);
|
| +
|
| + // Create the foreground image by combining the tinted frame image
|
| + // (IDR_THEME_TAB_BACKGROUND) and the custom theme provided overlay
|
| + // (IDR_THEME_TAB_BACKGROUND_OVERLAY). Tile the images because the images
|
| + // can be narrower than the new tab button for some themes.
|
| + NSImage* unmaskedForeground = TileHorizontally(bgActive,
|
| + yPositionAlignWithFrame, [mask size]);
|
| + if (bgActiveOverlay) {
|
| + NSImage* tiledOverlay = TileHorizontally(bgActiveOverlay,
|
| + yPositionAlignWithTabStrip, [mask size]);
|
| + unmaskedForeground = Overlay(unmaskedForeground, tiledOverlay, 1.0);
|
| + }
|
| + NSImage* foreground = ApplyMask(unmaskedForeground, mask);
|
|
|
| [[newTabButton_ cell] setImage:Overlay(foreground, normal, 1.0)
|
| forButtonState:image_button_cell::kDefaultState];
|
| @@ -2282,8 +2332,11 @@ NSImage* Overlay(NSImage* ground, NSImage* overlay, CGFloat alpha) {
|
| // IDR_THEME_TAB_BACKGROUND_INACTIVE is only used with the default theme.
|
| if (theme->UsingDefaultTheme()) {
|
| const CGFloat alpha = tabs::kImageNoFocusAlpha;
|
| - NSImage* background = ApplyMask(
|
| - theme->GetNSImageNamed(IDR_THEME_TAB_BACKGROUND_INACTIVE), mask);
|
| + NSImage* unmaskedBackground = TileHorizontally(
|
| + rb.GetNativeImageNamed(IDR_THEME_TAB_BACKGROUND_INACTIVE).ToNSImage(),
|
| + yPositionAlignWithTabStrip,
|
| + [mask size]);
|
| + NSImage* background = ApplyMask(unmaskedBackground, mask);
|
| [[newTabButton_ cell] setImage:Overlay(background, normal, alpha)
|
| forButtonState:image_button_cell::kDefaultStateBackground];
|
| [[newTabButton_ cell] setImage:Overlay(background, hover, alpha)
|
|
|