| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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_win.h" | 5 #include "ui/native_theme/native_theme_win.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <uxtheme.h> | 9 #include <uxtheme.h> |
| 10 #include <vsstyle.h> | 10 #include <vsstyle.h> |
| 11 #include <vssym32.h> | 11 #include <vssym32.h> |
| 12 | 12 |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/macros.h" | 14 #include "base/macros.h" |
| 15 #include "base/win/scoped_gdi_object.h" | 15 #include "base/win/scoped_gdi_object.h" |
| 16 #include "base/win/scoped_hdc.h" | 16 #include "base/win/scoped_hdc.h" |
| 17 #include "base/win/scoped_select_object.h" | 17 #include "base/win/scoped_select_object.h" |
| 18 #include "base/win/windows_version.h" | 18 #include "base/win/windows_version.h" |
| 19 #include "skia/ext/bitmap_platform_device.h" | 19 #include "skia/ext/bitmap_platform_device.h" |
| 20 #include "skia/ext/platform_canvas.h" | 20 #include "skia/ext/platform_canvas.h" |
| 21 #include "skia/ext/skia_utils_win.h" | 21 #include "skia/ext/skia_utils_win.h" |
| 22 #include "third_party/skia/include/core/SkCanvas.h" | 22 #include "third_party/skia/include/core/SkCanvas.h" |
| 23 #include "third_party/skia/include/core/SkColor.h" | 23 #include "third_party/skia/include/core/SkColor.h" |
| 24 #include "third_party/skia/include/core/SkColorPriv.h" | 24 #include "third_party/skia/include/core/SkColorPriv.h" |
| 25 #include "third_party/skia/include/core/SkRefCnt.h" | 25 #include "third_party/skia/include/core/SkRefCnt.h" |
| 26 #include "third_party/skia/include/core/SkShader.h" | 26 #include "third_party/skia/include/core/SkShader.h" |
| 27 #include "third_party/skia/include/core/SkSurface.h" |
| 27 #include "ui/base/material_design/material_design_controller.h" | 28 #include "ui/base/material_design/material_design_controller.h" |
| 28 #include "ui/display/win/dpi.h" | 29 #include "ui/display/win/dpi.h" |
| 29 #include "ui/gfx/color_palette.h" | 30 #include "ui/gfx/color_palette.h" |
| 30 #include "ui/gfx/color_utils.h" | 31 #include "ui/gfx/color_utils.h" |
| 31 #include "ui/gfx/gdi_util.h" | 32 #include "ui/gfx/gdi_util.h" |
| 32 #include "ui/gfx/geometry/rect.h" | 33 #include "ui/gfx/geometry/rect.h" |
| 33 #include "ui/gfx/geometry/rect_conversions.h" | 34 #include "ui/gfx/geometry/rect_conversions.h" |
| 34 #include "ui/gfx/skia_util.h" | 35 #include "ui/gfx/skia_util.h" |
| 35 #include "ui/native_theme/common_theme.h" | 36 #include "ui/native_theme/common_theme.h" |
| 36 | 37 |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 case kScrollbarHorizontalGripper: | 278 case kScrollbarHorizontalGripper: |
| 278 case kScrollbarVerticalGripper: | 279 case kScrollbarVerticalGripper: |
| 279 needs_paint_indirect = !GetThemeHandle(SCROLLBAR) || | 280 needs_paint_indirect = !GetThemeHandle(SCROLLBAR) || |
| 280 base::win::GetVersion() == base::win::VERSION_XP; | 281 base::win::GetVersion() == base::win::VERSION_XP; |
| 281 break; | 282 break; |
| 282 default: | 283 default: |
| 283 break; | 284 break; |
| 284 } | 285 } |
| 285 } | 286 } |
| 286 | 287 |
| 288 skia::ScopedPlatformPaint paint(canvas); |
| 289 HDC surface = paint.GetPlatformSurface(); |
| 287 if (needs_paint_indirect) | 290 if (needs_paint_indirect) |
| 288 PaintIndirect(canvas, part, state, rect, extra); | 291 PaintIndirect(canvas, surface, part, state, rect, extra); |
| 289 else | 292 else |
| 290 PaintDirect(canvas, part, state, rect, extra); | 293 PaintDirect(canvas, surface, part, state, rect, extra); |
| 291 } | 294 } |
| 292 | 295 |
| 293 NativeThemeWin::NativeThemeWin() | 296 NativeThemeWin::NativeThemeWin() |
| 294 : draw_theme_(NULL), | 297 : draw_theme_(NULL), |
| 295 draw_theme_ex_(NULL), | 298 draw_theme_ex_(NULL), |
| 296 get_theme_color_(NULL), | 299 get_theme_color_(NULL), |
| 297 get_theme_content_rect_(NULL), | 300 get_theme_content_rect_(NULL), |
| 298 get_theme_part_size_(NULL), | 301 get_theme_part_size_(NULL), |
| 299 open_theme_(NULL), | 302 open_theme_(NULL), |
| 300 close_theme_(NULL), | 303 close_theme_(NULL), |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 canvas->drawLine(position_x, rect.y(), position_x, rect.bottom(), paint); | 372 canvas->drawLine(position_x, rect.y(), position_x, rect.bottom(), paint); |
| 370 } | 373 } |
| 371 | 374 |
| 372 void NativeThemeWin::PaintMenuBackground(SkCanvas* canvas, | 375 void NativeThemeWin::PaintMenuBackground(SkCanvas* canvas, |
| 373 const gfx::Rect& rect) const { | 376 const gfx::Rect& rect) const { |
| 374 SkPaint paint; | 377 SkPaint paint; |
| 375 paint.setColor(GetSystemColor(NativeTheme::kColorId_MenuBackgroundColor)); | 378 paint.setColor(GetSystemColor(NativeTheme::kColorId_MenuBackgroundColor)); |
| 376 canvas->drawRect(gfx::RectToSkRect(rect), paint); | 379 canvas->drawRect(gfx::RectToSkRect(rect), paint); |
| 377 } | 380 } |
| 378 | 381 |
| 379 void NativeThemeWin::PaintDirect(SkCanvas* canvas, | 382 void NativeThemeWin::PaintDirect(SkCanvas* destination_canvas, |
| 383 HDC hdc, |
| 380 Part part, | 384 Part part, |
| 381 State state, | 385 State state, |
| 382 const gfx::Rect& rect, | 386 const gfx::Rect& rect, |
| 383 const ExtraParams& extra) const { | 387 const ExtraParams& extra) const { |
| 384 skia::ScopedPlatformPaint scoped_platform_paint(canvas); | |
| 385 HDC hdc = scoped_platform_paint.GetPlatformSurface(); | |
| 386 | |
| 387 switch (part) { | 388 switch (part) { |
| 388 case kCheckbox: | 389 case kCheckbox: |
| 389 PaintCheckbox(hdc, part, state, rect, extra.button); | 390 PaintCheckbox(hdc, part, state, rect, extra.button); |
| 390 return; | 391 return; |
| 391 case kInnerSpinButton: | 392 case kInnerSpinButton: |
| 392 PaintSpinButton(hdc, part, state, rect, extra.inner_spin); | 393 PaintSpinButton(hdc, part, state, rect, extra.inner_spin); |
| 393 return; | 394 return; |
| 394 case kMenuList: | 395 case kMenuList: |
| 395 PaintMenuList(hdc, state, rect, extra.menu_list); | 396 PaintMenuList(hdc, state, rect, extra.menu_list); |
| 396 return; | 397 return; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 PaintScrollbarArrow(hdc, part, state, rect, extra.scrollbar_arrow); | 432 PaintScrollbarArrow(hdc, part, state, rect, extra.scrollbar_arrow); |
| 432 return; | 433 return; |
| 433 case kScrollbarHorizontalThumb: | 434 case kScrollbarHorizontalThumb: |
| 434 case kScrollbarVerticalThumb: | 435 case kScrollbarVerticalThumb: |
| 435 case kScrollbarHorizontalGripper: | 436 case kScrollbarHorizontalGripper: |
| 436 case kScrollbarVerticalGripper: | 437 case kScrollbarVerticalGripper: |
| 437 PaintScrollbarThumb(hdc, part, state, rect, extra.scrollbar_thumb); | 438 PaintScrollbarThumb(hdc, part, state, rect, extra.scrollbar_thumb); |
| 438 return; | 439 return; |
| 439 case kScrollbarHorizontalTrack: | 440 case kScrollbarHorizontalTrack: |
| 440 case kScrollbarVerticalTrack: | 441 case kScrollbarVerticalTrack: |
| 441 PaintScrollbarTrack(canvas, hdc, part, state, rect, | 442 PaintScrollbarTrack(destination_canvas, hdc, part, state, rect, |
| 442 extra.scrollbar_track); | 443 extra.scrollbar_track); |
| 443 return; | 444 return; |
| 444 case kScrollbarCorner: | 445 case kScrollbarCorner: |
| 445 canvas->drawColor(SK_ColorWHITE, SkXfermode::kSrc_Mode); | 446 destination_canvas->drawColor(SK_ColorWHITE, SkXfermode::kSrc_Mode); |
| 446 return; | 447 return; |
| 447 case kTabPanelBackground: | 448 case kTabPanelBackground: |
| 448 PaintTabPanelBackground(hdc, rect); | 449 PaintTabPanelBackground(hdc, rect); |
| 449 return; | 450 return; |
| 450 case kTextField: | 451 case kTextField: |
| 451 PaintTextField(hdc, part, state, rect, extra.text_field); | 452 PaintTextField(hdc, part, state, rect, extra.text_field); |
| 452 return; | 453 return; |
| 453 case kTrackbarThumb: | 454 case kTrackbarThumb: |
| 454 case kTrackbarTrack: | 455 case kTrackbarTrack: |
| 455 PaintTrackbar(canvas, hdc, part, state, rect, extra.trackbar); | 456 PaintTrackbar(destination_canvas, hdc, part, state, rect, extra.trackbar); |
| 456 return; | 457 return; |
| 457 case kWindowResizeGripper: | 458 case kWindowResizeGripper: |
| 458 PaintWindowResizeGripper(hdc, rect); | 459 PaintWindowResizeGripper(hdc, rect); |
| 459 return; | 460 return; |
| 460 case kSliderTrack: | 461 case kSliderTrack: |
| 461 case kSliderThumb: | 462 case kSliderThumb: |
| 462 case kMaxPart: | 463 case kMaxPart: |
| 463 NOTREACHED(); | 464 NOTREACHED(); |
| 464 } | 465 } |
| 465 } | 466 } |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 case NativeTheme::kColorId_CallToActionColor: | 666 case NativeTheme::kColorId_CallToActionColor: |
| 666 return kCallToActionColorInvert; | 667 return kCallToActionColorInvert; |
| 667 default: | 668 default: |
| 668 return color_utils::InvertColor(GetAuraColor(color_id, this)); | 669 return color_utils::InvertColor(GetAuraColor(color_id, this)); |
| 669 } | 670 } |
| 670 } | 671 } |
| 671 | 672 |
| 672 return GetAuraColor(color_id, this); | 673 return GetAuraColor(color_id, this); |
| 673 } | 674 } |
| 674 | 675 |
| 675 void NativeThemeWin::PaintIndirect(SkCanvas* canvas, | 676 void NativeThemeWin::PaintIndirect(SkCanvas* destination_canvas, |
| 677 HDC destination_hdc, |
| 676 Part part, | 678 Part part, |
| 677 State state, | 679 State state, |
| 678 const gfx::Rect& rect, | 680 const gfx::Rect& rect, |
| 679 const ExtraParams& extra) const { | 681 const ExtraParams& extra) const { |
| 680 // TODO(asvitkine): This path is pretty inefficient - for each paint operation | 682 // TODO(asvitkine): This path is pretty inefficient - for each paint operation |
| 681 // it creates a new offscreen bitmap Skia canvas. This can | 683 // it creates a new offscreen bitmap Skia canvas. This can |
| 682 // be sped up by doing it only once per part/state and | 684 // be sped up by doing it only once per part/state and |
| 683 // keeping a cache of the resulting bitmaps. | 685 // keeping a cache of the resulting bitmaps. |
| 684 | 686 |
| 685 // Create an offscreen canvas that is backed by an HDC. | 687 // Create an offscreen canvas that is backed by an HDC. |
| 686 sk_sp<skia::BitmapPlatformDevice> device( | 688 base::win::ScopedCreateDC offscreen_hdc( |
| 687 skia::BitmapPlatformDevice::Create( | 689 skia::CreateOffscreenSurface(rect.width(), rect.height())); |
| 688 rect.width(), rect.height(), false, NULL)); | 690 sk_sp<SkSurface> offscreen_surface = |
| 689 DCHECK(device); | 691 skia::MapPlatformSurface(offscreen_hdc.Get()); |
| 690 SkCanvas offscreen_canvas(device.get()); | 692 DCHECK(offscreen_surface); |
| 691 DCHECK(skia::SupportsPlatformPaint(&offscreen_canvas)); | 693 SkCanvas* offscreen_canvas = offscreen_surface->getCanvas(); |
| 694 DCHECK(offscreen_canvas); |
| 692 | 695 |
| 693 // Some of the Windows theme drawing operations do not write correct alpha | 696 // Some of the Windows theme drawing operations do not write correct alpha |
| 694 // values for fully-opaque pixels; instead the pixels get alpha 0. This is | 697 // values for fully-opaque pixels; instead the pixels get alpha 0. This is |
| 695 // especially a problem on Windows XP or when using the Classic theme. | 698 // especially a problem on Windows XP or when using the Classic theme. |
| 696 // | 699 // |
| 697 // To work-around this, mark all pixels with a placeholder value, to detect | 700 // To work-around this, mark all pixels with a placeholder value, to detect |
| 698 // which pixels get touched by the paint operation. After paint, set any | 701 // which pixels get touched by the paint operation. After paint, set any |
| 699 // pixels that have alpha 0 to opaque and placeholders to fully-transparent. | 702 // pixels that have alpha 0 to opaque and placeholders to fully-transparent. |
| 700 const SkColor placeholder = SkColorSetARGB(1, 0, 0, 0); | 703 const SkColor placeholder = SkColorSetARGB(1, 0, 0, 0); |
| 701 offscreen_canvas.clear(placeholder); | 704 offscreen_canvas->clear(placeholder); |
| 702 | 705 |
| 703 // Offset destination rects to have origin (0,0). | 706 // Offset destination rects to have origin (0,0). |
| 704 gfx::Rect adjusted_rect(rect.size()); | 707 gfx::Rect adjusted_rect(rect.size()); |
| 705 ExtraParams adjusted_extra(extra); | 708 ExtraParams adjusted_extra(extra); |
| 706 switch (part) { | 709 switch (part) { |
| 707 case kProgressBar: | 710 case kProgressBar: |
| 708 adjusted_extra.progress_bar.value_rect_x = 0; | 711 adjusted_extra.progress_bar.value_rect_x = 0; |
| 709 adjusted_extra.progress_bar.value_rect_y = 0; | 712 adjusted_extra.progress_bar.value_rect_y = 0; |
| 710 break; | 713 break; |
| 711 case kScrollbarHorizontalTrack: | 714 case kScrollbarHorizontalTrack: |
| 712 case kScrollbarVerticalTrack: | 715 case kScrollbarVerticalTrack: |
| 713 adjusted_extra.scrollbar_track.track_x = 0; | 716 adjusted_extra.scrollbar_track.track_x = 0; |
| 714 adjusted_extra.scrollbar_track.track_y = 0; | 717 adjusted_extra.scrollbar_track.track_y = 0; |
| 715 break; | 718 break; |
| 716 default: | 719 default: |
| 717 break; | 720 break; |
| 718 } | 721 } |
| 719 // Draw the theme controls using existing HDC-drawing code. | 722 // Draw the theme controls using existing HDC-drawing code. |
| 720 PaintDirect(&offscreen_canvas, part, state, adjusted_rect, adjusted_extra); | 723 PaintDirect(offscreen_canvas, offscreen_hdc.Get(), part, state, |
| 724 adjusted_rect, adjusted_extra); |
| 721 | 725 |
| 722 SkBitmap bitmap = skia::ReadPixels(&offscreen_canvas); | 726 SkBitmap offscreen_bitmap = skia::MapPlatformBitmap(offscreen_hdc.Get()); |
| 723 | 727 |
| 724 // Post-process the pixels to fix up the alpha values (see big comment above). | 728 // Post-process the pixels to fix up the alpha values (see big comment above). |
| 725 const SkPMColor placeholder_value = SkPreMultiplyColor(placeholder); | 729 const SkPMColor placeholder_value = SkPreMultiplyColor(placeholder); |
| 726 const int pixel_count = rect.width() * rect.height(); | 730 const int pixel_count = rect.width() * rect.height(); |
| 727 SkPMColor* pixels = bitmap.getAddr32(0, 0); | 731 SkPMColor* pixels = offscreen_bitmap.getAddr32(0, 0); |
| 728 for (int i = 0; i < pixel_count; i++) { | 732 for (int i = 0; i < pixel_count; i++) { |
| 729 if (pixels[i] == placeholder_value) { | 733 if (pixels[i] == placeholder_value) { |
| 730 // Pixel wasn't touched - make it fully transparent. | 734 // Pixel wasn't touched - make it fully transparent. |
| 731 pixels[i] = SkPackARGB32(0, 0, 0, 0); | 735 pixels[i] = SkPackARGB32(0, 0, 0, 0); |
| 732 } else if (SkGetPackedA32(pixels[i]) == 0) { | 736 } else if (SkGetPackedA32(pixels[i]) == 0) { |
| 733 // Pixel was touched but has incorrect alpha of 0, make it fully opaque. | 737 // Pixel was touched but has incorrect alpha of 0, make it fully opaque. |
| 734 pixels[i] = SkPackARGB32(0xFF, | 738 pixels[i] = SkPackARGB32(0xFF, |
| 735 SkGetPackedR32(pixels[i]), | 739 SkGetPackedR32(pixels[i]), |
| 736 SkGetPackedG32(pixels[i]), | 740 SkGetPackedG32(pixels[i]), |
| 737 SkGetPackedB32(pixels[i])); | 741 SkGetPackedB32(pixels[i])); |
| 738 } | 742 } |
| 739 } | 743 } |
| 740 | 744 |
| 741 // Draw the offscreen bitmap to the destination canvas. | 745 destination_canvas->drawBitmap(offscreen_bitmap, rect.x(), rect.y()); |
| 742 canvas->drawBitmap(bitmap, rect.x(), rect.y()); | |
| 743 } | 746 } |
| 744 | 747 |
| 745 HRESULT NativeThemeWin::GetThemePartSize(ThemeName theme_name, | 748 HRESULT NativeThemeWin::GetThemePartSize(ThemeName theme_name, |
| 746 HDC hdc, | 749 HDC hdc, |
| 747 int part_id, | 750 int part_id, |
| 748 int state_id, | 751 int state_id, |
| 749 RECT* rect, | 752 RECT* rect, |
| 750 int ts, | 753 int ts, |
| 751 SIZE* size) const { | 754 SIZE* size) const { |
| 752 HANDLE handle = GetThemeHandle(theme_name); | 755 HANDLE handle = GetThemeHandle(theme_name); |
| (...skipping 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2079 break; | 2082 break; |
| 2080 case LAST: | 2083 case LAST: |
| 2081 NOTREACHED(); | 2084 NOTREACHED(); |
| 2082 break; | 2085 break; |
| 2083 } | 2086 } |
| 2084 theme_handles_[theme_name] = handle; | 2087 theme_handles_[theme_name] = handle; |
| 2085 return handle; | 2088 return handle; |
| 2086 } | 2089 } |
| 2087 | 2090 |
| 2088 } // namespace ui | 2091 } // namespace ui |
| OLD | NEW |