Chromium Code Reviews| Index: chrome/browser/chromeos/native_theme_chromeos.cc |
| diff --git a/chrome/browser/chromeos/native_theme_chromeos.cc b/chrome/browser/chromeos/native_theme_chromeos.cc |
| index c0cd0253d46cd44af3bbfd9d8a3005d15500351d..880861bb23669d488ccffa734da9610107d79bf9 100644 |
| --- a/chrome/browser/chromeos/native_theme_chromeos.cc |
| +++ b/chrome/browser/chromeos/native_theme_chromeos.cc |
| @@ -13,10 +13,45 @@ |
| #include "gfx/size.h" |
| #include "gfx/skbitmap_operations.h" |
| #include "grit/theme_resources.h" |
| +#include "third_party/skia/include/effects/SkGradientShader.h" |
| +#include "third_party/skia/include/core/SkPaint.h" |
| +#include "third_party/skia/include/core/SkPath.h" |
| #include "third_party/skia/include/core/SkShader.h" |
| namespace { |
| +// Color and geometry constants. See theme_draw for details. |
| + |
| +// Border color used for many widgets. |
| +const SkColor kBaseStroke = SkColorSetRGB(0x8F, 0x8F, 0x8F); |
| + |
| +// Disabled border color used for many widgets. |
| +const SkColor kDisabledBaseStroke = SkColorSetRGB(0xB7, 0xB7, 0xB7); |
| + |
| +// Common gradient stop and colors. |
| +const SkColor kGradient0 = SkColorSetRGB(255, 255, 255); |
|
DaveMoore
2011/01/19 17:10:39
Nit: Please use more descriptive names for these.
xiyuan
2011/01/19 19:42:15
Done.
|
| +const SkColor kGradient1 = SkColorSetRGB(255, 255, 255); |
| +const SkColor kGradient2 = SkColorSetRGB(0xD8, 0xD8, 0xD8); |
| + |
| +const SkColor kPressedGradient0 = SkColorSetRGB(0x95, 0x95, 0x95); |
| +const SkColor kPressedGradient1 = SkColorSetRGB(0xE3, 0xE3, 0xE3); |
| + |
| +const SkColor kIndicatorStrokeDisabledColor = SkColorSetRGB(0xB4, 0xB4, 0xB4); |
| +// TODO: these are wrong, what should they be? |
| +const SkColor kIndicatorStrokePressedColor = SkColorSetRGB(0, 0, 0); |
| +const SkColor kIndicatorStrokeColor = SkColorSetRGB(0, 0, 0); |
| + |
| +const SkColor kRadioIndicatorGradient0 = SkColorSetRGB(0, 0, 0); |
| +const SkColor kRadioIndicatorGradient1 = SkColorSetRGB(0x83, 0x83, 0x83); |
| + |
| +const SkColor kRadioIndicatorDisabledGradient0 = |
| + SkColorSetRGB(0xB4, 0xB4, 0xB4); |
| +const SkColor kRadioIndicatorDisabledGradient1 = |
| + SkColorSetRGB(0xB7, 0xB7, 0xB7); |
| + |
| +const int kBorderCornerRadius = 3; |
| +const int kRadioIndicatorSize = 7; |
| + |
|
DaveMoore
2011/01/19 17:10:39
There are many inlined constants in this file. Cou
xiyuan
2011/01/19 19:42:15
Done.
|
| bool IntersectsClipRectInt( |
| skia::PlatformCanvas* canvas, int x, int y, int w, int h) { |
| SkRect clip; |
| @@ -74,6 +109,154 @@ void DrawBitmapInt( |
| canvas->drawRect(dest_rect, p); |
| } |
| +void GetRoundRectPathWithPadding(const gfx::Rect rect, |
| + int corner_radius, |
| + SkScalar padding, |
| + SkPath* path) { |
| + SkRect bounds = { SkDoubleToScalar(rect.x()) + padding, |
| + SkDoubleToScalar(rect.y()) + padding, |
| + SkDoubleToScalar(rect.right()) - padding, |
| + SkDoubleToScalar(rect.bottom()) - padding }; |
| + path->addRoundRect(bounds, |
| + SkIntToScalar(corner_radius) - padding, |
| + SkIntToScalar(corner_radius) - padding); |
| +} |
| + |
| +void GetRoundRectPath(const gfx::Rect rect, |
| + int corner_radius, |
| + SkPath* path) { |
| + // Add 0.5 pixel padding so that antialias paint does not touch extra pixels. |
| + GetRoundRectPathWithPadding(rect, corner_radius, SkIntToScalar(1) / 2, |
| + path); |
| +} |
| + |
| +void GetGradientPaintForRect(const gfx::Rect& rect, |
| + const SkColor* colors, |
| + const SkScalar* stops, |
| + int count, |
| + SkPaint* paint) { |
| + paint->setStyle(SkPaint::kFill_Style); |
| + paint->setAntiAlias(true); |
| + |
| + SkPoint points[2]; |
| + points[0].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y())); |
| + points[1].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.bottom())); |
| + |
| + SkShader* shader = SkGradientShader::CreateLinear(points, |
| + colors, stops, count, SkShader::kClamp_TileMode); |
| + |
| + paint->setShader(shader); |
| + // Unref shader after paint takes ownership, otherwise never deleted. |
| + shader->unref(); |
| +} |
| + |
| +void GetGradientPaintForRect(const gfx::Rect& rect, |
| + SkColor start_color, |
| + SkColor end_color, |
| + SkPaint* paint) { |
| + SkColor colors[2] = { start_color, end_color }; |
| + GetGradientPaintForRect(rect, colors, NULL, 2, paint); |
| +} |
| + |
| +void GetButtonGradientPaint(const gfx::Rect bounds, |
| + gfx::NativeThemeLinux::State state, |
| + SkPaint* paint) { |
| + if (state == gfx::NativeThemeLinux::kPressed) { |
| + static const SkColor kGradientColors[2] = { |
| + kPressedGradient0, |
| + kPressedGradient1 |
| + }; |
| + |
| + static const SkScalar kGradientPoints[2] = { |
| + SkIntToScalar(0), |
| + SkIntToScalar(1) |
| + }; |
| + |
| + GetGradientPaintForRect(bounds, |
| + kGradientColors, kGradientPoints, arraysize(kGradientPoints), |
| + paint); |
| + } else { |
| + static const SkColor kGradientColors[3] = { |
| + kGradient0, |
| + kGradient1, |
| + kGradient2 |
| + }; |
| + |
| + static const SkScalar kGradientPoints[3] = { |
| + SkIntToScalar(0), |
| + SkDoubleToScalar(0.5), |
| + SkIntToScalar(1) |
| + }; |
| + |
| + GetGradientPaintForRect(bounds, |
| + kGradientColors, kGradientPoints, arraysize(kGradientPoints), |
| + paint); |
| + } |
| +} |
| + |
| +void GetStrokePaint(SkColor color, SkPaint* paint) { |
| + paint->setStyle(SkPaint::kStroke_Style); |
| + paint->setAntiAlias(true); |
| + paint->setColor(color); |
| +} |
| + |
| +void GetStrokePaint(gfx::NativeThemeLinux::State state, SkPaint* paint) { |
| + |
| + if (state == gfx::NativeThemeLinux::kDisabled) |
| + GetStrokePaint(kDisabledBaseStroke, paint); |
| + else |
| + GetStrokePaint(kBaseStroke, paint); |
| +} |
| + |
| +void GetIndicatorStrokePaint(gfx::NativeThemeLinux::State state, |
| + SkPaint* paint) { |
| + paint->setStyle(SkPaint::kStroke_Style); |
| + paint->setAntiAlias(true); |
| + |
| + if (state == gfx::NativeThemeLinux::kDisabled) |
| + paint->setColor(kIndicatorStrokeDisabledColor); |
| + else if (state == gfx::NativeThemeLinux::kPressed) |
| + paint->setColor(kIndicatorStrokePressedColor); |
| + else |
| + paint->setColor(kIndicatorStrokeColor); |
| +} |
| + |
| +void GetRadioIndicatorGradientPaint(const gfx::Rect bounds, |
| + gfx::NativeThemeLinux::State state, |
| + SkPaint* paint) { |
| + paint->setStyle(SkPaint::kFill_Style); |
| + paint->setAntiAlias(true); |
| + |
| + SkPoint points[2]; |
| + points[0].set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y())); |
| + points[1].set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.bottom())); |
| + |
| + static const SkScalar kGradientPoints[2] = { |
| + SkIntToScalar(0), |
| + SkIntToScalar(1) |
| + }; |
| + |
| + if (state == gfx::NativeThemeLinux::kDisabled) { |
| + static const SkColor kGradientColors[2] = { |
| + kRadioIndicatorDisabledGradient0, |
| + kRadioIndicatorDisabledGradient1 |
| + }; |
| + |
| + GetGradientPaintForRect(bounds, |
| + kGradientColors, kGradientPoints, arraysize(kGradientPoints), |
| + paint); |
| + } else { |
| + static const SkColor kGradientColors[2] = { |
| + kRadioIndicatorGradient0, |
| + kRadioIndicatorGradient1 |
| + }; |
| + |
| + GetGradientPaintForRect(bounds, |
| + kGradientColors, kGradientPoints, arraysize(kGradientPoints), |
| + paint); |
| + } |
| +} |
| + |
| } |
| /* static */ |
| @@ -124,6 +307,14 @@ gfx::Size NativeThemeChromeos::GetSize(Part part) const { |
| width = scrollbar_width; |
| height = scrollbar_width; |
| break; |
| + case kSliderThumb: |
| + width = 16; |
| + height = 16; |
|
DaveMoore
2011/01/19 17:10:39
Use constants
xiyuan
2011/01/19 19:42:15
Done.
|
| + break; |
| + case kInnerSpinButton: |
| + return gfx::Size(scrollbar_width, 0); |
| + default: |
| + return NativeThemeLinux::GetSize(part); |
| } |
| return gfx::Size(width, height); |
| } |
| @@ -234,7 +425,282 @@ void NativeThemeChromeos::PaintArrowButton(skia::PlatformCanvas* canvas, |
| bitmap = rb.GetBitmapNamed(resource_id); |
| else |
| bitmap = GetHorizontalBitmapNamed(resource_id); |
| - canvas->drawBitmap(*bitmap, rect.x(), rect.y()); |
| + DrawBitmapInt(canvas, *bitmap, |
| + 0, 0, bitmap->width(), bitmap->height(), |
| + rect.x(), rect.y(), rect.width(), rect.height()); |
| +} |
| + |
| +void NativeThemeChromeos::PaintCheckbox(skia::PlatformCanvas* canvas, |
| + State state, const gfx::Rect& rect, |
| + const ButtonExtraParams& button) { |
| + PaintButtonLike(canvas, state, rect, button); |
| + |
| + if (button.checked) { |
| + SkPaint indicator_paint; |
| + GetIndicatorStrokePaint(state, &indicator_paint); |
| + indicator_paint.setStrokeWidth(2); |
| + |
| + int midx = rect.x() + rect.width() / 2; |
| + int midy = rect.y() + rect.height() / 2; |
| + canvas->drawLine(SkIntToScalar(rect.x() + 3), SkIntToScalar(midy), |
| + SkIntToScalar(midx - 1), SkIntToScalar(rect.bottom() - 3), |
| + indicator_paint); |
| + canvas->drawLine(SkIntToScalar(midx - 1), SkIntToScalar(rect.bottom() - 3), |
| + SkIntToScalar(rect.right() - 3), SkIntToScalar(rect.y() + 3), |
| + indicator_paint); |
| + } |
| +} |
| + |
| +void NativeThemeChromeos::PaintRadio(skia::PlatformCanvas* canvas, |
| + State state, |
| + const gfx::Rect& rect, |
| + const ButtonExtraParams& button) { |
| + gfx::Point center = rect.CenterPoint(); |
| + SkPath border; |
| + border.addCircle(SkIntToScalar(center.x()), SkIntToScalar(center.y()), |
| + SkDoubleToScalar(rect.width() / 2.0)); |
| + |
| + SkPaint fill_paint; |
| + GetButtonGradientPaint(rect, state, &fill_paint); |
| + canvas->drawPath(border, fill_paint); |
| + |
| + SkPaint stroke_paint; |
| + GetStrokePaint(state, &stroke_paint); |
| + canvas->drawPath(border, stroke_paint); |
| + |
| + if (button.checked) { |
| + SkPath indicator_border; |
| + indicator_border.addCircle(SkIntToScalar(center.x()), |
| + SkIntToScalar(center.y()), |
| + SkDoubleToScalar(kRadioIndicatorSize / 2.0)); |
| + |
| + SkPaint indicator_fill_paint; |
| + GetRadioIndicatorGradientPaint(rect, state, &indicator_fill_paint); |
| + canvas->drawPath(indicator_border, indicator_fill_paint); |
| + |
| + SkPaint indicator_paint; |
| + GetIndicatorStrokePaint(state, &indicator_paint); |
| + canvas->drawPath(indicator_border, indicator_paint); |
| + } |
| +} |
| + |
| +void NativeThemeChromeos::PaintButton(skia::PlatformCanvas* canvas, |
| + State state, |
| + const gfx::Rect& rect, |
| + const ButtonExtraParams& button) { |
| + PaintButtonLike(canvas, state, rect, button); |
| +} |
| + |
| +void NativeThemeChromeos::PaintTextField(skia::PlatformCanvas* canvas, |
| + State state, |
| + const gfx::Rect& rect, |
| + const TextFieldExtraParams& text) { |
| + if (rect.height() == 0) |
| + return; |
| + |
| + SkColor background_color = text.background_color; |
| + |
| + SkPaint fill_paint; |
| + fill_paint.setStyle(SkPaint::kFill_Style); |
| + if (state == kDisabled) { |
| + fill_paint.setColor(background_color); |
| + } else { |
| + SkScalar base_hsv[3]; |
| + SkColorToHSV(background_color, base_hsv); |
| + |
| + const SkColor gradient_colors[3] = { |
| + SaturateAndBrighten(base_hsv, 0, -0.18), |
| + background_color, |
| + background_color |
| + }; |
| + |
| + const SkScalar gradient_points[3] = { |
| + SkIntToScalar(0), |
| + SkDoubleToScalar(4.0 / rect.height()), |
| + SkIntToScalar(1) |
| + }; |
| + |
| + SkPoint points[2]; |
| + points[0].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.y())); |
| + points[1].set(SkIntToScalar(rect.x()), SkIntToScalar(rect.bottom())); |
| + |
| + GetGradientPaintForRect(rect, |
| + gradient_colors, gradient_points, arraysize(gradient_points), |
| + &fill_paint); |
| + } |
| + |
| + SkPath border; |
| + GetRoundRectPath(rect, kBorderCornerRadius, &border); |
| + canvas->drawPath(border, fill_paint); |
| + |
| + SkPaint stroke_paint; |
| + GetStrokePaint(state, &stroke_paint); |
| + canvas->drawPath(border, stroke_paint); |
| +} |
| + |
| +void NativeThemeChromeos::PaintSliderTrack(skia::PlatformCanvas* canvas, |
| + State state, |
| + const gfx::Rect& rect, |
| + const SliderExtraParams& slider) { |
| + const int midx = rect.x() + rect.width() / 2; |
| + const int midy = rect.y() + rect.height() / 2; |
| + |
| + gfx::Rect track_bounds; |
| + if (slider.vertical) { |
| + track_bounds.SetRect(std::max(rect.x(), midx - 3), |
| + rect.y(), |
| + std::min(rect.width(), 6), |
| + rect.height()); |
| + } else { |
| + track_bounds.SetRect(rect.x(), |
| + std::max(rect.y(), midy - 3), |
| + rect.width(), |
| + std::min(rect.height(), 6)); |
| + } |
| + |
| + SkPath border; |
| + GetRoundRectPath(track_bounds, kBorderCornerRadius, &border); |
| + |
| + SkPaint fill_paint; |
| + // Use normal button background. |
| + GetButtonGradientPaint(rect, kNormal, &fill_paint); |
| + canvas->drawPath(border, fill_paint); |
| + |
| + SkPaint stroke_paint; |
| + GetStrokePaint(state, &stroke_paint); |
| + canvas->drawPath(border, stroke_paint); |
| +} |
| + |
| +void NativeThemeChromeos::PaintSliderThumb(skia::PlatformCanvas* canvas, |
| + State state, |
| + const gfx::Rect& rect, |
| + const SliderExtraParams& slider) { |
| + if (state != kDisabled && slider.in_drag) |
| + state = kPressed; |
| + |
| + ButtonExtraParams button = { 0 }; |
| + PaintButtonLike(canvas, state, rect, button); |
| +} |
| + |
| +void NativeThemeChromeos::PaintInnerSpinButton(skia::PlatformCanvas* canvas, |
| + State state, |
| + const gfx::Rect& rect, |
| + const InnerSpinButtonExtraParams& spin_button) { |
| + // Adjust bounds to compensate the overridden "2px inset" parent border. |
| + gfx::Rect bounds = rect; |
| + bounds.Inset(0, -1, -1, -1); |
| + |
| + NativeThemeLinux::PaintInnerSpinButton(canvas, state, bounds, spin_button); |
| +} |
| + |
| +void NativeThemeChromeos::PaintProgressBar(skia::PlatformCanvas* canvas, |
| + State state, |
| + const gfx::Rect& rect, |
| + const ProgressBarExtraParams& progress_bar) { |
| + static const int kBorderWidth = 1; |
| + static const SkColor kBackgroundColors[] = { |
| + SkColorSetRGB(0xBB, 0xBB, 0xBB), |
| + SkColorSetRGB(0xE7, 0xE7, 0xE7), |
| + SkColorSetRGB(0xFE, 0xFE, 0xFE) |
| + }; |
| + |
| + static const SkScalar kBackgroundPoints[] = { |
| + SkDoubleToScalar(0), |
| + SkDoubleToScalar(0.1), |
| + SkDoubleToScalar(1) |
| + }; |
| + static const SkColor kBackgroundBorderColor = SkColorSetRGB(0xA1, 0xA1, 0xA1); |
| + |
| + // Draw background. |
| + SkPath border; |
| + GetRoundRectPath(rect, kBorderCornerRadius, &border); |
| + |
| + SkPaint fill_paint; |
| + GetGradientPaintForRect(rect, |
| + kBackgroundColors, kBackgroundPoints, arraysize(kBackgroundPoints), |
| + &fill_paint); |
| + canvas->drawPath(border, fill_paint); |
| + |
| + SkPaint stroke_paint; |
| + GetStrokePaint(kBackgroundBorderColor, &stroke_paint); |
| + canvas->drawPath(border, stroke_paint); |
| + |
| + if (progress_bar.value_rect_width > 1) { |
| + bool enabled = state != kDisabled; |
| + gfx::Rect value_rect(progress_bar.value_rect_x, |
| + progress_bar.value_rect_y, |
| + progress_bar.value_rect_width, |
| + progress_bar.value_rect_height); |
| + |
| + const SkColor bar_color_start = enabled ? |
| + SkColorSetRGB(100, 116, 147) : |
| + SkColorSetRGB(229, 232, 237); |
| + const SkColor bar_color_end = enabled ? |
| + SkColorSetRGB(65, 73, 87) : |
| + SkColorSetRGB(224, 225, 227); |
| + |
| + const SkColor bar_outer_color = enabled ? |
| + SkColorSetRGB(0x4A, 0x4A, 0x4A) : |
| + SkColorSetARGB(0x80, 0x4A, 0x4A, 0x4A); |
| + |
| + const SkColor bar_inner_border_color = |
| + SkColorSetARGB(0x3F, 0xFF, 0xFF, 0xFF); // 0.25 white |
| + const SkColor bar_inner_shadow_color = |
| + SkColorSetARGB(0x54, 0xFF, 0xFF, 0xFF); // 0.33 white |
| + |
| + // Draw bar background |
| + SkPath value_border; |
| + GetRoundRectPath(value_rect, kBorderCornerRadius, &value_border); |
| + |
| + SkPaint value_fill_paint; |
| + GetGradientPaintForRect(rect,bar_color_start, bar_color_end, |
| + &value_fill_paint); |
| + canvas->drawPath(value_border, value_fill_paint); |
| + |
| + // Draw inner stroke and shadow if wide enough. |
| + if (progress_bar.value_rect_width > 2 * kBorderWidth) { |
| + canvas->save(); |
| + |
| + SkPath inner_path; |
| + GetRoundRectPathWithPadding(value_rect, kBorderCornerRadius, |
| + SkIntToScalar(kBorderWidth), &inner_path); |
| + canvas->clipPath(inner_path); |
| + |
| + // Draw bar inner stroke |
| + gfx::Rect inner_stroke_rect = value_rect; |
| + inner_stroke_rect.Inset(kBorderWidth, kBorderWidth); |
| + |
| + SkPath inner_stroke_path; |
| + GetRoundRectPath(inner_stroke_rect, kBorderCornerRadius - kBorderWidth, |
| + &inner_stroke_path); |
| + |
| + SkPaint inner_stroke_paint; |
| + GetStrokePaint(bar_inner_border_color, &inner_stroke_paint); |
| + |
| + canvas->drawPath(inner_stroke_path, inner_stroke_paint); |
| + |
| + // Draw bar inner shadow |
| + gfx::Rect inner_shadow_rect(progress_bar.value_rect_x, |
| + progress_bar.value_rect_y + kBorderWidth, |
| + progress_bar.value_rect_width, |
| + progress_bar.value_rect_height); |
| + SkPath inner_shadow_path; |
| + GetRoundRectPath(inner_shadow_rect, kBorderCornerRadius, |
| + &inner_shadow_path); |
| + |
| + SkPaint inner_shadow_paint; |
| + GetStrokePaint(bar_inner_shadow_color, &inner_shadow_paint); |
| + |
| + canvas->drawPath(inner_shadow_path, inner_shadow_paint); |
| + |
| + canvas->restore(); |
| + } |
| + |
| + // Draw bar stroke |
| + SkPaint value_stroke_paint; |
| + GetStrokePaint(bar_outer_color, &value_stroke_paint); |
| + canvas->drawPath(value_border, value_stroke_paint); |
| + } |
| } |
| SkBitmap* NativeThemeChromeos::GetHorizontalBitmapNamed(int resource_id) { |
| @@ -256,3 +722,17 @@ SkBitmap* NativeThemeChromeos::GetHorizontalBitmapNamed(int resource_id) { |
| return NULL; |
| } |
| +void NativeThemeChromeos::PaintButtonLike(skia::PlatformCanvas* canvas, |
| + State state, const gfx::Rect& rect, |
| + const ButtonExtraParams& button) { |
| + SkPath border; |
| + GetRoundRectPath(rect, kBorderCornerRadius, &border); |
| + |
| + SkPaint fill_paint; |
| + GetButtonGradientPaint(rect, state, &fill_paint); |
| + canvas->drawPath(border, fill_paint); |
| + |
| + SkPaint stroke_paint; |
| + GetStrokePaint(state, &stroke_paint); |
| + canvas->drawPath(border, stroke_paint); |
| +} |