summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authorbenrg@chromium.org <benrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-28 19:59:52 +0000
committerbenrg@chromium.org <benrg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-28 19:59:52 +0000
commit63500306b4fd634b340d227964449ec4fd13bda7 (patch)
tree6a07f715302e9eb54dd4d742c5a7158fd3219bc2 /ui/gfx
parentb8777b72fece4ad14347a57696c0a635e77baa2e (diff)
downloadchromium_src-63500306b4fd634b340d227964449ec4fd13bda7.zip
chromium_src-63500306b4fd634b340d227964449ec4fd13bda7.tar.gz
chromium_src-63500306b4fd634b340d227964449ec4fd13bda7.tar.bz2
Reorder methods in native_theme_{base,chromeos,win}.cc to match .h order.
Also moved some static constants and functions into the anonymous namespaces, and marked a couple of static locals as const (because they are, and non-const static locals make me nervous). NativeThemeWin is kind of a mess. I kept the public overload of PaintTextField next to the private overload because I think it probably should be private. The file length decreased by one line because I removed a blank line. BUG=none TEST=none Review URL: http://codereview.chromium.org/8679010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111754 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r--ui/gfx/native_theme_base.cc302
-rw-r--r--ui/gfx/native_theme_chromeos.cc40
-rw-r--r--ui/gfx/native_theme_win.cc1279
3 files changed, 810 insertions, 811 deletions
diff --git a/ui/gfx/native_theme_base.cc b/ui/gfx/native_theme_base.cc
index 04e2b844..2c344b0 100644
--- a/ui/gfx/native_theme_base.cc
+++ b/ui/gfx/native_theme_base.cc
@@ -20,30 +20,23 @@ namespace {
const SkColor kDefaultDialogBackgroundColor = SkColorSetRGB(200, 200, 200);
const SkColor kInvalidColorIdColor = SkColorSetRGB(255, 0, 128);
-} // namespace
-
-namespace gfx {
-
-unsigned int NativeThemeBase::button_length_ = 14;
-unsigned int NativeThemeBase::scrollbar_width_ = 15;
-
// These are the default dimensions of radio buttons and checkboxes.
-static const int kCheckboxAndRadioWidth = 13;
-static const int kCheckboxAndRadioHeight = 13;
+const int kCheckboxAndRadioWidth = 13;
+const int kCheckboxAndRadioHeight = 13;
// These sizes match the sizes in Chromium Win.
-static const int kSliderThumbWidth = 11;
-static const int kSliderThumbHeight = 21;
+const int kSliderThumbWidth = 11;
+const int kSliderThumbHeight = 21;
-static const SkColor kSliderTrackBackgroundColor =
+const SkColor kSliderTrackBackgroundColor =
SkColorSetRGB(0xe3, 0xdd, 0xd8);
-static const SkColor kSliderThumbLightGrey = SkColorSetRGB(0xf4, 0xf2, 0xef);
-static const SkColor kSliderThumbDarkGrey = SkColorSetRGB(0xea, 0xe5, 0xe0);
-static const SkColor kSliderThumbBorderDarkGrey =
+const SkColor kSliderThumbLightGrey = SkColorSetRGB(0xf4, 0xf2, 0xef);
+const SkColor kSliderThumbDarkGrey = SkColorSetRGB(0xea, 0xe5, 0xe0);
+const SkColor kSliderThumbBorderDarkGrey =
SkColorSetRGB(0x9d, 0x96, 0x8e);
// Get lightness adjusted color.
-static SkColor BrightenColor(const color_utils::HSL& hsl, SkAlpha alpha,
+SkColor BrightenColor(const color_utils::HSL& hsl, SkAlpha alpha,
double lightness_amount) {
color_utils::HSL adjusted = hsl;
adjusted.l += lightness_amount;
@@ -55,11 +48,12 @@ static SkColor BrightenColor(const color_utils::HSL& hsl, SkAlpha alpha,
return color_utils::HSLToSkColor(adjusted, alpha);
}
-NativeThemeBase::NativeThemeBase() {
-}
+} // namespace
-NativeThemeBase::~NativeThemeBase() {
-}
+namespace gfx {
+
+unsigned int NativeThemeBase::button_length_ = 14;
+unsigned int NativeThemeBase::scrollbar_width_ = 15;
gfx::Size NativeThemeBase::GetPartSize(Part part,
State state,
@@ -131,6 +125,106 @@ gfx::Size NativeThemeBase::GetPartSize(Part part,
return gfx::Size();
}
+void NativeThemeBase::Paint(SkCanvas* canvas,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const ExtraParams& extra) const {
+ switch (part) {
+ // Please keep these in the order of NativeTheme::Part.
+ case kCheckbox:
+ PaintCheckbox(canvas, state, rect, extra.button);
+ break;
+ case kInnerSpinButton:
+ PaintInnerSpinButton(canvas, state, rect, extra.inner_spin);
+ break;
+ case kMenuList:
+ PaintMenuList(canvas, state, rect, extra.menu_list);
+ break;
+ case kMenuCheck:
+ case kMenuCheckBackground:
+ case kMenuPopupArrow:
+ NOTIMPLEMENTED();
+ break;
+ case kMenuPopupBackground:
+ PaintMenuPopupBackground(canvas, state, rect, extra.menu_list);
+ break;
+ case kMenuPopupGutter:
+ case kMenuPopupSeparator:
+ NOTIMPLEMENTED();
+ break;
+ case kMenuItemBackground:
+ PaintMenuItemBackground(canvas, state, rect, extra.menu_list);
+ break;
+ case kProgressBar:
+ PaintProgressBar(canvas, state, rect, extra.progress_bar);
+ break;
+ case kPushButton:
+ PaintButton(canvas, state, rect, extra.button);
+ break;
+ case kRadio:
+ PaintRadio(canvas, state, rect, extra.button);
+ break;
+ case kScrollbarDownArrow:
+ case kScrollbarUpArrow:
+ case kScrollbarLeftArrow:
+ case kScrollbarRightArrow:
+ PaintArrowButton(canvas, rect, part, state);
+ break;
+ case kScrollbarHorizontalThumb:
+ case kScrollbarVerticalThumb:
+ PaintScrollbarThumb(canvas, part, state, rect);
+ break;
+ case kScrollbarHorizontalTrack:
+ case kScrollbarVerticalTrack:
+ PaintScrollbarTrack(canvas, part, state, extra.scrollbar_track, rect);
+ break;
+ case kScrollbarHorizontalGripper:
+ case kScrollbarVerticalGripper:
+ NOTIMPLEMENTED();
+ break;
+ case kSliderTrack:
+ PaintSliderTrack(canvas, state, rect, extra.slider);
+ break;
+ case kSliderThumb:
+ PaintSliderThumb(canvas, state, rect, extra.slider);
+ break;
+ case kTabPanelBackground:
+ NOTIMPLEMENTED();
+ break;
+ case kTextField:
+ PaintTextField(canvas, state, rect, extra.text_field);
+ break;
+ case kTrackbarThumb:
+ case kTrackbarTrack:
+ case kWindowResizeGripper:
+ NOTIMPLEMENTED();
+ break;
+ default:
+ NOTREACHED() << "Unknown theme part: " << part;
+ break;
+ }
+}
+
+SkColor NativeThemeBase::GetSystemColor(ColorId color_id) const {
+ // This implementation returns hardcoded colors. It's used by NativeThemeAura
+ // and NativeThemeChromeos and overridden by NativeThemeGtk.
+ switch (color_id) {
+ case kColorId_DialogBackground:
+ return kDefaultDialogBackgroundColor;
+ default:
+ NOTREACHED() << "Invalid color_id: " << color_id;
+ break;
+ }
+ return kInvalidColorIdColor;
+}
+
+NativeThemeBase::NativeThemeBase() {
+}
+
+NativeThemeBase::~NativeThemeBase() {
+}
+
void NativeThemeBase::PaintArrowButton(
SkCanvas* canvas,
const gfx::Rect& rect, Part direction, State state) const {
@@ -257,100 +351,6 @@ void NativeThemeBase::PaintArrowButton(
canvas->drawPath(path, paint);
}
-void NativeThemeBase::Paint(SkCanvas* canvas,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ExtraParams& extra) const {
- switch (part) {
- // Please keep these in the order of NativeTheme::Part.
- case kCheckbox:
- PaintCheckbox(canvas, state, rect, extra.button);
- break;
- case kInnerSpinButton:
- PaintInnerSpinButton(canvas, state, rect, extra.inner_spin);
- break;
- case kMenuList:
- PaintMenuList(canvas, state, rect, extra.menu_list);
- break;
- case kMenuCheck:
- case kMenuCheckBackground:
- case kMenuPopupArrow:
- NOTIMPLEMENTED();
- break;
- case kMenuPopupBackground:
- PaintMenuPopupBackground(canvas, state, rect, extra.menu_list);
- break;
- case kMenuPopupGutter:
- case kMenuPopupSeparator:
- NOTIMPLEMENTED();
- break;
- case kMenuItemBackground:
- PaintMenuItemBackground(canvas, state, rect, extra.menu_list);
- break;
- case kProgressBar:
- PaintProgressBar(canvas, state, rect, extra.progress_bar);
- break;
- case kPushButton:
- PaintButton(canvas, state, rect, extra.button);
- break;
- case kRadio:
- PaintRadio(canvas, state, rect, extra.button);
- break;
- case kScrollbarDownArrow:
- case kScrollbarUpArrow:
- case kScrollbarLeftArrow:
- case kScrollbarRightArrow:
- PaintArrowButton(canvas, rect, part, state);
- break;
- case kScrollbarHorizontalThumb:
- case kScrollbarVerticalThumb:
- PaintScrollbarThumb(canvas, part, state, rect);
- break;
- case kScrollbarHorizontalTrack:
- case kScrollbarVerticalTrack:
- PaintScrollbarTrack(canvas, part, state, extra.scrollbar_track, rect);
- break;
- case kScrollbarHorizontalGripper:
- case kScrollbarVerticalGripper:
- NOTIMPLEMENTED();
- break;
- case kSliderTrack:
- PaintSliderTrack(canvas, state, rect, extra.slider);
- break;
- case kSliderThumb:
- PaintSliderThumb(canvas, state, rect, extra.slider);
- break;
- case kTabPanelBackground:
- NOTIMPLEMENTED();
- break;
- case kTextField:
- PaintTextField(canvas, state, rect, extra.text_field);
- break;
- case kTrackbarThumb:
- case kTrackbarTrack:
- case kWindowResizeGripper:
- NOTIMPLEMENTED();
- break;
- default:
- NOTREACHED() << "Unknown theme part: " << part;
- break;
- }
-}
-
-SkColor NativeThemeBase::GetSystemColor(ColorId color_id) const {
- // This implementation returns hardcoded colors. It's used by NativeThemeAura
- // and NativeThemeChromeos and overridden by NativeThemeGtk.
- switch (color_id) {
- case kColorId_DialogBackground:
- return kDefaultDialogBackgroundColor;
- default:
- NOTREACHED() << "Invalid color_id: " << color_id;
- break;
- }
- return kInvalidColorIdColor;
-}
-
void NativeThemeBase::PaintScrollbarTrack(SkCanvas* canvas,
Part part,
State state,
@@ -846,37 +846,6 @@ bool NativeThemeBase::IntersectsClipRectInt(
SkIntToScalar(y + h));
}
-void NativeThemeBase::DrawVertLine(SkCanvas* canvas,
- int x,
- int y1,
- int y2,
- const SkPaint& paint) const {
- SkIRect skrect;
- skrect.set(x, y1, x + 1, y2 + 1);
- canvas->drawIRect(skrect, paint);
-}
-
-void NativeThemeBase::DrawHorizLine(SkCanvas* canvas,
- int x1,
- int x2,
- int y,
- const SkPaint& paint) const {
- SkIRect skrect;
- skrect.set(x1, y, x2 + 1, y + 1);
- canvas->drawIRect(skrect, paint);
-}
-
-void NativeThemeBase::DrawBox(SkCanvas* canvas,
- const gfx::Rect& rect,
- const SkPaint& paint) const {
- const int right = rect.x() + rect.width() - 1;
- const int bottom = rect.y() + rect.height() - 1;
- DrawHorizLine(canvas, rect.x(), right, rect.y(), paint);
- DrawVertLine(canvas, right, rect.y(), bottom, paint);
- DrawHorizLine(canvas, rect.x(), right, bottom, paint);
- DrawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
-}
-
void NativeThemeBase::DrawBitmapInt(
SkCanvas* canvas, const SkBitmap& bitmap,
int src_x, int src_y, int src_w, int src_h,
@@ -955,12 +924,6 @@ void NativeThemeBase::DrawTiledImage(SkCanvas* canvas,
canvas->restore();
}
-SkScalar NativeThemeBase::Clamp(SkScalar value,
- SkScalar min,
- SkScalar max) const {
- return std::min(std::max(value, min), max);
-}
-
SkColor NativeThemeBase::SaturateAndBrighten(SkScalar* hsv,
SkScalar saturate_amount,
SkScalar brighten_amount) const {
@@ -971,6 +934,43 @@ SkColor NativeThemeBase::SaturateAndBrighten(SkScalar* hsv,
return SkHSVToColor(color);
}
+void NativeThemeBase::DrawVertLine(SkCanvas* canvas,
+ int x,
+ int y1,
+ int y2,
+ const SkPaint& paint) const {
+ SkIRect skrect;
+ skrect.set(x, y1, x + 1, y2 + 1);
+ canvas->drawIRect(skrect, paint);
+}
+
+void NativeThemeBase::DrawHorizLine(SkCanvas* canvas,
+ int x1,
+ int x2,
+ int y,
+ const SkPaint& paint) const {
+ SkIRect skrect;
+ skrect.set(x1, y, x2 + 1, y + 1);
+ canvas->drawIRect(skrect, paint);
+}
+
+void NativeThemeBase::DrawBox(SkCanvas* canvas,
+ const gfx::Rect& rect,
+ const SkPaint& paint) const {
+ const int right = rect.x() + rect.width() - 1;
+ const int bottom = rect.y() + rect.height() - 1;
+ DrawHorizLine(canvas, rect.x(), right, rect.y(), paint);
+ DrawVertLine(canvas, right, rect.y(), bottom, paint);
+ DrawHorizLine(canvas, rect.x(), right, bottom, paint);
+ DrawVertLine(canvas, rect.x(), rect.y(), bottom, paint);
+}
+
+SkScalar NativeThemeBase::Clamp(SkScalar value,
+ SkScalar min,
+ SkScalar max) const {
+ return std::min(std::max(value, min), max);
+}
+
SkColor NativeThemeBase::OutlineColor(SkScalar* hsv1, SkScalar* hsv2) const {
// GTK Theme engines have way too much control over the layout of
// the scrollbar. We might be able to more closely approximate its
diff --git a/ui/gfx/native_theme_chromeos.cc b/ui/gfx/native_theme_chromeos.cc
index 3919d8f..0c08c25 100644
--- a/ui/gfx/native_theme_chromeos.cc
+++ b/ui/gfx/native_theme_chromeos.cc
@@ -351,6 +351,26 @@ void NativeThemeChromeos::PaintScrollbarTrack(
}
}
+void NativeThemeChromeos::PaintArrowButton(SkCanvas* canvas,
+ const gfx::Rect& rect, Part part, State state) const {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ int resource_id =
+ (part == kScrollbarUpArrow || part == kScrollbarLeftArrow) ?
+ IDR_SCROLL_ARROW_UP : IDR_SCROLL_ARROW_DOWN;
+ if (state == kHovered)
+ resource_id++;
+ else if (state == kPressed)
+ resource_id += 2;
+ SkBitmap* bitmap;
+ if (part == kScrollbarUpArrow || part == kScrollbarDownArrow)
+ bitmap = rb.GetBitmapNamed(resource_id);
+ else
+ bitmap = GetHorizontalBitmapNamed(resource_id);
+ DrawBitmapInt(canvas, *bitmap,
+ 0, 0, bitmap->width(), bitmap->height(),
+ rect.x(), rect.y(), rect.width(), rect.height());
+}
+
void NativeThemeChromeos::PaintScrollbarThumb(SkCanvas* canvas,
Part part, State state, const gfx::Rect& rect) const {
ResourceBundle& rb = ResourceBundle::GetSharedInstance();
@@ -396,26 +416,6 @@ void NativeThemeChromeos::PaintScrollbarThumb(SkCanvas* canvas,
}
}
-void NativeThemeChromeos::PaintArrowButton(SkCanvas* canvas,
- const gfx::Rect& rect, Part part, State state) const {
- ResourceBundle& rb = ResourceBundle::GetSharedInstance();
- int resource_id =
- (part == kScrollbarUpArrow || part == kScrollbarLeftArrow) ?
- IDR_SCROLL_ARROW_UP : IDR_SCROLL_ARROW_DOWN;
- if (state == kHovered)
- resource_id++;
- else if (state == kPressed)
- resource_id += 2;
- SkBitmap* bitmap;
- if (part == kScrollbarUpArrow || part == kScrollbarDownArrow)
- bitmap = rb.GetBitmapNamed(resource_id);
- else
- bitmap = GetHorizontalBitmapNamed(resource_id);
- DrawBitmapInt(canvas, *bitmap,
- 0, 0, bitmap->width(), bitmap->height(),
- rect.x(), rect.y(), rect.width(), rect.height());
-}
-
void NativeThemeChromeos::PaintCheckbox(SkCanvas* canvas,
State state, const gfx::Rect& rect,
const ButtonExtraParams& button) const {
diff --git a/ui/gfx/native_theme_win.cc b/ui/gfx/native_theme_win.cc
index e0c1d6e..b241cee 100644
--- a/ui/gfx/native_theme_win.cc
+++ b/ui/gfx/native_theme_win.cc
@@ -61,10 +61,106 @@ void SetCheckerboardShader(SkPaint* paint, const RECT& align_rect) {
SkSafeUnref(paint->setShader(shader));
}
+// <-a->
+// [ ***** ]
+// ____ | |
+// <-a-> <------b----->
+// a: object_width
+// b: frame_width
+// *: animating object
+//
+// - the animation goes from "[" to "]" repeatedly.
+// - the animation offset is at first "|"
+//
+int ComputeAnimationProgress(int frame_width,
+ int object_width,
+ int pixels_per_second,
+ double animated_seconds) {
+ int animation_width = frame_width + object_width;
+ double interval = static_cast<double>(animation_width) / pixels_per_second;
+ double ratio = fmod(animated_seconds, interval) / interval;
+ return static_cast<int>(animation_width * ratio) - object_width;
+}
+
+RECT InsetRect(const RECT* rect, int size) {
+ gfx::Rect result(*rect);
+ result.Inset(size, size);
+ return result.ToRECT();
+}
+
} // namespace
namespace gfx {
+bool NativeThemeWin::IsThemingActive() const {
+ if (is_theme_active_)
+ return !!is_theme_active_();
+ return false;
+}
+
+HRESULT NativeThemeWin::GetThemeColor(ThemeName theme,
+ int part_id,
+ int state_id,
+ int prop_id,
+ SkColor* color) const {
+ HANDLE handle = GetThemeHandle(theme);
+ if (handle && get_theme_color_) {
+ COLORREF color_ref;
+ if (get_theme_color_(handle, part_id, state_id, prop_id, &color_ref) ==
+ S_OK) {
+ *color = skia::COLORREFToSkColor(color_ref);
+ return S_OK;
+ }
+ }
+ return E_NOTIMPL;
+}
+
+SkColor NativeThemeWin::GetThemeColorWithDefault(ThemeName theme,
+ int part_id,
+ int state_id,
+ int prop_id,
+ int default_sys_color) const {
+ SkColor color;
+ if (GetThemeColor(theme, part_id, state_id, prop_id, &color) != S_OK)
+ color = skia::COLORREFToSkColor(GetSysColor(default_sys_color));
+ return color;
+}
+
+Size NativeThemeWin::GetThemeBorderSize(ThemeName theme) const {
+ // For simplicity use the wildcard state==0, part==0, since it works
+ // for the cases we currently depend on.
+ int border;
+ if (GetThemeInt(theme, 0, 0, TMT_BORDERSIZE, &border) == S_OK)
+ return Size(border, border);
+ else
+ return Size(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
+}
+
+void NativeThemeWin::DisableTheming() const {
+ if (!set_theme_properties_)
+ return;
+ set_theme_properties_(0);
+}
+
+void NativeThemeWin::CloseHandles() const {
+ if (!close_theme_)
+ return;
+
+ for (int i = 0; i < LAST; ++i) {
+ if (theme_handles_[i]) {
+ close_theme_(theme_handles_[i]);
+ theme_handles_[i] = NULL;
+ }
+ }
+}
+
+bool NativeThemeWin::IsClassicTheme(ThemeName name) const {
+ if (!theme_dll_)
+ return true;
+
+ return !GetThemeHandle(name);
+}
+
// static
const NativeTheme* NativeTheme::instance() {
return NativeThemeWin::instance();
@@ -156,77 +252,6 @@ gfx::Size NativeThemeWin::GetPartSize(Part part,
return Size(size.cx, size.cy);
}
-void NativeThemeWin::PaintToNonPlatformCanvas(SkCanvas* canvas,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ExtraParams& extra) const {
- // TODO(asvitkine): This path is pretty inefficient - for each paint operation
- // it creates a new offscreen bitmap Skia canvas. This can
- // be sped up by doing it only once per part/state and
- // keeping a cache of the resulting bitmaps.
-
- // Create an offscreen canvas that is backed by an HDC.
- scoped_ptr<SkCanvas> offscreen_canvas(
- skia::CreateBitmapCanvas(rect.width(), rect.height(), false));
- DCHECK(offscreen_canvas.get());
- DCHECK(skia::SupportsPlatformPaint(offscreen_canvas.get()));
-
- // Some of the Windows theme drawing operations do not write correct alpha
- // values for fully-opaque pixels; instead the pixels get alpha 0. This is
- // especially a problem on Windows XP or when using the Classic theme.
- //
- // To work-around this, mark all pixels with a placeholder value, to detect
- // which pixels get touched by the paint operation. After paint, set any
- // pixels that have alpha 0 to opaque and placeholders to fully-transparent.
- const SkColor placeholder = SkColorSetARGB(1, 0, 0, 0);
- offscreen_canvas->clear(placeholder);
-
- // Offset destination rects to have origin (0,0).
- gfx::Rect adjusted_rect(rect.size());
- ExtraParams adjusted_extra(extra);
- switch (part) {
- case kProgressBar:
- adjusted_extra.progress_bar.value_rect_x = 0;
- adjusted_extra.progress_bar.value_rect_y = 0;
- break;
- case kScrollbarHorizontalTrack:
- case kScrollbarVerticalTrack:
- adjusted_extra.scrollbar_track.track_x = 0;
- adjusted_extra.scrollbar_track.track_y = 0;
- break;
- default: break;
- }
- // Draw the theme controls using existing HDC-drawing code.
- Paint(offscreen_canvas.get(), part, state, adjusted_rect, adjusted_extra);
-
- // Copy the pixels to a bitmap that has ref-counted pixel storage, which is
- // necessary to have when drawing to a SkPicture.
- const SkBitmap& bitmap = offscreen_canvas->getDevice()->accessBitmap(false);
- SkBitmap ref_counted;
- bitmap.copyTo(&ref_counted, SkBitmap::kARGB_8888_Config);
-
- // Post-process the pixels to fix up the alpha values (see big comment above).
- const SkPMColor placeholder_value = SkPreMultiplyColor(placeholder);
- const int pixel_count = rect.width() * rect.height();
- SkPMColor* pixels = bitmap.getAddr32(0, 0);
- for (int i = 0; i < pixel_count; i++) {
- if (pixels[i] == placeholder_value) {
- // Pixel wasn't touched - make it fully transparent.
- pixels[i] = SkPackARGB32(0, 0, 0, 0);
- } else if (SkGetPackedA32(pixels[i]) == 0) {
- // Pixel was touched but has incorrect alpha of 0, make it fully opaque.
- pixels[i] = SkPackARGB32(0xFF,
- SkGetPackedR32(pixels[i]),
- SkGetPackedG32(pixels[i]),
- SkGetPackedB32(pixels[i]));
- }
- }
-
- // Draw the offscreen bitmap to the destination canvas.
- canvas->drawBitmap(ref_counted, rect.x(), rect.y());
-}
-
void NativeThemeWin::Paint(SkCanvas* canvas,
Part part,
State state,
@@ -334,299 +359,89 @@ SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const {
return kInvalidColorIdColor;
}
-HRESULT NativeThemeWin::PaintScrollbarArrow(
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ScrollbarArrowExtraParams& extra) const {
- static int state_id_matrix[4][kMaxState] = {
- ABS_DOWNDISABLED, ABS_DOWNHOT, ABS_DOWNNORMAL, ABS_DOWNPRESSED,
- ABS_LEFTDISABLED, ABS_LEFTHOT, ABS_LEFTNORMAL, ABS_LEFTPRESSED,
- ABS_RIGHTDISABLED, ABS_RIGHTHOT, ABS_RIGHTNORMAL, ABS_RIGHTPRESSED,
- ABS_UPDISABLED, ABS_UPHOT, ABS_UPNORMAL, ABS_UPPRESSED
- };
- HANDLE handle = GetThemeHandle(SCROLLBAR);
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_) {
- int index = part - kScrollbarDownArrow;
- DCHECK(index >=0 && index < 4);
- int state_id = state_id_matrix[index][state];
-
- // Hovering means that the cursor is over the scroolbar, but not over the
- // specific arrow itself. We don't want to show it "hot" mode, but only
- // in "hover" mode.
- if (state == kHovered && extra.is_hovering) {
- switch (part) {
- case kScrollbarDownArrow:
- state_id = ABS_DOWNHOVER;
- break;
- case kScrollbarLeftArrow:
- state_id = ABS_LEFTHOVER;
- break;
- case kScrollbarRightArrow:
- state_id = ABS_RIGHTHOVER;
- break;
- case kScrollbarUpArrow:
- state_id = ABS_UPHOVER;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
- }
-
- return draw_theme_(handle, hdc, SBP_ARROWBTN, state_id, &rect_win, NULL);
- }
-
- int classic_state = DFCS_SCROLLDOWN;
- switch (part) {
- case kScrollbarDownArrow:
- classic_state = DFCS_SCROLLDOWN;
- break;
- case kScrollbarLeftArrow:
- classic_state = DFCS_SCROLLLEFT;
- break;
- case kScrollbarRightArrow:
- classic_state = DFCS_SCROLLRIGHT;
- break;
- case kScrollbarUpArrow:
- classic_state = DFCS_SCROLLUP;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
- switch (state) {
- case kDisabled:
- classic_state |= DFCS_INACTIVE;
- break;
- case kHovered:
- classic_state |= DFCS_HOT;
- break;
- case kNormal:
- break;
- case kPressed:
- classic_state |= DFCS_PUSHED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
- DrawFrameControl(hdc, &rect_win, DFC_SCROLL, classic_state);
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintScrollbarTrack(
- SkCanvas* canvas,
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ScrollbarTrackExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(SCROLLBAR);
- RECT rect_win = rect.ToRECT();
- int part_id;
- int state_id;
-
- switch (part) {
- case gfx::NativeTheme::kScrollbarHorizontalTrack:
- part_id = extra.is_upper ? SBP_UPPERTRACKHORZ : SBP_LOWERTRACKHORZ;
- break;
- case gfx::NativeTheme::kScrollbarVerticalTrack:
- part_id = extra.is_upper ? SBP_UPPERTRACKVERT : SBP_LOWERTRACKVERT;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
-
- switch (state) {
- case kDisabled:
- state_id = SCRBS_DISABLED;
- break;
- case kHovered:
- state_id = SCRBS_HOVER;
- break;
- case kNormal:
- state_id = SCRBS_NORMAL;
- break;
- case kPressed:
- state_id = SCRBS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
+void NativeThemeWin::PaintToNonPlatformCanvas(SkCanvas* canvas,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const ExtraParams& extra) const {
+ // TODO(asvitkine): This path is pretty inefficient - for each paint operation
+ // it creates a new offscreen bitmap Skia canvas. This can
+ // be sped up by doing it only once per part/state and
+ // keeping a cache of the resulting bitmaps.
- // Draw it manually.
- const DWORD colorScrollbar = GetSysColor(COLOR_SCROLLBAR);
- const DWORD color3DFace = GetSysColor(COLOR_3DFACE);
- if ((colorScrollbar != color3DFace) &&
- (colorScrollbar != GetSysColor(COLOR_WINDOW))) {
- FillRect(hdc, &rect_win, reinterpret_cast<HBRUSH>(COLOR_SCROLLBAR + 1));
- } else {
- SkPaint paint;
- RECT align_rect = gfx::Rect(extra.track_x, extra.track_y, extra.track_width,
- extra.track_height).ToRECT();
- SetCheckerboardShader(&paint, align_rect);
- canvas->drawIRect(skia::RECTToSkIRect(rect_win), paint);
- }
- if (extra.classic_state & DFCS_PUSHED)
- InvertRect(hdc, &rect_win);
- return S_OK;
-}
+ // Create an offscreen canvas that is backed by an HDC.
+ scoped_ptr<SkCanvas> offscreen_canvas(
+ skia::CreateBitmapCanvas(rect.width(), rect.height(), false));
+ DCHECK(offscreen_canvas.get());
+ DCHECK(skia::SupportsPlatformPaint(offscreen_canvas.get()));
-HRESULT NativeThemeWin::PaintScrollbarThumb(
- HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ScrollbarThumbExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(SCROLLBAR);
- RECT rect_win = rect.ToRECT();
- int part_id;
- int state_id;
+ // Some of the Windows theme drawing operations do not write correct alpha
+ // values for fully-opaque pixels; instead the pixels get alpha 0. This is
+ // especially a problem on Windows XP or when using the Classic theme.
+ //
+ // To work-around this, mark all pixels with a placeholder value, to detect
+ // which pixels get touched by the paint operation. After paint, set any
+ // pixels that have alpha 0 to opaque and placeholders to fully-transparent.
+ const SkColor placeholder = SkColorSetARGB(1, 0, 0, 0);
+ offscreen_canvas->clear(placeholder);
+ // Offset destination rects to have origin (0,0).
+ gfx::Rect adjusted_rect(rect.size());
+ ExtraParams adjusted_extra(extra);
switch (part) {
- case gfx::NativeTheme::kScrollbarHorizontalThumb:
- part_id = SBP_THUMBBTNHORZ;
- break;
- case gfx::NativeTheme::kScrollbarVerticalThumb:
- part_id = SBP_THUMBBTNVERT;
- break;
- case gfx::NativeTheme::kScrollbarHorizontalGripper:
- part_id = SBP_GRIPPERHORZ;
- break;
- case gfx::NativeTheme::kScrollbarVerticalGripper:
- part_id = SBP_GRIPPERVERT;
- break;
- default:
- NOTREACHED() << "Invalid part: " << part;
- break;
- }
-
- switch (state) {
- case kDisabled:
- state_id = SCRBS_DISABLED;
- break;
- case kHovered:
- state_id = extra.is_hovering ? SCRBS_HOVER : SCRBS_HOT;
- break;
- case kNormal:
- state_id = SCRBS_NORMAL;
- break;
- case kPressed:
- state_id = SCRBS_PRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
-
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
-
- // Draw it manually.
- if ((part_id == SBP_THUMBBTNHORZ) || (part_id == SBP_THUMBBTNVERT))
- DrawEdge(hdc, &rect_win, EDGE_RAISED, BF_RECT | BF_MIDDLE);
- // Classic mode doesn't have a gripper.
- return S_OK;
-}
-
-HRESULT NativeThemeWin::PaintPushButton(HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ButtonExtraParams& extra) const {
- int state_id;
- switch (state) {
- case kDisabled:
- state_id = PBS_DISABLED;
- break;
- case kHovered:
- state_id = PBS_HOT;
- break;
- case kNormal:
- state_id = extra.is_default ? PBS_DEFAULTED : PBS_NORMAL;
- break;
- case kPressed:
- state_id = PBS_PRESSED;
+ case kProgressBar:
+ adjusted_extra.progress_bar.value_rect_x = 0;
+ adjusted_extra.progress_bar.value_rect_y = 0;
break;
- default:
- NOTREACHED() << "Invalid state: " << state;
+ case kScrollbarHorizontalTrack:
+ case kScrollbarVerticalTrack:
+ adjusted_extra.scrollbar_track.track_x = 0;
+ adjusted_extra.scrollbar_track.track_y = 0;
break;
+ default: break;
}
+ // Draw the theme controls using existing HDC-drawing code.
+ Paint(offscreen_canvas.get(), part, state, adjusted_rect, adjusted_extra);
- RECT rect_win = rect.ToRECT();
- return PaintButton(hdc, state, extra, BP_PUSHBUTTON, state_id, &rect_win);
-}
+ // Copy the pixels to a bitmap that has ref-counted pixel storage, which is
+ // necessary to have when drawing to a SkPicture.
+ const SkBitmap& bitmap = offscreen_canvas->getDevice()->accessBitmap(false);
+ SkBitmap ref_counted;
+ bitmap.copyTo(&ref_counted, SkBitmap::kARGB_8888_Config);
-HRESULT NativeThemeWin::PaintRadioButton(HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ButtonExtraParams& extra) const {
- int state_id;
- switch (state) {
- case kDisabled:
- state_id = extra.checked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED;
- break;
- case kHovered:
- state_id = extra.checked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT;
- break;
- case kNormal:
- state_id = extra.checked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL;
- break;
- case kPressed:
- state_id = extra.checked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
+ // Post-process the pixels to fix up the alpha values (see big comment above).
+ const SkPMColor placeholder_value = SkPreMultiplyColor(placeholder);
+ const int pixel_count = rect.width() * rect.height();
+ SkPMColor* pixels = bitmap.getAddr32(0, 0);
+ for (int i = 0; i < pixel_count; i++) {
+ if (pixels[i] == placeholder_value) {
+ // Pixel wasn't touched - make it fully transparent.
+ pixels[i] = SkPackARGB32(0, 0, 0, 0);
+ } else if (SkGetPackedA32(pixels[i]) == 0) {
+ // Pixel was touched but has incorrect alpha of 0, make it fully opaque.
+ pixels[i] = SkPackARGB32(0xFF,
+ SkGetPackedR32(pixels[i]),
+ SkGetPackedG32(pixels[i]),
+ SkGetPackedB32(pixels[i]));
+ }
}
- RECT rect_win = rect.ToRECT();
- return PaintButton(hdc, state, extra, BP_RADIOBUTTON, state_id, &rect_win);
+ // Draw the offscreen bitmap to the destination canvas.
+ canvas->drawBitmap(ref_counted, rect.x(), rect.y());
}
-HRESULT NativeThemeWin::PaintCheckbox(HDC hdc,
- Part part,
- State state,
- const gfx::Rect& rect,
- const ButtonExtraParams& extra) const {
- int state_id;
- switch (state) {
- case kDisabled:
- state_id = extra.checked ? CBS_CHECKEDDISABLED :
- extra.indeterminate ? CBS_MIXEDDISABLED :
- CBS_UNCHECKEDDISABLED;
- break;
- case kHovered:
- state_id = extra.checked ? CBS_CHECKEDHOT :
- extra.indeterminate ? CBS_MIXEDHOT :
- CBS_UNCHECKEDHOT;
- break;
- case kNormal:
- state_id = extra.checked ? CBS_CHECKEDNORMAL :
- extra.indeterminate ? CBS_MIXEDNORMAL :
- CBS_UNCHECKEDNORMAL;
- break;
- case kPressed:
- state_id = extra.checked ? CBS_CHECKEDPRESSED :
- extra.indeterminate ? CBS_MIXEDPRESSED :
- CBS_UNCHECKEDPRESSED;
- break;
- default:
- NOTREACHED() << "Invalid state: " << state;
- break;
- }
+HRESULT NativeThemeWin::GetThemePartSize(ThemeName theme_name,
+ HDC hdc,
+ int part_id,
+ int state_id,
+ RECT* rect,
+ int ts,
+ SIZE* size) const {
+ HANDLE handle = GetThemeHandle(theme_name);
+ if (handle && get_theme_part_size_)
+ return get_theme_part_size_(handle, hdc, part_id, state_id, rect, ts, size);
- RECT rect_win = rect.ToRECT();
- return PaintButton(hdc, state, extra, BP_CHECKBOX, state_id, &rect_win);
+ return E_NOTIMPL;
}
HRESULT NativeThemeWin::PaintButton(HDC hdc,
@@ -706,6 +521,37 @@ HRESULT NativeThemeWin::PaintButton(HDC hdc,
return S_OK;
}
+HRESULT NativeThemeWin::PaintMenuSeparator(
+ HDC hdc,
+ const gfx::Rect& rect,
+ const MenuSeparatorExtraParams& extra) const {
+ RECT rect_win = rect.ToRECT();
+ if (!extra.has_gutter)
+ rect_win.top = rect.y() + rect.height() / 3 + 1;
+
+ HANDLE handle = GetThemeHandle(MENU);
+ if (handle && draw_theme_) {
+ // Delta is needed for non-classic to move separator up slightly.
+ --rect_win.top;
+ --rect_win.bottom;
+ return draw_theme_(handle, hdc, MENU_POPUPSEPARATOR, MPI_NORMAL, &rect_win,
+ NULL);
+ }
+
+ DrawEdge(hdc, &rect_win, EDGE_ETCHED, BF_TOP);
+ return S_OK;
+}
+
+HRESULT NativeThemeWin::PaintMenuGutter(HDC hdc,
+ const gfx::Rect& rect) const {
+ RECT rect_win = rect.ToRECT();
+ HANDLE handle = GetThemeHandle(MENU);
+ if (handle && draw_theme_)
+ return draw_theme_(handle, hdc, MENU_POPUPGUTTER, MPI_NORMAL, &rect_win,
+ NULL);
+ return E_NOTIMPL;
+}
+
HRESULT NativeThemeWin::PaintMenuArrow(HDC hdc,
State state,
const gfx::Rect& rect,
@@ -774,19 +620,6 @@ HRESULT NativeThemeWin::PaintMenuBackground(HDC hdc,
return S_OK;
}
-HRESULT NativeThemeWin::PaintMenuCheckBackground(HDC hdc,
- State state,
- const gfx::Rect& rect) const {
- HANDLE handle = GetThemeHandle(MENU);
- int state_id = state == kDisabled ? MCB_DISABLED : MCB_NORMAL;
- RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, MENU_POPUPCHECKBACKGROUND, state_id,
- &rect_win, NULL);
- // Nothing to do for background.
- return S_OK;
-}
-
HRESULT NativeThemeWin::PaintMenuCheck(
HDC hdc,
State state,
@@ -809,14 +642,17 @@ HRESULT NativeThemeWin::PaintMenuCheck(
extra.is_selected, state);
}
-HRESULT NativeThemeWin::PaintMenuGutter(HDC hdc,
- const gfx::Rect& rect) const {
- RECT rect_win = rect.ToRECT();
+HRESULT NativeThemeWin::PaintMenuCheckBackground(HDC hdc,
+ State state,
+ const gfx::Rect& rect) const {
HANDLE handle = GetThemeHandle(MENU);
+ int state_id = state == kDisabled ? MCB_DISABLED : MCB_NORMAL;
+ RECT rect_win = rect.ToRECT();
if (handle && draw_theme_)
- return draw_theme_(handle, hdc, MENU_POPUPGUTTER, MPI_NORMAL, &rect_win,
- NULL);
- return E_NOTIMPL;
+ return draw_theme_(handle, hdc, MENU_POPUPCHECKBACKGROUND, state_id,
+ &rect_win, NULL);
+ // Nothing to do for background.
+ return S_OK;
}
HRESULT NativeThemeWin::PaintMenuItemBackground(
@@ -850,6 +686,98 @@ HRESULT NativeThemeWin::PaintMenuItemBackground(
return S_OK;
}
+HRESULT NativeThemeWin::PaintPushButton(HDC hdc,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const ButtonExtraParams& extra) const {
+ int state_id;
+ switch (state) {
+ case kDisabled:
+ state_id = PBS_DISABLED;
+ break;
+ case kHovered:
+ state_id = PBS_HOT;
+ break;
+ case kNormal:
+ state_id = extra.is_default ? PBS_DEFAULTED : PBS_NORMAL;
+ break;
+ case kPressed:
+ state_id = PBS_PRESSED;
+ break;
+ default:
+ NOTREACHED() << "Invalid state: " << state;
+ break;
+ }
+
+ RECT rect_win = rect.ToRECT();
+ return PaintButton(hdc, state, extra, BP_PUSHBUTTON, state_id, &rect_win);
+}
+
+HRESULT NativeThemeWin::PaintRadioButton(HDC hdc,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const ButtonExtraParams& extra) const {
+ int state_id;
+ switch (state) {
+ case kDisabled:
+ state_id = extra.checked ? RBS_CHECKEDDISABLED : RBS_UNCHECKEDDISABLED;
+ break;
+ case kHovered:
+ state_id = extra.checked ? RBS_CHECKEDHOT : RBS_UNCHECKEDHOT;
+ break;
+ case kNormal:
+ state_id = extra.checked ? RBS_CHECKEDNORMAL : RBS_UNCHECKEDNORMAL;
+ break;
+ case kPressed:
+ state_id = extra.checked ? RBS_CHECKEDPRESSED : RBS_UNCHECKEDPRESSED;
+ break;
+ default:
+ NOTREACHED() << "Invalid state: " << state;
+ break;
+ }
+
+ RECT rect_win = rect.ToRECT();
+ return PaintButton(hdc, state, extra, BP_RADIOBUTTON, state_id, &rect_win);
+}
+
+HRESULT NativeThemeWin::PaintCheckbox(HDC hdc,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const ButtonExtraParams& extra) const {
+ int state_id;
+ switch (state) {
+ case kDisabled:
+ state_id = extra.checked ? CBS_CHECKEDDISABLED :
+ extra.indeterminate ? CBS_MIXEDDISABLED :
+ CBS_UNCHECKEDDISABLED;
+ break;
+ case kHovered:
+ state_id = extra.checked ? CBS_CHECKEDHOT :
+ extra.indeterminate ? CBS_MIXEDHOT :
+ CBS_UNCHECKEDHOT;
+ break;
+ case kNormal:
+ state_id = extra.checked ? CBS_CHECKEDNORMAL :
+ extra.indeterminate ? CBS_MIXEDNORMAL :
+ CBS_UNCHECKEDNORMAL;
+ break;
+ case kPressed:
+ state_id = extra.checked ? CBS_CHECKEDPRESSED :
+ extra.indeterminate ? CBS_MIXEDPRESSED :
+ CBS_UNCHECKEDPRESSED;
+ break;
+ default:
+ NOTREACHED() << "Invalid state: " << state;
+ break;
+ }
+
+ RECT rect_win = rect.ToRECT();
+ return PaintButton(hdc, state, extra, BP_CHECKBOX, state_id, &rect_win);
+}
+
HRESULT NativeThemeWin::PaintMenuList(HDC hdc,
State state,
const gfx::Rect& rect,
@@ -885,87 +813,240 @@ HRESULT NativeThemeWin::PaintMenuList(HDC hdc,
return S_OK;
}
-HRESULT NativeThemeWin::PaintMenuSeparator(
+HRESULT NativeThemeWin::PaintScrollbarArrow(
HDC hdc,
+ Part part,
+ State state,
const gfx::Rect& rect,
- const MenuSeparatorExtraParams& extra) const {
+ const ScrollbarArrowExtraParams& extra) const {
+ static const int state_id_matrix[4][kMaxState] = {
+ ABS_DOWNDISABLED, ABS_DOWNHOT, ABS_DOWNNORMAL, ABS_DOWNPRESSED,
+ ABS_LEFTDISABLED, ABS_LEFTHOT, ABS_LEFTNORMAL, ABS_LEFTPRESSED,
+ ABS_RIGHTDISABLED, ABS_RIGHTHOT, ABS_RIGHTNORMAL, ABS_RIGHTPRESSED,
+ ABS_UPDISABLED, ABS_UPHOT, ABS_UPNORMAL, ABS_UPPRESSED
+ };
+ HANDLE handle = GetThemeHandle(SCROLLBAR);
RECT rect_win = rect.ToRECT();
- if (!extra.has_gutter)
- rect_win.top = rect.y() + rect.height() / 3 + 1;
-
- HANDLE handle = GetThemeHandle(MENU);
if (handle && draw_theme_) {
- // Delta is needed for non-classic to move separator up slightly.
- --rect_win.top;
- --rect_win.bottom;
- return draw_theme_(handle, hdc, MENU_POPUPSEPARATOR, MPI_NORMAL, &rect_win,
- NULL);
+ int index = part - kScrollbarDownArrow;
+ DCHECK(index >=0 && index < 4);
+ int state_id = state_id_matrix[index][state];
+
+ // Hovering means that the cursor is over the scroolbar, but not over the
+ // specific arrow itself. We don't want to show it "hot" mode, but only
+ // in "hover" mode.
+ if (state == kHovered && extra.is_hovering) {
+ switch (part) {
+ case kScrollbarDownArrow:
+ state_id = ABS_DOWNHOVER;
+ break;
+ case kScrollbarLeftArrow:
+ state_id = ABS_LEFTHOVER;
+ break;
+ case kScrollbarRightArrow:
+ state_id = ABS_RIGHTHOVER;
+ break;
+ case kScrollbarUpArrow:
+ state_id = ABS_UPHOVER;
+ break;
+ default:
+ NOTREACHED() << "Invalid part: " << part;
+ break;
+ }
+ }
+
+ return draw_theme_(handle, hdc, SBP_ARROWBTN, state_id, &rect_win, NULL);
}
- DrawEdge(hdc, &rect_win, EDGE_ETCHED, BF_TOP);
+ int classic_state = DFCS_SCROLLDOWN;
+ switch (part) {
+ case kScrollbarDownArrow:
+ classic_state = DFCS_SCROLLDOWN;
+ break;
+ case kScrollbarLeftArrow:
+ classic_state = DFCS_SCROLLLEFT;
+ break;
+ case kScrollbarRightArrow:
+ classic_state = DFCS_SCROLLRIGHT;
+ break;
+ case kScrollbarUpArrow:
+ classic_state = DFCS_SCROLLUP;
+ break;
+ default:
+ NOTREACHED() << "Invalid part: " << part;
+ break;
+ }
+ switch (state) {
+ case kDisabled:
+ classic_state |= DFCS_INACTIVE;
+ break;
+ case kHovered:
+ classic_state |= DFCS_HOT;
+ break;
+ case kNormal:
+ break;
+ case kPressed:
+ classic_state |= DFCS_PUSHED;
+ break;
+ default:
+ NOTREACHED() << "Invalid state: " << state;
+ break;
+ }
+ DrawFrameControl(hdc, &rect_win, DFC_SCROLL, classic_state);
return S_OK;
}
-HRESULT NativeThemeWin::PaintSpinButton(
+HRESULT NativeThemeWin::PaintScrollbarThumb(
HDC hdc,
Part part,
State state,
const gfx::Rect& rect,
- const InnerSpinButtonExtraParams& extra) const {
- HANDLE handle = GetThemeHandle(SPIN);
+ const ScrollbarThumbExtraParams& extra) const {
+ HANDLE handle = GetThemeHandle(SCROLLBAR);
RECT rect_win = rect.ToRECT();
- int part_id = extra.spin_up ? SPNP_UP : SPNP_DOWN;
+ int part_id;
int state_id;
+
+ switch (part) {
+ case gfx::NativeTheme::kScrollbarHorizontalThumb:
+ part_id = SBP_THUMBBTNHORZ;
+ break;
+ case gfx::NativeTheme::kScrollbarVerticalThumb:
+ part_id = SBP_THUMBBTNVERT;
+ break;
+ case gfx::NativeTheme::kScrollbarHorizontalGripper:
+ part_id = SBP_GRIPPERHORZ;
+ break;
+ case gfx::NativeTheme::kScrollbarVerticalGripper:
+ part_id = SBP_GRIPPERVERT;
+ break;
+ default:
+ NOTREACHED() << "Invalid part: " << part;
+ break;
+ }
+
switch (state) {
case kDisabled:
- state_id = extra.spin_up ? UPS_DISABLED : DNS_DISABLED;
+ state_id = SCRBS_DISABLED;
break;
case kHovered:
- state_id = extra.spin_up ? UPS_HOT : DNS_HOT;
+ state_id = extra.is_hovering ? SCRBS_HOVER : SCRBS_HOT;
break;
case kNormal:
- state_id = extra.spin_up ? UPS_NORMAL : DNS_NORMAL;
+ state_id = SCRBS_NORMAL;
break;
case kPressed:
- state_id = extra.spin_up ? UPS_PRESSED : DNS_PRESSED;
+ state_id = SCRBS_PRESSED;
break;
default:
- NOTREACHED() << "Invalid state " << state;
+ NOTREACHED() << "Invalid state: " << state;
break;
}
if (handle && draw_theme_)
return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
- DrawFrameControl(hdc, &rect_win, DFC_SCROLL, extra.classic_state);
+
+ // Draw it manually.
+ if ((part_id == SBP_THUMBBTNHORZ) || (part_id == SBP_THUMBBTNVERT))
+ DrawEdge(hdc, &rect_win, EDGE_RAISED, BF_RECT | BF_MIDDLE);
+ // Classic mode doesn't have a gripper.
return S_OK;
}
-HRESULT NativeThemeWin::PaintWindowResizeGripper(HDC hdc,
- const gfx::Rect& rect) const {
- HANDLE handle = GetThemeHandle(STATUS);
+HRESULT NativeThemeWin::PaintScrollbarTrack(
+ SkCanvas* canvas,
+ HDC hdc,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const ScrollbarTrackExtraParams& extra) const {
+ HANDLE handle = GetThemeHandle(SCROLLBAR);
RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_) {
- // Paint the status bar gripper. There doesn't seem to be a
- // standard gripper in Windows for the space between
- // scrollbars. This is pretty close, but it's supposed to be
- // painted over a status bar.
- return draw_theme_(handle, hdc, SP_GRIPPER, 0, &rect_win, NULL);
+ int part_id;
+ int state_id;
+
+ switch (part) {
+ case gfx::NativeTheme::kScrollbarHorizontalTrack:
+ part_id = extra.is_upper ? SBP_UPPERTRACKHORZ : SBP_LOWERTRACKHORZ;
+ break;
+ case gfx::NativeTheme::kScrollbarVerticalTrack:
+ part_id = extra.is_upper ? SBP_UPPERTRACKVERT : SBP_LOWERTRACKVERT;
+ break;
+ default:
+ NOTREACHED() << "Invalid part: " << part;
+ break;
}
- // Draw a windows classic scrollbar gripper.
- DrawFrameControl(hdc, &rect_win, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
+ switch (state) {
+ case kDisabled:
+ state_id = SCRBS_DISABLED;
+ break;
+ case kHovered:
+ state_id = SCRBS_HOVER;
+ break;
+ case kNormal:
+ state_id = SCRBS_NORMAL;
+ break;
+ case kPressed:
+ state_id = SCRBS_PRESSED;
+ break;
+ default:
+ NOTREACHED() << "Invalid state: " << state;
+ break;
+ }
+
+ if (handle && draw_theme_)
+ return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
+
+ // Draw it manually.
+ const DWORD colorScrollbar = GetSysColor(COLOR_SCROLLBAR);
+ const DWORD color3DFace = GetSysColor(COLOR_3DFACE);
+ if ((colorScrollbar != color3DFace) &&
+ (colorScrollbar != GetSysColor(COLOR_WINDOW))) {
+ FillRect(hdc, &rect_win, reinterpret_cast<HBRUSH>(COLOR_SCROLLBAR + 1));
+ } else {
+ SkPaint paint;
+ RECT align_rect = gfx::Rect(extra.track_x, extra.track_y, extra.track_width,
+ extra.track_height).ToRECT();
+ SetCheckerboardShader(&paint, align_rect);
+ canvas->drawIRect(skia::RECTToSkIRect(rect_win), paint);
+ }
+ if (extra.classic_state & DFCS_PUSHED)
+ InvertRect(hdc, &rect_win);
return S_OK;
}
-HRESULT NativeThemeWin::PaintTabPanelBackground(HDC hdc,
- const gfx::Rect& rect) const {
- HANDLE handle = GetThemeHandle(TAB);
+HRESULT NativeThemeWin::PaintSpinButton(
+ HDC hdc,
+ Part part,
+ State state,
+ const gfx::Rect& rect,
+ const InnerSpinButtonExtraParams& extra) const {
+ HANDLE handle = GetThemeHandle(SPIN);
RECT rect_win = rect.ToRECT();
- if (handle && draw_theme_)
- return draw_theme_(handle, hdc, TABP_BODY, 0, &rect_win, NULL);
+ int part_id = extra.spin_up ? SPNP_UP : SPNP_DOWN;
+ int state_id;
+ switch (state) {
+ case kDisabled:
+ state_id = extra.spin_up ? UPS_DISABLED : DNS_DISABLED;
+ break;
+ case kHovered:
+ state_id = extra.spin_up ? UPS_HOT : DNS_HOT;
+ break;
+ case kNormal:
+ state_id = extra.spin_up ? UPS_NORMAL : DNS_NORMAL;
+ break;
+ case kPressed:
+ state_id = extra.spin_up ? UPS_PRESSED : DNS_PRESSED;
+ break;
+ default:
+ NOTREACHED() << "Invalid state " << state;
+ break;
+ }
- // Classic just renders a flat color background.
- FillRect(hdc, &rect_win, reinterpret_cast<HBRUSH>(COLOR_3DFACE + 1));
+ if (handle && draw_theme_)
+ return draw_theme_(handle, hdc, part_id, state_id, &rect_win, NULL);
+ DrawFrameControl(hdc, &rect_win, DFC_SCROLL, extra.classic_state);
return S_OK;
}
@@ -1076,33 +1157,6 @@ HRESULT NativeThemeWin::PaintTrackbar(
return S_OK;
}
-// <-a->
-// [ ***** ]
-// ____ | |
-// <-a-> <------b----->
-// a: object_width
-// b: frame_width
-// *: animating object
-//
-// - the animation goes from "[" to "]" repeatedly.
-// - the animation offset is at first "|"
-//
-static int ComputeAnimationProgress(int frame_width,
- int object_width,
- int pixels_per_second,
- double animated_seconds) {
- int animation_width = frame_width + object_width;
- double interval = static_cast<double>(animation_width) / pixels_per_second;
- double ratio = fmod(animated_seconds, interval) / interval;
- return static_cast<int>(animation_width * ratio) - object_width;
-}
-
-static RECT InsetRect(const RECT* rect, int size) {
- gfx::Rect result(*rect);
- result.Inset(size, size);
- return result.ToRECT();
-}
-
HRESULT NativeThemeWin::PaintProgressBar(
HDC hdc,
const gfx::Rect& rect,
@@ -1200,6 +1254,35 @@ HRESULT NativeThemeWin::PaintProgressBar(
return S_OK;
}
+HRESULT NativeThemeWin::PaintWindowResizeGripper(HDC hdc,
+ const gfx::Rect& rect) const {
+ HANDLE handle = GetThemeHandle(STATUS);
+ RECT rect_win = rect.ToRECT();
+ if (handle && draw_theme_) {
+ // Paint the status bar gripper. There doesn't seem to be a
+ // standard gripper in Windows for the space between
+ // scrollbars. This is pretty close, but it's supposed to be
+ // painted over a status bar.
+ return draw_theme_(handle, hdc, SP_GRIPPER, 0, &rect_win, NULL);
+ }
+
+ // Draw a windows classic scrollbar gripper.
+ DrawFrameControl(hdc, &rect_win, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
+ return S_OK;
+}
+
+HRESULT NativeThemeWin::PaintTabPanelBackground(HDC hdc,
+ const gfx::Rect& rect) const {
+ HANDLE handle = GetThemeHandle(TAB);
+ RECT rect_win = rect.ToRECT();
+ if (handle && draw_theme_)
+ return draw_theme_(handle, hdc, TABP_BODY, 0, &rect_win, NULL);
+
+ // Classic just renders a flat color background.
+ FillRect(hdc, &rect_win, reinterpret_cast<HBRUSH>(COLOR_3DFACE + 1));
+ return S_OK;
+}
+
HRESULT NativeThemeWin::PaintTextField(
HDC hdc,
Part part,
@@ -1260,12 +1343,12 @@ HRESULT NativeThemeWin::PaintTextField(HDC hdc,
// draw_theme_ex_ is NULL and draw_theme_ is non-null.
if (handle && (draw_theme_ex_ || (draw_theme_ && draw_edges))) {
if (draw_theme_ex_) {
- static DTBGOPTS omit_border_options = {
+ static const DTBGOPTS omit_border_options = {
sizeof(DTBGOPTS),
DTBG_OMITBORDER,
{ 0, 0, 0, 0 }
};
- DTBGOPTS* draw_opts = draw_edges ? NULL : &omit_border_options;
+ const DTBGOPTS* draw_opts = draw_edges ? NULL : &omit_border_options;
hr = draw_theme_ex_(handle, hdc, part_id, state_id, rect, draw_opts);
} else {
hr = draw_theme_(handle, hdc, part_id, state_id, rect, NULL);
@@ -1293,208 +1376,6 @@ HRESULT NativeThemeWin::PaintTextField(HDC hdc,
return hr;
}
-bool NativeThemeWin::IsThemingActive() const {
- if (is_theme_active_)
- return !!is_theme_active_();
- return false;
-}
-
-HRESULT NativeThemeWin::GetThemePartSize(ThemeName theme_name,
- HDC hdc,
- int part_id,
- int state_id,
- RECT* rect,
- int ts,
- SIZE* size) const {
- HANDLE handle = GetThemeHandle(theme_name);
- if (handle && get_theme_part_size_)
- return get_theme_part_size_(handle, hdc, part_id, state_id, rect, ts, size);
-
- return E_NOTIMPL;
-}
-
-HRESULT NativeThemeWin::GetThemeColor(ThemeName theme,
- int part_id,
- int state_id,
- int prop_id,
- SkColor* color) const {
- HANDLE handle = GetThemeHandle(theme);
- if (handle && get_theme_color_) {
- COLORREF color_ref;
- if (get_theme_color_(handle, part_id, state_id, prop_id, &color_ref) ==
- S_OK) {
- *color = skia::COLORREFToSkColor(color_ref);
- return S_OK;
- }
- }
- return E_NOTIMPL;
-}
-
-SkColor NativeThemeWin::GetThemeColorWithDefault(ThemeName theme,
- int part_id,
- int state_id,
- int prop_id,
- int default_sys_color) const {
- SkColor color;
- if (GetThemeColor(theme, part_id, state_id, prop_id, &color) != S_OK)
- color = skia::COLORREFToSkColor(GetSysColor(default_sys_color));
- return color;
-}
-
-HRESULT NativeThemeWin::GetThemeInt(ThemeName theme,
- int part_id,
- int state_id,
- int prop_id,
- int *value) const {
- HANDLE handle = GetThemeHandle(theme);
- if (handle && get_theme_int_)
- return get_theme_int_(handle, part_id, state_id, prop_id, value);
- return E_NOTIMPL;
-}
-
-Size NativeThemeWin::GetThemeBorderSize(ThemeName theme) const {
- // For simplicity use the wildcard state==0, part==0, since it works
- // for the cases we currently depend on.
- int border;
- if (GetThemeInt(theme, 0, 0, TMT_BORDERSIZE, &border) == S_OK)
- return Size(border, border);
- else
- return Size(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
-}
-
-
-void NativeThemeWin::DisableTheming() const {
- if (!set_theme_properties_)
- return;
- set_theme_properties_(0);
-}
-
-HRESULT NativeThemeWin::PaintFrameControl(HDC hdc,
- const gfx::Rect& rect,
- UINT type,
- UINT state,
- bool is_selected,
- State control_state) const {
- const int width = rect.width();
- const int height = rect.height();
-
- // DrawFrameControl for menu arrow/check wants a monochrome bitmap.
- base::win::ScopedBitmap mask_bitmap(CreateBitmap(width, height, 1, 1, NULL));
-
- if (mask_bitmap == NULL)
- return E_OUTOFMEMORY;
-
- base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(NULL));
- base::win::ScopedSelectObject select_bitmap(bitmap_dc, mask_bitmap);
- RECT local_rect = { 0, 0, width, height };
- DrawFrameControl(bitmap_dc, &local_rect, type, state);
-
- // We're going to use BitBlt with a b&w mask. This results in using the dest
- // dc's text color for the black bits in the mask, and the dest dc's
- // background color for the white bits in the mask. DrawFrameControl draws the
- // check in black, and the background in white.
- int bg_color_key;
- int text_color_key;
- switch (control_state) {
- case gfx::NativeTheme::kHovered:
- bg_color_key = COLOR_HIGHLIGHT;
- text_color_key = COLOR_HIGHLIGHTTEXT;
- break;
- case gfx::NativeTheme::kNormal:
- bg_color_key = COLOR_MENU;
- text_color_key = COLOR_MENUTEXT;
- break;
- case gfx::NativeTheme::kDisabled:
- bg_color_key = is_selected ? COLOR_HIGHLIGHT : COLOR_MENU;
- text_color_key = COLOR_GRAYTEXT;
- break;
- default:
- NOTREACHED();
- bg_color_key = COLOR_MENU;
- text_color_key = COLOR_MENUTEXT;
- break;
- }
- COLORREF old_bg_color = SetBkColor(hdc, GetSysColor(bg_color_key));
- COLORREF old_text_color = SetTextColor(hdc, GetSysColor(text_color_key));
- BitBlt(hdc, rect.x(), rect.y(), width, height, bitmap_dc, 0, 0, SRCCOPY);
- SetBkColor(hdc, old_bg_color);
- SetTextColor(hdc, old_text_color);
-
- return S_OK;
-}
-
-void NativeThemeWin::CloseHandles() const {
- if (!close_theme_)
- return;
-
- for (int i = 0; i < LAST; ++i) {
- if (theme_handles_[i]) {
- close_theme_(theme_handles_[i]);
- theme_handles_[i] = NULL;
- }
- }
-}
-
-bool NativeThemeWin::IsClassicTheme(ThemeName name) const {
- if (!theme_dll_)
- return true;
-
- return !GetThemeHandle(name);
-}
-
-HANDLE NativeThemeWin::GetThemeHandle(ThemeName theme_name) const {
- if (!open_theme_ || theme_name < 0 || theme_name >= LAST)
- return 0;
-
- if (theme_handles_[theme_name])
- return theme_handles_[theme_name];
-
- // Not found, try to load it.
- HANDLE handle = 0;
- switch (theme_name) {
- case BUTTON:
- handle = open_theme_(NULL, L"Button");
- break;
- case LIST:
- handle = open_theme_(NULL, L"Listview");
- break;
- case MENU:
- handle = open_theme_(NULL, L"Menu");
- break;
- case MENULIST:
- handle = open_theme_(NULL, L"Combobox");
- break;
- case SCROLLBAR:
- handle = open_theme_(NULL, L"Scrollbar");
- break;
- case STATUS:
- handle = open_theme_(NULL, L"Status");
- break;
- case TAB:
- handle = open_theme_(NULL, L"Tab");
- break;
- case TEXTFIELD:
- handle = open_theme_(NULL, L"Edit");
- break;
- case TRACKBAR:
- handle = open_theme_(NULL, L"Trackbar");
- break;
- case WINDOW:
- handle = open_theme_(NULL, L"Window");
- break;
- case PROGRESS:
- handle = open_theme_(NULL, L"Progress");
- break;
- case SPIN:
- handle = open_theme_(NULL, L"Spin");
- break;
- default:
- NOTREACHED();
- }
- theme_handles_[theme_name] = handle;
- return handle;
-}
-
// static
NativeThemeWin::ThemeName NativeThemeWin::GetThemeName(Part part) {
ThemeName name;
@@ -1701,4 +1582,122 @@ int NativeThemeWin::GetWindowsState(Part part,
return state_id;
}
+HRESULT NativeThemeWin::GetThemeInt(ThemeName theme,
+ int part_id,
+ int state_id,
+ int prop_id,
+ int *value) const {
+ HANDLE handle = GetThemeHandle(theme);
+ if (handle && get_theme_int_)
+ return get_theme_int_(handle, part_id, state_id, prop_id, value);
+ return E_NOTIMPL;
+}
+
+HRESULT NativeThemeWin::PaintFrameControl(HDC hdc,
+ const gfx::Rect& rect,
+ UINT type,
+ UINT state,
+ bool is_selected,
+ State control_state) const {
+ const int width = rect.width();
+ const int height = rect.height();
+
+ // DrawFrameControl for menu arrow/check wants a monochrome bitmap.
+ base::win::ScopedBitmap mask_bitmap(CreateBitmap(width, height, 1, 1, NULL));
+
+ if (mask_bitmap == NULL)
+ return E_OUTOFMEMORY;
+
+ base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(NULL));
+ base::win::ScopedSelectObject select_bitmap(bitmap_dc, mask_bitmap);
+ RECT local_rect = { 0, 0, width, height };
+ DrawFrameControl(bitmap_dc, &local_rect, type, state);
+
+ // We're going to use BitBlt with a b&w mask. This results in using the dest
+ // dc's text color for the black bits in the mask, and the dest dc's
+ // background color for the white bits in the mask. DrawFrameControl draws the
+ // check in black, and the background in white.
+ int bg_color_key;
+ int text_color_key;
+ switch (control_state) {
+ case gfx::NativeTheme::kHovered:
+ bg_color_key = COLOR_HIGHLIGHT;
+ text_color_key = COLOR_HIGHLIGHTTEXT;
+ break;
+ case gfx::NativeTheme::kNormal:
+ bg_color_key = COLOR_MENU;
+ text_color_key = COLOR_MENUTEXT;
+ break;
+ case gfx::NativeTheme::kDisabled:
+ bg_color_key = is_selected ? COLOR_HIGHLIGHT : COLOR_MENU;
+ text_color_key = COLOR_GRAYTEXT;
+ break;
+ default:
+ NOTREACHED();
+ bg_color_key = COLOR_MENU;
+ text_color_key = COLOR_MENUTEXT;
+ break;
+ }
+ COLORREF old_bg_color = SetBkColor(hdc, GetSysColor(bg_color_key));
+ COLORREF old_text_color = SetTextColor(hdc, GetSysColor(text_color_key));
+ BitBlt(hdc, rect.x(), rect.y(), width, height, bitmap_dc, 0, 0, SRCCOPY);
+ SetBkColor(hdc, old_bg_color);
+ SetTextColor(hdc, old_text_color);
+
+ return S_OK;
+}
+
+HANDLE NativeThemeWin::GetThemeHandle(ThemeName theme_name) const {
+ if (!open_theme_ || theme_name < 0 || theme_name >= LAST)
+ return 0;
+
+ if (theme_handles_[theme_name])
+ return theme_handles_[theme_name];
+
+ // Not found, try to load it.
+ HANDLE handle = 0;
+ switch (theme_name) {
+ case BUTTON:
+ handle = open_theme_(NULL, L"Button");
+ break;
+ case LIST:
+ handle = open_theme_(NULL, L"Listview");
+ break;
+ case MENU:
+ handle = open_theme_(NULL, L"Menu");
+ break;
+ case MENULIST:
+ handle = open_theme_(NULL, L"Combobox");
+ break;
+ case SCROLLBAR:
+ handle = open_theme_(NULL, L"Scrollbar");
+ break;
+ case STATUS:
+ handle = open_theme_(NULL, L"Status");
+ break;
+ case TAB:
+ handle = open_theme_(NULL, L"Tab");
+ break;
+ case TEXTFIELD:
+ handle = open_theme_(NULL, L"Edit");
+ break;
+ case TRACKBAR:
+ handle = open_theme_(NULL, L"Trackbar");
+ break;
+ case WINDOW:
+ handle = open_theme_(NULL, L"Window");
+ break;
+ case PROGRESS:
+ handle = open_theme_(NULL, L"Progress");
+ break;
+ case SPIN:
+ handle = open_theme_(NULL, L"Spin");
+ break;
+ default:
+ NOTREACHED();
+ }
+ theme_handles_[theme_name] = handle;
+ return handle;
+}
+
} // namespace gfx