Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(790)

Side by Side Diff: chrome/browser/chromeos/status/network_menu_icon.cc

Issue 10694045: Loading/Creating images for mutiple scale factors on the fly (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: size fix Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | ui/gfx/image/image_skia.h » ('j') | ui/gfx/image/image_skia.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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>
10 #include <utility>
9 11
10 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/chromeos/accessibility/accessibility_util.h" 13 #include "chrome/browser/chromeos/accessibility/accessibility_util.h"
12 #include "chrome/browser/chromeos/cros/cros_library.h" 14 #include "chrome/browser/chromeos/cros/cros_library.h"
13 #include "grit/generated_resources.h" 15 #include "grit/generated_resources.h"
14 #include "grit/theme_resources.h" 16 #include "grit/theme_resources.h"
15 #include "grit/theme_resources_standard.h" 17 #include "grit/theme_resources_standard.h"
16 #include "ui/base/l10n/l10n_util.h" 18 #include "ui/base/l10n/l10n_util.h"
17 #include "ui/base/resource/resource_bundle.h" 19 #include "ui/base/resource/resource_bundle.h"
18 #include "ui/gfx/canvas.h" 20 #include "ui/gfx/canvas.h"
21 #include "ui/gfx/image/image_skia_source.h"
19 #include "ui/gfx/skbitmap_operations.h" 22 #include "ui/gfx/skbitmap_operations.h"
20 23
21 using std::max; 24 using std::max;
22 using std::min; 25 using std::min;
23 26
24 namespace chromeos { 27 namespace chromeos {
25 28
26 namespace { 29 namespace {
27 30
28 // Amount to fade icons while connecting. 31 // Amount to fade icons while connecting.
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 break; 145 break;
143 case NETWORK_TECHNOLOGY_UNKNOWN: 146 case NETWORK_TECHNOLOGY_UNKNOWN:
144 break; 147 break;
145 } 148 }
146 if (id == kUnknownBadgeType) 149 if (id == kUnknownBadgeType)
147 return NULL; 150 return NULL;
148 else 151 else
149 return ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id); 152 return ResourceBundle::GetSharedInstance().GetImageSkiaNamed(id);
150 } 153 }
151 154
152 // Blend source image with a black image to fade the image. 155 const SkBitmap GetEmptyBitmapOfSameSize(const gfx::ImageSkiaRep& reference) {
153 const gfx::ImageSkia GenerateFadedImage(gfx::ImageSkia source, 156 typedef std::pair<int, int> SizeKey;
154 gfx::ImageSkia empty_image, 157 typedef std::map<SizeKey, SkBitmap> SizeBitmapMap;
155 double alpha) { 158 static SizeBitmapMap* empty_bitmaps_ = new SizeBitmapMap;
156 gfx::ImageSkia faded_image; 159
157 std::vector<gfx::ImageSkiaRep> image_reps = source.image_reps(); 160 SizeKey key(reference.pixel_width(), reference.pixel_height());
158 for (size_t i = 0; i < image_reps.size(); ++i) { 161
159 gfx::ImageSkiaRep image_rep = image_reps[i]; 162 SizeBitmapMap::iterator iter = empty_bitmaps_->find(key);
160 ui::ScaleFactor scale_factor = image_rep.scale_factor(); 163 if (iter != empty_bitmaps_->end())
161 gfx::ImageSkiaRep empty_image_rep = 164 return iter->second;
162 empty_image.GetRepresentation(scale_factor); 165
163 SkBitmap empty_bitmap = empty_image_rep.sk_bitmap(); 166 SkBitmap empty;
164 if (empty_image_rep.is_null() || 167 empty.setConfig(SkBitmap::kARGB_8888_Config, key.first, key.second);
165 empty_image_rep.scale_factor() != scale_factor) { 168 empty.allocPixels();
166 empty_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 169 empty.eraseARGB(0, 0, 0, 0);
167 image_rep.pixel_width(), 170 (*empty_bitmaps_)[key] = empty;
168 image_rep.pixel_height()); 171 return empty;
169 empty_bitmap.allocPixels();
170 empty_bitmap.eraseARGB(0, 0, 0, 0);
171 empty_image.AddRepresentation(gfx::ImageSkiaRep(empty_bitmap,
172 scale_factor));
173 }
174 SkBitmap faded_bitmap = SkBitmapOperations::CreateBlendedBitmap(
175 empty_bitmap, image_rep.sk_bitmap(), alpha);
176 faded_image.AddRepresentation(gfx::ImageSkiaRep(faded_bitmap,
177 scale_factor));
178 }
179 return faded_image;
180 } 172 }
181 173
182 const SkBitmap GetVpnResource(int resource_id) { 174 class FadedImageSource : public gfx::ImageSkiaSource {
175 public:
176 FadedImageSource(const gfx::ImageSkia& source, double alpha)
177 : source_(source),
178 alpha_(alpha) {
179 }
180 virtual ~FadedImageSource() {}
181
182 virtual gfx::ImageSkiaRep GetImageForScale(
183 ui::ScaleFactor scale_factor) OVERRIDE {
184 gfx::ImageSkiaRep image_rep = source_.GetRepresentation(scale_factor);
185 const SkBitmap empty_bitmap = GetEmptyBitmapOfSameSize(image_rep);
186 SkBitmap faded_bitmap = SkBitmapOperations::CreateBlendedBitmap(
187 empty_bitmap, image_rep.sk_bitmap(), alpha_);
188 return gfx::ImageSkiaRep(faded_bitmap, image_rep.scale_factor());
189 }
190
191 private:
192 const gfx::ImageSkia source_;
193 const float alpha_;
194
195 DISALLOW_COPY_AND_ASSIGN(FadedImageSource);
196 };
197
198 // This defines how we assemble a network icon.
199 class NetworkIconImageSource : public gfx::ImageSkiaSource {
200 public:
201 NetworkIconImageSource(const gfx::ImageSkia& icon,
202 const gfx::ImageSkia* top_left_badge,
203 const gfx::ImageSkia* top_right_badge,
204 const gfx::ImageSkia* bottom_left_badge,
205 const gfx::ImageSkia* bottom_right_badge)
206 : icon_(icon),
207 top_left_badge_(top_left_badge),
208 top_right_badge_(top_right_badge),
209 bottom_left_badge_(bottom_left_badge),
210 bottom_right_badge_(bottom_right_badge) {
211 }
212 virtual ~NetworkIconImageSource() {}
213
214 virtual gfx::ImageSkiaRep GetImageForScale(
215 ui::ScaleFactor scale_factor) OVERRIDE {
216 gfx::ImageSkiaRep icon_rep = icon_.GetRepresentation(scale_factor);
217 if (icon_rep.is_null())
218 return gfx::ImageSkiaRep();
219 gfx::Canvas canvas(icon_rep, false);
220 if (top_left_badge_)
221 canvas.DrawImageInt(*top_left_badge_, kBadgeLeftX, kBadgeTopY);
222 if (top_right_badge_)
223 canvas.DrawImageInt(*top_right_badge_,
224 icon_.width() - top_right_badge_->width(),
225 kBadgeTopY);
226 if (bottom_left_badge_) {
227 canvas.DrawImageInt(*bottom_left_badge_,
228 kBadgeLeftX,
229 icon_.height() - bottom_left_badge_->height());
230 }
231 if (bottom_right_badge_) {
232 canvas.DrawImageInt(*bottom_right_badge_,
233 icon_.width() - bottom_right_badge_->width(),
234 icon_.height() - bottom_right_badge_->height());
235 }
236 return gfx::ImageSkiaRep(canvas.ExtractBitmap(), icon_rep.scale_factor());
237 }
238
239 private:
240 const gfx::ImageSkia icon_;
241 const gfx::ImageSkia *top_left_badge_;
242 const gfx::ImageSkia *top_right_badge_;
243 const gfx::ImageSkia *bottom_left_badge_;
244 const gfx::ImageSkia *bottom_right_badge_;
245
246 DISALLOW_COPY_AND_ASSIGN(NetworkIconImageSource);
247 };
248
249 // This defines how we assemble a network menu icon.
250 class NetworkMenuIconSource : public gfx::ImageSkiaSource {
251 public:
252 NetworkMenuIconSource(NetworkMenuIcon::ImageType type,
253 int index,
254 NetworkMenuIcon::ResourceColorTheme color)
255 : type_(type),
256 index_(index),
257 color_(color) {
258 }
259 virtual ~NetworkMenuIconSource() {}
260
261 virtual gfx::ImageSkiaRep GetImageForScale(
262 ui::ScaleFactor scale_factor) OVERRIDE {
263 int width, height;
264 gfx::ImageSkia* images;
265 if (type_ == NetworkMenuIcon::ARCS) {
266 if (index_ >= kNumArcsImages)
267 return gfx::ImageSkia();
268 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
269 color_ == NetworkMenuIcon::COLOR_DARK ?
270 IDR_STATUSBAR_NETWORK_ARCS_DARK : IDR_STATUSBAR_NETWORK_ARCS_LIGHT);
271 width = images->width();
272 height = images->height() / kNumArcsImages;
273 } else {
274 if (index_ >= kNumBarsImages)
275 return gfx::ImageSkia();
276
277 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
278 color_ == NetworkMenuIcon::COLOR_DARK ?
279 IDR_STATUSBAR_NETWORK_BARS_DARK : IDR_STATUSBAR_NETWORK_BARS_LIGHT);
280 width = images->width();
281 height = images->height() / kNumBarsImages;
282 }
283 gfx::ImageSkiaRep image_rep = images->GetRepresentation(scale_factor);
284
285 float scale = ui::GetScaleFactorScale(image_rep.scale_factor());
286 height *= scale;
287 width *= scale;
288
289 SkIRect subset = SkIRect::MakeXYWH(0, index_ * height, width, height);
290
291 SkBitmap dst_bitmap;
292 image_rep.sk_bitmap().extractSubset(&dst_bitmap, subset);
293 return gfx::ImageSkiaRep(dst_bitmap, image_rep.scale_factor());
294 }
295
296 gfx::Size size() const {
297 // NeworkMenuIcons all have the same size in DIP for arc/bars.
298 if (type_ == NetworkMenuIcon::ARCS) {
299 gfx::Size size = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
300 IDR_STATUSBAR_NETWORK_ARCS_DARK)->size();
301 return gfx::Size(size.width(), size.height() / kNumArcsImages);
302 } else {
303 gfx::Size size = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
304 IDR_STATUSBAR_NETWORK_BARS_DARK)->size();
305 return gfx::Size(size.width(), size.height() / kNumBarsImages);
306 }
307 }
308
309 private:
310 const NetworkMenuIcon::ImageType type_;
311 const int index_;
312 const NetworkMenuIcon::ResourceColorTheme color_;
313
314 DISALLOW_COPY_AND_ASSIGN(NetworkMenuIconSource);
315 };
316
317 gfx::ImageSkia CreateVpnImage() {
183 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 318 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
184 const gfx::ImageSkia* ethernet_icon = rb.GetImageSkiaNamed(resource_id); 319 const gfx::ImageSkia* ethernet_icon = rb.GetImageSkiaNamed(IDR_STATUSBAR_VPN);
185 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId); 320 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId);
186 return NetworkMenuIcon::GenerateImageFromComponents( 321 return NetworkMenuIcon::GenerateImageFromComponents(
187 *ethernet_icon, NULL, NULL, vpn_badge, NULL); 322 *ethernet_icon, NULL, NULL, vpn_badge, NULL);
188 } 323 }
189 324
190 } // namespace 325 } // namespace
191 326
192 //////////////////////////////////////////////////////////////////////////////// 327 ////////////////////////////////////////////////////////////////////////////////
193 // NetworkIcon 328 // NetworkIcon
194 // TODO(stevenjb): Separate class implementation from the definition. 329 // TODO(stevenjb): Separate class implementation from the definition.
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 icon_->UpdateIcon(network); 816 icon_->UpdateIcon(network);
682 // Overlay the VPN badge if connecting to a VPN. 817 // Overlay the VPN badge if connecting to a VPN.
683 if (network->type() != TYPE_VPN && cros->virtual_network()) { 818 if (network->type() != TYPE_VPN && cros->virtual_network()) {
684 if (cros->virtual_network()->connecting()) { 819 if (cros->virtual_network()->connecting()) {
685 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId); 820 const gfx::ImageSkia* vpn_badge = rb.GetImageSkiaNamed(kVpnBadgeId);
686 const double animation = GetAnimation(); 821 const double animation = GetAnimation();
687 animating = true; 822 animating = true;
688 // Even though this is the only place we use vpn_connecting_badge_, 823 // Even though this is the only place we use vpn_connecting_badge_,
689 // it is important that this is a member variable since we set a 824 // it is important that this is a member variable since we set a
690 // pointer to it and access that pointer in icon_->GenerateImage(). 825 // pointer to it and access that pointer in icon_->GenerateImage().
691 CR_DEFINE_STATIC_LOCAL(gfx::ImageSkia, empty_image, ()); 826 vpn_connecting_badge_ = gfx::ImageSkia(
692 vpn_connecting_badge_ = GenerateFadedImage(*vpn_badge, empty_image, 827 new FadedImageSource(*vpn_badge, animation), vpn_badge->size());
693 animation);
694 icon_->set_bottom_left_badge(&vpn_connecting_badge_); 828 icon_->set_bottom_left_badge(&vpn_connecting_badge_);
695 } 829 }
696 } 830 }
697 if (!animating) 831 if (!animating)
698 animation_connecting_.Stop(); 832 animation_connecting_.Stop();
699 833
700 // Set the text to display. 834 // Set the text to display.
701 if (network->type() == TYPE_ETHERNET) { 835 if (network->type() == TYPE_ETHERNET) {
702 if (mode_ == MENU_MODE) { 836 if (mode_ == MENU_MODE) {
703 text_ = l10n_util::GetStringFUTF16( 837 text_ = l10n_util::GetStringFUTF16(
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
748 // Currently we iterate over all the available resolutions in |icon|. This will 882 // Currently we iterate over all the available resolutions in |icon|. This will
749 // be wrong once we dynamically load image resolutions. 883 // be wrong once we dynamically load image resolutions.
750 // TODO(pkotwicz): Figure out what to do when a new image resolution becomes 884 // TODO(pkotwicz): Figure out what to do when a new image resolution becomes
751 // available. 885 // available.
752 const gfx::ImageSkia NetworkMenuIcon::GenerateImageFromComponents( 886 const gfx::ImageSkia NetworkMenuIcon::GenerateImageFromComponents(
753 const gfx::ImageSkia& icon, 887 const gfx::ImageSkia& icon,
754 const gfx::ImageSkia* top_left_badge, 888 const gfx::ImageSkia* top_left_badge,
755 const gfx::ImageSkia* top_right_badge, 889 const gfx::ImageSkia* top_right_badge,
756 const gfx::ImageSkia* bottom_left_badge, 890 const gfx::ImageSkia* bottom_left_badge,
757 const gfx::ImageSkia* bottom_right_badge) { 891 const gfx::ImageSkia* bottom_right_badge) {
758 DCHECK(!icon.empty()); 892 return gfx::ImageSkia(new NetworkIconImageSource(icon,
759 gfx::ImageSkia badged; 893 top_left_badge,
760 int dip_width = icon.width(); 894 top_right_badge,
761 int dip_height = icon.height(); 895 bottom_left_badge,
762 std::vector<gfx::ImageSkiaRep> image_reps = icon.image_reps(); 896 bottom_right_badge),
763 for (std::vector<gfx::ImageSkiaRep>::iterator it = image_reps.begin(); 897 icon.size());
764 it != image_reps.end(); ++it) {
765 gfx::Canvas canvas(*it, false);
766 if (top_left_badge)
767 canvas.DrawImageInt(*top_left_badge, kBadgeLeftX, kBadgeTopY);
768 if (top_right_badge)
769 canvas.DrawImageInt(*top_right_badge,
770 dip_width - top_right_badge->width(),
771 kBadgeTopY);
772 if (bottom_left_badge)
773 canvas.DrawImageInt(*bottom_left_badge,
774 kBadgeLeftX,
775 dip_height - bottom_left_badge->height());
776 if (bottom_right_badge)
777 canvas.DrawImageInt(*bottom_right_badge,
778 dip_width - bottom_right_badge->width(),
779 dip_height - bottom_right_badge->height());
780 badged.AddRepresentation(canvas.ExtractImageSkiaRep());
781 }
782 return badged;
783 } 898 }
784 899
785 // We blend connecting icons with a black image to generate a faded icon. 900 // We blend connecting icons with a black image to generate a faded icon.
786 const gfx::ImageSkia NetworkMenuIcon::GenerateConnectingImage( 901 const gfx::ImageSkia NetworkMenuIcon::GenerateConnectingImage(
787 const gfx::ImageSkia& source) { 902 const gfx::ImageSkia& source) {
788 CR_DEFINE_STATIC_LOCAL(gfx::ImageSkia, empty_badge, ()); 903 return gfx::ImageSkia(new FadedImageSource(source, kConnectingImageAlpha),
789 return GenerateFadedImage(source, empty_badge, kConnectingImageAlpha); 904 source.size());
790 } 905 }
791 906
792 // Generates and caches an icon image for a network's current state. 907 // Generates and caches an icon image for a network's current state.
793 const gfx::ImageSkia NetworkMenuIcon::GetImage(const Network* network, 908 const gfx::ImageSkia NetworkMenuIcon::GetImage(const Network* network,
794 ResourceColorTheme color) { 909 ResourceColorTheme color) {
795 DCHECK(network); 910 DCHECK(network);
796 // Maintain a static (global) icon map. Note: Icons are never destroyed; 911 // Maintain a static (global) icon map. Note: Icons are never destroyed;
797 // it is assumed that a finite and reasonable number of network icons will be 912 // it is assumed that a finite and reasonable number of network icons will be
798 // created during a session. 913 // created during a session.
799 914
(...skipping 16 matching lines...) Expand all
816 } else { 931 } else {
817 icon = iter->second; 932 icon = iter->second;
818 } 933 }
819 // Update and return the icon's image. 934 // Update and return the icon's image.
820 icon->Update(); 935 icon->Update();
821 return icon->GetImage(); 936 return icon->GetImage();
822 } 937 }
823 938
824 // Returns an icon for a disconnected VPN. 939 // Returns an icon for a disconnected VPN.
825 const gfx::ImageSkia NetworkMenuIcon::GetVpnImage() { 940 const gfx::ImageSkia NetworkMenuIcon::GetVpnImage() {
826 static gfx::ImageSkia* vpn_image = NULL; 941 static const gfx::ImageSkia *vpn_image = new gfx::ImageSkia(CreateVpnImage());
827 if (vpn_image == NULL)
828 vpn_image = new gfx::ImageSkia(GetVpnResource(IDR_STATUSBAR_VPN));
829 return *vpn_image; 942 return *vpn_image;
830 } 943 }
831 944
832 const gfx::ImageSkia NetworkMenuIcon::GetImage(ImageType type, 945 const gfx::ImageSkia NetworkMenuIcon::GetImage(ImageType type,
833 int index, 946 int index,
834 ResourceColorTheme color) { 947 ResourceColorTheme color) {
835 int width, height; 948 NetworkMenuIconSource* source = new NetworkMenuIconSource(type, index, color);
836 gfx::ImageSkia* images; 949 return gfx::ImageSkia(source, source->size());
837 if (type == ARCS) {
838 if (index >= kNumArcsImages)
839 return gfx::ImageSkia();
840
841 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
842 color == COLOR_DARK ? IDR_STATUSBAR_NETWORK_ARCS_DARK :
843 IDR_STATUSBAR_NETWORK_ARCS_LIGHT);
844 width = images->width();
845 height = images->height() / kNumArcsImages;
846 } else {
847 if (index >= kNumBarsImages)
848 return gfx::ImageSkia();
849
850 images = ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
851 color == COLOR_DARK ? IDR_STATUSBAR_NETWORK_BARS_DARK :
852 IDR_STATUSBAR_NETWORK_BARS_LIGHT);
853 width = images->width();
854 height = images->height() / kNumBarsImages;
855 }
856
857 SkIRect subset = SkIRect::MakeXYWH(0, index * height, width, height);
858 gfx::ImageSkia image;
859 images->extractSubset(&image, subset);
860 return image;
861 } 950 }
862 951
863 const gfx::ImageSkia NetworkMenuIcon::GetDisconnectedImage( 952 const gfx::ImageSkia NetworkMenuIcon::GetDisconnectedImage(
864 ImageType type, 953 ImageType type,
865 ResourceColorTheme color) { 954 ResourceColorTheme color) {
866 return GetImage(type, 0, color); 955 return GetImage(type, 0, color);
867 } 956 }
868 957
869 const gfx::ImageSkia NetworkMenuIcon::GetConnectedImage(ImageType type, 958 const gfx::ImageSkia NetworkMenuIcon::GetConnectedImage(ImageType type,
870 ResourceColorTheme color) { 959 ResourceColorTheme color) {
871 return GetImage(type, NumImages(type) - 1, color); 960 return GetImage(type, NumImages(type) - 1, color);
872 } 961 }
873 962
874 int NetworkMenuIcon::NumImages(ImageType type) { 963 int NetworkMenuIcon::NumImages(ImageType type) {
875 return (type == ARCS) ? kNumArcsImages : kNumBarsImages; 964 return (type == ARCS) ? kNumArcsImages : kNumBarsImages;
876 } 965 }
877 966
878 } // chromeos 967 } // chromeos
OLDNEW
« no previous file with comments | « no previous file | ui/gfx/image/image_skia.h » ('j') | ui/gfx/image/image_skia.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698