Commit 3a2f267b authored by Joey Arhar's avatar Joey Arhar Committed by Commit Bot

Enable form control refresh for Android

This patch enables the new form control refresh feature, controlled by
the flag #form-controls-refresh, for Android by moving the new form
controls from NativeThemeAura to NativeThemeBase.

Bug: 1022073
Change-Id: I1fbc4cd2962becbe93a227518354c46886467aa4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1900651
Commit-Queue: Joey Arhar <jarhar@chromium.org>
Reviewed-by: default avatarMason Freed <masonfreed@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#715293}
parent afa7f664
...@@ -43,6 +43,7 @@ static void GetNativeThemeExtraParams( ...@@ -43,6 +43,7 @@ static void GetNativeThemeExtraParams(
native_theme_extra_params->button.checked = extra_params->button.checked; native_theme_extra_params->button.checked = extra_params->button.checked;
native_theme_extra_params->button.indeterminate = native_theme_extra_params->button.indeterminate =
extra_params->button.indeterminate; extra_params->button.indeterminate;
native_theme_extra_params->button.zoom = extra_params->button.zoom;
break; break;
case WebThemeEngine::kPartRadio: case WebThemeEngine::kPartRadio:
native_theme_extra_params->button.checked = extra_params->button.checked; native_theme_extra_params->button.checked = extra_params->button.checked;
...@@ -80,6 +81,10 @@ static void GetNativeThemeExtraParams( ...@@ -80,6 +81,10 @@ static void GetNativeThemeExtraParams(
extra_params->menu_list.background_color; extra_params->menu_list.background_color;
break; break;
case WebThemeEngine::kPartSliderTrack: case WebThemeEngine::kPartSliderTrack:
native_theme_extra_params->slider.thumb_x = extra_params->slider.thumb_x;
native_theme_extra_params->slider.thumb_y = extra_params->slider.thumb_y;
native_theme_extra_params->slider.zoom = extra_params->slider.zoom;
FALLTHROUGH;
case WebThemeEngine::kPartSliderThumb: case WebThemeEngine::kPartSliderThumb:
native_theme_extra_params->slider.vertical = native_theme_extra_params->slider.vertical =
extra_params->slider.vertical; extra_params->slider.vertical;
......
...@@ -42,20 +42,6 @@ constexpr int kOverlayScrollbarCenterPatchSize = 1; ...@@ -42,20 +42,6 @@ constexpr int kOverlayScrollbarCenterPatchSize = 1;
const SkColor kTrackColor = SkColorSetRGB(0xF1, 0xF1, 0xF1); const SkColor kTrackColor = SkColorSetRGB(0xF1, 0xF1, 0xF1);
const SkScalar kScrollRadius = const SkScalar kScrollRadius =
1; // select[multiple] radius+width are set in css 1; // select[multiple] radius+width are set in css
const int kCheckboxBorderRadius = 2;
const int kInputBorderRadius = 2;
const SkScalar kBorderWidth = 1.f;
const SkScalar kSliderTrackBorderRadius = 40.f;
const SkScalar kSliderTrackHeight = 8.f;
const int kSliderThumbSize = 16;
const SkScalar kSliderThumbBorderWidth = 1.f;
const SkScalar kSliderThumbBorderHoveredWidth = 1.f;
const SkScalar kMenuListArrowStrokeWidth = 2.f;
// The "dash" is 8x2 px by default (the checkbox is 13x13 px).
const SkScalar kIndeterminateInsetWidthRatio = (13 - 8) / 2.0f / 13;
const SkScalar kIndeterminateInsetHeightRatio = (13 - 2) / 2.0f / 13;
// Default height for progress is 16px and the track is 8px.
const SkScalar kTrackHeightRatio = 8.0f / 16;
} // namespace } // namespace
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -117,104 +103,6 @@ SkColor NativeThemeAura::GetSystemColor(ColorId color_id, ...@@ -117,104 +103,6 @@ SkColor NativeThemeAura::GetSystemColor(ColorId color_id,
return GetAuraColor(color_id, this, color_scheme); return GetAuraColor(color_id, this, color_scheme);
} }
SkColor NativeThemeAura::GetControlColor(ControlColorId color_id,
ColorScheme color_scheme) const {
if (UsesHighContrastColors())
return GetHighContrastControlColor(color_id, color_scheme);
switch (color_id) {
case kBorder:
return SkColorSetRGB(0x76, 0x76, 0x76);
case kHoveredBorder:
return SkColorSetRGB(0x4F, 0x4F, 0x4F);
case kDisabledBorder:
return SkColorSetARGB(0x4D, 0x76, 0x76, 0x76);
case kAccent:
return SkColorSetRGB(0x00, 0x75, 0xFF);
case kHoveredAccent:
return SkColorSetRGB(0x00, 0x5C, 0xC8);
case kDisabledAccent:
return SkColorSetARGB(0x4D, 0x76, 0x76, 0x76);
case kBackground:
return SK_ColorWHITE;
case kDisabledBackground:
return SkColorSetA(SK_ColorWHITE, 0x99);
case kFill:
return SkColorSetRGB(0xEF, 0xEF, 0xEF);
case kHoveredFill:
return SkColorSetRGB(0xE5, 0xE5, 0xE5);
case kDisabledFill:
return SkColorSetARGB(0x4D, 0xEF, 0xEF, 0xEF);
case kLightenLayer:
return SkColorSetARGB(0x33, 0xA9, 0xA9, 0xA9);
case kProgressValue:
return SkColorSetRGB(0x00, 0x75, 0xFF);
case kSlider:
return SkColorSetRGB(0x00, 0x75, 0xFF);
case kHoveredSlider:
return SkColorSetRGB(0x00, 0x5C, 0xC8);
case kDisabledSlider:
return SkColorSetRGB(0xCB, 0xCB, 0xCB);
}
NOTREACHED();
return gfx::kPlaceholderColor;
}
SkColor NativeThemeAura::GetHighContrastControlColor(
ControlColorId color_id,
ColorScheme color_scheme) const {
if (!system_colors_.empty()) {
switch (color_id) {
case kDisabledBorder:
case kDisabledAccent:
case kDisabledSlider:
return system_colors_[SystemThemeColor::kGrayText];
case kBorder:
case kHoveredBorder:
return system_colors_[SystemThemeColor::kButtonText];
case kAccent:
case kHoveredAccent:
case kProgressValue:
case kSlider:
case kHoveredSlider:
return system_colors_[SystemThemeColor::kHighlight];
case kBackground:
case kDisabledBackground:
case kFill:
case kHoveredFill:
case kDisabledFill:
case kLightenLayer:
return system_colors_[SystemThemeColor::kWindow];
}
} else {
// Default high contrast colors (used in web test mode)
switch (color_id) {
case kDisabledBorder:
case kDisabledAccent:
case kDisabledSlider:
return SK_ColorGREEN;
case kBorder:
case kHoveredBorder:
return SK_ColorWHITE;
case kAccent:
case kHoveredAccent:
case kProgressValue:
case kSlider:
case kHoveredSlider:
return SK_ColorCYAN;
case kBackground:
case kDisabledBackground:
case kFill:
case kHoveredFill:
case kDisabledFill:
case kLightenLayer:
return SK_ColorBLACK;
}
}
NOTREACHED();
return gfx::kPlaceholderColor;
}
void NativeThemeAura::PaintMenuPopupBackground( void NativeThemeAura::PaintMenuPopupBackground(
cc::PaintCanvas* canvas, cc::PaintCanvas* canvas,
const gfx::Size& size, const gfx::Size& size,
...@@ -296,14 +184,12 @@ void NativeThemeAura::PaintArrowButton( ...@@ -296,14 +184,12 @@ void NativeThemeAura::PaintArrowButton(
SkScalar lower_right_radius = 0; SkScalar lower_right_radius = 0;
float zoom = arrow.zoom ? arrow.zoom : 1.0; float zoom = arrow.zoom ? arrow.zoom : 1.0;
if (direction == kScrollbarUpArrow) { if (direction == kScrollbarUpArrow) {
static_assert(kInputBorderRadius > 0, "no border radius present");
if (arrow.right_to_left) { if (arrow.right_to_left) {
upper_left_radius = kScrollRadius * zoom; upper_left_radius = kScrollRadius * zoom;
} else { } else {
upper_right_radius = kScrollRadius * zoom; upper_right_radius = kScrollRadius * zoom;
} }
} else if (direction == kScrollbarDownArrow) { } else if (direction == kScrollbarDownArrow) {
static_assert(kInputBorderRadius > 0, "no border radius present");
if (arrow.right_to_left) { if (arrow.right_to_left) {
lower_left_radius = kScrollRadius * zoom; lower_left_radius = kScrollRadius * zoom;
} else { } else {
...@@ -449,529 +335,6 @@ void NativeThemeAura::PaintScrollbarCorner(cc::PaintCanvas* canvas, ...@@ -449,529 +335,6 @@ void NativeThemeAura::PaintScrollbarCorner(cc::PaintCanvas* canvas,
canvas->drawIRect(RectToSkIRect(rect), flags); canvas->drawIRect(RectToSkIRect(rect), flags);
} }
SkColor NativeThemeAura::ControlsAccentColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredAccent;
} else if (state == kPressed) {
color_id = kHoveredAccent;
} else if (state == kDisabled) {
color_id = kDisabledAccent;
} else {
color_id = kAccent;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeAura::ControlsSliderColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredSlider;
} else if (state == kPressed) {
color_id = kHoveredSlider;
} else if (state == kDisabled) {
color_id = kDisabledSlider;
} else {
color_id = kSlider;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeAura::ControlsBorderColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredBorder;
} else if (state == kDisabled) {
color_id = kDisabledBorder;
} else {
color_id = kBorder;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeAura::ControlsFillColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredFill;
} else if (state == kPressed) {
color_id = kHoveredFill;
} else if (state == kDisabled) {
color_id = kDisabledFill;
} else {
color_id = kFill;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeAura::ControlsBackgroundColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kDisabled) {
color_id = kDisabledBackground;
} else {
color_id = kBackground;
}
return GetControlColor(color_id, color_scheme);
}
void NativeThemeAura::PaintCheckbox(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintCheckbox(canvas, state, rect, button,
color_scheme);
}
const float border_radius =
SkIntToScalar(kCheckboxBorderRadius) * button.zoom;
SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, true,
border_radius, color_scheme);
if (!skrect.isEmpty()) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
if (button.indeterminate) {
// Draw the dash.
flags.setColor(ControlsBorderColorForState(state, color_scheme));
const auto indeterminate =
skrect.makeInset(skrect.width() * kIndeterminateInsetWidthRatio,
skrect.height() * kIndeterminateInsetHeightRatio);
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRoundRect(indeterminate, border_radius, border_radius, flags);
} else if (button.checked) {
// Draw the accent background.
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(ControlsAccentColorForState(state, color_scheme));
canvas->drawRoundRect(skrect, border_radius, border_radius, flags);
// Draw the checkmark.
SkPath check;
check.moveTo(skrect.x() + skrect.width() * 0.2, skrect.centerY());
check.rLineTo(skrect.width() * 0.2, skrect.height() * 0.2);
check.lineTo(skrect.right() - skrect.width() * 0.2,
skrect.y() + skrect.height() * 0.2);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(SkFloatToScalar(skrect.height() * 0.16));
SkColor checkmark_color =
ControlsBackgroundColorForState(state, color_scheme);
flags.setColor(checkmark_color);
canvas->drawPath(check, flags);
}
}
}
void NativeThemeAura::PaintRadio(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintRadio(canvas, state, rect, button,
color_scheme);
}
// Most of a radio button is the same as a checkbox, except the the rounded
// square is a circle (i.e. border radius >= 100%).
const SkScalar radius = SkFloatToScalar(
static_cast<float>(std::max(rect.width(), rect.height())) * 0.5);
SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, false,
radius, color_scheme);
if (!skrect.isEmpty() && button.checked) {
// Draw the dot.
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(ControlsAccentColorForState(state, color_scheme));
skrect.inset(skrect.width() * 0.2, skrect.height() * 0.2);
// Use drawRoundedRect instead of drawOval to be completely consistent
// with the border in PaintCheckboxRadioNewCommon.
canvas->drawRoundRect(skrect, radius, radius, flags);
}
}
// Draws the common elements of checkboxes and radio buttons.
// Returns the rectangle within which any additional decorations should be
// drawn, or empty if none.
SkRect NativeThemeAura::PaintCheckboxRadioCommon(
cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
bool is_checkbox,
const SkScalar borderRadius,
ColorScheme color_scheme) const {
SkRect skrect = gfx::RectToSkRect(rect);
// Use the largest square that fits inside the provided rectangle.
// No other browser seems to support non-square widget, so accidentally
// having non-square sizes is common (eg. amazon and webkit dev tools).
if (skrect.width() != skrect.height()) {
SkScalar size = SkMinScalar(skrect.width(), skrect.height());
skrect.inset((skrect.width() - size) / 2, (skrect.height() - size) / 2);
}
// If the rectangle is too small then paint only a rectangle. We don't want
// to have to worry about '- 1' and '+ 1' calculations below having overflow
// or underflow.
if (skrect.width() <= 2) {
cc::PaintFlags flags;
flags.setColor(GetControlColor(kBorder, color_scheme));
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRect(skrect, flags);
// Too small to draw anything more.
return SkRect::MakeEmpty();
}
cc::PaintFlags flags;
flags.setAntiAlias(true);
// Paint the background (is not visible behind the rounded corners).
// Note we need to shrink the rect for background a little bit so we don't see
// artifacts introduced by antialiasing between the border and the background
// near the rounded corners of checkbox.
const auto background_rect =
skrect.makeInset(kBorderWidth * 0.2f, kBorderWidth * 0.2f);
PaintLightenLayer(canvas, background_rect, state, borderRadius, color_scheme);
flags.setColor(ControlsBackgroundColorForState(state, color_scheme));
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRoundRect(background_rect, borderRadius, borderRadius, flags);
// Draw the border.
if (!(is_checkbox && button.checked)) {
// Shrink half border width so the final pixels of the border will be within
// the rectangle.
const auto border_rect =
skrect.makeInset(kBorderWidth / 2, kBorderWidth / 2);
SkColor border_color =
button.checked ? ControlsAccentColorForState(state, color_scheme)
: ControlsBorderColorForState(state, color_scheme);
flags.setColor(border_color);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
canvas->drawRoundRect(border_rect, borderRadius, borderRadius, flags);
}
// Return the rectangle for drawing any additional decorations.
return skrect;
}
void NativeThemeAura::PaintTextField(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const TextFieldExtraParams& text,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintTextField(canvas, state, rect, text,
color_scheme);
}
SkRect bounds = gfx::RectToSkRect(rect);
const SkScalar borderRadius = SkIntToScalar(kInputBorderRadius);
// Paint the background (is not visible behind the rounded corners).
bounds.inset(kBorderWidth / 2, kBorderWidth / 2);
cc::PaintFlags fill_flags;
fill_flags.setStyle(cc::PaintFlags::kFill_Style);
if (text.background_color != 0) {
PaintLightenLayer(canvas, bounds, state, borderRadius, color_scheme);
fill_flags.setColor(ControlsBackgroundColorForState(state, color_scheme));
canvas->drawRoundRect(bounds, borderRadius, borderRadius, fill_flags);
}
// Paint the border: 1px solid.
cc::PaintFlags stroke_flags;
stroke_flags.setColor(ControlsBorderColorForState(state, color_scheme));
stroke_flags.setStyle(cc::PaintFlags::kStroke_Style);
stroke_flags.setStrokeWidth(kBorderWidth);
canvas->drawRoundRect(bounds, borderRadius, borderRadius, stroke_flags);
}
void NativeThemeAura::PaintLightenLayer(cc::PaintCanvas* canvas,
SkRect skrect,
State state,
SkScalar border_radius,
ColorScheme color_scheme) const {
if (state == kDisabled) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
// Draw the lighten layer to lighten the background so the translucent
// disabled color works regardless of what it's over.
flags.setColor(GetControlColor(kLightenLayer, color_scheme));
canvas->drawRoundRect(skrect, border_radius, border_radius, flags);
}
}
void NativeThemeAura::PaintButton(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintButton(canvas, state, rect, button,
color_scheme);
}
cc::PaintFlags flags;
SkRect skrect = gfx::RectToSkRect(rect);
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
// If the button is too small, fallback to drawing a single, solid color.
if (rect.width() < 5 || rect.height() < 5) {
flags.setColor(ControlsFillColorForState(state, color_scheme));
canvas->drawRect(skrect, flags);
return;
}
// Paint the background (is not visible behind the rounded corners).
skrect.inset(kBorderWidth / 2, kBorderWidth / 2);
PaintLightenLayer(canvas, skrect, state, kInputBorderRadius, color_scheme);
flags.setColor(ControlsFillColorForState(state, color_scheme));
canvas->drawRoundRect(skrect, kInputBorderRadius, kInputBorderRadius, flags);
// Paint the border: 1px solid.
if (button.has_border) {
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
flags.setColor(ControlsBorderColorForState(state, color_scheme));
canvas->drawRoundRect(skrect, kInputBorderRadius, kInputBorderRadius,
flags);
}
}
SkRect AlignSliderTrack(const gfx::Rect& slider_rect,
const NativeTheme::SliderExtraParams& slider,
bool is_value,
float track_height) {
const float kAlignment = track_height / 2;
const float mid_x = slider_rect.x() + slider_rect.width() / 2.0f;
const float mid_y = slider_rect.y() + slider_rect.height() / 2.0f;
SkRect aligned_rect;
if (slider.vertical) {
const float top = is_value ? slider_rect.y() + slider.thumb_y + kAlignment
: slider_rect.y();
aligned_rect.setLTRB(
std::max(float(slider_rect.x()), mid_x - kAlignment), top,
std::min(float(slider_rect.right()), mid_x + kAlignment),
slider_rect.bottom());
} else {
const float right = is_value ? slider_rect.x() + slider.thumb_x + kAlignment
: slider_rect.right();
aligned_rect.setLTRB(
slider_rect.x(), std::max(float(slider_rect.y()), mid_y - kAlignment),
right, std::min(float(slider_rect.bottom()), mid_y + kAlignment));
}
return aligned_rect;
}
void NativeThemeAura::PaintSliderTrack(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintSliderTrack(canvas, state, rect, slider,
color_scheme);
}
// Paint the entire slider track.
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setColor(ControlsFillColorForState(state, color_scheme));
const float track_height = kSliderTrackHeight * slider.zoom;
SkRect track_rect = AlignSliderTrack(rect, slider, false, track_height);
// Shrink the track by 1 pixel so the thumb can completely cover the track on
// both ends.
if (slider.vertical)
track_rect.inset(0, 1);
else
track_rect.inset(1, 0);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
// Clip the track to create rounded corners for the value bar.
SkRRect rounded_rect;
rounded_rect.setRectXY(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius);
canvas->clipRRect(rounded_rect, SkClipOp::kIntersect, true);
// Paint the value slider track.
flags.setColor(ControlsSliderColorForState(state, color_scheme));
SkRect value_rect = AlignSliderTrack(rect, slider, true, track_height);
canvas->drawRect(value_rect, flags);
// Paint the border.
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
SkColor border_color = ControlsBorderColorForState(state, color_scheme);
if (!UsesHighContrastColors() && state != kDisabled)
border_color = SkColorSetA(border_color, 0x80);
flags.setColor(border_color);
track_rect.inset(kBorderWidth / 2, kBorderWidth / 2);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
}
void NativeThemeAura::PaintSliderThumb(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintSliderThumb(canvas, state, rect, slider,
color_scheme);
}
const SkScalar radius = SkFloatToScalar(
static_cast<float>(std::max(rect.width(), rect.height())) * 0.5);
SkRect thumb_rect = gfx::RectToSkRect(rect);
cc::PaintFlags flags;
flags.setAntiAlias(true);
SkScalar border_width = kSliderThumbBorderWidth;
if (state == kHovered || state == kPressed) {
border_width = kSliderThumbBorderHoveredWidth;
}
// Paint the background (is not visible behind the rounded corners).
thumb_rect.inset(border_width / 2, border_width / 2);
flags.setColor(ControlsSliderColorForState(state, color_scheme));
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRoundRect(thumb_rect, radius, radius, flags);
}
void NativeThemeAura::PaintProgressBar(
cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ProgressBarExtraParams& progress_bar,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintProgressBar(canvas, state, rect, progress_bar,
color_scheme);
}
DCHECK(!rect.IsEmpty());
// Paint the track.
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(GetControlColor(kFill, color_scheme));
SliderExtraParams slider;
slider.vertical = false;
float track_height = rect.height() * kTrackHeightRatio;
SkRect track_rect = AlignSliderTrack(rect, slider, false, track_height);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
// Clip the track to create rounded corners for the value bar.
SkRRect rounded_rect;
rounded_rect.setRectXY(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius);
canvas->clipRRect(rounded_rect, SkClipOp::kIntersect, true);
// Paint the progress value bar.
const SkScalar kMinimumProgressValueWidth = 2;
SkScalar adjusted_width = progress_bar.value_rect_width;
if (adjusted_width > 0 && adjusted_width < kMinimumProgressValueWidth)
adjusted_width = kMinimumProgressValueWidth;
gfx::Rect original_value_rect(progress_bar.value_rect_x,
progress_bar.value_rect_y, adjusted_width,
progress_bar.value_rect_height);
SkRect value_rect =
AlignSliderTrack(original_value_rect, slider, false, track_height);
flags.setColor(GetControlColor(kAccent, color_scheme));
if (progress_bar.determinate) {
canvas->drawRect(value_rect, flags);
} else {
canvas->drawRoundRect(value_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
}
// Paint the border.
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
SkColor border_color = GetControlColor(kBorder, color_scheme);
if (!UsesHighContrastColors())
border_color = SkColorSetA(border_color, 0x80);
flags.setColor(border_color);
track_rect.inset(kBorderWidth / 2, kBorderWidth / 2);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
}
void NativeThemeAura::PaintMenuList(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const MenuListExtraParams& menu_list,
ColorScheme color_scheme) const {
if (!features::IsFormControlsRefreshEnabled()) {
return NativeThemeBase::PaintMenuList(canvas, state, rect, menu_list,
color_scheme);
}
// If a border radius is specified paint the background and the border of
// the menulist, otherwise let the non-theming code paint the background
// and the border of the control. The arrow (menulist button) is always
// painted by the theming code.
if (!menu_list.has_border_radius) {
TextFieldExtraParams text_field = {0};
text_field.background_color = menu_list.background_color;
PaintTextField(canvas, state, rect, text_field, color_scheme);
}
// Paint the arrow.
cc::PaintFlags flags;
flags.setColor(menu_list.arrow_color);
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kMenuListArrowStrokeWidth);
float arrow_width = menu_list.arrow_size;
int arrow_height = arrow_width * 0.5;
gfx::Rect arrow(menu_list.arrow_x, menu_list.arrow_y - (arrow_height / 2),
arrow_width, arrow_height);
arrow.Intersect(rect);
if (arrow_width != arrow.width() || arrow_height != arrow.height()) {
// The arrow is clipped after being constrained to the paint rect so we need
// to recalculate its size.
int height_clip = arrow_height - arrow.height();
int width_clip = arrow_width - arrow.width();
if (height_clip > width_clip) {
arrow.set_width(arrow.height() * 1.6);
} else {
arrow.set_height(arrow.width() * 0.6);
}
arrow.set_y(menu_list.arrow_y - (arrow.height() / 2));
}
SkPath path;
path.moveTo(arrow.x(), arrow.y());
path.lineTo(arrow.x() + arrow.width() / 2, arrow.y() + arrow.height());
path.lineTo(arrow.x() + arrow.width(), arrow.y());
canvas->drawPath(path, flags);
}
gfx::Size NativeThemeAura::GetPartSize(Part part, gfx::Size NativeThemeAura::GetPartSize(Part part,
State state, State state,
const ExtraParams& extra) const { const ExtraParams& extra) const {
...@@ -994,10 +357,6 @@ gfx::Size NativeThemeAura::GetPartSize(Part part, ...@@ -994,10 +357,6 @@ gfx::Size NativeThemeAura::GetPartSize(Part part,
} }
} }
if (part == kSliderThumb && features::IsFormControlsRefreshEnabled()) {
return gfx::Size(kSliderThumbSize, kSliderThumbSize);
}
return NativeThemeBase::GetPartSize(part, state, extra); return NativeThemeBase::GetPartSize(part, state, extra);
} }
......
...@@ -18,52 +18,12 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase { ...@@ -18,52 +18,12 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase {
friend class NativeThemeAuraTest; friend class NativeThemeAuraTest;
friend class base::NoDestructor<NativeThemeAura>; friend class base::NoDestructor<NativeThemeAura>;
// Colors for form controls refresh.
enum ControlColorId {
kBorder,
kDisabledBorder,
kHoveredBorder,
kAccent,
kDisabledAccent,
kHoveredAccent,
kBackground,
kDisabledBackground,
kFill,
kDisabledFill,
kHoveredFill,
kLightenLayer,
kProgressValue,
kSlider,
kDisabledSlider,
kHoveredSlider
};
explicit NativeThemeAura(bool use_overlay_scrollbars); explicit NativeThemeAura(bool use_overlay_scrollbars);
~NativeThemeAura() override; ~NativeThemeAura() override;
static NativeThemeAura* instance(); static NativeThemeAura* instance();
static NativeThemeAura* web_instance(); static NativeThemeAura* web_instance();
void PaintLightenLayer(cc::PaintCanvas* canvas,
SkRect skrect,
State state,
SkScalar border_radius,
ColorScheme color_scheme) const;
SkColor ControlsAccentColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsBorderColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsFillColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsBackgroundColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsSliderColorForState(State state,
ColorScheme color_scheme) const;
SkColor GetHighContrastControlColor(ControlColorId color_id,
ColorScheme color_scheme) const;
SkColor GetControlColor(ControlColorId color_id,
ColorScheme color_scheme) const;
// NativeThemeBase: // NativeThemeBase:
SkColor GetSystemColor(ColorId color_id, SkColor GetSystemColor(ColorId color_id,
ColorScheme color_scheme) const override; ColorScheme color_scheme) const override;
...@@ -77,11 +37,6 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase { ...@@ -77,11 +37,6 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase {
const gfx::Rect& rect, const gfx::Rect& rect,
const MenuItemExtraParams& menu_item, const MenuItemExtraParams& menu_item,
ColorScheme color_scheme) const override; ColorScheme color_scheme) const override;
void PaintProgressBar(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ProgressBarExtraParams& progress_bar,
ColorScheme color_scheme) const override;
void PaintArrowButton(cc::PaintCanvas* gc, void PaintArrowButton(cc::PaintCanvas* gc,
const gfx::Rect& rect, const gfx::Rect& rect,
Part direction, Part direction,
...@@ -104,41 +59,6 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase { ...@@ -104,41 +59,6 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase {
State state, State state,
const gfx::Rect& rect, const gfx::Rect& rect,
ColorScheme color_scheme) const override; ColorScheme color_scheme) const override;
void PaintCheckbox(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const override;
void PaintRadio(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const override;
void PaintTextField(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const TextFieldExtraParams& text,
ColorScheme color_scheme) const override;
void PaintButton(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const override;
void PaintSliderTrack(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme) const override;
void PaintSliderThumb(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const SliderExtraParams& slider,
ColorScheme color_scheme) const override;
void PaintMenuList(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const MenuListExtraParams& menu_list,
ColorScheme color_scheme) const override;
gfx::Size GetPartSize(Part part, gfx::Size GetPartSize(Part part,
State state, State state,
const ExtraParams& extra) const override; const ExtraParams& extra) const override;
...@@ -147,16 +67,6 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase { ...@@ -147,16 +67,6 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase {
gfx::Rect GetNinePatchAperture(Part part) const override; gfx::Rect GetNinePatchAperture(Part part) const override;
private: private:
// Paint the common parts of the checkboxes and radio buttons.
// borderRadius specifies how rounded the corners should be.
SkRect PaintCheckboxRadioCommon(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
bool is_checkbox,
const SkScalar borderRadius,
ColorScheme color_scheme) const;
static void DrawPartiallyRoundRect(cc::PaintCanvas* canvas, static void DrawPartiallyRoundRect(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const SkScalar upper_left_radius, const SkScalar upper_left_radius,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/base/layout.h" #include "ui/base/layout.h"
#include "ui/base/resource/resource_bundle.h" #include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h" #include "ui/base/ui_base_switches.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
...@@ -111,6 +112,21 @@ constexpr SkColor kArrowDisabledColor[2] = {SK_ColorBLACK, SK_ColorWHITE}; ...@@ -111,6 +112,21 @@ constexpr SkColor kArrowDisabledColor[2] = {SK_ColorBLACK, SK_ColorWHITE};
constexpr SkColor kButtonBorderColor[2] = {SK_ColorBLACK, SK_ColorWHITE}; constexpr SkColor kButtonBorderColor[2] = {SK_ColorBLACK, SK_ColorWHITE};
constexpr SkColor kProgressBackgroundColor[2] = {SK_ColorWHITE, SK_ColorBLACK}; constexpr SkColor kProgressBackgroundColor[2] = {SK_ColorWHITE, SK_ColorBLACK};
const int kCheckboxBorderRadius = 2;
// The "dash" is 8x2 px by default (the checkbox is 13x13 px).
const SkScalar kIndeterminateInsetWidthRatio = (13 - 8) / 2.0f / 13;
const SkScalar kIndeterminateInsetHeightRatio = (13 - 2) / 2.0f / 13;
const SkScalar kBorderWidth = 1.f;
const SkScalar kSliderTrackHeight = 8.f;
const SkScalar kSliderTrackBorderRadius = 40.f;
const SkScalar kSliderThumbBorderWidth = 1.f;
const SkScalar kSliderThumbBorderHoveredWidth = 1.f;
// Default height for progress is 16px and the track is 8px.
const SkScalar kTrackHeightRatio = 8.0f / 16;
const SkScalar kMenuListArrowStrokeWidth = 2.f;
const int kSliderThumbSize = 16;
const int kInputBorderRadius = 2;
// Get a color constant based on color-scheme // Get a color constant based on color-scheme
SkColor GetColor(const SkColor colors[2], SkColor GetColor(const SkColor colors[2],
ui::NativeTheme::ColorScheme color_scheme) { ui::NativeTheme::ColorScheme color_scheme) {
...@@ -177,6 +193,8 @@ gfx::Size NativeThemeBase::GetPartSize(Part part, ...@@ -177,6 +193,8 @@ gfx::Size NativeThemeBase::GetPartSize(Part part,
return gfx::Size(); // No default size. return gfx::Size(); // No default size.
case kSliderThumb: case kSliderThumb:
// These sizes match the sizes in Chromium Win. // These sizes match the sizes in Chromium Win.
if (features::IsFormControlsRefreshEnabled())
return gfx::Size(kSliderThumbSize, kSliderThumbSize);
return gfx::Size(kSliderThumbWidth, kSliderThumbHeight); return gfx::Size(kSliderThumbWidth, kSliderThumbHeight);
case kTabPanelBackground: case kTabPanelBackground:
NOTIMPLEMENTED(); NOTIMPLEMENTED();
...@@ -557,6 +575,48 @@ void NativeThemeBase::PaintCheckbox(cc::PaintCanvas* canvas, ...@@ -557,6 +575,48 @@ void NativeThemeBase::PaintCheckbox(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const ButtonExtraParams& button, const ButtonExtraParams& button,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
const float border_radius =
SkIntToScalar(kCheckboxBorderRadius) * button.zoom;
SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, true,
border_radius, color_scheme);
if (!skrect.isEmpty()) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
if (button.indeterminate) {
// Draw the dash.
flags.setColor(ControlsBorderColorForState(state, color_scheme));
const auto indeterminate =
skrect.makeInset(skrect.width() * kIndeterminateInsetWidthRatio,
skrect.height() * kIndeterminateInsetHeightRatio);
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRoundRect(indeterminate, border_radius, border_radius,
flags);
} else if (button.checked) {
// Draw the accent background.
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(ControlsAccentColorForState(state, color_scheme));
canvas->drawRoundRect(skrect, border_radius, border_radius, flags);
// Draw the checkmark.
SkPath check;
check.moveTo(skrect.x() + skrect.width() * 0.2, skrect.centerY());
check.rLineTo(skrect.width() * 0.2, skrect.height() * 0.2);
check.lineTo(skrect.right() - skrect.width() * 0.2,
skrect.y() + skrect.height() * 0.2);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(SkFloatToScalar(skrect.height() * 0.16));
SkColor checkmark_color =
ControlsBackgroundColorForState(state, color_scheme);
flags.setColor(checkmark_color);
canvas->drawPath(check, flags);
}
}
return;
}
SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, true, SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, true,
SkIntToScalar(2), color_scheme); SkIntToScalar(2), color_scheme);
if (!skrect.isEmpty()) { if (!skrect.isEmpty()) {
...@@ -598,6 +658,63 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon( ...@@ -598,6 +658,63 @@ SkRect NativeThemeBase::PaintCheckboxRadioCommon(
bool is_checkbox, bool is_checkbox,
const SkScalar border_radius, const SkScalar border_radius,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
SkRect skrect = gfx::RectToSkRect(rect);
// Use the largest square that fits inside the provided rectangle.
// No other browser seems to support non-square widget, so accidentally
// having non-square sizes is common (eg. amazon and webkit dev tools).
if (skrect.width() != skrect.height()) {
SkScalar size = SkMinScalar(skrect.width(), skrect.height());
skrect.inset((skrect.width() - size) / 2, (skrect.height() - size) / 2);
}
// If the rectangle is too small then paint only a rectangle. We don't want
// to have to worry about '- 1' and '+ 1' calculations below having overflow
// or underflow.
if (skrect.width() <= 2) {
cc::PaintFlags flags;
flags.setColor(GetControlColor(kBorder, color_scheme));
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRect(skrect, flags);
// Too small to draw anything more.
return SkRect::MakeEmpty();
}
cc::PaintFlags flags;
flags.setAntiAlias(true);
// Paint the background (is not visible behind the rounded corners).
// Note we need to shrink the rect for background a little bit so we don't
// see artifacts introduced by antialiasing between the border and the
// background near the rounded corners of checkbox.
const auto background_rect =
skrect.makeInset(kBorderWidth * 0.2f, kBorderWidth * 0.2f);
PaintLightenLayer(canvas, background_rect, state, border_radius,
color_scheme);
flags.setColor(ControlsBackgroundColorForState(state, color_scheme));
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRoundRect(background_rect, border_radius, border_radius, flags);
// Draw the border.
if (!(is_checkbox && button.checked)) {
// Shrink half border width so the final pixels of the border will be
// within the rectangle.
const auto border_rect =
skrect.makeInset(kBorderWidth / 2, kBorderWidth / 2);
SkColor border_color =
button.checked ? ControlsAccentColorForState(state, color_scheme)
: ControlsBorderColorForState(state, color_scheme);
flags.setColor(border_color);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
canvas->drawRoundRect(border_rect, border_radius, border_radius, flags);
}
// Return the rectangle for drawing any additional decorations.
return skrect;
}
SkRect skrect = gfx::RectToSkRect(rect); SkRect skrect = gfx::RectToSkRect(rect);
// Use the largest square that fits inside the provided rectangle. // Use the largest square that fits inside the provided rectangle.
...@@ -691,6 +808,29 @@ void NativeThemeBase::PaintRadio(cc::PaintCanvas* canvas, ...@@ -691,6 +808,29 @@ void NativeThemeBase::PaintRadio(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const ButtonExtraParams& button, const ButtonExtraParams& button,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
// Most of a radio button is the same as a checkbox, except the the rounded
// square is a circle (i.e. border radius >= 100%).
const SkScalar radius = SkFloatToScalar(
static_cast<float>(std::max(rect.width(), rect.height())) * 0.5);
SkRect skrect = PaintCheckboxRadioCommon(canvas, state, rect, button, false,
radius, color_scheme);
if (!skrect.isEmpty() && button.checked) {
// Draw the dot.
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(ControlsAccentColorForState(state, color_scheme));
skrect.inset(skrect.width() * 0.2, skrect.height() * 0.2);
// Use drawRoundedRect instead of drawOval to be completely consistent
// with the border in PaintCheckboxRadioNewCommon.
canvas->drawRoundRect(skrect, radius, radius, flags);
}
return;
}
// Most of a radio button is the same as a checkbox, except the the rounded // Most of a radio button is the same as a checkbox, except the the rounded
// square is a circle (i.e. border radius >= 100%). // square is a circle (i.e. border radius >= 100%).
const SkScalar radius = SkFloatToScalar( const SkScalar radius = SkFloatToScalar(
...@@ -717,6 +857,38 @@ void NativeThemeBase::PaintButton(cc::PaintCanvas* canvas, ...@@ -717,6 +857,38 @@ void NativeThemeBase::PaintButton(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const ButtonExtraParams& button, const ButtonExtraParams& button,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
cc::PaintFlags flags;
SkRect skrect = gfx::RectToSkRect(rect);
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
// If the button is too small, fallback to drawing a single, solid color.
if (rect.width() < 5 || rect.height() < 5) {
flags.setColor(ControlsFillColorForState(state, color_scheme));
canvas->drawRect(skrect, flags);
return;
}
// Paint the background (is not visible behind the rounded corners).
skrect.inset(kBorderWidth / 2, kBorderWidth / 2);
PaintLightenLayer(canvas, skrect, state, kInputBorderRadius, color_scheme);
flags.setColor(ControlsFillColorForState(state, color_scheme));
canvas->drawRoundRect(skrect, kInputBorderRadius, kInputBorderRadius,
flags);
// Paint the border: 1px solid.
if (button.has_border) {
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
flags.setColor(ControlsBorderColorForState(state, color_scheme));
canvas->drawRoundRect(skrect, kInputBorderRadius, kInputBorderRadius,
flags);
}
return;
}
cc::PaintFlags flags; cc::PaintFlags flags;
SkRect skrect = gfx::RectToSkRect(rect); SkRect skrect = gfx::RectToSkRect(rect);
SkColor base_color = button.background_color; SkColor base_color = button.background_color;
...@@ -771,6 +943,29 @@ void NativeThemeBase::PaintTextField(cc::PaintCanvas* canvas, ...@@ -771,6 +943,29 @@ void NativeThemeBase::PaintTextField(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const TextFieldExtraParams& text, const TextFieldExtraParams& text,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
SkRect bounds = gfx::RectToSkRect(rect);
const SkScalar borderRadius = SkIntToScalar(kInputBorderRadius);
// Paint the background (is not visible behind the rounded corners).
bounds.inset(kBorderWidth / 2, kBorderWidth / 2);
cc::PaintFlags fill_flags;
fill_flags.setStyle(cc::PaintFlags::kFill_Style);
if (text.background_color != 0) {
PaintLightenLayer(canvas, bounds, state, borderRadius, color_scheme);
fill_flags.setColor(ControlsBackgroundColorForState(state, color_scheme));
canvas->drawRoundRect(bounds, borderRadius, borderRadius, fill_flags);
}
// Paint the border: 1px solid.
cc::PaintFlags stroke_flags;
stroke_flags.setColor(ControlsBorderColorForState(state, color_scheme));
stroke_flags.setStyle(cc::PaintFlags::kStroke_Style);
stroke_flags.setStrokeWidth(kBorderWidth);
canvas->drawRoundRect(bounds, borderRadius, borderRadius, stroke_flags);
return;
}
SkRect bounds; SkRect bounds;
bounds.setLTRB(rect.x(), rect.y(), rect.right() - 1, rect.bottom() - 1); bounds.setLTRB(rect.x(), rect.y(), rect.right() - 1, rect.bottom() - 1);
...@@ -792,6 +987,51 @@ void NativeThemeBase::PaintMenuList(cc::PaintCanvas* canvas, ...@@ -792,6 +987,51 @@ void NativeThemeBase::PaintMenuList(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const MenuListExtraParams& menu_list, const MenuListExtraParams& menu_list,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
// If a border radius is specified paint the background and the border of
// the menulist, otherwise let the non-theming code paint the background
// and the border of the control. The arrow (menulist button) is always
// painted by the theming code.
if (!menu_list.has_border_radius) {
TextFieldExtraParams text_field = {0};
text_field.background_color = menu_list.background_color;
PaintTextField(canvas, state, rect, text_field, color_scheme);
}
// Paint the arrow.
cc::PaintFlags flags;
flags.setColor(menu_list.arrow_color);
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kMenuListArrowStrokeWidth);
float arrow_width = menu_list.arrow_size;
int arrow_height = arrow_width * 0.5;
gfx::Rect arrow(menu_list.arrow_x, menu_list.arrow_y - (arrow_height / 2),
arrow_width, arrow_height);
arrow.Intersect(rect);
if (arrow_width != arrow.width() || arrow_height != arrow.height()) {
// The arrow is clipped after being constrained to the paint rect so we
// need to recalculate its size.
int height_clip = arrow_height - arrow.height();
int width_clip = arrow_width - arrow.width();
if (height_clip > width_clip) {
arrow.set_width(arrow.height() * 1.6);
} else {
arrow.set_height(arrow.width() * 0.6);
}
arrow.set_y(menu_list.arrow_y - (arrow.height() / 2));
}
SkPath path;
path.moveTo(arrow.x(), arrow.y());
path.lineTo(arrow.x() + arrow.width() / 2, arrow.y() + arrow.height());
path.lineTo(arrow.x() + arrow.width(), arrow.y());
canvas->drawPath(path, flags);
return;
}
// If a border radius is specified, we let the WebCore paint the background // If a border radius is specified, we let the WebCore paint the background
// and the border of the control. // and the border of the control.
if (!menu_list.has_border_radius) { if (!menu_list.has_border_radius) {
...@@ -863,6 +1103,46 @@ void NativeThemeBase::PaintSliderTrack(cc::PaintCanvas* canvas, ...@@ -863,6 +1103,46 @@ void NativeThemeBase::PaintSliderTrack(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const SliderExtraParams& slider, const SliderExtraParams& slider,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
// Paint the entire slider track.
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setColor(ControlsFillColorForState(state, color_scheme));
const float track_height = kSliderTrackHeight * slider.zoom;
SkRect track_rect = AlignSliderTrack(rect, slider, false, track_height);
// Shrink the track by 1 pixel so the thumb can completely cover the track
// on both ends.
if (slider.vertical)
track_rect.inset(0, 1);
else
track_rect.inset(1, 0);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
// Clip the track to create rounded corners for the value bar.
SkRRect rounded_rect;
rounded_rect.setRectXY(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius);
canvas->clipRRect(rounded_rect, SkClipOp::kIntersect, true);
// Paint the value slider track.
flags.setColor(ControlsSliderColorForState(state, color_scheme));
SkRect value_rect = AlignSliderTrack(rect, slider, true, track_height);
canvas->drawRect(value_rect, flags);
// Paint the border.
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
SkColor border_color = ControlsBorderColorForState(state, color_scheme);
if (!UsesHighContrastColors() && state != kDisabled)
border_color = SkColorSetA(border_color, 0x80);
flags.setColor(border_color);
track_rect.inset(kBorderWidth / 2, kBorderWidth / 2);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
return;
}
const int kMidX = rect.x() + rect.width() / 2; const int kMidX = rect.x() + rect.width() / 2;
const int kMidY = rect.y() + rect.height() / 2; const int kMidY = rect.y() + rect.height() / 2;
...@@ -885,6 +1165,26 @@ void NativeThemeBase::PaintSliderThumb(cc::PaintCanvas* canvas, ...@@ -885,6 +1165,26 @@ void NativeThemeBase::PaintSliderThumb(cc::PaintCanvas* canvas,
const gfx::Rect& rect, const gfx::Rect& rect,
const SliderExtraParams& slider, const SliderExtraParams& slider,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
const SkScalar radius = SkFloatToScalar(
static_cast<float>(std::max(rect.width(), rect.height())) * 0.5);
SkRect thumb_rect = gfx::RectToSkRect(rect);
cc::PaintFlags flags;
flags.setAntiAlias(true);
SkScalar border_width = kSliderThumbBorderWidth;
if (state == kHovered || state == kPressed) {
border_width = kSliderThumbBorderHoveredWidth;
}
// Paint the background (is not visible behind the rounded corners).
thumb_rect.inset(border_width / 2, border_width / 2);
flags.setColor(ControlsSliderColorForState(state, color_scheme));
flags.setStyle(cc::PaintFlags::kFill_Style);
canvas->drawRoundRect(thumb_rect, radius, radius, flags);
return;
}
const bool hovered = (state == kHovered) || slider.in_drag; const bool hovered = (state == kHovered) || slider.in_drag;
const int kMidX = rect.x() + rect.width() / 2; const int kMidX = rect.x() + rect.width() / 2;
const int kMidY = rect.y() + rect.height() / 2; const int kMidY = rect.y() + rect.height() / 2;
...@@ -957,6 +1257,58 @@ void NativeThemeBase::PaintProgressBar( ...@@ -957,6 +1257,58 @@ void NativeThemeBase::PaintProgressBar(
const gfx::Rect& rect, const gfx::Rect& rect,
const ProgressBarExtraParams& progress_bar, const ProgressBarExtraParams& progress_bar,
ColorScheme color_scheme) const { ColorScheme color_scheme) const {
if (features::IsFormControlsRefreshEnabled()) {
DCHECK(!rect.IsEmpty());
// Paint the track.
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(GetControlColor(kFill, color_scheme));
SliderExtraParams slider;
slider.vertical = false;
float track_height = rect.height() * kTrackHeightRatio;
SkRect track_rect = AlignSliderTrack(rect, slider, false, track_height);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
// Clip the track to create rounded corners for the value bar.
SkRRect rounded_rect;
rounded_rect.setRectXY(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius);
canvas->clipRRect(rounded_rect, SkClipOp::kIntersect, true);
// Paint the progress value bar.
const SkScalar kMinimumProgressValueWidth = 2;
SkScalar adjusted_width = progress_bar.value_rect_width;
if (adjusted_width > 0 && adjusted_width < kMinimumProgressValueWidth)
adjusted_width = kMinimumProgressValueWidth;
gfx::Rect original_value_rect(progress_bar.value_rect_x,
progress_bar.value_rect_y, adjusted_width,
progress_bar.value_rect_height);
SkRect value_rect =
AlignSliderTrack(original_value_rect, slider, false, track_height);
flags.setColor(GetControlColor(kAccent, color_scheme));
if (progress_bar.determinate) {
canvas->drawRect(value_rect, flags);
} else {
canvas->drawRoundRect(value_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
}
// Paint the border.
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setStrokeWidth(kBorderWidth);
SkColor border_color = GetControlColor(kBorder, color_scheme);
if (!UsesHighContrastColors())
border_color = SkColorSetA(border_color, 0x80);
flags.setColor(border_color);
track_rect.inset(kBorderWidth / 2, kBorderWidth / 2);
canvas->drawRoundRect(track_rect, kSliderTrackBorderRadius,
kSliderTrackBorderRadius, flags);
return;
}
DCHECK(!rect.IsEmpty()); DCHECK(!rect.IsEmpty());
canvas->drawColor(GetColor(kProgressBackgroundColor, color_scheme)); canvas->drawColor(GetColor(kProgressBackgroundColor, color_scheme));
...@@ -1107,4 +1459,220 @@ SkColor NativeThemeBase::OutlineColor(SkScalar* hsv1, SkScalar* hsv2) const { ...@@ -1107,4 +1459,220 @@ SkColor NativeThemeBase::OutlineColor(SkScalar* hsv1, SkScalar* hsv2) const {
return SaturateAndBrighten(hsv2, -0.2f, diff); return SaturateAndBrighten(hsv2, -0.2f, diff);
} }
SkColor NativeThemeBase::ControlsAccentColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredAccent;
} else if (state == kPressed) {
color_id = kHoveredAccent;
} else if (state == kDisabled) {
color_id = kDisabledAccent;
} else {
color_id = kAccent;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeBase::ControlsSliderColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredSlider;
} else if (state == kPressed) {
color_id = kHoveredSlider;
} else if (state == kDisabled) {
color_id = kDisabledSlider;
} else {
color_id = kSlider;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeBase::ControlsBorderColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredBorder;
} else if (state == kDisabled) {
color_id = kDisabledBorder;
} else {
color_id = kBorder;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeBase::ControlsFillColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kHovered) {
color_id = kHoveredFill;
} else if (state == kPressed) {
color_id = kHoveredFill;
} else if (state == kDisabled) {
color_id = kDisabledFill;
} else {
color_id = kFill;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeBase::ControlsBackgroundColorForState(
State state,
ColorScheme color_scheme) const {
ControlColorId color_id;
if (state == kDisabled) {
color_id = kDisabledBackground;
} else {
color_id = kBackground;
}
return GetControlColor(color_id, color_scheme);
}
SkColor NativeThemeBase::GetControlColor(ControlColorId color_id,
ColorScheme color_scheme) const {
if (UsesHighContrastColors())
return GetHighContrastControlColor(color_id, color_scheme);
switch (color_id) {
case kBorder:
return SkColorSetRGB(0x76, 0x76, 0x76);
case kHoveredBorder:
return SkColorSetRGB(0x4F, 0x4F, 0x4F);
case kDisabledBorder:
return SkColorSetARGB(0x4D, 0x76, 0x76, 0x76);
case kAccent:
return SkColorSetRGB(0x00, 0x75, 0xFF);
case kHoveredAccent:
return SkColorSetRGB(0x00, 0x5C, 0xC8);
case kDisabledAccent:
return SkColorSetARGB(0x4D, 0x76, 0x76, 0x76);
case kBackground:
return SK_ColorWHITE;
case kDisabledBackground:
return SkColorSetA(SK_ColorWHITE, 0x99);
case kFill:
return SkColorSetRGB(0xEF, 0xEF, 0xEF);
case kHoveredFill:
return SkColorSetRGB(0xE5, 0xE5, 0xE5);
case kDisabledFill:
return SkColorSetARGB(0x4D, 0xEF, 0xEF, 0xEF);
case kLightenLayer:
return SkColorSetARGB(0x33, 0xA9, 0xA9, 0xA9);
case kProgressValue:
return SkColorSetRGB(0x00, 0x75, 0xFF);
case kSlider:
return SkColorSetRGB(0x00, 0x75, 0xFF);
case kHoveredSlider:
return SkColorSetRGB(0x00, 0x5C, 0xC8);
case kDisabledSlider:
return SkColorSetRGB(0xCB, 0xCB, 0xCB);
}
NOTREACHED();
return gfx::kPlaceholderColor;
}
SkColor NativeThemeBase::GetHighContrastControlColor(
ControlColorId color_id,
ColorScheme color_scheme) const {
if (!system_colors_.empty()) {
switch (color_id) {
case kDisabledBorder:
case kDisabledAccent:
case kDisabledSlider:
return system_colors_[SystemThemeColor::kGrayText];
case kBorder:
case kHoveredBorder:
return system_colors_[SystemThemeColor::kButtonText];
case kAccent:
case kHoveredAccent:
case kProgressValue:
case kSlider:
case kHoveredSlider:
return system_colors_[SystemThemeColor::kHighlight];
case kBackground:
case kDisabledBackground:
case kFill:
case kHoveredFill:
case kDisabledFill:
case kLightenLayer:
return system_colors_[SystemThemeColor::kWindow];
}
} else {
// Default high contrast colors (used in web test mode)
switch (color_id) {
case kDisabledBorder:
case kDisabledAccent:
case kDisabledSlider:
return SK_ColorGREEN;
case kBorder:
case kHoveredBorder:
return SK_ColorWHITE;
case kAccent:
case kHoveredAccent:
case kProgressValue:
case kSlider:
case kHoveredSlider:
return SK_ColorCYAN;
case kBackground:
case kDisabledBackground:
case kFill:
case kHoveredFill:
case kDisabledFill:
case kLightenLayer:
return SK_ColorBLACK;
}
}
NOTREACHED();
return gfx::kPlaceholderColor;
}
void NativeThemeBase::PaintLightenLayer(cc::PaintCanvas* canvas,
SkRect skrect,
State state,
SkScalar border_radius,
ColorScheme color_scheme) const {
if (state == kDisabled) {
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
// Draw the lighten layer to lighten the background so the translucent
// disabled color works regardless of what it's over.
flags.setColor(GetControlColor(kLightenLayer, color_scheme));
canvas->drawRoundRect(skrect, border_radius, border_radius, flags);
}
}
SkRect NativeThemeBase::AlignSliderTrack(
const gfx::Rect& slider_rect,
const NativeTheme::SliderExtraParams& slider,
bool is_value,
float track_height) const {
const float kAlignment = track_height / 2;
const float mid_x = slider_rect.x() + slider_rect.width() / 2.0f;
const float mid_y = slider_rect.y() + slider_rect.height() / 2.0f;
SkRect aligned_rect;
if (slider.vertical) {
const float top = is_value ? slider_rect.y() + slider.thumb_y + kAlignment
: slider_rect.y();
aligned_rect.setLTRB(
std::max(float(slider_rect.x()), mid_x - kAlignment), top,
std::min(float(slider_rect.right()), mid_x + kAlignment),
slider_rect.bottom());
} else {
const float right = is_value ? slider_rect.x() + slider.thumb_x + kAlignment
: slider_rect.right();
aligned_rect.setLTRB(
slider_rect.x(), std::max(float(slider_rect.y()), mid_y - kAlignment),
right, std::min(float(slider_rect.bottom()), mid_y + kAlignment));
}
return aligned_rect;
}
} // namespace ui } // namespace ui
...@@ -39,6 +39,26 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { ...@@ -39,6 +39,26 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
gfx::Rect GetNinePatchAperture(Part part) const override; gfx::Rect GetNinePatchAperture(Part part) const override;
protected: protected:
// Colors for form controls refresh.
enum ControlColorId {
kBorder,
kDisabledBorder,
kHoveredBorder,
kAccent,
kDisabledAccent,
kHoveredAccent,
kBackground,
kDisabledBackground,
kFill,
kDisabledFill,
kHoveredFill,
kLightenLayer,
kProgressValue,
kSlider,
kDisabledSlider,
kHoveredSlider
};
NativeThemeBase(); NativeThemeBase();
~NativeThemeBase() override; ~NativeThemeBase() override;
...@@ -72,35 +92,35 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { ...@@ -72,35 +92,35 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const gfx::Rect& rect, const gfx::Rect& rect,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintCheckbox(cc::PaintCanvas* canvas, void PaintCheckbox(cc::PaintCanvas* canvas,
State state, State state,
const gfx::Rect& rect, const gfx::Rect& rect,
const ButtonExtraParams& button, const ButtonExtraParams& button,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintRadio(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const;
virtual void PaintButton(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const;
virtual void PaintTextField(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const TextFieldExtraParams& text,
ColorScheme color_scheme) const;
virtual void PaintMenuList(cc::PaintCanvas* canvas, void PaintRadio(cc::PaintCanvas* canvas,
State state, State state,
const gfx::Rect& rect, const gfx::Rect& rect,
const MenuListExtraParams& menu_list, const ButtonExtraParams& button,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
void PaintButton(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const ButtonExtraParams& button,
ColorScheme color_scheme) const;
void PaintTextField(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const TextFieldExtraParams& text,
ColorScheme color_scheme) const;
void PaintMenuList(cc::PaintCanvas* canvas,
State state,
const gfx::Rect& rect,
const MenuListExtraParams& menu_list,
ColorScheme color_scheme) const;
virtual void PaintMenuPopupBackground( virtual void PaintMenuPopupBackground(
cc::PaintCanvas* canvas, cc::PaintCanvas* canvas,
...@@ -121,17 +141,17 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { ...@@ -121,17 +141,17 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const MenuSeparatorExtraParams& menu_separator, const MenuSeparatorExtraParams& menu_separator,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintSliderTrack(cc::PaintCanvas* canvas, void PaintSliderTrack(cc::PaintCanvas* canvas,
State state, State state,
const gfx::Rect& rect, const gfx::Rect& rect,
const SliderExtraParams& slider, const SliderExtraParams& slider,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintSliderThumb(cc::PaintCanvas* canvas, void PaintSliderThumb(cc::PaintCanvas* canvas,
State state, State state,
const gfx::Rect& rect, const gfx::Rect& rect,
const SliderExtraParams& slider, const SliderExtraParams& slider,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintInnerSpinButton( virtual void PaintInnerSpinButton(
cc::PaintCanvas* canvas, cc::PaintCanvas* canvas,
...@@ -140,11 +160,11 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { ...@@ -140,11 +160,11 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const InnerSpinButtonExtraParams& spin_button, const InnerSpinButtonExtraParams& spin_button,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintProgressBar(cc::PaintCanvas* canvas, void PaintProgressBar(cc::PaintCanvas* canvas,
State state, State state,
const gfx::Rect& rect, const gfx::Rect& rect,
const ProgressBarExtraParams& progress_bar, const ProgressBarExtraParams& progress_bar,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintFrameTopArea(cc::PaintCanvas* canvas, virtual void PaintFrameTopArea(cc::PaintCanvas* canvas,
State state, State state,
...@@ -152,6 +172,12 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { ...@@ -152,6 +172,12 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const FrameTopAreaExtraParams& frame_top_area, const FrameTopAreaExtraParams& frame_top_area,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
virtual void PaintLightenLayer(cc::PaintCanvas* canvas,
SkRect skrect,
State state,
SkScalar border_radius,
ColorScheme color_scheme) const;
// Shrinks checkbox/radio button rect, if necessary, to make room for padding // Shrinks checkbox/radio button rect, if necessary, to make room for padding
// and drop shadow. // and drop shadow.
// TODO(mohsen): This is needed because checkboxes/radio buttons on Android // TODO(mohsen): This is needed because checkboxes/radio buttons on Android
...@@ -210,6 +236,25 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme { ...@@ -210,6 +236,25 @@ class NATIVE_THEME_EXPORT NativeThemeBase : public NativeTheme {
const SkScalar border_radius, const SkScalar border_radius,
ColorScheme color_scheme) const; ColorScheme color_scheme) const;
SkColor ControlsAccentColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsBorderColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsFillColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsBackgroundColorForState(State state,
ColorScheme color_scheme) const;
SkColor ControlsSliderColorForState(State state,
ColorScheme color_scheme) const;
SkColor GetHighContrastControlColor(ControlColorId color_id,
ColorScheme color_scheme) const;
SkColor GetControlColor(ControlColorId color_id,
ColorScheme color_scheme) const;
SkRect AlignSliderTrack(const gfx::Rect& slider_rect,
const NativeTheme::SliderExtraParams& slider,
bool is_value,
float track_height) const;
// The length of the arrow buttons, 0 means no buttons are drawn. // The length of the arrow buttons, 0 means no buttons are drawn.
int scrollbar_button_length_; int scrollbar_button_length_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment