Browse Source

fix: missing badge text on Windows (#41628)

https://chromium-review.googlesource.com/c/chromium/src/+/5053607

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <[email protected]>
trop[bot] 1 year ago
parent
commit
98283d1dae

+ 2 - 1
shell/browser/browser_win.cc

@@ -40,6 +40,7 @@
 #include "shell/common/gin_helper/dictionary.h"
 #include "shell/common/skia_util.h"
 #include "shell/common/thread_restrictions.h"
+#include "skia/ext/font_utils.h"
 #include "skia/ext/legacy_display_globals.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkFont.h"
@@ -591,7 +592,7 @@ void Browser::UpdateBadgeContents(
     paint.reset();
     paint.setColor(kForegroundColor);
 
-    SkFont font;
+    SkFont font = skia::DefaultFont();
 
     SkRect bounds;
     int text_size = kMaxTextSize;

+ 48 - 2
shell/browser/ui/win/taskbar_host.cc

@@ -11,7 +11,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/win/scoped_gdi_object.h"
 #include "shell/browser/native_window.h"
+#include "skia/ext/image_operations.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkRRect.h"
 #include "ui/display/win/screen_win.h"
 #include "ui/gfx/icon_util.h"
 
@@ -166,13 +169,56 @@ bool TaskbarHost::SetProgressBar(HWND window,
   return success;
 }
 
+// Adapted from SetOverlayIcon in
+// chrome/browser/taskbar/taskbar_decorator_win.cc.
 bool TaskbarHost::SetOverlayIcon(HWND window,
-                                 const SkBitmap& overlay,
+                                 const SkBitmap& bitmap,
                                  const std::string& text) {
   if (!InitializeTaskbar())
     return false;
 
-  base::win::ScopedHICON icon(IconUtil::CreateHICONFromSkBitmap(overlay));
+  base::win::ScopedGDIObject<HICON> icon;
+  if (!bitmap.isNull()) {
+    DCHECK_GE(bitmap.width(), bitmap.height());
+
+    constexpr int kOverlayIconSize = 16;
+
+    // Maintain aspect ratio on resize, but prefer more square.
+    // (We used to round down here, but rounding up produces nicer results.)
+    const int resized_height =
+        base::ClampCeil(kOverlayIconSize *
+                        (static_cast<float>(bitmap.height()) / bitmap.width()));
+
+    DCHECK_GE(kOverlayIconSize, resized_height);
+    // Since the target size is so small, we use our best resizer.
+    SkBitmap sk_icon = skia::ImageOperations::Resize(
+        bitmap, skia::ImageOperations::RESIZE_LANCZOS3, kOverlayIconSize,
+        resized_height);
+
+    // Paint the resized icon onto a 16x16 canvas otherwise Windows will badly
+    // hammer it to 16x16. We'll use a circular clip to be consistent with the
+    // way profile icons are rendered in the profile switcher.
+    SkBitmap offscreen_bitmap;
+    offscreen_bitmap.allocN32Pixels(kOverlayIconSize, kOverlayIconSize);
+    SkCanvas offscreen_canvas(offscreen_bitmap, SkSurfaceProps{});
+    offscreen_canvas.clear(SK_ColorTRANSPARENT);
+
+    static const SkRRect overlay_icon_clip =
+        SkRRect::MakeOval(SkRect::MakeWH(kOverlayIconSize, kOverlayIconSize));
+    offscreen_canvas.clipRRect(overlay_icon_clip, true);
+
+    // Note: the original code used kOverlayIconSize - resized_height, but in
+    // order to center the icon in the circle clip area, we're going to center
+    // it in the paintable region instead, rounding up to the closest pixel to
+    // avoid smearing.
+    const int y_offset = std::ceilf((kOverlayIconSize - resized_height) / 2.0f);
+    offscreen_canvas.drawImage(sk_icon.asImage(), 0, y_offset);
+
+    icon = IconUtil::CreateHICONFromSkBitmap(offscreen_bitmap);
+    if (!icon.is_valid())
+      return false;
+  }
+
   return SUCCEEDED(taskbar_->SetOverlayIcon(window, icon.get(),
                                             base::UTF8ToWide(text).c_str()));
 }

+ 1 - 1
shell/browser/ui/win/taskbar_host.h

@@ -52,7 +52,7 @@ class TaskbarHost {
 
   // Set the overlay icon in taskbar.
   bool SetOverlayIcon(HWND window,
-                      const SkBitmap& overlay,
+                      const SkBitmap& bitmap,
                       const std::string& text);
 
   // Set the region of the window to show as a thumbnail in taskbar.