Index: chrome/browser/web_applications/web_app_mac.mm |
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm |
index 5c933cd5239e7f8d4d1ba6460265ca76067acf2a..343470ba235aa49464bb9448f14d94d4fd1a0817 100644 |
--- a/chrome/browser/web_applications/web_app_mac.mm |
+++ b/chrome/browser/web_applications/web_app_mac.mm |
@@ -4,6 +4,7 @@ |
#import "chrome/browser/web_applications/web_app_mac.h" |
+#import <Carbon/Carbon.h> |
#import <Cocoa/Cocoa.h> |
#include "base/file_util.h" |
@@ -22,67 +23,69 @@ |
#include "content/public/browser/browser_thread.h" |
#include "grit/chromium_strings.h" |
#include "skia/ext/skia_utils_mac.h" |
-#include "third_party/icon_family/IconFamily.h" |
+#include "third_party/skia/include/core/SkBitmap.h" |
+#include "third_party/skia/include/core/SkColor.h" |
#include "ui/base/l10n/l10n_util_mac.h" |
#include "ui/gfx/image/image_family.h" |
namespace { |
-// Get the 100% image representation for |image|. |
-// This returns the representation with the same width and height as |image| |
-// itself. If there is no such representation, returns nil. |
-NSBitmapImageRep* NSImageGet100PRepresentation(NSImage* image) { |
- NSSize image_size = [image size]; |
- for (NSBitmapImageRep* image_rep in [image representations]) { |
- NSSize image_rep_size = [image_rep size]; |
- if (image_rep_size.width == image_size.width && |
- image_rep_size.height == image_size.height) { |
- return image_rep; |
+void ConvertSkiaToARGB(const SkBitmap& bitmap, char* argb) { |
tapted
2013/05/22 08:27:33
This is similar to a function in skia_utils.h, but
|
+ SkAutoLockPixels lock(bitmap); |
+ for (int y = 0; y < bitmap.height(); ++y) { |
+ for (int x = 0; x < bitmap.width(); ++x) { |
+ SkColor pixel = bitmap.getColor(x, y); // Unpremultiplies. |
+ argb[0] = SkColorGetA(pixel); |
+ argb[1] = SkColorGetR(pixel); |
+ argb[2] = SkColorGetG(pixel); |
+ argb[3] = SkColorGetB(pixel); |
+ argb += 4; |
} |
} |
- return nil; |
} |
-// Adds |image_rep| to |icon_family|. Returns true on success, false on failure. |
-bool AddBitmapImageRepToIconFamily(IconFamily* icon_family, |
- NSBitmapImageRep* image_rep) { |
- NSSize size = [image_rep size]; |
- if (size.width != size.height) |
+// Adds |image| to |icon_family|. Returns true on success, false on failure. |
+bool AddGfxImageToIconFamily(IconFamilyHandle icon_family, |
+ const gfx::Image& image) { |
+ // When called via ShowCreateChromeAppShortcutsDialog the ImageFamily will |
+ // have all the representations desired here for mac, from the kDesiredSizes |
+ // array in web_app_ui.cc. |
+ SkBitmap bitmap = image.AsBitmap(); |
+ if (bitmap.config() != SkBitmap::kARGB_8888_Config || |
+ bitmap.width() != bitmap.height()) { |
return false; |
+ } |
- switch (static_cast<int>(size.width)) { |
+ OSType icon_type; |
+ switch (bitmap.width()) { |
case 512: |
- return [icon_family setIconFamilyElement:kIconServices512PixelDataARGB |
- fromBitmapImageRep:image_rep]; |
+ icon_type = kIconServices512PixelDataARGB; |
+ break; |
case 256: |
- return [icon_family setIconFamilyElement:kIconServices256PixelDataARGB |
- fromBitmapImageRep:image_rep]; |
+ icon_type = kIconServices256PixelDataARGB; |
+ break; |
case 128: |
- return [icon_family setIconFamilyElement:kThumbnail32BitData |
- fromBitmapImageRep:image_rep] && |
- [icon_family setIconFamilyElement:kThumbnail8BitMask |
- fromBitmapImageRep:image_rep]; |
+ icon_type = kIconServices128PixelDataARGB; |
+ break; |
+ case 48: |
+ icon_type = kIconServices48PixelDataARGB; |
+ break; |
case 32: |
- return [icon_family setIconFamilyElement:kLarge32BitData |
- fromBitmapImageRep:image_rep] && |
- [icon_family setIconFamilyElement:kLarge8BitData |
- fromBitmapImageRep:image_rep] && |
- [icon_family setIconFamilyElement:kLarge8BitMask |
- fromBitmapImageRep:image_rep] && |
- [icon_family setIconFamilyElement:kLarge1BitMask |
- fromBitmapImageRep:image_rep]; |
+ icon_type = kIconServices32PixelDataARGB; |
+ break; |
case 16: |
- return [icon_family setIconFamilyElement:kSmall32BitData |
- fromBitmapImageRep:image_rep] && |
- [icon_family setIconFamilyElement:kSmall8BitData |
- fromBitmapImageRep:image_rep] && |
- [icon_family setIconFamilyElement:kSmall8BitMask |
- fromBitmapImageRep:image_rep] && |
- [icon_family setIconFamilyElement:kSmall1BitMask |
- fromBitmapImageRep:image_rep]; |
+ icon_type = kIconServices16PixelDataARGB; |
+ break; |
default: |
return false; |
} |
+ |
+ Handle raw_data = NewHandle(bitmap.getSize()); |
benwells
2013/05/23 00:42:04
I can see that it is guaranteed by the config chec
benwells
2013/05/23 00:42:04
Is there a scoped version of the handle you can us
tapted
2013/05/23 04:03:43
Done.
tapted
2013/05/23 04:03:43
Done.
|
+ ConvertSkiaToARGB(bitmap, *raw_data); |
+ OSErr result = SetIconFamilyData(icon_family, icon_type, raw_data); |
+ DisposeHandle(raw_data); |
+ |
+ return result == noErr; |
} |
base::FilePath GetWritableApplicationsDirectory() { |
@@ -96,8 +99,37 @@ base::FilePath GetWritableApplicationsDirectory() { |
return base::FilePath(); |
} |
-} // namespace |
+template <class T> |
+class ScopedCarbonHandle { |
+ public: |
+ ScopedCarbonHandle() { |
+ typed_handle_ = reinterpret_cast<T>(NewHandle(0)); |
+ } |
+ ~ScopedCarbonHandle() { |
+ DisposeHandle(AsHandle()); |
+ } |
+ |
+ T get() { |
+ return typed_handle_; |
+ } |
+ |
+ bool WriteDataToFile(const base::FilePath& path) { |
+ NSData* data = [NSData dataWithBytes:*AsHandle() |
+ length:GetHandleSize(AsHandle())]; |
+ return [data writeToFile:base::mac::FilePathToNSString(path) |
+ atomically:NO]; |
+ } |
+ |
+ private: |
+ Handle AsHandle() { |
+ return reinterpret_cast<Handle>(typed_handle_); |
+ } |
+ |
+ T typed_handle_; |
+}; |
+ |
+} // namespace |
namespace web_app { |
@@ -237,19 +269,16 @@ bool WebAppShortcutCreator::UpdateIcon(const base::FilePath& app_path) const { |
if (info_.favicon.empty()) |
return true; |
- scoped_nsobject<IconFamily> icon_family([[IconFamily alloc] init]); |
+ ScopedCarbonHandle<IconFamilyHandle> icon_family; |
bool image_added = false; |
for (gfx::ImageFamily::const_iterator it = info_.favicon.begin(); |
it != info_.favicon.end(); ++it) { |
if (it->IsEmpty()) |
continue; |
- NSBitmapImageRep* image_rep = NSImageGet100PRepresentation(it->ToNSImage()); |
- if (!image_rep) |
- continue; |
// Missing an icon size is not fatal so don't fail if adding the bitmap |
// doesn't work. |
- if (!AddBitmapImageRepToIconFamily(icon_family, image_rep)) |
+ if (!AddGfxImageToIconFamily(icon_family.get(), *it)) |
continue; |
image_added = true; |
@@ -262,8 +291,8 @@ bool WebAppShortcutCreator::UpdateIcon(const base::FilePath& app_path) const { |
app_path.Append("Contents").Append("Resources"); |
if (!file_util::CreateDirectory(resources_path)) |
return false; |
- base::FilePath icon_path = resources_path.Append("app.icns"); |
- return [icon_family writeToFile:base::mac::FilePathToNSString(icon_path)]; |
+ |
+ return icon_family.WriteDataToFile(resources_path.Append("app.icns")); |
} |
NSString* WebAppShortcutCreator::GetBundleIdentifier(NSDictionary* plist) const |