Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/status/network_menu_icon.h" | 5 #include "chrome/browser/chromeos/status/network_menu_icon.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/chromeos/accessibility/accessibility_util.h" | 13 #include "chrome/browser/chromeos/accessibility/accessibility_util.h" |
| 14 #include "chrome/browser/chromeos/cros/cros_library.h" | 14 #include "chrome/browser/chromeos/cros/cros_library.h" |
| 15 #include "grit/generated_resources.h" | 15 #include "grit/generated_resources.h" |
| 16 #include "grit/theme_resources.h" | 16 #include "grit/theme_resources.h" |
| 17 #include "ui/base/l10n/l10n_util.h" | 17 #include "ui/base/l10n/l10n_util.h" |
| 18 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
| 19 #include "ui/gfx/canvas.h" | 19 #include "ui/gfx/canvas.h" |
| 20 #include "ui/gfx/image/image_skia_operations.h" | |
| 20 #include "ui/gfx/image/image_skia_source.h" | 21 #include "ui/gfx/image/image_skia_source.h" |
| 21 #include "ui/gfx/skbitmap_operations.h" | |
| 22 | 22 |
| 23 using std::max; | 23 using std::max; |
| 24 using std::min; | 24 using std::min; |
| 25 | 25 |
| 26 namespace chromeos { | 26 namespace chromeos { |
| 27 | 27 |
| 28 namespace { | 28 namespace { |
| 29 | 29 |
| 30 // Amount to fade icons while connecting. | 30 // Amount to fade icons while connecting. |
| 31 const double kConnectingImageAlpha = 0.5; | 31 const double kConnectingImageAlpha = 0.5; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 break; | 151 break; |
| 152 case NETWORK_TECHNOLOGY_UNKNOWN: | 152 case NETWORK_TECHNOLOGY_UNKNOWN: |
| 153 break; | 153 break; |
| 154 } | 154 } |
| 155 if (id == kUnknownBadgeType) | 155 if (id == kUnknownBadgeType) |
| 156 return NULL; | 156 return NULL; |
| 157 else | 157 else |
| 158 return ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id); | 158 return ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id); |
| 159 } | 159 } |
| 160 | 160 |
| 161 const SkBitmap GetEmptyBitmapOfSameSize(const gfx::ImageSkiaRep& reference) { | 161 class EmptyImageSource: public gfx::ImageSkiaSource { |
| 162 typedef std::pair<int, int> SizeKey; | |
| 163 typedef std::map<SizeKey, SkBitmap> SizeBitmapMap; | |
| 164 static SizeBitmapMap* empty_bitmaps_ = new SizeBitmapMap; | |
| 165 | |
| 166 SizeKey key(reference.pixel_width(), reference.pixel_height()); | |
| 167 | |
| 168 SizeBitmapMap::iterator iter = empty_bitmaps_->find(key); | |
| 169 if (iter != empty_bitmaps_->end()) | |
| 170 return iter->second; | |
| 171 | |
| 172 SkBitmap empty; | |
| 173 empty.setConfig(SkBitmap::kARGB_8888_Config, key.first, key.second); | |
| 174 empty.allocPixels(); | |
| 175 empty.eraseARGB(0, 0, 0, 0); | |
| 176 (*empty_bitmaps_)[key] = empty; | |
| 177 return empty; | |
| 178 } | |
| 179 | |
| 180 class FadedImageSource : public gfx::ImageSkiaSource { | |
| 181 public: | 162 public: |
| 182 FadedImageSource(const gfx::ImageSkia& source, double alpha) | 163 EmptyImageSource(const gfx::Size& size) |
| 183 : source_(source), | 164 : size_(size) { |
| 184 alpha_(alpha) { | |
| 185 } | 165 } |
| 186 virtual ~FadedImageSource() {} | |
| 187 | 166 |
| 188 virtual gfx::ImageSkiaRep GetImageForScale( | 167 virtual gfx::ImageSkiaRep GetImageForScale( |
| 189 ui::ScaleFactor scale_factor) OVERRIDE { | 168 ui::ScaleFactor scale_factor) OVERRIDE { |
| 190 gfx::ImageSkiaRep image_rep = source_.GetRepresentation(scale_factor); | 169 SkBitmap empty; |
| 191 const SkBitmap empty_bitmap = GetEmptyBitmapOfSameSize(image_rep); | 170 empty.setConfig(SkBitmap::kARGB_8888_Config, size_.width(), |
| 192 SkBitmap faded_bitmap = SkBitmapOperations::CreateBlendedBitmap( | 171 size_.height()); |
| 193 empty_bitmap, image_rep.sk_bitmap(), alpha_); | 172 empty.allocPixels(); |
| 194 return gfx::ImageSkiaRep(faded_bitmap, image_rep.scale_factor()); | 173 empty.eraseARGB(0, 0, 0, 0); |
|
oshima
2012/07/13 16:54:55
can we cache this? I think it'd save more than cac
| |
| 174 return gfx::ImageSkiaRep(empty, scale_factor); | |
| 195 } | 175 } |
| 176 private: | |
| 177 const gfx::Size size_; | |
| 196 | 178 |
| 197 private: | 179 DISALLOW_COPY_AND_ASSIGN(EmptyImageSource); |
| 198 const gfx::ImageSkia source_; | |
| 199 const float alpha_; | |
| 200 | |
| 201 DISALLOW_COPY_AND_ASSIGN(FadedImageSource); | |
| 202 }; | 180 }; |
| 203 | 181 |
| 204 // This defines how we assemble a network icon. | 182 // This defines how we assemble a network icon. |
| 205 class NetworkIconImageSource : public gfx::ImageSkiaSource { | 183 class NetworkIconImageSource : public gfx::ImageSkiaSource { |
| 206 public: | 184 public: |
| 207 NetworkIconImageSource(const gfx::ImageSkia& icon, | 185 NetworkIconImageSource(const gfx::ImageSkia& icon, |
| 208 const gfx::ImageSkia* top_left_badge, | 186 const gfx::ImageSkia* top_left_badge, |
| 209 const gfx::ImageSkia* top_right_badge, | 187 const gfx::ImageSkia* top_right_badge, |
| 210 const gfx::ImageSkia* bottom_left_badge, | 188 const gfx::ImageSkia* bottom_left_badge, |
| 211 const gfx::ImageSkia* bottom_right_badge) | 189 const gfx::ImageSkia* bottom_right_badge) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 245 private: | 223 private: |
| 246 const gfx::ImageSkia icon_; | 224 const gfx::ImageSkia icon_; |
| 247 const gfx::ImageSkia *top_left_badge_; | 225 const gfx::ImageSkia *top_left_badge_; |
| 248 const gfx::ImageSkia *top_right_badge_; | 226 const gfx::ImageSkia *top_right_badge_; |
| 249 const gfx::ImageSkia *bottom_left_badge_; | 227 const gfx::ImageSkia *bottom_left_badge_; |
| 250 const gfx::ImageSkia *bottom_right_badge_; | 228 const gfx::ImageSkia *bottom_right_badge_; |
| 251 | 229 |
| 252 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource); | 230 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource); |
| 253 }; | 231 }; |
| 254 | 232 |
| 255 // This defines how we assemble a network menu icon. | |
| 256 class NetworkMenuIconSource : public gfx::ImageSkiaSource { | |
| 257 public: | |
| 258 NetworkMenuIconSource(NetworkMenuIcon::ImageType type, | |
| 259 int index, | |
| 260 NetworkMenuIcon::ResourceColorTheme color) | |
| 261 : type_(type), | |
| 262 index_(index), | |
| 263 color_(color) { | |
| 264 } | |
| 265 virtual ~NetworkMenuIconSource() {} | |
| 266 | |
| 267 virtual gfx::ImageSkiaRep GetImageForScale( | |
| 268 ui::ScaleFactor scale_factor) OVERRIDE { | |
| 269 int width, height; | |
| 270 gfx::ImageSkia* images; | |
| 271 if (type_ == NetworkMenuIcon::ARCS) { | |
| 272 if (index_ >= kNumArcsImages) | |
| 273 return gfx::ImageSkiaRep(); | |
| 274 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 275 color_ == NetworkMenuIcon::COLOR_DARK ? | |
| 276 IDR_STATUSBAR_NETWORK_ARCS_DARK : IDR_STATUSBAR_NETWORK_ARCS_LIGHT); | |
| 277 width = images->width(); | |
| 278 height = images->height() / kNumArcsImages; | |
| 279 } else { | |
| 280 if (index_ >= kNumBarsImages) | |
| 281 return gfx::ImageSkiaRep(); | |
| 282 | |
| 283 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 284 color_ == NetworkMenuIcon::COLOR_DARK ? | |
| 285 IDR_STATUSBAR_NETWORK_BARS_DARK : IDR_STATUSBAR_NETWORK_BARS_LIGHT); | |
| 286 width = images->width(); | |
| 287 height = images->height() / kNumBarsImages; | |
| 288 } | |
| 289 gfx::ImageSkiaRep image_rep = images->GetRepresentation(scale_factor); | |
| 290 | |
| 291 float scale = ui::GetScaleFactorScale(image_rep.scale_factor()); | |
| 292 height *= scale; | |
| 293 width *= scale; | |
| 294 | |
| 295 SkIRect subset = SkIRect::MakeXYWH(0, index_ * height, width, height); | |
| 296 | |
| 297 SkBitmap dst_bitmap; | |
| 298 image_rep.sk_bitmap().extractSubset(&dst_bitmap, subset); | |
| 299 return gfx::ImageSkiaRep(dst_bitmap, image_rep.scale_factor()); | |
| 300 } | |
| 301 | |
| 302 gfx::Size size() const { | |
| 303 // NeworkMenuIcons all have the same size in DIP for arc/bars. | |
| 304 if (type_ == NetworkMenuIcon::ARCS) { | |
| 305 gfx::Size size = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 306 IDR_STATUSBAR_NETWORK_ARCS_DARK)->size(); | |
| 307 return gfx::Size(size.width(), size.height() / kNumArcsImages); | |
| 308 } else { | |
| 309 gfx::Size size = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 310 IDR_STATUSBAR_NETWORK_BARS_DARK)->size(); | |
| 311 return gfx::Size(size.width(), size.height() / kNumBarsImages); | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 private: | |
| 316 const NetworkMenuIcon::ImageType type_; | |
| 317 const int index_; | |
| 318 const NetworkMenuIcon::ResourceColorTheme color_; | |
| 319 | |
| 320 DISALLOW_COPY_AND_ASSIGN(NetworkMenuIconSource); | |
| 321 }; | |
| 322 | |
| 323 gfx::ImageSkia CreateVpnImage() { | 233 gfx::ImageSkia CreateVpnImage() { |
| 324 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 234 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 325 const gfx::ImageSkia* ethernet_icon = rb.GetImageSkiaNamed(IDR_STATUSBAR_VPN); | 235 const gfx::ImageSkia* ethernet_icon = rb.GetImageSkiaNamed(IDR_STATUSBAR_VPN); |
| 326 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId); | 236 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId); |
| 327 return NetworkMenuIcon::GenerateImageFromComponents( | 237 return NetworkMenuIcon::GenerateImageFromComponents( |
| 328 *ethernet_icon, NULL, NULL, vpn_badge, NULL); | 238 *ethernet_icon, NULL, NULL, vpn_badge, NULL); |
| 329 } | 239 } |
| 330 | 240 |
| 241 gfx::ImageSkia CreateEmptyImage(const gfx::Size& size) { | |
|
oshima
2012/07/13 16:54:55
GetEmptyImage is probably better. Is this only pla
pkotwicz
2012/07/15 03:36:48
I haven't found a place which does something simil
| |
| 242 typedef std::pair<int, int> SizeKey; | |
| 243 typedef std::map<SizeKey, gfx::ImageSkia> SizeImageMap; | |
| 244 static SizeImageMap* empty_images = new SizeImageMap; | |
| 245 | |
| 246 SizeKey key(size.width(), size.height()); | |
| 247 SizeImageMap::iterator iter = empty_images->find(key); | |
| 248 | |
| 249 if (iter != empty_images->end()) | |
| 250 return iter->second; | |
| 251 | |
| 252 gfx::ImageSkia empty = gfx::ImageSkia(new EmptyImageSource(size), size); | |
| 253 (*empty_images)[key] = empty; | |
| 254 return empty; | |
| 255 } | |
| 256 | |
| 331 } // namespace | 257 } // namespace |
| 332 | 258 |
| 333 //////////////////////////////////////////////////////////////////////////////// | 259 //////////////////////////////////////////////////////////////////////////////// |
| 334 // NetworkIcon | 260 // NetworkIcon |
| 335 // TODO(stevenjb): Separate class implementation from the definition. | 261 // TODO(stevenjb): Separate class implementation from the definition. |
| 336 | 262 |
| 337 // Sets up and generates an ImageSkia for a Network icon. | 263 // Sets up and generates an ImageSkia for a Network icon. |
| 338 class NetworkIcon { | 264 class NetworkIcon { |
| 339 public: | 265 public: |
| 340 // Default constructor is used by the status bar icon (NetworkMenuIcon). | 266 // Default constructor is used by the status bar icon (NetworkMenuIcon). |
| (...skipping 485 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 826 icon_->UpdateIcon(network); | 752 icon_->UpdateIcon(network); |
| 827 // Overlay the VPN badge if connecting to a VPN. | 753 // Overlay the VPN badge if connecting to a VPN. |
| 828 if (network->type() != TYPE_VPN && cros->virtual_network()) { | 754 if (network->type() != TYPE_VPN && cros->virtual_network()) { |
| 829 if (cros->virtual_network()->connecting()) { | 755 if (cros->virtual_network()->connecting()) { |
| 830 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId); | 756 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId); |
| 831 const double animation = GetAnimation(); | 757 const double animation = GetAnimation(); |
| 832 animating = true; | 758 animating = true; |
| 833 // Even though this is the only place we use vpn_connecting_badge_, | 759 // Even though this is the only place we use vpn_connecting_badge_, |
| 834 // it is important that this is a member variable since we set a | 760 // it is important that this is a member variable since we set a |
| 835 // pointer to it and access that pointer in icon_->GenerateImage(). | 761 // pointer to it and access that pointer in icon_->GenerateImage(). |
| 836 vpn_connecting_badge_ = gfx::ImageSkia( | 762 vpn_connecting_badge_ = gfx::ImageSkiaOperations::CreateBlendedImage( |
| 837 new FadedImageSource(*vpn_badge, animation), vpn_badge->size()); | 763 CreateEmptyImage(vpn_badge->size()), *vpn_badge, animation); |
| 838 icon_->set_bottom_left_badge(&vpn_connecting_badge_); | 764 icon_->set_bottom_left_badge(&vpn_connecting_badge_); |
| 839 } | 765 } |
| 840 } | 766 } |
| 841 if (!animating) | 767 if (!animating) |
| 842 animation_connecting_.Stop(); | 768 animation_connecting_.Stop(); |
| 843 | 769 |
| 844 // Set the text to display. | 770 // Set the text to display. |
| 845 if (network->type() == TYPE_ETHERNET) { | 771 if (network->type() == TYPE_ETHERNET) { |
| 846 if (mode_ == MENU_MODE) { | 772 if (mode_ == MENU_MODE) { |
| 847 text_ = l10n_util::GetStringFUTF16( | 773 text_ = l10n_util::GetStringFUTF16( |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 903 top_left_badge, | 829 top_left_badge, |
| 904 top_right_badge, | 830 top_right_badge, |
| 905 bottom_left_badge, | 831 bottom_left_badge, |
| 906 bottom_right_badge), | 832 bottom_right_badge), |
| 907 icon.size()); | 833 icon.size()); |
| 908 } | 834 } |
| 909 | 835 |
| 910 // We blend connecting icons with a black image to generate a faded icon. | 836 // We blend connecting icons with a black image to generate a faded icon. |
| 911 const gfx::ImageSkia NetworkMenuIcon::GenerateConnectingImage( | 837 const gfx::ImageSkia NetworkMenuIcon::GenerateConnectingImage( |
| 912 const gfx::ImageSkia& source) { | 838 const gfx::ImageSkia& source) { |
| 913 return gfx::ImageSkia(new FadedImageSource(source, kConnectingImageAlpha), | 839 return gfx::ImageSkiaOperations::CreateBlendedImage( |
| 914 source.size()); | 840 CreateEmptyImage(source.size()), source, kConnectingImageAlpha); |
| 915 } | 841 } |
| 916 | 842 |
| 917 // Generates and caches an icon image for a network's current state. | 843 // Generates and caches an icon image for a network's current state. |
| 918 const gfx::ImageSkia NetworkMenuIcon::GetImage(const Network* network, | 844 const gfx::ImageSkia NetworkMenuIcon::GetImage(const Network* network, |
| 919 ResourceColorTheme color) { | 845 ResourceColorTheme color) { |
| 920 DCHECK(network); | 846 DCHECK(network); |
| 921 // Maintain a static (global) icon map. Note: Icons are never destroyed; | 847 // Maintain a static (global) icon map. Note: Icons are never destroyed; |
| 922 // it is assumed that a finite and reasonable number of network icons will be | 848 // it is assumed that a finite and reasonable number of network icons will be |
| 923 // created during a session. | 849 // created during a session. |
| 924 | 850 |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 948 | 874 |
| 949 // Returns an icon for a disconnected VPN. | 875 // Returns an icon for a disconnected VPN. |
| 950 const gfx::ImageSkia NetworkMenuIcon::GetVpnImage() { | 876 const gfx::ImageSkia NetworkMenuIcon::GetVpnImage() { |
| 951 static const gfx::ImageSkia *vpn_image = new gfx::ImageSkia(CreateVpnImage()); | 877 static const gfx::ImageSkia *vpn_image = new gfx::ImageSkia(CreateVpnImage()); |
| 952 return *vpn_image; | 878 return *vpn_image; |
| 953 } | 879 } |
| 954 | 880 |
| 955 const gfx::ImageSkia NetworkMenuIcon::GetImage(ImageType type, | 881 const gfx::ImageSkia NetworkMenuIcon::GetImage(ImageType type, |
| 956 int index, | 882 int index, |
| 957 ResourceColorTheme color) { | 883 ResourceColorTheme color) { |
| 958 NetworkMenuIconSource* source = new NetworkMenuIconSource(type, index, color); | 884 int width, height; |
| 959 return gfx::ImageSkia(source, source->size()); | 885 gfx::ImageSkia* images; |
| 886 if (type == NetworkMenuIcon::ARCS) { | |
| 887 if (index >= kNumArcsImages) | |
| 888 return gfx::ImageSkia(); | |
| 889 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 890 color == NetworkMenuIcon::COLOR_DARK ? | |
| 891 IDR_STATUSBAR_NETWORK_ARCS_DARK : IDR_STATUSBAR_NETWORK_ARCS_LIGHT); | |
| 892 width = images->width(); | |
| 893 height = images->height() / kNumArcsImages; | |
| 894 } else { | |
| 895 if (index >= kNumBarsImages) | |
| 896 return gfx::ImageSkia(); | |
| 897 | |
| 898 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | |
| 899 color == NetworkMenuIcon::COLOR_DARK ? | |
| 900 IDR_STATUSBAR_NETWORK_BARS_DARK : IDR_STATUSBAR_NETWORK_BARS_LIGHT); | |
| 901 width = images->width(); | |
| 902 height = images->height() / kNumBarsImages; | |
| 903 } | |
| 904 return gfx::ImageSkiaOperations::ExtractSubset(*images, | |
| 905 gfx::Rect(0, index * height, width, height)); | |
| 960 } | 906 } |
| 961 | 907 |
| 962 const gfx::ImageSkia NetworkMenuIcon::GetDisconnectedImage( | 908 const gfx::ImageSkia NetworkMenuIcon::GetDisconnectedImage( |
| 963 ImageType type, | 909 ImageType type, |
| 964 ResourceColorTheme color) { | 910 ResourceColorTheme color) { |
| 965 return GetImage(type, 0, color); | 911 return GetImage(type, 0, color); |
| 966 } | 912 } |
| 967 | 913 |
| 968 const gfx::ImageSkia NetworkMenuIcon::GetConnectedImage(ImageType type, | 914 const gfx::ImageSkia NetworkMenuIcon::GetConnectedImage(ImageType type, |
| 969 ResourceColorTheme color) { | 915 ResourceColorTheme color) { |
| 970 return GetImage(type, NumImages(type) - 1, color); | 916 return GetImage(type, NumImages(type) - 1, color); |
| 971 } | 917 } |
| 972 | 918 |
| 973 int NetworkMenuIcon::NumImages(ImageType type) { | 919 int NetworkMenuIcon::NumImages(ImageType type) { |
| 974 return (type == ARCS) ? kNumArcsImages : kNumBarsImages; | 920 return (type == ARCS) ? kNumArcsImages : kNumBarsImages; |
| 975 } | 921 } |
| 976 | 922 |
| 977 } // chromeos | 923 } // chromeos |
| OLD | NEW |