diff options
author | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-24 23:06:19 +0000 |
---|---|---|
committer | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-08-24 23:06:19 +0000 |
commit | 7624dc623e076ad374d3fe259d98ad1525de0a0d (patch) | |
tree | 9863983099cb48145aa319787d7a9928aca1e3c6 | |
parent | a7a702c1b5283d4fad6ca02bcbcfaf13009b978e (diff) | |
download | chromium_src-7624dc623e076ad374d3fe259d98ad1525de0a0d.zip chromium_src-7624dc623e076ad374d3fe259d98ad1525de0a0d.tar.gz chromium_src-7624dc623e076ad374d3fe259d98ad1525de0a0d.tar.bz2 |
Cache images on theme install so startup does no image processing.
BUG= http://crbug.com/18768
TEST= none
Review URL: http://codereview.chromium.org/174085
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@24170 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/browser_theme_provider.cc | 219 | ||||
-rw-r--r-- | chrome/browser/browser_theme_provider.h | 24 | ||||
-rw-r--r-- | chrome/common/chrome_constants.cc | 1 | ||||
-rw-r--r-- | chrome/common/chrome_constants.h | 1 | ||||
-rw-r--r-- | chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate | 13 |
5 files changed, 200 insertions, 58 deletions
diff --git a/chrome/browser/browser_theme_provider.cc b/chrome/browser/browser_theme_provider.cc index f9aa52b..6021712 100644 --- a/chrome/browser/browser_theme_provider.cc +++ b/chrome/browser/browser_theme_provider.cc @@ -4,7 +4,9 @@ #include "chrome/browser/browser_theme_provider.h" +#include "base/file_util.h" #include "base/gfx/png_decoder.h" +#include "base/gfx/png_encoder.h" #include "base/string_util.h" #include "base/values.h" #include "chrome/browser/browser_list.h" @@ -12,6 +14,7 @@ #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" #include "chrome/browser/theme_resources_util.h" +#include "chrome/common/chrome_constants.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" @@ -185,6 +188,35 @@ static std::map<const int, bool> themeable_images_; // A map of frame image IDs to the tints for those ids. static std::map<const int, int> frame_tints_; +void BrowserThemeProvider::WriteImagesToDisk() { + // TODO(mirandac): move this to a different thread. + BrowserThemeProvider::ImageSaveCache::iterator iter; + for (iter = image_save_cache_.begin(); iter != image_save_cache_.end(); + iter++) { + FilePath image_path = (*iter).first; + if ((*iter).second != NULL) { + SkBitmap* bitmap = (*iter).second; + + std::vector<unsigned char> image_data; + if (!PNGEncoder::EncodeBGRASkBitmap(*bitmap, false, &image_data)) { + NOTREACHED() << "Image file could not be encoded."; + return; + } + + const char* image_data_ptr = + reinterpret_cast<const char*>(&image_data[0]); + if (!file_util::WriteFile(image_path, + image_data_ptr, image_data.size())) { + NOTREACHED() << "Image file could not be written to disk."; + return; + } + } else { + NOTREACHED(); + return; + } + } +} + BrowserThemeProvider::BrowserThemeProvider() : rb_(ResourceBundle::GetSharedInstance()) { static bool initialized = false; @@ -202,6 +234,15 @@ BrowserThemeProvider::BrowserThemeProvider() frame_tints_[IDR_THEME_FRAME_INCOGNITO] = TINT_FRAME_INCOGNITO; frame_tints_[IDR_THEME_FRAME_INCOGNITO_INACTIVE] = TINT_FRAME_INCOGNITO_INACTIVE; + + resource_names_[IDR_THEME_FRAME] = "theme_frame"; + resource_names_[IDR_THEME_FRAME_INACTIVE] = "theme_frame_inactive"; + resource_names_[IDR_THEME_FRAME_OVERLAY] = "theme_frame_overlay"; + resource_names_[IDR_THEME_FRAME_OVERLAY_INACTIVE] = + "theme_frame_overlay_inactive"; + resource_names_[IDR_THEME_FRAME_INCOGNITO] = "theme_frame_incognito"; + resource_names_[IDR_THEME_FRAME_INCOGNITO_INACTIVE] = + "theme_frame_incognito_inactive"; } } @@ -212,6 +253,12 @@ BrowserThemeProvider::~BrowserThemeProvider() { void BrowserThemeProvider::Init(Profile* profile) { DCHECK(CalledOnValidThread()); profile_ = profile; + + image_dir_ = profile_->GetPath().AppendASCII( + WideToASCII(chrome::kThemeImagesDirname)); + if (!file_util::PathExists(image_dir_)) + file_util::CreateDirectory(image_dir_); + LoadThemePrefs(); } @@ -234,11 +281,6 @@ SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) { // Try to load the image from the extension. result.reset(LoadThemeBitmap(id)); - // If the extension doesn't provide the requested image, but has provided - // a custom frame, then we may be able to generate the image required. - if (!result.get()) - result.reset(GenerateBitmap(id)); - // If we still don't have an image, load it from resourcebundle. if (!result.get()) result.reset(new SkBitmap(*rb_.GetBitmapNamed(id))); @@ -450,9 +492,13 @@ void BrowserThemeProvider::SetTheme(Extension* extension) { SaveDisplayPropertyData(); SaveThemeID(extension->id()); + // Process all images when we first set theme. + process_images_ = true; + GenerateFrameColors(); GenerateFrameImages(); GenerateTabImages(); + WriteImagesToDisk(); NotifyThemeChanged(); UserMetrics::RecordAction(L"Themes_Installed", profile_); @@ -529,6 +575,30 @@ SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) { } } +void BrowserThemeProvider::SaveThemeBitmap( + const std::string resource_name, int id) { + DCHECK(CalledOnValidThread()); + if (!image_cache_[id]) { + NOTREACHED(); + return; + } + +#if defined(OS_WIN) + FilePath image_path = image_dir_.Append(FilePath(UTF8ToWide(resource_name))); +#elif defined(OS_POSIX) + FilePath image_path = image_dir_.Append(FilePath(resource_name)); +#endif + + DictionaryValue* pref_images = + profile_->GetPrefs()->GetMutableDictionary(prefs::kCurrentThemeImages); + // TODO(mirandac): remove ToWStringHack from this class. + pref_images->SetString(UTF8ToWide(resource_name), + WideToUTF8(image_path.ToWStringHack())); + image_save_cache_[image_path] = image_cache_[id]; +} + + + const std::string BrowserThemeProvider::GetTintKey(int id) { switch (id) { case TINT_FRAME: @@ -599,6 +669,7 @@ void BrowserThemeProvider::SetImageData(DictionaryValue* images_value, if (!images_path.empty()) { images_[id] = WideToUTF8(images_path.AppendASCII(val) .ToWStringHack()); + resource_names_[id] = WideToASCII(*iter); } else { images_[id] = val; } @@ -813,35 +884,57 @@ void BrowserThemeProvider::GenerateFrameImages() { // the default provided frame. If that's not provided, skip this whole // thing and just use the default images. int base_id; - if (id == IDR_THEME_FRAME_INCOGNITO_INACTIVE) - base_id = (HasCustomImage(IDR_THEME_FRAME_INCOGNITO)) ? - IDR_THEME_FRAME_INCOGNITO : - IDR_THEME_FRAME; - else if (id == IDR_THEME_FRAME_OVERLAY_INACTIVE) - base_id = IDR_THEME_FRAME_OVERLAY; - else if (id == IDR_THEME_FRAME_INACTIVE) - base_id = IDR_THEME_FRAME; - else if (id == IDR_THEME_FRAME_INCOGNITO && - !HasCustomImage(IDR_THEME_FRAME_INCOGNITO)) - base_id = IDR_THEME_FRAME; - else - base_id = id; - - if (HasCustomImage(id)) { + std::string resource_name; + + // If we've already processed the images for this theme, they're all + // waiting on disk -- just load them in. + if (!process_images_) { frame.reset(LoadThemeBitmap(id)); - } else if (base_id != id && HasCustomImage(base_id)) { - frame.reset(LoadThemeBitmap(base_id)); + if (frame.get()) + image_cache_[id] = new SkBitmap(*frame.get()); } else { - // If the theme doesn't specify an image, then apply the tint to - // the default frame. Note that the default theme provides default - // bitmaps for all frame types, so this isn't strictly necessary - // in the case where no tint is provided either. - frame.reset(new SkBitmap(*rb_.GetBitmapNamed(IDR_THEME_FRAME))); - } + if (id == IDR_THEME_FRAME_INCOGNITO_INACTIVE) { + resource_name = "theme_frame_incognito_inactive"; + base_id = HasCustomImage(IDR_THEME_FRAME_INCOGNITO) ? + IDR_THEME_FRAME_INCOGNITO : IDR_THEME_FRAME; + } else if (id == IDR_THEME_FRAME_OVERLAY_INACTIVE) { + base_id = IDR_THEME_FRAME_OVERLAY; + resource_name = "theme_frame_overlay_inactive"; + } else if (id == IDR_THEME_FRAME_INACTIVE) { + base_id = IDR_THEME_FRAME; + resource_name = "theme_frame_inactive"; + } else if (id == IDR_THEME_FRAME_INCOGNITO && + !HasCustomImage(IDR_THEME_FRAME_INCOGNITO)) { + base_id = IDR_THEME_FRAME; + resource_name = "theme_frame_incognito"; + } else { + base_id = id; + resource_name = resource_names_[id]; + } + + if (HasCustomImage(id)) { + frame.reset(LoadThemeBitmap(id)); + } else if (base_id != id && HasCustomImage(base_id)) { + frame.reset(LoadThemeBitmap(base_id)); + } else if (base_id == IDR_THEME_FRAME_OVERLAY && + HasCustomImage(IDR_THEME_FRAME)) { + // If there is no theme overlay, don't tint the default frame, + // because it will overwrite the custom frame image when we cache and + // reload from disk. + frame.reset(NULL); + } else { + // If the theme doesn't specify an image, then apply the tint to + // the default frame. Note that the default theme provides default + // bitmaps for all frame types, so this isn't strictly necessary + // in the case where no tint is provided either. + frame.reset(new SkBitmap(*rb_.GetBitmapNamed(IDR_THEME_FRAME))); + } - if (frame.get()) { - SkBitmap* tinted = new SkBitmap(TintBitmap(*frame, iter->second)); - image_cache_[id] = tinted; + if (frame.get()) { + SkBitmap* tinted = new SkBitmap(TintBitmap(*frame, iter->second)); + image_cache_[id] = tinted; + SaveThemeBitmap(resource_name, id); + } } ++iter; } @@ -876,32 +969,46 @@ SkBitmap* BrowserThemeProvider::GenerateBitmap(int id) { // tab against. As themes don't use the glass frame, we don't have to // worry about compositing them together, as our default theme provides // the necessary bitmaps. - int base_id = (id == IDR_THEME_TAB_BACKGROUND) ? - IDR_THEME_FRAME : IDR_THEME_FRAME_INCOGNITO; - - std::map<int, SkBitmap*>::iterator it = image_cache_.find(base_id); - if (it != image_cache_.end()) { - SkBitmap* frame = it->second; - int blur_amount = (HasCustomImage(id)) ? 1 : 2; - SkBitmap blurred = + if (!process_images_) { + scoped_ptr<SkBitmap> frame; + frame.reset(LoadThemeBitmap(id)); + if (frame.get()) + image_cache_[id] = new SkBitmap(*frame.get()); + } else { + int base_id; + std::string resource_name; + if (id == IDR_THEME_TAB_BACKGROUND) { + base_id = IDR_THEME_FRAME; + resource_name = "theme_tab_background"; + } else { + base_id = IDR_THEME_FRAME_INCOGNITO; + resource_name = "theme_tab_background_incognito"; + } + std::map<int, SkBitmap*>::iterator it = image_cache_.find(base_id); + if (it != image_cache_.end()) { + SkBitmap* frame = it->second; + int blur_amount = HasCustomImage(id) ? 1 : 2; + SkBitmap blurred = skia::ImageOperations::CreateBlurredBitmap(*frame, blur_amount); - SkBitmap* bg_tab = new SkBitmap(TintBitmap(blurred, TINT_BACKGROUND_TAB)); - - // If they've provided a custom image, overlay it. - if (HasCustomImage(id)) { - SkBitmap* overlay = LoadThemeBitmap(id); - if (overlay) { - SkCanvas canvas(*bg_tab); - for (int x = 0; x < bg_tab->width(); x += overlay->width()) - canvas.drawBitmap(*overlay, static_cast<SkScalar>(x), 0, NULL); + SkBitmap* bg_tab = new SkBitmap(TintBitmap(blurred, + TINT_BACKGROUND_TAB)); + + // If they've provided a custom image, overlay it. + if (HasCustomImage(id)) { + SkBitmap* overlay = LoadThemeBitmap(id); + if (overlay) { + SkCanvas canvas(*bg_tab); + for (int x = 0; x < bg_tab->width(); x += overlay->width()) + canvas.drawBitmap(*overlay, static_cast<SkScalar>(x), 0, NULL); + } } - } - image_cache_[id] = bg_tab; - return bg_tab; + image_cache_[id] = bg_tab; + SaveThemeBitmap(resource_name, id); + return bg_tab; + } } } - return NULL; } @@ -1009,6 +1116,9 @@ void BrowserThemeProvider::NotifyThemeChanged() { } void BrowserThemeProvider::LoadThemePrefs() { + // Images were already processed when theme was set. + process_images_ = false; + PrefService* prefs = profile_->GetPrefs(); // TODO(glen): Figure out if any custom prefs were loaded, and if so @@ -1038,6 +1148,11 @@ void BrowserThemeProvider::ClearCaches() { delete i->second; } image_cache_.clear(); + + // The SkBitmaps in the image_save_cache_ are a subset of those stored in + // the image_cache_, and have therefore all been deleted in the lines above. + // TODO(mirandac): make memory management clearer here. + image_save_cache_.clear(); } #if defined(TOOLKIT_VIEWS) diff --git a/chrome/browser/browser_theme_provider.h b/chrome/browser/browser_theme_provider.h index 0b4eecb..6d81937 100644 --- a/chrome/browser/browser_theme_provider.h +++ b/chrome/browser/browser_theme_provider.h @@ -211,7 +211,8 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>, void GenerateFrameColors(); // Generate any frame images that weren't specified. The resulting images - // will be stored in our cache. + // will be stored in our cache and written to disk. If images have already + // been generated and cached, load them from disk. void GenerateFrameImages(); // Generate any tab images that weren't specified. The resulting images @@ -231,6 +232,9 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>, // otherwise modified, or an application default. virtual SkBitmap* LoadThemeBitmap(int id); + // Save the modified bitmap at image_cache_[id]. + virtual void SaveThemeBitmap(const std::string resource_name, int id); + Profile* profile() { return profile_; } private: @@ -239,6 +243,7 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>, typedef std::map<const std::string, skia::HSL> TintMap; typedef std::map<const std::string, int> DisplayPropertyMap; typedef std::map<const int, std::vector<unsigned char> > RawDataMap; + typedef std::map<const int, std::string> ResourceNameMap; // Returns the string key for the given tint |id| TINT_* enum value. const std::string GetTintKey(int id); @@ -300,6 +305,9 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>, // from ClearCaches(). void FreePlatformCaches(); + // Encode image at image_cache_[id] as PNG and write to disk. + void WriteImagesToDisk(); + #if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) // Loads an image and flips it horizontally if |rtl_enabled| is true. GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled); @@ -320,6 +328,11 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>, NSColorMap nscolor_cache_; #endif + // We save here the images to be written to disk, along with the file paths + // where they are to be written. + typedef std::map<FilePath, SkBitmap*> ImageSaveCache; + ImageSaveCache image_save_cache_; + ResourceBundle& rb_; Profile* profile_; @@ -329,6 +342,15 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>, RawDataMap raw_data_; DisplayPropertyMap display_properties_; + // Reverse of theme_resources_map, so we can cache images properly. + ResourceNameMap resource_names_; + + // If true, process all images; if false, just load from disk. + bool process_images_; + + // Where we will store our generated images. + FilePath image_dir_; + DISALLOW_COPY_AND_ASSIGN(BrowserThemeProvider); }; diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index 7f11c88..6e578c5 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc @@ -65,6 +65,7 @@ const FilePath::CharType kMediaCacheDirname[] = FPL("Media Cache"); const FilePath::CharType kOffTheRecordMediaCacheDirname[] = FPL("Incognito Media Cache"); const wchar_t kChromePluginDataDirname[] = L"Plugin Data"; +const wchar_t kThemeImagesDirname[] = L"Cached Theme Images"; const FilePath::CharType kCookieFilename[] = FPL("Cookies"); const FilePath::CharType kExtensionsCookieFilename[] = FPL("Extension Cookies"); const FilePath::CharType kHistoryFilename[] = FPL("History"); diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 516b7c89..9e76426 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h @@ -31,6 +31,7 @@ extern const FilePath::CharType kCacheDirname[]; extern const FilePath::CharType kMediaCacheDirname[]; extern const FilePath::CharType kOffTheRecordMediaCacheDirname[]; extern const wchar_t kChromePluginDataDirname[]; +extern const wchar_t kThemeImagesDirname[]; extern const FilePath::CharType kCookieFilename[]; extern const FilePath::CharType kExtensionsCookieFilename[]; extern const FilePath::CharType kHistoryFilename[]; diff --git a/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate b/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate index 227f142..0297245 100644 --- a/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate +++ b/chrome/test/data/profiles/complex_theme/Default/PreferencesTemplate @@ -18,9 +18,6 @@ "colors": { "bookmark_text": [ 0, 0, 0 ], "frame": [ 57, 137, 194 ], - "frame_inactive": [ 155, 196, 224 ], - "frame_incognito": [ 68, 90, 106 ], - "frame_incognito_inactive": [ 118, 156, 183 ], "ntp_background": [ 57, 137, 194 ], "ntp_link": [ 0, 0, 0 ], "ntp_section": [ 131, 138, 146, 0.8 ], @@ -34,9 +31,15 @@ "id": "mblmlcbknbnfebdfjnolmcapmdofhmme", "images": { "theme_button_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYwsgCDA", - "theme_frame": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYw8gCDA", + "theme_frame": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame", + "theme_frame_inactive": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_inactive", + "theme_frame_incognito": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_incognito", + "theme_frame_incognito_inactive": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_incognito_inactive", + "theme_frame_overlay": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_overlay", + "theme_frame_overlay_inactive": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_frame_overlay_inactive", "theme_ntp_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYj9gCDA", - "theme_tab_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUY_c8CDA", + "theme_tab_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_tab_background", + "theme_tab_background_incognito": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/theme_tab_background_incognito", "theme_toolbar": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYnMgCDA", "theme_window_control_background": "$1/Default/Extensions/mblmlcbknbnfebdfjnolmcapmdofhmme/1.1/i/agxjaHJvbWV0aGVtZXNyDAsSBEZpbGUYjNgCDA" }, |