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 |