icon_loader_chromeos.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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 3// found in the LICENSE file. 4 5#include "chrome/browser/icon_loader.h" 6 7#include <map> 8#include <string> 9#include <utility> 10 11#include "base/bind.h" 12#include "base/files/file_path.h" 13#include "base/lazy_instance.h" 14#include "base/memory/ref_counted_memory.h" 15#include "base/message_loop/message_loop.h" 16#include "base/strings/string_util.h" 17#include "chrome/browser/icon_loader.h" 18#include "grit/theme_resources.h" 19#include "third_party/skia/include/core/SkBitmap.h" 20#include "ui/base/layout.h" 21#include "ui/base/resource/resource_bundle.h" 22#include "ui/gfx/canvas.h" 23#include "ui/gfx/codec/png_codec.h" 24#include "ui/gfx/image/image.h" 25#include "ui/gfx/image/image_skia.h" 26#include "ui/gfx/image/image_skia_operations.h" 27 28namespace { 29 30// Used with GenerateImageWithSize() to indicate that the image shouldn't be 31// resized. 32const int kDoNotResize = -1; 33 34struct IdrBySize { 35 int idr_small; 36 int idr_normal; 37 int idr_large; 38}; 39 40// Performs mapping of <file extension, icon size> to icon resource IDs. 41class IconMapper { 42 public: 43 IconMapper(); 44 45 // Lookup icon resource ID for a given filename |extension| and 46 // |icon_size|. Defaults to generic icons if there are no icons for the given 47 // extension. 48 int Lookup(const std::string& extension, IconLoader::IconSize icon_size); 49 50 private: 51 typedef std::map<std::string, IdrBySize> ExtensionIconMap; 52 53 ExtensionIconMap extension_icon_map_; 54}; 55 56const IdrBySize kAudioIdrs = { 57 IDR_FILE_MANAGER_IMG_FILETYPE_AUDIO, 58 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_AUDIO, 59 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_AUDIO 60}; 61const IdrBySize kGenericIdrs = { 62 IDR_FILE_MANAGER_IMG_FILETYPE_GENERIC, 63 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_GENERIC, 64 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_GENERIC 65}; 66const IdrBySize kImageIdrs = { 67 IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE, 68 IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE, 69 IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE 70}; 71const IdrBySize kPdfIdrs = { 72 IDR_FILE_MANAGER_IMG_FILETYPE_PDF, 73 IDR_FILE_MANAGER_IMG_FILETYPE_PDF, 74 IDR_FILE_MANAGER_IMG_FILETYPE_PDF 75}; 76const IdrBySize kVideoIdrs = { 77 IDR_FILE_MANAGER_IMG_FILETYPE_VIDEO, 78 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO, 79 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO 80}; 81 82IconMapper::IconMapper() { 83 // The code below should match translation in 84 // chrome/browser/resources/file_manager/js/file_manager.js 85 // chrome/browser/resources/file_manager/css/file_manager.css 86 // 'audio': /\.(mp3|m4a|oga|ogg|wav)$/i, 87 // 'html': /\.(html?)$/i, 88 // 'image': /\.(bmp|gif|jpe?g|ico|png|webp)$/i, 89 // 'pdf' : /\.(pdf)$/i, 90 // 'text': /\.(pod|rst|txt|log)$/i, 91 // 'video': /\.(mov|mp4|m4v|mpe?g4?|ogm|ogv|ogx|webm)$/i 92 93 const ExtensionIconMap::value_type kExtensionIdrBySizeData[] = { 94#if defined(GOOGLE_CHROME_BUILD) || defined(USE_PROPRIETARY_CODECS) 95 std::make_pair(".m4a", kAudioIdrs), 96 std::make_pair(".mp3", kAudioIdrs), 97 std::make_pair(".pdf", kPdfIdrs), 98 std::make_pair(".3gp", kVideoIdrs), 99 std::make_pair(".avi", kVideoIdrs), 100 std::make_pair(".m4v", kVideoIdrs), 101 std::make_pair(".mov", kVideoIdrs), 102 std::make_pair(".mp4", kVideoIdrs), 103 std::make_pair(".mpeg", kVideoIdrs), 104 std::make_pair(".mpg", kVideoIdrs), 105 std::make_pair(".mpeg4", kVideoIdrs), 106 std::make_pair(".mpg4", kVideoIdrs), 107#endif 108 std::make_pair(".flac", kAudioIdrs), 109 std::make_pair(".oga", kAudioIdrs), 110 std::make_pair(".ogg", kAudioIdrs), 111 std::make_pair(".wav", kAudioIdrs), 112 std::make_pair(".bmp", kImageIdrs), 113 std::make_pair(".gif", kImageIdrs), 114 std::make_pair(".ico", kImageIdrs), 115 std::make_pair(".jpeg", kImageIdrs), 116 std::make_pair(".jpg", kImageIdrs), 117 std::make_pair(".png", kImageIdrs), 118 std::make_pair(".webp", kImageIdrs), 119 std::make_pair(".ogm", kVideoIdrs), 120 std::make_pair(".ogv", kVideoIdrs), 121 std::make_pair(".ogx", kVideoIdrs), 122 std::make_pair(".webm", kVideoIdrs), 123 }; 124 125 const size_t kESize = arraysize(kExtensionIdrBySizeData); 126 ExtensionIconMap source(&kExtensionIdrBySizeData[0], 127 &kExtensionIdrBySizeData[kESize]); 128 extension_icon_map_.swap(source); 129} 130 131int IconMapper::Lookup(const std::string& extension, 132 IconLoader::IconSize icon_size) { 133 DCHECK(icon_size == IconLoader::SMALL || 134 icon_size == IconLoader::NORMAL || 135 icon_size == IconLoader::LARGE); 136 ExtensionIconMap::const_iterator it = extension_icon_map_.find(extension); 137 const IdrBySize& idrbysize = 138 ((it == extension_icon_map_.end()) ? kGenericIdrs : it->second); 139 int idr = -1; 140 switch (icon_size) { 141 case IconLoader::SMALL: idr = idrbysize.idr_small; break; 142 case IconLoader::NORMAL: idr = idrbysize.idr_normal; break; 143 case IconLoader::LARGE: idr = idrbysize.idr_large; break; 144 case IconLoader::ALL: 145 default: 146 NOTREACHED(); 147 } 148 return idr; 149} 150 151// Returns a copy of |source| that is |dip_size| in width and height. If 152// |dip_size| is |kDoNotResize|, returns an unmodified copy of |source|. 153// |source| must be a square image (width == height). 154gfx::ImageSkia ResizeImage(const gfx::ImageSkia& source, int dip_size) { 155 DCHECK(!source.isNull()); 156 DCHECK(source.width() == source.height()); 157 158 if (dip_size == kDoNotResize || source.width() == dip_size) 159 return source; 160 161 return gfx::ImageSkiaOperations::CreateResizedImage(source, 162 skia::ImageOperations::RESIZE_BEST, gfx::Size(dip_size, dip_size)); 163} 164 165int IconSizeToDIPSize(IconLoader::IconSize size) { 166 switch (size) { 167 case IconLoader::SMALL: return 16; 168 case IconLoader::NORMAL: return 32; 169 case IconLoader::LARGE: // fallthrough 170 // On ChromeOS, we consider LARGE to mean "the largest image we have." 171 // Since we have already chosen the largest applicable image resource, we 172 // return the image as-is. 173 case IconLoader::ALL: // fallthrough 174 default: 175 return kDoNotResize; 176 } 177} 178 179} // namespace 180 181// static 182IconGroupID IconLoader::ReadGroupIDFromFilepath( 183 const base::FilePath& filepath) { 184 return StringToLowerASCII(filepath.Extension()); 185} 186 187bool IconLoader::IsIconMutableFromFilepath(const base::FilePath&) { 188 return false; 189} 190 191void IconLoader::ReadIcon() { 192 static base::LazyInstance<IconMapper>::Leaky icon_mapper = 193 LAZY_INSTANCE_INITIALIZER; 194 int idr = icon_mapper.Get().Lookup(group_, icon_size_); 195 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 196 gfx::ImageSkia image_skia(ResizeImage(*(rb.GetImageNamed(idr)).ToImageSkia(), 197 IconSizeToDIPSize(icon_size_))); 198 image_skia.MakeThreadSafe(); 199 image_.reset(new gfx::Image(image_skia)); 200 target_message_loop_->PostTask( 201 FROM_HERE, base::Bind(&IconLoader::NotifyDelegate, this)); 202} 203