blob: 692360fa91d39b5ede3b65cfee16d28f8102c8b1 [file] [log] [blame]
[email protected]25cc7502012-01-31 19:33:551// 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"
[email protected]bc0147b2013-04-03 20:50:5912#include "base/files/file_path.h"
[email protected]25cc7502012-01-31 19:33:5513#include "base/lazy_instance.h"
[email protected]90fa2652012-04-24 16:18:3514#include "base/memory/ref_counted_memory.h"
[email protected]467a106e2013-07-18 12:07:1915#include "base/message_loop/message_loop.h"
[email protected]9c7ddc92013-06-11 01:40:5716#include "base/strings/string_util.h"
[email protected]25cc7502012-01-31 19:33:5517#include "chrome/browser/icon_loader.h"
[email protected]b07e606e2012-09-15 20:16:1518#include "grit/theme_resources.h"
[email protected]25cc7502012-01-31 19:33:5519#include "third_party/skia/include/core/SkBitmap.h"
[email protected]c49201a2012-05-24 11:04:5720#include "ui/base/layout.h"
[email protected]25cc7502012-01-31 19:33:5521#include "ui/base/resource/resource_bundle.h"
[email protected]a7db88142012-03-14 14:43:0922#include "ui/gfx/canvas.h"
[email protected]25cc7502012-01-31 19:33:5523#include "ui/gfx/codec/png_codec.h"
24#include "ui/gfx/image/image.h"
[email protected]2b8ac342012-08-29 03:46:2725#include "ui/gfx/image/image_skia.h"
[email protected]679facce2012-07-25 16:13:1226#include "ui/gfx/image/image_skia_operations.h"
[email protected]25cc7502012-01-31 19:33:5527
28namespace {
29
[email protected]679facce2012-07-25 16:13:1230// Used with GenerateImageWithSize() to indicate that the image shouldn't be
[email protected]25cc7502012-01-31 19:33:5531// 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};
[email protected]25cc7502012-01-31 19:33:5566const IdrBySize kImageIdrs = {
67 IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE,
68 IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE,
69 IDR_FILE_MANAGER_IMG_FILETYPE_IMAGE
70};
[email protected]dfe8987d72013-10-19 16:20:5871#if defined(USE_PROPRIETARY_CODECS)
[email protected]25cc7502012-01-31 19:33:5572const IdrBySize kPdfIdrs = {
73 IDR_FILE_MANAGER_IMG_FILETYPE_PDF,
74 IDR_FILE_MANAGER_IMG_FILETYPE_PDF,
75 IDR_FILE_MANAGER_IMG_FILETYPE_PDF
76};
[email protected]dfe8987d72013-10-19 16:20:5877#endif
[email protected]25cc7502012-01-31 19:33:5578const IdrBySize kVideoIdrs = {
79 IDR_FILE_MANAGER_IMG_FILETYPE_VIDEO,
80 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO,
81 IDR_FILE_MANAGER_IMG_FILETYPE_LARGE_VIDEO
82};
83
84IconMapper::IconMapper() {
85 // The code below should match translation in
86 // chrome/browser/resources/file_manager/js/file_manager.js
87 // chrome/browser/resources/file_manager/css/file_manager.css
88 // 'audio': /\.(mp3|m4a|oga|ogg|wav)$/i,
89 // 'html': /\.(html?)$/i,
90 // 'image': /\.(bmp|gif|jpe?g|ico|png|webp)$/i,
91 // 'pdf' : /\.(pdf)$/i,
92 // 'text': /\.(pod|rst|txt|log)$/i,
93 // 'video': /\.(mov|mp4|m4v|mpe?g4?|ogm|ogv|ogx|webm)$/i
94
95 const ExtensionIconMap::value_type kExtensionIdrBySizeData[] = {
[email protected]0d841b7d2013-08-20 20:22:2296#if defined(USE_PROPRIETARY_CODECS)
[email protected]25cc7502012-01-31 19:33:5597 std::make_pair(".m4a", kAudioIdrs),
98 std::make_pair(".mp3", kAudioIdrs),
99 std::make_pair(".pdf", kPdfIdrs),
100 std::make_pair(".3gp", kVideoIdrs),
101 std::make_pair(".avi", kVideoIdrs),
102 std::make_pair(".m4v", kVideoIdrs),
103 std::make_pair(".mov", kVideoIdrs),
104 std::make_pair(".mp4", kVideoIdrs),
105 std::make_pair(".mpeg", kVideoIdrs),
106 std::make_pair(".mpg", kVideoIdrs),
107 std::make_pair(".mpeg4", kVideoIdrs),
108 std::make_pair(".mpg4", kVideoIdrs),
109#endif
110 std::make_pair(".flac", kAudioIdrs),
111 std::make_pair(".oga", kAudioIdrs),
112 std::make_pair(".ogg", kAudioIdrs),
113 std::make_pair(".wav", kAudioIdrs),
[email protected]25cc7502012-01-31 19:33:55114 std::make_pair(".bmp", kImageIdrs),
115 std::make_pair(".gif", kImageIdrs),
116 std::make_pair(".ico", kImageIdrs),
117 std::make_pair(".jpeg", kImageIdrs),
118 std::make_pair(".jpg", kImageIdrs),
119 std::make_pair(".png", kImageIdrs),
120 std::make_pair(".webp", kImageIdrs),
[email protected]25cc7502012-01-31 19:33:55121 std::make_pair(".ogm", kVideoIdrs),
122 std::make_pair(".ogv", kVideoIdrs),
123 std::make_pair(".ogx", kVideoIdrs),
124 std::make_pair(".webm", kVideoIdrs),
125 };
126
127 const size_t kESize = arraysize(kExtensionIdrBySizeData);
128 ExtensionIconMap source(&kExtensionIdrBySizeData[0],
129 &kExtensionIdrBySizeData[kESize]);
130 extension_icon_map_.swap(source);
131}
132
133int IconMapper::Lookup(const std::string& extension,
134 IconLoader::IconSize icon_size) {
135 DCHECK(icon_size == IconLoader::SMALL ||
136 icon_size == IconLoader::NORMAL ||
137 icon_size == IconLoader::LARGE);
138 ExtensionIconMap::const_iterator it = extension_icon_map_.find(extension);
139 const IdrBySize& idrbysize =
140 ((it == extension_icon_map_.end()) ? kGenericIdrs : it->second);
141 int idr = -1;
142 switch (icon_size) {
143 case IconLoader::SMALL: idr = idrbysize.idr_small; break;
144 case IconLoader::NORMAL: idr = idrbysize.idr_normal; break;
145 case IconLoader::LARGE: idr = idrbysize.idr_large; break;
146 case IconLoader::ALL:
147 default:
148 NOTREACHED();
149 }
150 return idr;
151}
152
[email protected]679facce2012-07-25 16:13:12153// Returns a copy of |source| that is |dip_size| in width and height. If
154// |dip_size| is |kDoNotResize|, returns an unmodified copy of |source|.
[email protected]25cc7502012-01-31 19:33:55155// |source| must be a square image (width == height).
[email protected]679facce2012-07-25 16:13:12156gfx::ImageSkia ResizeImage(const gfx::ImageSkia& source, int dip_size) {
[email protected]93079e02012-05-15 15:42:59157 DCHECK(!source.isNull());
158 DCHECK(source.width() == source.height());
[email protected]25cc7502012-01-31 19:33:55159
[email protected]679facce2012-07-25 16:13:12160 if (dip_size == kDoNotResize || source.width() == dip_size)
[email protected]93079e02012-05-15 15:42:59161 return source;
[email protected]25cc7502012-01-31 19:33:55162
[email protected]679facce2012-07-25 16:13:12163 return gfx::ImageSkiaOperations::CreateResizedImage(source,
[email protected]3a49e502012-08-16 21:24:41164 skia::ImageOperations::RESIZE_BEST, gfx::Size(dip_size, dip_size));
[email protected]25cc7502012-01-31 19:33:55165}
166
[email protected]679facce2012-07-25 16:13:12167int IconSizeToDIPSize(IconLoader::IconSize size) {
[email protected]25cc7502012-01-31 19:33:55168 switch (size) {
169 case IconLoader::SMALL: return 16;
170 case IconLoader::NORMAL: return 32;
171 case IconLoader::LARGE: // fallthrough
172 // On ChromeOS, we consider LARGE to mean "the largest image we have."
173 // Since we have already chosen the largest applicable image resource, we
174 // return the image as-is.
175 case IconLoader::ALL: // fallthrough
176 default:
177 return kDoNotResize;
178 }
179}
180
181} // namespace
182
[email protected]bc0147b2013-04-03 20:50:59183// static
184IconGroupID IconLoader::ReadGroupIDFromFilepath(
185 const base::FilePath& filepath) {
186 return StringToLowerASCII(filepath.Extension());
187}
188
[email protected]b3b6a372014-03-12 01:48:04189// static
[email protected]681b4b82013-04-09 23:34:21190bool IconLoader::IsIconMutableFromFilepath(const base::FilePath&) {
191 return false;
192}
193
[email protected]b3b6a372014-03-12 01:48:04194// static
195content::BrowserThread::ID IconLoader::ReadIconThreadID() {
196 return content::BrowserThread::FILE;
197}
198
[email protected]25cc7502012-01-31 19:33:55199void IconLoader::ReadIcon() {
200 static base::LazyInstance<IconMapper>::Leaky icon_mapper =
201 LAZY_INSTANCE_INITIALIZER;
202 int idr = icon_mapper.Get().Lookup(group_, icon_size_);
203 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
[email protected]2b8ac342012-08-29 03:46:27204 gfx::ImageSkia image_skia(ResizeImage(*(rb.GetImageNamed(idr)).ToImageSkia(),
205 IconSizeToDIPSize(icon_size_)));
206 image_skia.MakeThreadSafe();
207 image_.reset(new gfx::Image(image_skia));
[email protected]25cc7502012-01-31 19:33:55208 target_message_loop_->PostTask(
209 FROM_HERE, base::Bind(&IconLoader::NotifyDelegate, this));
210}