Skip to content

Commit

Permalink
Theme image support for the Mac.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
avi@chromium.org committed Jun 22, 2009
1 parent 3e3f0eb commit 1279d5f
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 44 deletions.
1 change: 1 addition & 0 deletions app/app.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
12 changes: 12 additions & 0 deletions app/theme_provider.cc
Original file line number Diff line number Diff line change
@@ -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() {
}
18 changes: 16 additions & 2 deletions app/theme_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@

#if defined(OS_LINUX)
#include <gdk/gdk.h>
#endif
#elif defined(OS_MACOSX)
#ifdef __OBJC__
@class NSImage;
#else
class NSImage;
#endif // __OBJC__
#endif // OS_*

class SkBitmap;

Expand All @@ -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).
Expand Down Expand Up @@ -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
};

Expand Down
77 changes: 41 additions & 36 deletions chrome/browser/browser_theme_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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<unsigned char> raw_data, png_data;
bool BrowserThemeProvider::ReadThemeFileData(
int id, std::vector<unsigned char>* raw_data) {
if (images_.count(id)) {
// First check to see if we have a registered theme extension and whether
// it can handle this resource.
Expand All @@ -330,35 +320,43 @@ SkBitmap* BrowserThemeProvider::LoadThemeBitmap(int id) {
int64 avail = file.Available();
if (avail > 0 && avail < INT_MAX) {
size_t size = static_cast<size_t>(avail);
raw_data.resize(size);
char* data = reinterpret_cast<char*>(&(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<char*>(&(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<unsigned char> 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) {
Expand Down Expand Up @@ -732,10 +730,17 @@ SkColor BrowserThemeProvider::FindColor(const char* id,
}

void BrowserThemeProvider::FreeImages() {
FreePlatformImages();
for (std::vector<SkBitmap*>::iterator i = generated_images_.begin();
i != generated_images_.end(); i++) {
delete *i;
}
generated_images_.clear();
image_cache_.clear();
}

#if defined(OS_WIN)
void BrowserThemeProvider::FreePlatformImages() {
// Windows has no platform image cache to clear.
}
#endif
21 changes: 15 additions & 6 deletions chrome/browser/browser_theme_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
#include "base/ref_counted.h"
#include "skia/ext/skia_utils.h"

#if defined(OS_LINUX)
#include <gdk/gdk.h>
#endif

class Extension;
class Profile;
class DictionaryValue;
Expand Down Expand Up @@ -74,8 +70,10 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
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|.
Expand All @@ -98,6 +96,10 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
typedef std::map<const std::string, skia::HSL> TintMap;
typedef std::map<const std::string, int> DisplayPropertyMap;

// Reads the image data from the theme file into the specified vector. Returns
// true on success.
bool ReadThemeFileData(int id, std::vector<unsigned char>* raw_data);

// Loads a bitmap from the theme, which may be tinted or
// otherwise modified, or an application default.
SkBitmap* LoadThemeBitmap(int id);
Expand Down Expand Up @@ -158,13 +160,20 @@ class BrowserThemeProvider : public base::RefCounted<BrowserThemeProvider>,
// 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<int, SkBitmap*> ImageCache;
ImageCache image_cache_;
#if defined(OS_LINUX)
#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
typedef std::map<int, GdkPixbuf*> GdkPixbufMap;
GdkPixbufMap gdk_pixbufs_;
#elif defined(OS_MACOSX)
typedef std::map<int, NSImage*> NSImageMap;
NSImageMap nsimage_cache_;
#endif

// List of generate images that aren't stored in ResourceBundles image cache
Expand Down
11 changes: 11 additions & 0 deletions chrome/browser/browser_theme_provider_gtk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
50 changes: 50 additions & 0 deletions chrome/browser/browser_theme_provider_mac.mm
Original file line number Diff line number Diff line change
@@ -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 <Cocoa/Cocoa.h>

#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<unsigned char> 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();
}
1 change: 1 addition & 0 deletions chrome/chrome.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down

0 comments on commit 1279d5f

Please sign in to comment.