Improve API for contrast blending functions.

This reduces the number of functions and makes the naming and functionality more
coherent.

Bug: 870384
Change-Id: I67586068ddd32463ad72f0f923540ec6d7bdf737
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1610486
Commit-Queue: Fernando Serboncini <fserb@chromium.org>
Reviewed-by: Fernando Serboncini <fserb@chromium.org>
Reviewed-by: Xiyuan Xia <xiyuan@chromium.org>
Reviewed-by: Michael Wasserman <msw@chromium.org>
Auto-Submit: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#661702}
diff --git a/ash/media/media_notification_background.cc b/ash/media/media_notification_background.cc
index 1a8a2a3..b4e99a15 100644
--- a/ash/media/media_notification_background.cc
+++ b/ash/media/media_notification_background.cc
@@ -343,10 +343,10 @@
 }
 
 SkColor MediaNotificationBackground::GetForegroundColor() const {
-  return color_utils::GetColorWithMinimumContrast(
-      foreground_color_.value_or(views::style::GetColor(
-          *owner_, views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY)),
-      GetBackgroundColor());
+  const SkColor foreground = foreground_color_.value_or(views::style::GetColor(
+      *owner_, views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY));
+  return color_utils::BlendForMinContrast(foreground, GetBackgroundColor())
+      .color;
 }
 
 int MediaNotificationBackground::GetArtworkWidth(
diff --git a/ash/public/cpp/default_frame_header.cc b/ash/public/cpp/default_frame_header.cc
index 606c9c9..3a4762a 100644
--- a/ash/public/cpp/default_frame_header.cc
+++ b/ash/public/cpp/default_frame_header.cc
@@ -172,7 +172,7 @@
   const SkColor desired_color = color_utils::IsDark(frame_color)
                                     ? SK_ColorWHITE
                                     : SkColorSetRGB(40, 40, 40);
-  return color_utils::GetColorWithMinimumContrast(desired_color, frame_color);
+  return color_utils::BlendForMinContrast(desired_color, frame_color).color;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/search/ntp_icon_source.cc b/chrome/browser/search/ntp_icon_source.cc
index 2367e2b..fbde10ae 100644
--- a/chrome/browser/search/ntp_icon_source.cc
+++ b/chrome/browser/search/ntp_icon_source.cc
@@ -229,8 +229,10 @@
 
   // If necessary, draw the colored fallback monogram.
   if (favicon.empty()) {
-    SkColor fallback_color = color_utils::GetColorWithMinimumContrast(
-        GetBackgroundColorForUrl(icon_url), kFallbackIconLetterColor);
+    SkColor fallback_color =
+        color_utils::BlendForMinContrast(GetBackgroundColorForUrl(icon_url),
+                                         kFallbackIconLetterColor)
+            .color;
 
     int offset = (icon_size - fallback_size) / 2;
     DrawCircleInCanvas(&canvas, fallback_size, offset, fallback_color);
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 9a72375..dbd7574 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -812,10 +812,10 @@
     frame_text_color = color_utils::GetColorWithMaxContrast(frame_color);
     SkColor blend_target =
         color_utils::GetColorWithMaxContrast(frame_text_color);
-    SkAlpha alpha = color_utils::GetBlendValueWithMinimumContrast(
-        frame_color, blend_target, frame_text_color,
-        kPreferredReadableContrastRatio);
-    frame_color = color_utils::AlphaBlend(blend_target, frame_color, alpha);
+    frame_color = color_utils::BlendForMinContrast(
+                      frame_color, frame_text_color, blend_target,
+                      kPreferredReadableContrastRatio)
+                      .color;
 
     // Generate active tab color so that it has enough contrast with the
     // |frame_color| to avoid the isolation line in the tab strip.
@@ -1828,9 +1828,9 @@
     }
   }
 
-  const SkColor result_color =
-      color_utils::GetColorWithMinimumContrast(blend_source_color, bg_color);
-  SetColor(text_color_id, result_color);
+  SetColor(
+      text_color_id,
+      color_utils::BlendForMinContrast(blend_source_color, bg_color).color);
 }
 
 void BrowserThemePack::GenerateMissingNtpColors() {
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 6dde625..660d6a3 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -770,12 +770,13 @@
     separator_color = color_utils::GetColorWithMaxContrast(separator_color);
   }
 
-  SkAlpha alpha = color_utils::FindBlendValueForContrastRatio(
-      frame_color, separator_color, frame_color, kContrastRatio, 0);
-  if (color_utils::GetContrastRatio(
-          color_utils::AlphaBlend(separator_color, frame_color, alpha),
-          frame_color) >= kContrastRatio) {
-    return SkColorSetA(separator_color, alpha);
+  {
+    const auto result = color_utils::BlendForMinContrast(
+        frame_color, frame_color, separator_color, kContrastRatio);
+    if (color_utils::GetContrastRatio(result.color, frame_color) >=
+        kContrastRatio) {
+      return SkColorSetA(separator_color, result.alpha);
+    }
   }
 
   separator_color = color_utils::GetColorWithMaxContrast(separator_color);
@@ -786,9 +787,9 @@
   // dark or very light, just not quite as much so as the frame color.  Blend
   // towards the opposite separator color, and compute the contrast against the
   // tab instead of the frame to ensure both contrasts hit the desired minimum.
-  alpha = color_utils::FindBlendValueForContrastRatio(
-      frame_color, separator_color, tab_color, kContrastRatio, 0);
-  return SkColorSetA(separator_color, alpha);
+  const auto result = color_utils::BlendForMinContrast(
+      frame_color, tab_color, separator_color, kContrastRatio);
+  return SkColorSetA(separator_color, result.alpha);
 }
 
 void ThemeService::DoSetTheme(const Extension* extension,
diff --git a/chrome/browser/ui/libgtkui/gtk_ui.cc b/chrome/browser/ui/libgtkui/gtk_ui.cc
index 9d5254b0..26e9fd2 100644
--- a/chrome/browser/ui/libgtkui/gtk_ui.cc
+++ b/chrome/browser/ui/libgtkui/gtk_ui.cc
@@ -920,17 +920,19 @@
     color_map[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT] =
         background_tab_text_color;
     color_map[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT_INCOGNITO] =
-        color_utils::GetColorWithMinimumContrast(
+        color_utils::BlendForMinContrast(
             color_utils::HSLShift(background_tab_text_color,
                                   kDefaultTintFrameIncognito),
-            frame_color_incognito);
+            frame_color_incognito)
+            .color;
     color_map[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT_INACTIVE] =
         background_tab_text_color_inactive;
     color_map[ThemeProperties::COLOR_BACKGROUND_TAB_TEXT_INCOGNITO_INACTIVE] =
-        color_utils::GetColorWithMinimumContrast(
+        color_utils::BlendForMinContrast(
             color_utils::HSLShift(background_tab_text_color_inactive,
                                   kDefaultTintFrameIncognito),
-            frame_color_incognito_inactive);
+            frame_color_incognito_inactive)
+            .color;
 
     // These colors represent the border drawn around tabs and between
     // the tabstrip and toolbar.
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index ce99958b..93fd77e 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -2028,7 +2028,8 @@
 
 SkColor BookmarkBarView::GetBookmarkBarTextColor() {
   const ui::ThemeProvider* theme_provider = GetThemeProvider();
-  return color_utils::GetColorWithMinimumContrast(
-      theme_provider->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT),
-      theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR));
+  return color_utils::BlendForMinContrast(
+             theme_provider->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT),
+             theme_provider->GetColor(ThemeProperties::COLOR_TOOLBAR))
+      .color;
 }
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 644c4d04..18e9caa 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1717,8 +1717,8 @@
         color_utils::AlphaBlend(default_color, background_color, 0.75f);
   }
 
-  return color_utils::GetColorWithMinimumContrast(default_color,
-                                                  background_color);
+  return color_utils::BlendForMinContrast(default_color, background_color)
+      .color;
 }
 
 // Returns the accessible tab name for the tab.
@@ -2386,14 +2386,14 @@
     return;
 
   const SkColor inactive_bg = GetTabBackgroundColor(TAB_INACTIVE);
-  const auto get_alpha = [inactive_bg](SkColor target, float contrast) {
-    return color_utils::GetBlendValueWithMinimumContrast(inactive_bg, target,
-                                                         inactive_bg, contrast);
+  const auto get_blend = [inactive_bg](SkColor target, float contrast) {
+    return color_utils::BlendForMinContrast(inactive_bg, inactive_bg, target,
+                                            contrast);
   };
 
   const SkColor active_bg = GetTabBackgroundColor(TAB_ACTIVE);
-  const auto get_hover_opacity = [active_bg, &get_alpha](float contrast) {
-    return get_alpha(active_bg, contrast) / 255.0f;
+  const auto get_hover_opacity = [active_bg, &get_blend](float contrast) {
+    return get_blend(active_bg, contrast).alpha / 255.0f;
   };
 
   // The contrast ratio for the hover effect on standard-width tabs.
@@ -2414,9 +2414,7 @@
   const SkColor inactive_fg = GetTabForegroundColor(TAB_INACTIVE, inactive_bg);
   // The contrast ratio for the separator between inactive tabs.
   constexpr float kTabSeparatorContrast = 2.5f;
-  const SkAlpha separator_alpha = get_alpha(inactive_fg, kTabSeparatorContrast);
-  separator_color_ =
-      color_utils::AlphaBlend(inactive_fg, inactive_bg, separator_alpha);
+  separator_color_ = get_blend(inactive_fg, kTabSeparatorContrast).color;
 }
 
 void TabStrip::ResizeLayoutTabs() {
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc
index ef3ebc4..95bb3d37 100644
--- a/chrome/browser/ui/views/tabs/tab_style_views.cc
+++ b/chrome/browser/ui/views/tabs/tab_style_views.cc
@@ -400,20 +400,19 @@
 
   SkColor title_color = tab_->controller()->GetTabForegroundColor(
       expected_opacity > 0.5f ? TAB_ACTIVE : TAB_INACTIVE, bg_color);
-  title_color = color_utils::GetColorWithMinimumContrast(title_color, bg_color);
+  title_color = color_utils::BlendForMinContrast(title_color, bg_color).color;
 
   const SkColor base_hovered_color = theme_provider->GetColor(
       ThemeProperties::COLOR_TAB_CLOSE_BUTTON_BACKGROUND_HOVER);
   const SkColor base_pressed_color = theme_provider->GetColor(
       ThemeProperties::COLOR_TAB_CLOSE_BUTTON_BACKGROUND_PRESSED);
 
-  const auto get_color_for_contrast_ratio = [](SkColor fg_color,
-                                               SkColor bg_color,
-                                               float contrast_ratio) {
-    const SkAlpha blend_alpha = color_utils::GetBlendValueWithMinimumContrast(
-        bg_color, fg_color, bg_color, contrast_ratio);
-    return color_utils::AlphaBlend(fg_color, bg_color, blend_alpha);
-  };
+  const auto get_color_for_contrast_ratio =
+      [](SkColor fg_color, SkColor bg_color, float contrast_ratio) {
+        return color_utils::BlendForMinContrast(bg_color, bg_color, fg_color,
+                                                contrast_ratio)
+            .color;
+      };
 
   const SkColor generated_icon_color = get_color_for_contrast_ratio(
       title_color, bg_color,
@@ -425,11 +424,11 @@
       base_pressed_color, bg_color, kMinimumPressedContrastRatio);
 
   const SkColor generated_hovered_icon_color =
-      color_utils::GetColorWithMinimumContrast(title_color,
-                                               generated_hovered_color);
+      color_utils::BlendForMinContrast(title_color, generated_hovered_color)
+          .color;
   const SkColor generated_pressed_icon_color =
-      color_utils::GetColorWithMinimumContrast(title_color,
-                                               generated_pressed_color);
+      color_utils::BlendForMinContrast(title_color, generated_pressed_color)
+          .color;
 
   return {bg_color,
           title_color,
@@ -665,9 +664,9 @@
       // Tint with group color. With a dark scheme, the tint needs a higher
       // contrast to stand out effectively.
       const float target_contrast = color_utils::IsDark(color) ? 1.8f : 1.2f;
-      const SkAlpha blend_alpha = color_utils::GetBlendValueWithMinimumContrast(
-          color, group_color.value(), color, target_contrast);
-      color = color_utils::AlphaBlend(group_color.value(), color, blend_alpha);
+      color = color_utils::BlendForMinContrast(
+                  color, color, group_color.value(), target_contrast)
+                  .color;
     }
   }
 
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index f7df132..815f670 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -313,11 +313,10 @@
 
   // Add a fudge factor to the minimum contrast ratio since we'll actually be
   // blending with the adjusted color.
-  const SkAlpha blend_alpha = color_utils::GetBlendValueWithMinimumContrast(
-      contrasting_color, limit, base_color,
-      color_utils::kMinimumReadableContrastRatio * 1.05);
-
-  return color_utils::AlphaBlend(limit, contrasting_color, blend_alpha);
+  return color_utils::BlendForMinContrast(
+             contrasting_color, base_color, limit,
+             color_utils::kMinimumReadableContrastRatio * 1.05)
+      .color;
 }
 
 bool ToolbarButton::ShouldShowMenu() {
diff --git a/ui/gfx/color_utils.cc b/ui/gfx/color_utils.cc
index 92ba1407..c058749 100644
--- a/ui/gfx/color_utils.cc
+++ b/ui/gfx/color_utils.cc
@@ -324,61 +324,40 @@
       foreground1 : foreground2;
 }
 
-SkColor GetColorWithMinimumContrast(SkColor default_foreground,
-                                    SkColor background) {
-  const SkColor contrasting_color = GetColorWithMaxContrast(background);
-  const SkAlpha alpha = GetBlendValueWithMinimumContrast(
-      default_foreground, contrasting_color, background,
-      kMinimumReadableContrastRatio);
-  return AlphaBlend(contrasting_color, default_foreground, alpha);
-}
+BlendResult BlendForMinContrast(
+    SkColor default_foreground,
+    SkColor background,
+    base::Optional<SkColor> high_contrast_foreground,
+    float contrast_ratio) {
+  DCHECK_EQ(SkColorGetA(background), SK_AlphaOPAQUE);
+  default_foreground = GetResultingPaintColor(default_foreground, background);
+  if (GetContrastRatio(default_foreground, background) >= contrast_ratio)
+    return {SK_AlphaTRANSPARENT, default_foreground};
+  const SkColor target_foreground = GetResultingPaintColor(
+      high_contrast_foreground.value_or(GetColorWithMaxContrast(background)),
+      background);
 
-SkAlpha GetBlendValueWithMinimumContrast(SkColor source,
-                                         SkColor target,
-                                         SkColor base,
-                                         float contrast_ratio) {
-  DCHECK_EQ(SkColorGetA(base), SK_AlphaOPAQUE);
+  const float background_luminance = GetRelativeLuminance(background);
 
-  source = GetResultingPaintColor(source, base);
-  if (GetContrastRatio(source, base) >= contrast_ratio)
-    return 0;
-  target = GetResultingPaintColor(target, base);
-
-  constexpr int kCloseEnoughAlphaDelta = 0x04;
-  return FindBlendValueForContrastRatio(source, target, base, contrast_ratio,
-                                        kCloseEnoughAlphaDelta);
-}
-
-SkAlpha FindBlendValueForContrastRatio(SkColor source,
-                                       SkColor target,
-                                       SkColor base,
-                                       float contrast_ratio,
-                                       int alpha_error_tolerance) {
-  DCHECK_EQ(SkColorGetA(source), SK_AlphaOPAQUE);
-  DCHECK_EQ(SkColorGetA(target), SK_AlphaOPAQUE);
-  DCHECK_EQ(SkColorGetA(base), SK_AlphaOPAQUE);
-  DCHECK_GE(alpha_error_tolerance, 0);
-
-  const float base_luminance = GetRelativeLuminance(base);
-
+  SkAlpha best_alpha = SK_AlphaOPAQUE;
+  SkColor best_color = target_foreground;
   // Use int for inclusive lower bound and exclusive upper bound, reserving
   // conversion to SkAlpha for the end (reduces casts).
-  int low = SK_AlphaTRANSPARENT;
-  int high = SK_AlphaOPAQUE + 1;
-  SkAlpha best = SK_AlphaOPAQUE;
-  while (low + alpha_error_tolerance < high) {
+  for (int low = SK_AlphaTRANSPARENT, high = SK_AlphaOPAQUE + 1; low < high;) {
     const SkAlpha alpha = (low + high) / 2;
-    const SkColor blended = AlphaBlend(target, source, alpha);
-    const float luminance = GetRelativeLuminance(blended);
-    const float contrast = GetContrastRatio(luminance, base_luminance);
+    const SkColor color =
+        AlphaBlend(target_foreground, default_foreground, alpha);
+    const float luminance = GetRelativeLuminance(color);
+    const float contrast = GetContrastRatio(luminance, background_luminance);
     if (contrast >= contrast_ratio) {
-      best = alpha;
+      best_alpha = alpha;
+      best_color = color;
       high = alpha;
     } else {
       low = alpha + 1;
     }
   }
-  return best;
+  return {best_alpha, best_color};
 }
 
 SkColor InvertColor(SkColor color) {
diff --git a/ui/gfx/color_utils.h b/ui/gfx/color_utils.h
index c443749..a0853455 100644
--- a/ui/gfx/color_utils.h
+++ b/ui/gfx/color_utils.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <tuple>
 
+#include "base/optional.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/gfx_export.h"
 
@@ -22,6 +23,13 @@
   double l;
 };
 
+// The blend alpha and resulting color when blending to achieve a desired
+// contrast raio.
+struct BlendResult {
+  SkAlpha alpha;
+  SkColor color;
+};
+
 // The minimum contrast between text and background that is still readable.
 // This value is taken from w3c accessibility guidelines.
 constexpr float kMinimumReadableContrastRatio = 4.5f;
@@ -129,37 +137,18 @@
                                         SkColor foreground2,
                                         SkColor background);
 
-// This function attempts to select a color based on |default_foreground| that
-// will meet the minimum contrast ratio when used as a text color on top of
-// |background|. If |default_foreground| already meets the minimum contrast
-// ratio, this function will simply return it. Otherwise it will blend the color
-// darker/lighter until either the contrast ratio is acceptable or the color
-// cannot become any more extreme. Only use with opaque background.
-GFX_EXPORT SkColor GetColorWithMinimumContrast(SkColor default_foreground,
-                                               SkColor background);
-
-// Attempts to select an alpha value such that blending |target| onto |source|
-// with that alpha produces a color of at least |contrast_ratio| against |base|.
-// If |source| already meets the minimum contrast ratio, this function will
-// simply return 0. Otherwise it will blend the |target| onto |source| until
-// either the contrast ratio is acceptable or the color cannot become any more
-// extreme. |base| must be opaque.
-GFX_EXPORT SkAlpha GetBlendValueWithMinimumContrast(SkColor source,
-                                                    SkColor target,
-                                                    SkColor base,
-                                                    float contrast_ratio);
-
-// Returns the minimum alpha value such that blending |target| onto |source|
-// produces a color that contrasts against |base| with at least |contrast_ratio|
-// unless this is impossible, in which case SK_AlphaOPAQUE is returned.
-// Use only with opaque colors. |alpha_error_tolerance| should normally be 0 for
-// best accuracy, but if performance is critical then it can be a positive value
-// (4 is recommended) to save a few cycles and give "close enough" alpha.
-GFX_EXPORT SkAlpha FindBlendValueForContrastRatio(SkColor source,
-                                                  SkColor target,
-                                                  SkColor base,
-                                                  float contrast_ratio,
-                                                  int alpha_error_tolerance);
+// Alpha-blends |default_foreground| toward either |high_contrast_foreground|
+// (if specified) or the color with max contrast with |background| until either
+// the result has a contrast ratio against |background| of at least
+// |contrast_ratio| or the blend can go no further.  Returns the blended color
+// and the alpha used to achieve that blend.  If |default_foreground| already
+// has sufficient contrast, returns an alpha of 0 and color of
+// |default_foreground|.
+GFX_EXPORT BlendResult BlendForMinContrast(
+    SkColor default_foreground,
+    SkColor background,
+    base::Optional<SkColor> high_contrast_foreground = base::nullopt,
+    float contrast_ratio = kMinimumReadableContrastRatio);
 
 // Invert a color.
 GFX_EXPORT SkColor InvertColor(SkColor color);
diff --git a/ui/gfx/color_utils_unittest.cc b/ui/gfx/color_utils_unittest.cc
index 9fcedd3..68c14dd 100644
--- a/ui/gfx/color_utils_unittest.cc
+++ b/ui/gfx/color_utils_unittest.cc
@@ -239,46 +239,49 @@
   EXPECT_EQ(old_darkest_color, GetColorWithMaxContrast(SK_ColorWHITE));
 }
 
-TEST(ColorUtils, GetColorWithMinimumContrast_ForegroundAlreadyMeetsMinimum) {
-  EXPECT_EQ(SK_ColorBLACK,
-            GetColorWithMinimumContrast(SK_ColorBLACK, SK_ColorWHITE));
+TEST(ColorUtils, BlendForMinContrast_ForegroundAlreadyMeetsMinimum) {
+  const auto result = BlendForMinContrast(SK_ColorBLACK, SK_ColorWHITE);
+  EXPECT_EQ(SK_AlphaTRANSPARENT, result.alpha);
+  EXPECT_EQ(SK_ColorBLACK, result.color);
 }
 
-TEST(ColorUtils, GetColorWithMinimumContrast_BlendDarker) {
+TEST(ColorUtils, BlendForMinContrast_BlendDarker) {
   const SkColor foreground = SkColorSetRGB(0xAA, 0xAA, 0xAA);
-  const SkColor result = GetColorWithMinimumContrast(foreground, SK_ColorWHITE);
-  EXPECT_NE(foreground, result);
-  EXPECT_GE(GetContrastRatio(result, SK_ColorWHITE),
+  const auto result = BlendForMinContrast(foreground, SK_ColorWHITE);
+  EXPECT_NE(SK_AlphaTRANSPARENT, result.alpha);
+  EXPECT_NE(foreground, result.color);
+  EXPECT_GE(GetContrastRatio(result.color, SK_ColorWHITE),
             kMinimumReadableContrastRatio);
 }
 
-TEST(ColorUtils, GetColorWithMinimumContrast_BlendLighter) {
+TEST(ColorUtils, BlendForMinContrast_BlendLighter) {
   const SkColor foreground = SkColorSetRGB(0x33, 0x33, 0x33);
-  const SkColor result = GetColorWithMinimumContrast(foreground, SK_ColorBLACK);
-  EXPECT_NE(foreground, result);
-  EXPECT_GE(GetContrastRatio(result, SK_ColorBLACK),
+  const auto result = BlendForMinContrast(foreground, SK_ColorBLACK);
+  EXPECT_NE(SK_AlphaTRANSPARENT, result.alpha);
+  EXPECT_NE(foreground, result.color);
+  EXPECT_GE(GetContrastRatio(result.color, SK_ColorBLACK),
             kMinimumReadableContrastRatio);
 }
 
-TEST(ColorUtils, GetColorWithMinimumContrast_StopsAtDarkestColor) {
+TEST(ColorUtils, BlendForMinContrast_StopsAtDarkestColor) {
   const SkColor darkest_color = SkColorSetRGB(0x44, 0x44, 0x44);
   const SkColor old_darkest_color = SetDarkestColorForTesting(darkest_color);
-  EXPECT_EQ(darkest_color,
-            GetColorWithMinimumContrast(SkColorSetRGB(0x55, 0x55, 0x55),
-                                        SkColorSetRGB(0xAA, 0xAA, 0xAA)));
+  EXPECT_EQ(darkest_color, BlendForMinContrast(SkColorSetRGB(0x55, 0x55, 0x55),
+                                               SkColorSetRGB(0xAA, 0xAA, 0xAA))
+                               .color);
 
   SetDarkestColorForTesting(old_darkest_color);
 }
 
-TEST(ColorUtils, GetBlendValueWithMinimumContrast_ComputesExpectedOpacities) {
+TEST(ColorUtils, BlendForMinContrast_ComputesExpectedOpacities) {
   const SkColor source = SkColorSetRGB(0xDE, 0xE1, 0xE6);
   const SkColor target = SkColorSetRGB(0xFF, 0xFF, 0xFF);
   const SkColor base = source;
-  SkAlpha alpha = GetBlendValueWithMinimumContrast(source, target, base, 1.11f);
+  SkAlpha alpha = BlendForMinContrast(source, base, target, 1.11f).alpha;
   EXPECT_NEAR(alpha / 255.0f, 0.4f, 0.03f);
-  alpha = GetBlendValueWithMinimumContrast(source, target, base, 1.19f);
+  alpha = BlendForMinContrast(source, base, target, 1.19f).alpha;
   EXPECT_NEAR(alpha / 255.0f, 0.65f, 0.03f);
-  alpha = GetBlendValueWithMinimumContrast(source, target, base, 1.13728f);
+  alpha = BlendForMinContrast(source, base, target, 1.13728f).alpha;
   EXPECT_NEAR(alpha / 255.0f, 0.45f, 0.03f);
 }
 
@@ -304,25 +307,26 @@
   }
 }
 
-TEST(ColorUtils, FindBlendValueForContrastRatio_MatchesNaiveImplementation) {
-  const SkColor source = SkColorSetRGB(0xDE, 0xE1, 0xE6);
-  const SkColor target = SkColorSetRGB(0xFF, 0xFF, 0xFF);
-  const SkColor base = source;
-  const float contrast_ratio = 1.11f;
-  const SkAlpha alpha =
-      FindBlendValueForContrastRatio(source, target, base, contrast_ratio, 0);
+TEST(ColorUtils, BlendForMinContrast_MatchesNaiveImplementation) {
+  constexpr SkColor default_foreground = SkColorSetRGB(0xDE, 0xE1, 0xE6);
+  constexpr SkColor high_contrast_foreground = SK_ColorWHITE;
+  constexpr SkColor background = default_foreground;
+  constexpr float kContrastRatio = 1.11f;
+  const auto result = BlendForMinContrast(
+      default_foreground, background, high_contrast_foreground, kContrastRatio);
 
   // Naive implementation is direct translation of function description.
-  SkAlpha check = SK_AlphaTRANSPARENT;
-  for (SkAlpha alpha = SK_AlphaTRANSPARENT; alpha <= SK_AlphaOPAQUE; ++alpha) {
-    const SkColor blended = AlphaBlend(target, source, alpha);
-    const float contrast = GetContrastRatio(blended, base);
-    check = alpha;
-    if (contrast >= contrast_ratio)
+  SkAlpha alpha = SK_AlphaTRANSPARENT;
+  SkColor color = default_foreground;
+  for (int i = SK_AlphaTRANSPARENT; i <= SK_AlphaOPAQUE; ++i) {
+    alpha = SkAlpha{i};
+    color = AlphaBlend(high_contrast_foreground, default_foreground, alpha);
+    if (GetContrastRatio(color, background) >= kContrastRatio)
       break;
   }
 
-  EXPECT_EQ(check, alpha);
+  EXPECT_EQ(alpha, result.alpha);
+  EXPECT_EQ(color, result.color);
 }
 
 }  // namespace color_utils
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index de56de6..8b42eab 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -873,7 +873,7 @@
 SkColor Label::GetForegroundColor(SkColor foreground,
                                   SkColor background) const {
   return (auto_color_readability_ && IsOpaque(background))
-             ? color_utils::GetColorWithMinimumContrast(foreground, background)
+             ? color_utils::BlendForMinContrast(foreground, background).color
              : foreground;
 }
 
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h
index f07f285..f21722f 100644
--- a/ui/views/controls/label.h
+++ b/ui/views/controls/label.h
@@ -86,9 +86,9 @@
 
   // Enables or disables auto-color-readability (enabled by default).  If this
   // is enabled, then calls to set any foreground or background color will
-  // trigger an automatic mapper that uses
-  // color_utils::GetColorWithMinimumContrast() to ensure that the foreground
-  // colors are readable over the background color.
+  // trigger an automatic mapper that uses color_utils::BlendForMinContrast()
+  // to ensure that the foreground colors are readable over the background
+  // color.
   void SetAutoColorReadabilityEnabled(bool enabled);
 
   // Sets the color.  This will automatically force the color to be readable
diff --git a/ui/views/window/frame_caption_button.cc b/ui/views/window/frame_caption_button.cc
index 25fcf50..2d0e9acb 100644
--- a/ui/views/window/frame_caption_button.cc
+++ b/ui/views/window/frame_caption_button.cc
@@ -75,16 +75,17 @@
   // colors) can change between light/dark targets at the same time.  It looks
   // bad when the title and caption buttons disagree about whether to be light
   // or dark.
-  const SkColor source = color_utils::IsDark(background_color)
-                             ? gfx::kGoogleGrey200
-                             : gfx::kGoogleGrey700;
-  const SkColor target = color_utils::GetColorWithMaxContrast(background_color);
+  const SkColor default_foreground = color_utils::IsDark(background_color)
+                                         ? gfx::kGoogleGrey200
+                                         : gfx::kGoogleGrey700;
+  const SkColor high_contrast_foreground =
+      color_utils::GetColorWithMaxContrast(background_color);
   // Guarantee the caption buttons reach at least contrast ratio 3; this ratio
   // matches that used for focus indicators, large text, and other "have to see
   // it but perhaps don't have to read fine detail" cases.
-  const SkAlpha alpha = color_utils::GetBlendValueWithMinimumContrast(
-      source, target, background_color, 3.0f);
-  return color_utils::AlphaBlend(target, source, alpha);
+  return color_utils::BlendForMinContrast(default_foreground, background_color,
+                                          high_contrast_foreground, 3.0f)
+      .color;
 }
 
 // static