From 1279d5f395182c6fa783da0d85216777d931af6b Mon Sep 17 00:00:00 2001 From: "avi@chromium.org" Date: Mon, 22 Jun 2009 18:34:10 +0000 Subject: Theme image support for the Mac. BUG=none TEST=none Review URL: http://codereview.chromium.org/140007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18925 0039d316-1c4b-4281-b951-d872f2087c98 --- app/app.gyp | 1 + app/theme_provider.cc | 12 +++++ app/theme_provider.h | 18 ++++++- chrome/browser/browser_theme_provider.cc | 77 +++++++++++++++------------- chrome/browser/browser_theme_provider.h | 21 +++++--- chrome/browser/browser_theme_provider_gtk.cc | 11 ++++ chrome/browser/browser_theme_provider_mac.mm | 50 ++++++++++++++++++ chrome/chrome.gyp | 1 + 8 files changed, 147 insertions(+), 44 deletions(-) create mode 100644 app/theme_provider.cc create mode 100644 chrome/browser/browser_theme_provider_mac.mm diff --git a/app/app.gyp b/app/app.gyp index e316d41d..faced76 100644 --- a/app/app.gyp +++ b/app/app.gyp @@ -101,6 +101,7 @@ 'resource_bundle_mac.mm', 'slide_animation.cc', 'slide_animation.h', + 'theme_provider.cc', 'theme_provider.h', 'throb_animation.cc', 'throb_animation.h', diff --git a/app/theme_provider.cc b/app/theme_provider.cc new file mode 100644 index 0000000..7593e15 --- /dev/null +++ b/app/theme_provider.cc @@ -0,0 +1,12 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "app/theme_provider.h" + +// We have the destructor here because GCC puts the vtable in the first file +// that includes a virtual function of the class. Leaving it just in the .h file +// means that GCC will fail to link. + +ThemeProvider::~ThemeProvider() { +} diff --git a/app/theme_provider.h b/app/theme_provider.h index 774810e..75e9255 100644 --- a/app/theme_provider.h +++ b/app/theme_provider.h @@ -10,7 +10,13 @@ #if defined(OS_LINUX) #include -#endif +#elif defined(OS_MACOSX) +#ifdef __OBJC__ +@class NSImage; +#else +class NSImage; +#endif // __OBJC__ +#endif // OS_* class SkBitmap; @@ -25,7 +31,7 @@ class SkBitmap; class ThemeProvider { public: - virtual ~ThemeProvider() { } + virtual ~ThemeProvider(); // Get the bitmap specified by |id|. An implementation of ThemeProvider should // have its own source of ids (e.g. an enum, or external resource bundle). @@ -56,6 +62,14 @@ class ThemeProvider { // pointer to a shared empty placeholder bitmap so it will be visible what // is missing. virtual GdkPixbuf* GetPixbufNamed(int id) = 0; +#elif defined(OS_MACOSX) + // Gets the NSImage with the specified |id|. Returns a pointer to a shared + // instance of the NSImage. This shared NSImage is owned by the theme + // provider and should not be freed. + // + // The bitmap is not assumed to exist. If a theme does not provide an image, + // this function will return nil. + virtual NSImage* GetNSImageNamed(int id) = 0; #endif }; diff --git a/chrome/browser/browser_theme_provider.cc b/chrome/browser/browser_theme_provider.cc index 6307c86..03b8575 100644 --- a/chrome/browser/browser_theme_provider.cc +++ b/chrome/browser/browser_theme_provider.cc @@ -136,14 +136,6 @@ BrowserThemeProvider::BrowserThemeProvider() BrowserThemeProvider::~BrowserThemeProvider() { FreeImages(); -#if defined(OS_LINUX) - // Free GdkPixbufs. - for (GdkPixbufMap::iterator i = gdk_pixbufs_.begin(); - i != gdk_pixbufs_.end(); i++) { - g_object_unref(i->second); - } - gdk_pixbufs_.clear(); -#endif } void BrowserThemeProvider::Init(Profile* profile) { @@ -311,10 +303,8 @@ void BrowserThemeProvider::UseDefaultTheme() { UserMetrics::RecordAction(L"Themes_Reset", profile_); } -SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) { - DCHECK(CalledOnValidThread()); - // Attempt to find the image in our theme bundle. - std::vector raw_data, png_data; +bool BrowserThemeProvider::ReadThemeFileData( + int id, std::vector* raw_data) { if (images_.count(id)) { // First check to see if we have a registered theme extension and whether // it can handle this resource. @@ -330,35 +320,43 @@ SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) { int64 avail = file.Available(); if (avail > 0 && avail < INT_MAX) { size_t size = static_cast(avail); - raw_data.resize(size); - char* data = reinterpret_cast(&(raw_data.front())); - if (file.ReadUntilComplete(data, size) == avail) { - // Decode the PNG. - int image_width = 0; - int image_height = 0; - - if (!PNGDecoder::Decode(&raw_data.front(), raw_data.size(), - PNGDecoder::FORMAT_BGRA, &png_data, - &image_width, &image_height)) { - NOTREACHED() << "Unable to decode theme image resource " << id; - return NULL; - } - - return PNGDecoder::CreateSkBitmapFromBGRAFormat(png_data, - image_width, - image_height); - } + raw_data->resize(size); + char* data = reinterpret_cast(&(raw_data->front())); + if (file.ReadUntilComplete(data, size) == avail) + return true; } - } else { - // TODO(glen): File no-longer exists, we're out of date. We should - // clear the theme (or maybe just the pref that points to this - // image). - return NULL; } } } - return NULL; + return false; +} + +SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) { + DCHECK(CalledOnValidThread()); + // Attempt to find the image in our theme bundle. + std::vector raw_data, png_data; + if (ReadThemeFileData(id, &raw_data)) { + // Decode the PNG. + int image_width = 0; + int image_height = 0; + + if (!PNGDecoder::Decode(&raw_data.front(), raw_data.size(), + PNGDecoder::FORMAT_BGRA, &png_data, + &image_width, &image_height)) { + NOTREACHED() << "Unable to decode theme image resource " << id; + return NULL; + } + + return PNGDecoder::CreateSkBitmapFromBGRAFormat(png_data, + image_width, + image_height); + } else { + // TODO(glen): File no-longer exists, we're out of date. We should + // clear the theme (or maybe just the pref that points to this + // image). + return NULL; + } } skia::HSL BrowserThemeProvider::GetTint(int id) { @@ -732,6 +730,7 @@ SkColor BrowserThemeProvider::FindColor(const char* id, } void BrowserThemeProvider::FreeImages() { + FreePlatformImages(); for (std::vector::iterator i = generated_images_.begin(); i != generated_images_.end(); i++) { delete *i; @@ -739,3 +738,9 @@ void BrowserThemeProvider::FreeImages() { generated_images_.clear(); image_cache_.clear(); } + +#if defined(OS_WIN) +void BrowserThemeProvider::FreePlatformImages() { + // Windows has no platform image cache to clear. +} +#endif diff --git a/chrome/browser/browser_theme_provider.h b/chrome/browser/browser_theme_provider.h index 9883c67..b5817a2 100644 --- a/chrome/browser/browser_theme_provider.h +++ b/chrome/browser/browser_theme_provider.h @@ -16,10 +16,6 @@ #include "base/ref_counted.h" #include "skia/ext/skia_utils.h" -#if defined(OS_LINUX) -#include -#endif - class Extension; class Profile; class DictionaryValue; @@ -74,8 +70,10 @@ class BrowserThemeProvider : public base::RefCounted, virtual bool GetDisplayProperty(int id, int* result); virtual bool ShouldUseNativeFrame(); virtual bool HasCustomImage(int id); -#if defined(OS_LINUX) +#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) virtual GdkPixbuf* GetPixbufNamed(int id); +#elif defined(OS_MACOSX) + virtual NSImage* GetNSImageNamed(int id); #endif // Set the current theme to the theme defined in |extension|. @@ -98,6 +96,10 @@ class BrowserThemeProvider : public base::RefCounted, typedef std::map TintMap; typedef std::map DisplayPropertyMap; + // Reads the image data from the theme file into the specified vector. Returns + // true on success. + bool ReadThemeFileData(int id, std::vector* raw_data); + // Loads a bitmap from the theme, which may be tinted or // otherwise modified, or an application default. SkBitmap* LoadThemeBitmap(int id); @@ -158,13 +160,20 @@ class BrowserThemeProvider : public base::RefCounted, // Frees generated images and clears the image cache. void FreeImages(); + // Clears the platform-specific image cache. Do not call directly; it's called + // from FreeImages(). + void FreePlatformImages(); + // Cached images. We cache all retrieved and generated bitmaps and keep // track of the pointers. typedef std::map ImageCache; ImageCache image_cache_; -#if defined(OS_LINUX) +#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS) typedef std::map GdkPixbufMap; GdkPixbufMap gdk_pixbufs_; +#elif defined(OS_MACOSX) + typedef std::map NSImageMap; + NSImageMap nsimage_cache_; #endif // List of generate images that aren't stored in ResourceBundles image cache diff --git a/chrome/browser/browser_theme_provider_gtk.cc b/chrome/browser/browser_theme_provider_gtk.cc index 84ad293..370e773 100644 --- a/chrome/browser/browser_theme_provider_gtk.cc +++ b/chrome/browser/browser_theme_provider_gtk.cc @@ -40,3 +40,14 @@ GdkPixbuf* BrowserThemeProvider::GetPixbufNamed(int id) { } return empty_bitmap; } + +void BrowserThemeProvider::FreePlatformImages() { + DCHECK(CalledOnValidThread()); + + // Free GdkPixbufs. + for (GdkPixbufMap::iterator i = gdk_pixbufs_.begin(); + i != gdk_pixbufs_.end(); i++) { + g_object_unref(i->second); + } + gdk_pixbufs_.clear(); +} diff --git a/chrome/browser/browser_theme_provider_mac.mm b/chrome/browser/browser_theme_provider_mac.mm new file mode 100644 index 0000000..a1709f9 --- /dev/null +++ b/chrome/browser/browser_theme_provider_mac.mm @@ -0,0 +1,50 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/browser_theme_provider.h" + +#import + +#include "base/logging.h" + +NSImage* BrowserThemeProvider::GetNSImageNamed(int id) { + DCHECK(CalledOnValidThread()); + + // Check to see if we already have the image in the cache. + NSImageMap::const_iterator found = nsimage_cache_.find(id); + if (found != nsimage_cache_.end()) + return found->second; + + // Why do we load the file directly into the image rather than doing the whole + // SkBitmap > native conversion that others do? Going direct means: + // - we use the color profiles and other embedded info in the image file + // - we don't fall back to the default resources which we don't use on the Mac + std::vector raw_data; + if (ReadThemeFileData(id, &raw_data)) { + NSData* ns_data = [NSData dataWithBytes:&raw_data.front() + length:raw_data.size()]; + if (ns_data) { + NSImage* nsimage = [[NSImage alloc] initWithData:ns_data]; + + // We loaded successfully. Cache the image. + if (nsimage) { + nsimage_cache_[id] = nsimage; + return nsimage; + } + } + } + + return nil; +} + +void BrowserThemeProvider::FreePlatformImages() { + DCHECK(CalledOnValidThread()); + + // Free images. + for (NSImageMap::iterator i = nsimage_cache_.begin(); + i != nsimage_cache_.end(); i++) { + [i->second release]; + } + nsimage_cache_.clear(); +} diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 09513d8..1fcfa58 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -668,6 +668,7 @@ 'browser/browser_shutdown.cc', 'browser/browser_shutdown.h', 'browser/browser_theme_provider_gtk.cc', + 'browser/browser_theme_provider_mac.mm', 'browser/browser_theme_provider.cc', 'browser/browser_theme_provider.h', 'browser/browser_trial.cc', -- cgit v1.1