| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/native_theme/native_theme_mac.h" | 5 #include "ui/native_theme/native_theme_mac.h" |
| 6 | 6 |
| 7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
| 11 #include "base/mac/scoped_cftyperef.h" | |
| 12 #include "base/mac/sdk_forward_declarations.h" | 11 #include "base/mac/sdk_forward_declarations.h" |
| 13 #include "base/macros.h" | 12 #include "base/macros.h" |
| 14 #import "skia/ext/skia_utils_mac.h" | 13 #import "skia/ext/skia_utils_mac.h" |
| 15 #include "third_party/skia/include/core/SkDrawLooper.h" | |
| 16 #include "third_party/skia/include/core/SkRRect.h" | |
| 17 #include "third_party/skia/include/effects/SkGradientShader.h" | |
| 18 #include "ui/base/material_design/material_design_controller.h" | 14 #include "ui/base/material_design/material_design_controller.h" |
| 19 #include "ui/gfx/color_palette.h" | |
| 20 #include "ui/gfx/geometry/rect.h" | 15 #include "ui/gfx/geometry/rect.h" |
| 21 #include "ui/gfx/shadow_value.h" | |
| 22 #include "ui/gfx/skia_paint_util.h" | |
| 23 #include "ui/gfx/skia_util.h" | 16 #include "ui/gfx/skia_util.h" |
| 24 #include "ui/native_theme/common_theme.h" | 17 #include "ui/native_theme/common_theme.h" |
| 25 | 18 |
| 26 namespace { | 19 namespace { |
| 27 | 20 |
| 28 // Values calculated by reading pixels and solving simultaneous equations | 21 // Values calculated by reading pixels and solving simultaneous equations |
| 29 // derived from "A over B" alpha compositing. Steps: Sample the semi-transparent | 22 // derived from "A over B" alpha compositing. Steps: Sample the semi-transparent |
| 30 // pixel over two backgrounds; P1, P2 over backgrounds B1, B2. Use the color | 23 // pixel over two backgrounds; P1, P2 over backgrounds B1, B2. Use the color |
| 31 // value between 0.0 and 1.0 (i.e. divide by 255.0). Then, | 24 // value between 0.0 and 1.0 (i.e. divide by 255.0). Then, |
| 32 // alpha = (P2 - P1 + B1 - B2) / (B1 - B2) | 25 // alpha = (P2 - P1 + B1 - B2) / (B1 - B2) |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 // and is a good shade of gray, it's not blue enough for the Blue theme. | 272 // and is a good shade of gray, it's not blue enough for the Blue theme. |
| 280 flags.setColor(GetSystemColor(kColorId_FocusedMenuItemBackgroundColor)); | 273 flags.setColor(GetSystemColor(kColorId_FocusedMenuItemBackgroundColor)); |
| 281 canvas->drawRect(gfx::RectToSkRect(rect), flags); | 274 canvas->drawRect(gfx::RectToSkRect(rect), flags); |
| 282 break; | 275 break; |
| 283 default: | 276 default: |
| 284 NOTREACHED(); | 277 NOTREACHED(); |
| 285 break; | 278 break; |
| 286 } | 279 } |
| 287 } | 280 } |
| 288 | 281 |
| 289 // static | |
| 290 sk_sp<SkShader> NativeThemeMac::GetButtonBackgroundShader( | |
| 291 ButtonBackgroundType type, | |
| 292 int height) { | |
| 293 using ColorByState = EnumArray<ButtonBackgroundType, SkColor>; | |
| 294 SkPoint gradient_points[2]; | |
| 295 gradient_points[0].iset(0, 0); | |
| 296 gradient_points[1].iset(0, height); | |
| 297 | |
| 298 SkScalar gradient_positions[] = { 0.0, 1.0 }; | |
| 299 | |
| 300 // These hex values are directly from the detailed specs in | |
| 301 // https://crbug.com/543683. | |
| 302 const SkColor kGrey = SkColorSetRGB(0xf6, 0xf6, 0xf6); | |
| 303 const SkColor kBlueStart = SkColorSetRGB(0x6b, 0xb3, 0xfa); | |
| 304 const SkColor kBlueEnd = SkColorSetRGB(0x07, 0x7d, 0xff); | |
| 305 const SkColor kPressedBlueStart = SkColorSetRGB(0x3e, 0x8b, 0xf6); | |
| 306 const SkColor kPressedBlueEnd = SkColorSetRGB(0x03, 0x51, 0xff); | |
| 307 | |
| 308 ColorByState start_colors; | |
| 309 start_colors[ButtonBackgroundType::DISABLED] = kGrey; | |
| 310 start_colors[ButtonBackgroundType::HIGHLIGHTED] = kBlueStart; | |
| 311 start_colors[ButtonBackgroundType::NORMAL] = SK_ColorWHITE; | |
| 312 start_colors[ButtonBackgroundType::PRESSED] = kPressedBlueStart; | |
| 313 | |
| 314 ColorByState end_colors; | |
| 315 end_colors[ButtonBackgroundType::DISABLED] = kGrey; | |
| 316 end_colors[ButtonBackgroundType::HIGHLIGHTED] = kBlueEnd; | |
| 317 end_colors[ButtonBackgroundType::NORMAL] = SK_ColorWHITE; | |
| 318 end_colors[ButtonBackgroundType::PRESSED] = kPressedBlueEnd; | |
| 319 | |
| 320 SkColor gradient_colors[] = {start_colors[type], end_colors[type]}; | |
| 321 | |
| 322 for (size_t i = 0; i < arraysize(gradient_colors); ++i) | |
| 323 gradient_colors[i] = ApplySystemControlTint(gradient_colors[i]); | |
| 324 | |
| 325 return SkGradientShader::MakeLinear( | |
| 326 gradient_points, gradient_colors, gradient_positions, | |
| 327 arraysize(gradient_positions), | |
| 328 SkShader::kClamp_TileMode); | |
| 329 } | |
| 330 | |
| 331 // static | |
| 332 sk_sp<SkShader> NativeThemeMac::GetButtonBorderShader(ButtonBackgroundType type, | |
| 333 int height) { | |
| 334 using ColorByState = EnumArray<ButtonBackgroundType, SkColor>; | |
| 335 SkPoint gradient_points[2]; | |
| 336 gradient_points[0].iset(0, 0); | |
| 337 gradient_points[1].iset(0, height); | |
| 338 | |
| 339 // Two positions works well for pressed and highlighted, but the side edges of | |
| 340 // disabled and normal are more heavily weighted at the top and bottom. | |
| 341 // TODO(tapted): Use more positions for normal and disabled. | |
| 342 SkScalar gradient_positions[] = {0.0, 1.0}; | |
| 343 | |
| 344 ColorByState top_edge; | |
| 345 top_edge[ButtonBackgroundType::DISABLED] = SkColorSetRGB(0xd2, 0xc2, 0xc2); | |
| 346 top_edge[ButtonBackgroundType::HIGHLIGHTED] = SkColorSetRGB(0x6a, 0x9f, 0xff); | |
| 347 top_edge[ButtonBackgroundType::NORMAL] = SkColorSetRGB(0xcc, 0xcc, 0xcc); | |
| 348 top_edge[ButtonBackgroundType::PRESSED] = SkColorSetRGB(0x4f, 0x72, 0xfb); | |
| 349 ColorByState bottom_edge; | |
| 350 bottom_edge[ButtonBackgroundType::DISABLED] = SkColorSetRGB(0xbe, 0xbe, 0xbe); | |
| 351 bottom_edge[ButtonBackgroundType::HIGHLIGHTED] = | |
| 352 SkColorSetRGB(0x43, 0x52, 0xff); | |
| 353 bottom_edge[ButtonBackgroundType::NORMAL] = SkColorSetRGB(0x9d, 0x9d, 0x9d); | |
| 354 bottom_edge[ButtonBackgroundType::PRESSED] = SkColorSetRGB(0x3e, 0x12, 0xff); | |
| 355 | |
| 356 SkColor gradient_colors[] = {top_edge[type], bottom_edge[type]}; | |
| 357 | |
| 358 for (size_t i = 0; i < arraysize(gradient_colors); ++i) | |
| 359 gradient_colors[i] = ApplySystemControlTint(gradient_colors[i]); | |
| 360 | |
| 361 return SkGradientShader::MakeLinear( | |
| 362 gradient_points, gradient_colors, gradient_positions, | |
| 363 arraysize(gradient_positions), SkShader::kClamp_TileMode); | |
| 364 } | |
| 365 | |
| 366 // static | |
| 367 void NativeThemeMac::PaintStyledGradientButton(cc::PaintCanvas* canvas, | |
| 368 const gfx::Rect& integer_bounds, | |
| 369 ButtonBackgroundType type, | |
| 370 bool round_left, | |
| 371 bool round_right, | |
| 372 bool focus) { | |
| 373 const SkScalar kBorderThickness = 1; | |
| 374 const SkScalar kFocusRingThickness = 4; | |
| 375 const SkColor kFocusRingColor = ApplySystemControlTint( | |
| 376 SkColorSetARGB(0x94, 0x79, 0xa7, 0xe9)); | |
| 377 | |
| 378 const SkVector kNoCurve = {0, 0}; | |
| 379 const SkVector kCurve = {kButtonCornerRadius, kButtonCornerRadius}; | |
| 380 const SkVector kLeftCurves[4] = {kCurve, kNoCurve, kNoCurve, kCurve}; | |
| 381 const SkVector kRightCurves[4] = {kNoCurve, kCurve, kCurve, kNoCurve}; | |
| 382 | |
| 383 const SkScalar kShadowOffsetY = 1; | |
| 384 const SkColor kShadowColor = SkColorSetA(SK_ColorBLACK, 0x05); | |
| 385 const double kShadowBlur = 0.0; | |
| 386 const std::vector<gfx::ShadowValue> shadows( | |
| 387 1, gfx::ShadowValue(gfx::Vector2d(0, kShadowOffsetY), kShadowBlur, | |
| 388 kShadowColor)); | |
| 389 | |
| 390 SkRect bounds = gfx::RectToSkRect(integer_bounds); | |
| 391 | |
| 392 // Inset to account for the focus ring. Note it draws over the border stroke. | |
| 393 bounds.inset(kFocusRingThickness - kBorderThickness, | |
| 394 kFocusRingThickness - kBorderThickness); | |
| 395 | |
| 396 SkRRect shape; | |
| 397 if (round_left && round_right) | |
| 398 shape.setRectXY(bounds, kButtonCornerRadius, kButtonCornerRadius); | |
| 399 else if (round_left) | |
| 400 shape.setRectRadii(bounds, kLeftCurves); | |
| 401 else if (round_right) | |
| 402 shape.setRectRadii(bounds, kRightCurves); | |
| 403 else | |
| 404 shape.setRect(bounds); | |
| 405 | |
| 406 cc::PaintFlags flags; | |
| 407 flags.setStyle(cc::PaintFlags::kFill_Style); | |
| 408 flags.setAntiAlias(true); | |
| 409 | |
| 410 // First draw the darker "outer" border, with its gradient and shadow. Inside | |
| 411 // a tab strip, this will draw over the outer border and inner separator. | |
| 412 flags.setLooper(gfx::CreateShadowDrawLooper(shadows)); | |
| 413 flags.setShader( | |
| 414 cc::WrapSkShader(GetButtonBorderShader(type, shape.height()))); | |
| 415 canvas->drawRRect(shape, flags); | |
| 416 | |
| 417 // Then, inset the rounded rect and draw over that with the inner gradient. | |
| 418 shape.inset(kBorderThickness, kBorderThickness); | |
| 419 flags.setLooper(nullptr); | |
| 420 flags.setShader( | |
| 421 cc::WrapSkShader(GetButtonBackgroundShader(type, shape.height()))); | |
| 422 canvas->drawRRect(shape, flags); | |
| 423 | |
| 424 if (!focus) | |
| 425 return; | |
| 426 | |
| 427 SkRRect outer_shape; | |
| 428 shape.outset(kFocusRingThickness, kFocusRingThickness, &outer_shape); | |
| 429 flags.setShader(nullptr); | |
| 430 flags.setColor(kFocusRingColor); | |
| 431 canvas->drawDRRect(outer_shape, shape, flags); | |
| 432 } | |
| 433 | |
| 434 NativeThemeMac::NativeThemeMac() { | 282 NativeThemeMac::NativeThemeMac() { |
| 435 } | 283 } |
| 436 | 284 |
| 437 NativeThemeMac::~NativeThemeMac() { | 285 NativeThemeMac::~NativeThemeMac() { |
| 438 } | 286 } |
| 439 | 287 |
| 440 } // namespace ui | 288 } // namespace ui |
| OLD | NEW |