1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/views/tab_icon_view.h" 6 7 #if defined(OS_WIN) 8 #include <windows.h> 9 #include <shellapi.h> 10 #endif 11 12 #include "base/file_util.h" 13 #include "base/logging.h" 14 #include "chrome/app/chrome_command_ids.h" 15 #include "grit/app_resources.h" 16 #include "grit/theme_resources.h" 17 #include "ui/base/resource/resource_bundle.h" 18 #include "ui/base/theme_provider.h" 19 #include "ui/gfx/canvas.h" 20 #include "ui/gfx/favicon_size.h" 21 22 #if defined(OS_WIN) 23 #include "chrome/browser/app_icon_win.h" 24 #include "ui/gfx/icon_util.h" 25 #endif 26 27 static bool g_initialized = false; 28 static SkBitmap* g_default_favicon = NULL; 29 30 // static 31 void TabIconView::InitializeIfNeeded() { 32 if (!g_initialized) { 33 g_initialized = true; 34 35 #if defined(OS_WIN) 36 // The default window icon is the application icon, not the default 37 // favicon. 38 HICON app_icon = GetAppIcon(); 39 g_default_favicon = 40 IconUtil::CreateSkBitmapFromHICON(app_icon, gfx::Size(16, 16)); 41 DestroyIcon(app_icon); 42 #else 43 g_default_favicon = 44 ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_PRODUCT_LOGO_16); 45 #endif 46 } 47 } 48 49 TabIconView::TabIconView(TabIconViewModel* model) 50 : model_(model), 51 throbber_running_(false), 52 is_light_(false), 53 throbber_frame_(0) { 54 InitializeIfNeeded(); 55 } 56 57 TabIconView::~TabIconView() { 58 } 59 60 void TabIconView::Update() { 61 static bool initialized = false; 62 static int throbber_frame_count = 0; 63 if (!initialized) { 64 initialized = true; 65 SkBitmap throbber( 66 *ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_THROBBER)); 67 throbber_frame_count = throbber.width() / throbber.height(); 68 } 69 70 if (throbber_running_) { 71 // We think the tab is loading. 72 if (!model_->ShouldTabIconViewAnimate()) { 73 // Woops, tab is invalid or not loading, reset our status and schedule 74 // a paint. 75 throbber_running_ = false; 76 SchedulePaint(); 77 } else { 78 // The tab is still loading, increment the frame. 79 throbber_frame_ = (throbber_frame_ + 1) % throbber_frame_count; 80 SchedulePaint(); 81 } 82 } else if (model_->ShouldTabIconViewAnimate()) { 83 // We didn't think we were loading, but the tab is loading. Reset the 84 // frame and status and schedule a paint. 85 throbber_running_ = true; 86 throbber_frame_ = 0; 87 SchedulePaint(); 88 } 89 } 90 91 void TabIconView::PaintThrobber(gfx::Canvas* canvas) { 92 SkBitmap throbber(*GetThemeProvider()->GetBitmapNamed( 93 is_light_ ? IDR_THROBBER_LIGHT : IDR_THROBBER)); 94 int image_size = throbber.height(); 95 PaintIcon(canvas, throbber, throbber_frame_ * image_size, 0, image_size, 96 image_size, false); 97 } 98 99 void TabIconView::PaintFavicon(gfx::Canvas* canvas, const SkBitmap& bitmap) { 100 PaintIcon(canvas, bitmap, 0, 0, bitmap.width(), bitmap.height(), true); 101 } 102 103 void TabIconView::PaintIcon(gfx::Canvas* canvas, 104 const SkBitmap& bitmap, 105 int src_x, 106 int src_y, 107 int src_w, 108 int src_h, 109 bool filter) { 110 // For source images smaller than the favicon square, scale them as if they 111 // were padded to fit the favicon square, so we don't blow up tiny favicons 112 // into larger or nonproportional results. 113 float float_src_w = static_cast<float>(src_w); 114 float float_src_h = static_cast<float>(src_h); 115 float scalable_w, scalable_h; 116 if (src_w <= kFaviconSize && src_h <= kFaviconSize) { 117 scalable_w = scalable_h = kFaviconSize; 118 } else { 119 scalable_w = float_src_w; 120 scalable_h = float_src_h; 121 } 122 123 // Scale proportionately. 124 float scale = std::min(static_cast<float>(width()) / scalable_w, 125 static_cast<float>(height()) / scalable_h); 126 int dest_w = static_cast<int>(float_src_w * scale); 127 int dest_h = static_cast<int>(float_src_h * scale); 128 129 // Center the scaled image. 130 canvas->DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, 131 (width() - dest_w) / 2, (height() - dest_h) / 2, dest_w, 132 dest_h, filter); 133 } 134 135 void TabIconView::OnPaint(gfx::Canvas* canvas) { 136 bool rendered = false; 137 138 if (throbber_running_) { 139 rendered = true; 140 PaintThrobber(canvas); 141 } else { 142 SkBitmap favicon = model_->GetFaviconForTabIconView(); 143 if (!favicon.isNull()) { 144 rendered = true; 145 PaintFavicon(canvas, favicon); 146 } 147 } 148 149 if (!rendered) 150 PaintFavicon(canvas, *g_default_favicon); 151 } 152 153 gfx::Size TabIconView::GetPreferredSize() { 154 return gfx::Size(kFaviconSize, kFaviconSize); 155 } 156