summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrohitrao@chromium.org <rohitrao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-14 12:55:23 +0000
committerrohitrao@chromium.org <rohitrao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-14 12:55:23 +0000
commitd5f5c2a08c3130d4836551f713dab341f4c06db3 (patch)
tree6210951e7f43d3bf8aaf2377e2855d5b2b2b2b03
parent9a9f8bd9220215ae97cab7cb43bba8eb0b0d52bf (diff)
downloadchromium_src-d5f5c2a08c3130d4836551f713dab341f4c06db3.zip
chromium_src-d5f5c2a08c3130d4836551f713dab341f4c06db3.tar.gz
chromium_src-d5f5c2a08c3130d4836551f713dab341f4c06db3.tar.bz2
Adds an iOS implementation of gfx::Image.
BUG=None TEST=None Review URL: https://chromiumcodereview.appspot.com/10928093 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@156787 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--skia/ext/skia_utils_ios.h30
-rw-r--r--skia/ext/skia_utils_ios.mm77
-rw-r--r--skia/skia.gyp8
-rw-r--r--ui/base/layout.cc7
-rw-r--r--ui/gfx/image/image.cc118
-rw-r--r--ui/gfx/image/image.h12
-rw-r--r--ui/gfx/image/image_ios.mm71
-rw-r--r--ui/gfx/image/image_skia_util_ios.h27
-rw-r--r--ui/gfx/image/image_skia_util_ios.mm59
-rw-r--r--ui/gfx/image/image_unittest.cc21
-rw-r--r--ui/gfx/image/image_unittest_util.cc24
-rw-r--r--ui/gfx/image/image_unittest_util.h4
-rw-r--r--ui/gfx/image/image_util.cc15
-rw-r--r--ui/gfx/image/image_util.h10
-rw-r--r--ui/gfx/image/image_util_ios.mm27
-rw-r--r--ui/ui.gyp36
-rw-r--r--ui/ui_unittests.gypi19
17 files changed, 511 insertions, 54 deletions
diff --git a/skia/ext/skia_utils_ios.h b/skia/ext/skia_utils_ios.h
new file mode 100644
index 0000000..0b086ad
--- /dev/null
+++ b/skia/ext/skia_utils_ios.h
@@ -0,0 +1,30 @@
+// Copyright 2012 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.
+
+#ifndef SKIA_EXT_SKIA_UTILS_IOS_H_
+#define SKIA_EXT_SKIA_UTILS_IOS_H_
+
+#include <CoreGraphics/CoreGraphics.h>
+#include <vector>
+
+#include "third_party/skia/include/core/SkBitmap.h"
+
+#ifdef __OBJC__
+@class UIImage;
+#else
+class UIImage;
+#endif
+
+namespace gfx {
+
+// Draws a UIImage with a given size into a SkBitmap.
+SK_API SkBitmap UIImageToSkBitmap(UIImage* image, CGSize size, bool is_opaque);
+
+// Given an SkBitmap and a color space, return an autoreleased UIImage.
+SK_API UIImage* SkBitmapToUIImageWithColorSpace(const SkBitmap& skia_bitmap,
+ CGColorSpaceRef color_space);
+
+} // namespace gfx
+
+#endif // SKIA_EXT_SKIA_UTILS_IOS_H_
diff --git a/skia/ext/skia_utils_ios.mm b/skia/ext/skia_utils_ios.mm
new file mode 100644
index 0000000..9d4c14a
--- /dev/null
+++ b/skia/ext/skia_utils_ios.mm
@@ -0,0 +1,77 @@
+// Copyright 2012 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 "skia/ext/skia_utils_ios.h"
+
+#import <UIKit/UIKit.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "third_party/skia/include/utils/mac/SkCGUtils.h"
+
+namespace gfx {
+
+SkBitmap UIImageToSkBitmap(UIImage* image, CGSize size, bool is_opaque) {
+ SkBitmap bitmap;
+ if (!image)
+ return bitmap;
+
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width, size.height);
+ if (!bitmap.allocPixels())
+ return bitmap;
+
+ bitmap.setIsOpaque(is_opaque);
+ void* data = bitmap.getPixels();
+
+ // Allocate a bitmap context with 4 components per pixel (BGRA). Apple
+ // recommends these flags for improved CG performance.
+#define HAS_ARGB_SHIFTS(a, r, g, b) \
+ (SK_A32_SHIFT == (a) && SK_R32_SHIFT == (r) \
+ && SK_G32_SHIFT == (g) && SK_B32_SHIFT == (b))
+#if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
+ base::mac::ScopedCFTypeRef<CGColorSpaceRef> color_space(
+ CGColorSpaceCreateDeviceRGB());
+ base::mac::ScopedCFTypeRef<CGContextRef> context(
+ CGBitmapContextCreate(data, size.width, size.height, 8, size.width*4,
+ color_space,
+ kCGImageAlphaPremultipliedFirst |
+ kCGBitmapByteOrder32Host));
+#else
+#error We require that Skia's and CoreGraphics's recommended \
+ image memory layout match.
+#endif
+#undef HAS_ARGB_SHIFTS
+
+ DCHECK(context);
+ if (!context)
+ return bitmap;
+
+ // UIGraphicsPushContext be called from the main thread.
+ // TODO(rohitrao): We can use CG to make this thread safe, but the mac code
+ // calls setCurrentContext, so it's similarly limited to the main thread.
+ DCHECK([NSThread isMainThread]);
+ UIGraphicsPushContext(context);
+ [image drawInRect:CGRectMake(0, 0, size.width, size.height)
+ blendMode:kCGBlendModeCopy
+ alpha:1.0];
+ UIGraphicsPopContext();
+
+ return bitmap;
+}
+
+UIImage* SkBitmapToUIImageWithColorSpace(const SkBitmap& skia_bitmap,
+ CGColorSpaceRef color_space) {
+ if (skia_bitmap.isNull())
+ return nil;
+
+ // First convert SkBitmap to CGImageRef.
+ base::mac::ScopedCFTypeRef<CGImageRef> cg_image(
+ SkCreateCGImageRefWithColorspace(skia_bitmap, color_space));
+
+ // Now convert to UIImage.
+ // TODO(rohitrao): Gotta incorporate the scale factor somewhere!
+ return [UIImage imageWithCGImage:cg_image.get()];
+}
+
+} // namespace gfx
diff --git a/skia/skia.gyp b/skia/skia.gyp
index 618ac91..894e360 100644
--- a/skia/skia.gyp
+++ b/skia/skia.gyp
@@ -183,6 +183,8 @@
'ext/skia_sandbox_support_win.h',
'ext/skia_sandbox_support_win.cc',
'ext/skia_trace_shim.h',
+ 'ext/skia_utils_ios.mm',
+ 'ext/skia_utils_ios.h',
'ext/skia_utils_mac.mm',
'ext/skia_utils_mac.h',
'ext/skia_utils_win.cc',
@@ -308,6 +310,11 @@
'SK_DEFAULT_FONT_CACHE_LIMIT=(20*1024*1024)',
],
}],
+ [ 'OS != "ios"', {
+ 'sources/': [
+ ['exclude', '_ios\\.(cc|cpp|mm?)$'],
+ ],
+ }],
[ 'OS != "mac"', {
'sources/': [
['exclude', '_mac\\.(cc|cpp|mm?)$'],
@@ -593,6 +600,7 @@
'sources/': [
['include', 'SkFontHost_mac\\.cpp$',],
['include', 'SkStream_mac\\.cpp$',],
+ ['include', 'SkCreateCGImageRef\\.cpp$',],
],
}],
],
diff --git a/ui/base/layout.cc b/ui/base/layout.cc
index ffc7082..48bdab6 100644
--- a/ui/base/layout.cc
+++ b/ui/base/layout.cc
@@ -19,7 +19,7 @@
#include "ui/compositor/compositor.h"
#endif // defined(USE_AURA) && !defined(OS_WIN)
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
#include "base/mac/mac_util.h"
#endif
@@ -70,7 +70,10 @@ std::vector<ui::ScaleFactor>& GetSupportedScaleFactorsInternal() {
new std::vector<ui::ScaleFactor>();
if (supported_scale_factors->empty()) {
supported_scale_factors->push_back(ui::SCALE_FACTOR_100P);
-#if defined(OS_MACOSX) && defined(ENABLE_HIDPI)
+// TODO(rohitrao): Set the appropriate scale factors for iOS. Ideally set
+// either 100P or 200P but not both, since a given device will only ever use one
+// scale factor.
+#if defined(OS_MACOSX) && !defined(OS_IOS) && defined(ENABLE_HIDPI)
if (base::mac::IsOSLionOrLater())
supported_scale_factors->push_back(ui::SCALE_FACTOR_200P);
#elif defined(OS_WIN) && defined(ENABLE_HIDPI)
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc
index c5c0c76..7a87cc3 100644
--- a/ui/gfx/image/image.cc
+++ b/ui/gfx/image/image.cc
@@ -9,10 +9,13 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/size.h"
+#if !defined(OS_IOS)
+#include "ui/gfx/codec/png_codec.h"
+#endif
+
#if defined(TOOLKIT_GTK)
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdk.h>
@@ -21,6 +24,9 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/gtk_util.h"
#include "ui/gfx/image/cairo_cached_surface.h"
+#elif defined(OS_IOS)
+#include "base/mac/foundation_util.h"
+#include "ui/gfx/image/image_skia_util_ios.h"
#elif defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#include "ui/gfx/image/image_skia_util_mac.h"
@@ -84,11 +90,18 @@ void PNGFromGdkPixbuf(GdkPixbuf* pixbuf, std::vector<unsigned char>* png) {
#endif // defined(TOOLKIT_GTK)
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+void PNGFromUIImage(UIImage* nsimage, std::vector<unsigned char>* png);
+UIImage* CreateUIImageFromPNG(const std::vector<unsigned char>& png);
+#elif defined(OS_MACOSX)
void PNGFromNSImage(NSImage* nsimage, std::vector<unsigned char>* png);
NSImage* NSImageFromPNG(const std::vector<unsigned char>& png);
#endif // defined(OS_MACOSX)
+#if defined(OS_IOS)
+ImageSkia* ImageSkiaFromPNG(const std::vector<unsigned char>& png);
+void PNGFromImageSkia(const ImageSkia* skia, std::vector<unsigned char>* png);
+#else
ImageSkia* ImageSkiaFromPNG(const std::vector<unsigned char>& png) {
SkBitmap bitmap;
if (!gfx::PNGCodec::Decode(&png.front(), png.size(), &bitmap)) {
@@ -104,12 +117,14 @@ ImageSkia* ImageSkiaFromPNG(const std::vector<unsigned char>& png) {
void PNGFromImageSkia(const ImageSkia* skia, std::vector<unsigned char>* png) {
CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(*skia->bitmap(), false, png));
}
+#endif
class ImageRepPNG;
class ImageRepSkia;
class ImageRepGdk;
class ImageRepCairo;
class ImageRepCocoa;
+class ImageRepCocoaTouch;
// An ImageRep is the object that holds the backing memory for an Image. Each
// RepresentationType has an ImageRep subclass that is responsible for freeing
@@ -146,7 +161,12 @@ class ImageRep {
}
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+ ImageRepCocoaTouch* AsImageRepCocoaTouch() {
+ CHECK_EQ(type_, Image::kImageRepCocoaTouch);
+ return reinterpret_cast<ImageRepCocoaTouch*>(this);
+ }
+#elif defined(OS_MACOSX)
ImageRepCocoa* AsImageRepCocoa() {
CHECK_EQ(type_, Image::kImageRepCocoa);
return reinterpret_cast<ImageRepCocoa*>(this);
@@ -245,7 +265,28 @@ class ImageRepCairo : public ImageRep {
};
#endif // defined(TOOLKIT_GTK)
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+class ImageRepCocoaTouch : public ImageRep {
+ public:
+ explicit ImageRepCocoaTouch(UIImage* image)
+ : ImageRep(Image::kImageRepCocoaTouch),
+ image_(image) {
+ CHECK(image);
+ }
+
+ virtual ~ImageRepCocoaTouch() {
+ base::mac::NSObjectRelease(image_);
+ image_ = nil;
+ }
+
+ UIImage* image() const { return image_; }
+
+ private:
+ UIImage* image_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageRepCocoaTouch);
+};
+#elif defined(OS_MACOSX)
class ImageRepCocoa : public ImageRep {
public:
explicit ImageRepCocoa(NSImage* image)
@@ -343,7 +384,15 @@ Image::Image(GdkPixbuf* pixbuf) {
}
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+Image::Image(UIImage* image)
+ : storage_(new internal::ImageStorage(Image::kImageRepCocoaTouch)) {
+ if (image) {
+ internal::ImageRepCocoaTouch* rep = new internal::ImageRepCocoaTouch(image);
+ AddRepresentation(rep);
+ }
+}
+#elif defined(OS_MACOSX)
Image::Image(NSImage* image) {
if (image) {
storage_ = new internal::ImageStorage(Image::kImageRepCocoa);
@@ -376,6 +425,14 @@ const std::vector<unsigned char>* Image::ToImagePNG() const {
internal::PNGFromGdkPixbuf(gdk_rep->pixbuf(), png_rep->image());
break;
}
+#elif defined(OS_IOS)
+ case kImageRepCocoaTouch: {
+ internal::ImageRepCocoaTouch* cocoa_touch_rep =
+ GetRepresentation(kImageRepCocoaTouch, true)
+ ->AsImageRepCocoaTouch();
+ internal::PNGFromUIImage(cocoa_touch_rep->image(), png_rep->image());
+ break;
+ }
#elif defined(OS_MACOSX)
case kImageRepCocoa: {
internal::ImageRepCocoa* cocoa_rep =
@@ -424,6 +481,15 @@ const ImageSkia* Image::ToImageSkia() const {
internal::ImageSkiaFromGdkPixbuf(native_rep->pixbuf())));
break;
}
+#elif defined(OS_IOS)
+ case kImageRepCocoaTouch: {
+ internal::ImageRepCocoaTouch* native_rep =
+ GetRepresentation(kImageRepCocoaTouch, true)
+ ->AsImageRepCocoaTouch();
+ rep = new internal::ImageRepSkia(new ImageSkia(
+ ImageSkiaFromUIImage(native_rep->image())));
+ break;
+ }
#elif defined(OS_MACOSX)
case kImageRepCocoa: {
internal::ImageRepCocoa* native_rep =
@@ -483,7 +549,35 @@ CairoCachedSurface* const Image::ToCairo() const {
}
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+UIImage* Image::ToUIImage() const {
+ internal::ImageRep* rep = GetRepresentation(kImageRepCocoaTouch, false);
+ if (!rep) {
+ switch (DefaultRepresentationType()) {
+ case kImageRepPNG: {
+ internal::ImageRepPNG* png_rep =
+ GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
+ rep = new internal::ImageRepCocoaTouch(internal::CreateUIImageFromPNG(
+ *png_rep->image()));
+ break;
+ }
+ case kImageRepSkia: {
+ internal::ImageRepSkia* skia_rep =
+ GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
+ UIImage* image = UIImageFromImageSkia(*skia_rep->image());
+ base::mac::NSObjectRetain(image);
+ rep = new internal::ImageRepCocoaTouch(image);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+ CHECK(rep);
+ AddRepresentation(rep);
+ }
+ return rep->AsImageRepCocoaTouch()->image();
+}
+#elif defined(OS_MACOSX)
NSImage* Image::ToNSImage() const {
internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
if (!rep) {
@@ -525,7 +619,7 @@ ImageSkia Image::AsImageSkia() const {
return IsEmpty() ? ImageSkia() : *ToImageSkia();
}
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
NSImage* Image::AsNSImage() const {
return IsEmpty() ? nil : ToNSImage();
}
@@ -547,7 +641,13 @@ GdkPixbuf* Image::CopyGdkPixbuf() const {
}
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+UIImage* Image::CopyUIImage() const {
+ UIImage* image = ToUIImage();
+ base::mac::NSObjectRetain(image);
+ return image;
+}
+#elif defined(OS_MACOSX)
NSImage* Image::CopyNSImage() const {
NSImage* image = ToNSImage();
base::mac::NSObjectRetain(image);
@@ -555,7 +655,7 @@ NSImage* Image::CopyNSImage() const {
}
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
Image::operator NSImage*() const {
return ToNSImage();
}
diff --git a/ui/gfx/image/image.h b/ui/gfx/image/image.h
index 999e397..05a50a4 100644
--- a/ui/gfx/image/image.h
+++ b/ui/gfx/image/image.h
@@ -52,6 +52,7 @@ class UI_EXPORT Image {
enum RepresentationType {
kImageRepGdk,
kImageRepCocoa,
+ kImageRepCocoaTouch,
kImageRepCairo,
kImageRepSkia,
kImageRepPNG,
@@ -80,6 +81,9 @@ class UI_EXPORT Image {
#if defined(TOOLKIT_GTK)
// Does not increase |pixbuf|'s reference count; expects to take ownership.
explicit Image(GdkPixbuf* pixbuf);
+#elif defined(OS_IOS)
+ // Does not retain |image|; expects to take ownership.
+ explicit Image(UIImage* image);
#elif defined(OS_MACOSX)
// Does not retain |image|; expects to take ownership.
// A single NSImage object can contain multiple bitmaps so there's no reason
@@ -106,6 +110,8 @@ class UI_EXPORT Image {
#if defined(TOOLKIT_GTK)
GdkPixbuf* ToGdkPixbuf() const;
CairoCachedSurface* const ToCairo() const;
+#elif defined(OS_IOS)
+ UIImage* ToUIImage() const;
#elif defined(OS_MACOSX)
NSImage* ToNSImage() const;
#endif
@@ -117,7 +123,7 @@ class UI_EXPORT Image {
// image is empty.
ImageSkia AsImageSkia() const;
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
// Same as ToSkBitmap(), but returns nil if this image is empty.
NSImage* AsNSImage() const;
#endif
@@ -133,13 +139,15 @@ class UI_EXPORT Image {
SkBitmap* CopySkBitmap() const;
#if defined(TOOLKIT_GTK)
GdkPixbuf* CopyGdkPixbuf() const;
+#elif defined(OS_IOS)
+ UIImage* CopyUIImage() const;
#elif defined(OS_MACOSX)
NSImage* CopyNSImage() const;
#endif
// DEPRECATED ----------------------------------------------------------------
// Conversion handlers. These wrap the ToType() variants.
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
operator NSImage*() const;
#endif
// ---------------------------------------------------------------------------
diff --git a/ui/gfx/image/image_ios.mm b/ui/gfx/image/image_ios.mm
new file mode 100644
index 0000000..c8db540
--- /dev/null
+++ b/ui/gfx/image/image_ios.mm
@@ -0,0 +1,71 @@
+// Copyright 2012 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 "ui/gfx/image/image.h"
+
+#import <UIKit/UIKit.h>
+
+#include "base/logging.h"
+#include "base/memory/scoped_nsobject.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_util_ios.h"
+
+namespace gfx {
+namespace internal {
+
+void PNGFromUIImage(UIImage* uiimage, std::vector<unsigned char>* png) {
+ NSData* data = UIImagePNGRepresentation(uiimage);
+
+ if ([data length] == 0)
+ return;
+
+ png->resize([data length]);
+ [data getBytes:&png->at(0) length:[data length]];
+}
+
+UIImage* CreateUIImageFromPNG(const std::vector<unsigned char>& png) {
+ NSData* data = [NSData dataWithBytes:&png.front() length:png.size()];
+ scoped_nsobject<UIImage> image ([[UIImage alloc] initWithData:data]);
+ if (!image) {
+ LOG(WARNING) << "Unable to decode PNG into UIImage.";
+ // Return a 16x16 red image to visually show error.
+ UIGraphicsBeginImageContext(CGSizeMake(16, 16));
+ CGContextRef context = UIGraphicsGetCurrentContext();
+ CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
+ CGContextFillRect(context, CGRectMake(0.0, 0.0, 16, 16));
+ image.reset([UIGraphicsGetImageFromCurrentImageContext() retain]);
+ UIGraphicsEndImageContext();
+ }
+ return image.release();
+}
+
+void PNGFromImageSkia(const ImageSkia* skia, std::vector<unsigned char>* png) {
+ // iOS does not expose libpng, so conversion from ImageSkia to PNG must go
+ // through UIImage.
+ // TODO(rohitrao): Rewrite the callers of this function to save the UIImage
+ // representation in the gfx::Image. If we're generating it, we might as well
+ // hold on to it.
+ UIImage* image = UIImageFromImageSkia(*skia);
+ PNGFromUIImage(image, png);
+}
+
+ImageSkia* ImageSkiaFromPNG(const std::vector<unsigned char>& png) {
+ // iOS does not expose libpng, so conversion from PNG to ImageSkia must go
+ // through UIImage.
+ scoped_nsobject<UIImage> uiimage(CreateUIImageFromPNG(png));
+ if (!uiimage) {
+ LOG(WARNING) << "Unable to decode PNG into ImageSkia.";
+ // Return a 16x16 red image to visually show error.
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
+ bitmap.allocPixels();
+ bitmap.eraseRGB(0xff, 0, 0);
+ return new ImageSkia(bitmap);
+ }
+
+ return new ImageSkia(ImageSkiaFromUIImage(uiimage));
+}
+
+} // namespace internal
+} // namespace gfx
diff --git a/ui/gfx/image/image_skia_util_ios.h b/ui/gfx/image/image_skia_util_ios.h
new file mode 100644
index 0000000..3862d1d
--- /dev/null
+++ b/ui/gfx/image/image_skia_util_ios.h
@@ -0,0 +1,27 @@
+// Copyright 2012 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.
+
+#ifndef UI_GFX_IMAGE_IMAGE_SKIA_UTIL_IOS_H_
+#define UI_GFX_IMAGE_IMAGE_SKIA_UTIL_IOS_H_
+
+#include "ui/base/ui_export.h"
+
+#ifdef __OBJC__
+@class UIImage;
+#else
+class UIImage;
+#endif
+
+namespace gfx {
+class ImageSkia;
+
+// Converts to ImageSkia from UIImage.
+UI_EXPORT gfx::ImageSkia ImageSkiaFromUIImage(UIImage* image);
+
+// Converts to UIImage from ImageSkia. Returns an autoreleased UIImage.
+UI_EXPORT UIImage* UIImageFromImageSkia(const gfx::ImageSkia& image_skia);
+
+} // namespace gfx
+
+#endif // UI_GFX_IMAGE_IMAGE_SKIA_UTIL_IOS_H_
diff --git a/ui/gfx/image/image_skia_util_ios.mm b/ui/gfx/image/image_skia_util_ios.mm
new file mode 100644
index 0000000..47f076f
--- /dev/null
+++ b/ui/gfx/image/image_skia_util_ios.mm
@@ -0,0 +1,59 @@
+// Copyright 2012 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 "ui/gfx/image/image_skia_util_ios.h"
+
+#include <UIKit/UIKit.h>
+
+#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "skia/ext/skia_utils_ios.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/image/image_skia.h"
+
+namespace gfx {
+
+gfx::ImageSkia ImageSkiaFromUIImage(UIImage* image) {
+ gfx::ImageSkia image_skia;
+ if (!image)
+ return image_skia;
+
+ // iOS only supports one scale factor.
+ std::vector<ui::ScaleFactor> supported_scale_factors =
+ ui::GetSupportedScaleFactors();
+ DCHECK_EQ(1U, supported_scale_factors.size());
+ if (supported_scale_factors.size() < 1)
+ return image_skia;
+
+ ui::ScaleFactor scale_factor = supported_scale_factors[0];
+ float scale = ui::GetScaleFactorScale(scale_factor);
+ CGSize size = image.size;
+ CGSize desired_size_for_scale =
+ CGSizeMake(size.width * scale, size.height * scale);
+ SkBitmap bitmap(gfx::UIImageToSkBitmap(image, desired_size_for_scale, false));
+ if (!bitmap.isNull())
+ image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale_factor));
+ return image_skia;
+}
+
+UIImage* UIImageFromImageSkia(const gfx::ImageSkia& image_skia) {
+ if (image_skia.isNull())
+ return nil;
+
+ // iOS only supports one scale factor.
+ std::vector<ui::ScaleFactor> supported_scale_factors =
+ ui::GetSupportedScaleFactors();
+ DCHECK_EQ(1U, supported_scale_factors.size());
+ if (supported_scale_factors.size() < 1)
+ return nil;
+
+ image_skia.EnsureRepsForSupportedScaleFactors();
+ const ImageSkiaRep& rep =
+ image_skia.GetRepresentation(supported_scale_factors[0]);
+ base::mac::ScopedCFTypeRef<CGColorSpaceRef> color_space(
+ CGColorSpaceCreateDeviceRGB());
+ return gfx::SkBitmapToUIImageWithColorSpace(rep.sk_bitmap(), color_space);
+}
+
+} // namespace gfx
diff --git a/ui/gfx/image/image_unittest.cc b/ui/gfx/image/image_unittest.cc
index 967bb3a..5c5dd23 100644
--- a/ui/gfx/image/image_unittest.cc
+++ b/ui/gfx/image/image_unittest.cc
@@ -10,6 +10,9 @@
#if defined(TOOLKIT_GTK)
#include <gtk/gtk.h>
#include "ui/gfx/gtk_util.h"
+#elif defined(OS_IOS)
+#include "base/mac/foundation_util.h"
+#include "skia/ext/skia_utils_ios.h"
#elif defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#include "skia/ext/skia_utils_mac.h"
@@ -171,11 +174,15 @@ TEST_F(ImageTest, PNGDecodeToSkiaFailure) {
gt::CheckColor(bitmap->getColor(10, 10), true);
}
+// TODO(rohitrao): This test needs an iOS implementation of
+// GetPlatformImageColor().
+#if !defined(OS_IOS)
TEST_F(ImageTest, PNGDecodeToPlatformFailure) {
std::vector<unsigned char> png(100, 0);
gfx::Image image(&png.front(), png.size());
gt::CheckColor(gt::GetPlatformImageColor(gt::ToPlatformType(image)), true);
}
+#endif
TEST_F(ImageTest, SkiaToPlatform) {
gfx::Image image(gt::CreateBitmap(25, 25));
@@ -264,7 +271,19 @@ TEST_F(ImageTest, SkiaToCairoCreatesGdk) {
}
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+TEST_F(ImageTest, SkiaToCocoaTouchCopy) {
+ UIImage* ui_image;
+
+ {
+ gfx::Image image(gt::CreateBitmap(25, 25));
+ ui_image = image.CopyUIImage();
+ }
+
+ EXPECT_TRUE(ui_image);
+ base::mac::NSObjectRelease(ui_image);
+}
+#elif defined(OS_MACOSX)
TEST_F(ImageTest, SkiaToCocoaCopy) {
NSImage* ns_image;
diff --git a/ui/gfx/image/image_unittest_util.cc b/ui/gfx/image/image_unittest_util.cc
index f7486ea..6291b23 100644
--- a/ui/gfx/image/image_unittest_util.cc
+++ b/ui/gfx/image/image_unittest_util.cc
@@ -14,6 +14,10 @@
#if defined(TOOLKIT_GTK)
#include <gtk/gtk.h>
#include "ui/gfx/gtk_util.h"
+#elif defined(OS_IOS)
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "skia/ext/skia_utils_ios.h"
#elif defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#include "skia/ext/skia_utils_mac.h"
@@ -79,7 +83,13 @@ bool IsEmpty(const gfx::Image& image) {
PlatformImage CreatePlatformImage() {
const SkBitmap bitmap(CreateBitmap(25, 25));
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+ base::mac::ScopedCFTypeRef<CGColorSpaceRef> color_space(
+ CGColorSpaceCreateDeviceRGB());
+ UIImage* image = gfx::SkBitmapToUIImageWithColorSpace(bitmap, color_space);
+ base::mac::NSObjectRetain(image);
+ return image;
+#elif defined(OS_MACOSX)
NSImage* image = gfx::SkBitmapToNSImage(bitmap);
base::mac::NSObjectRetain(image);
return image;
@@ -91,7 +101,9 @@ PlatformImage CreatePlatformImage() {
}
gfx::Image::RepresentationType GetPlatformRepresentationType() {
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+ return gfx::Image::kImageRepCocoaTouch;
+#elif defined(OS_MACOSX)
return gfx::Image::kImageRepCocoa;
#elif defined(TOOLKIT_GTK)
return gfx::Image::kImageRepGdk;
@@ -101,7 +113,9 @@ gfx::Image::RepresentationType GetPlatformRepresentationType() {
}
PlatformImage ToPlatformType(const gfx::Image& image) {
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+ return image.ToUIImage();
+#elif defined(OS_MACOSX)
return image.ToNSImage();
#elif defined(TOOLKIT_GTK)
return image.ToGdkPixbuf();
@@ -111,7 +125,9 @@ PlatformImage ToPlatformType(const gfx::Image& image) {
}
PlatformImage CopyPlatformType(const gfx::Image& image) {
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+ return image.CopyUIImage();
+#elif defined(OS_MACOSX)
return image.CopyNSImage();
#elif defined(TOOLKIT_GTK)
return image.CopyGdkPixbuf();
diff --git a/ui/gfx/image/image_unittest_util.h b/ui/gfx/image/image_unittest_util.h
index de97133..4560ce6 100644
--- a/ui/gfx/image/image_unittest_util.h
+++ b/ui/gfx/image/image_unittest_util.h
@@ -14,7 +14,9 @@
namespace gfx {
namespace test {
-#if defined(OS_MACOSX)
+#if defined(OS_IOS)
+typedef UIImage* PlatformImage;
+#elif defined(OS_MACOSX)
typedef NSImage* PlatformImage;
#elif defined(TOOLKIT_GTK)
typedef GdkPixbuf* PlatformImage;
diff --git a/ui/gfx/image/image_util.cc b/ui/gfx/image/image_util.cc
index 6403419..04bc5a2 100644
--- a/ui/gfx/image/image_util.cc
+++ b/ui/gfx/image/image_util.cc
@@ -17,6 +17,14 @@ Image* ImageFromPNGEncodedData(const unsigned char* input, size_t input_size) {
return image;
}
+bool PNGEncodedDataFromImage(const Image& image,
+ std::vector<unsigned char>* dst) {
+ *dst = *image.ToImagePNG();
+ return !dst->empty();
+}
+
+// The iOS implementations of the JPEG functions are in image_util_ios.mm.
+#if !defined(OS_IOS)
Image ImageFromJPEGEncodedData(const unsigned char* input, size_t input_size) {
scoped_ptr<SkBitmap> bitmap(gfx::JPEGCodec::Decode(input, input_size));
if (bitmap.get())
@@ -25,12 +33,6 @@ Image ImageFromJPEGEncodedData(const unsigned char* input, size_t input_size) {
return Image();
}
-bool PNGEncodedDataFromImage(const Image& image,
- std::vector<unsigned char>* dst) {
- *dst = *image.ToImagePNG();
- return !dst->empty();
-}
-
bool JPEGEncodedDataFromImage(const Image& image, int quality,
std::vector<unsigned char>* dst) {
const SkBitmap& bitmap = *image.ToSkBitmap();
@@ -46,5 +48,6 @@ bool JPEGEncodedDataFromImage(const Image& image, int quality,
static_cast<int>(bitmap.rowBytes()), quality,
dst);
}
+#endif // !defined(OS_IOS)
}
diff --git a/ui/gfx/image/image_util.h b/ui/gfx/image/image_util.h
index 06643172..6767062 100644
--- a/ui/gfx/image/image_util.h
+++ b/ui/gfx/image/image_util.h
@@ -21,17 +21,17 @@ namespace gfx {
UI_EXPORT Image* ImageFromPNGEncodedData(const unsigned char* input,
size_t input_size);
+// Fills the |dst| vector with PNG-encoded bytes based on the given Image.
+// Returns true if the Image was encoded successfully.
+UI_EXPORT bool PNGEncodedDataFromImage(const Image& image,
+ std::vector<unsigned char>* dst);
+
// Creates an image from the given JPEG-encoded input. The caller owns the
// returned Image. If there was an error creating the image, returns an
// IsEmpty() Image.
UI_EXPORT Image ImageFromJPEGEncodedData(const unsigned char* input,
size_t input_size);
-// Fills the |dst| vector with PNG-encoded bytes based on the given Image.
-// Returns true if the Image was encoded successfully.
-UI_EXPORT bool PNGEncodedDataFromImage(const Image& image,
- std::vector<unsigned char>* dst);
-
// Fills the |dst| vector with JPEG-encoded bytes based on the given Image.
// |quality| determines the compression level, 0 == lowest, 100 == highest.
// Returns true if the Image was encoded successfully.
diff --git a/ui/gfx/image/image_util_ios.mm b/ui/gfx/image/image_util_ios.mm
new file mode 100644
index 0000000..d3a1cf7
--- /dev/null
+++ b/ui/gfx/image/image_util_ios.mm
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 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 <UIKit/UIKit.h>
+
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_util.h"
+
+#include "base/logging.h"
+
+namespace gfx {
+
+bool JPEGEncodedDataFromImage(const Image& image,
+ int quality,
+ std::vector<unsigned char>* dst) {
+ NSData* data = UIImageJPEGRepresentation(image.ToUIImage(), quality / 100.0);
+
+ if ([data length] == 0)
+ return false;
+
+ dst->resize([data length]);
+ [data getBytes:&dst->at(0) length:[data length]];
+ return true;
+}
+
+} // end namespace gfx
diff --git a/ui/ui.gyp b/ui/ui.gyp
index 699e0c2..03b7e04 100644
--- a/ui/ui.gyp
+++ b/ui/ui.gyp
@@ -41,6 +41,8 @@
# iOS uses a small subset of ui. common_sources are the only files that
# are built on iOS.
'common_sources' : [
+ 'base/layout.cc',
+ 'base/layout.h',
'base/models/tree_node_iterator.h',
'base/models/tree_node_model.h',
'base/ui_base_paths.cc',
@@ -48,6 +50,24 @@
'base/ui_base_switches.cc',
'base/ui_base_switches.h',
'base/ui_export.h',
+ 'gfx/image/image.cc',
+ 'gfx/image/image.h',
+ 'gfx/image/image_ios.mm',
+ 'gfx/image/image_mac.mm',
+ 'gfx/image/image_skia.cc',
+ 'gfx/image/image_skia.h',
+ 'gfx/image/image_skia_operations.cc',
+ 'gfx/image/image_skia_operations.h',
+ 'gfx/image/image_skia_rep.cc',
+ 'gfx/image/image_skia_rep.h',
+ 'gfx/image/image_skia_source.h',
+ 'gfx/image/image_skia_util_ios.h',
+ 'gfx/image/image_skia_util_ios.mm',
+ 'gfx/image/image_skia_util_mac.h',
+ 'gfx/image/image_skia_util_mac.mm',
+ 'gfx/image/image_util.cc',
+ 'gfx/image/image_util.h',
+ 'gfx/image/image_util_ios.mm',
'gfx/insets.cc',
'gfx/insets.h',
'gfx/point.cc',
@@ -264,8 +284,6 @@
'base/l10n/l10n_util_posix.cc',
'base/l10n/l10n_util_win.cc',
'base/l10n/l10n_util_win.h',
- 'base/layout.cc',
- 'base/layout.h',
'base/layout_mac.mm',
'base/models/button_menu_item_model.cc',
'base/models/button_menu_item_model.h',
@@ -421,20 +439,6 @@
'gfx/gfx_paths.h',
'gfx/image/canvas_image_source.cc',
'gfx/image/canvas_image_source.h',
- 'gfx/image/image.cc',
- 'gfx/image/image.h',
- 'gfx/image/image_mac.mm',
- 'gfx/image/image_skia.cc',
- 'gfx/image/image_skia.h',
- 'gfx/image/image_skia_operations.cc',
- 'gfx/image/image_skia_operations.h',
- 'gfx/image/image_skia_rep.cc',
- 'gfx/image/image_skia_rep.h',
- 'gfx/image/image_skia_source.h',
- 'gfx/image/image_skia_util_mac.h',
- 'gfx/image/image_skia_util_mac.mm',
- 'gfx/image/image_util.cc',
- 'gfx/image/image_util.h',
'gfx/interpolated_transform.h',
'gfx/interpolated_transform.cc',
'gfx/mac/nsimage_cache.h',
diff --git a/ui/ui_unittests.gypi b/ui/ui_unittests.gypi
index 17088c2..7297af5 100644
--- a/ui/ui_unittests.gypi
+++ b/ui/ui_unittests.gypi
@@ -58,6 +58,11 @@
# are built on iOS.
'common_sources' : [
'base/models/tree_node_iterator_unittest.cc',
+ 'gfx/image/image_skia_unittest.cc',
+ 'gfx/image/image_unittest.cc',
+ 'gfx/image/image_unittest_util.cc',
+ 'gfx/image/image_unittest_util.h',
+ 'gfx/image/image_unittest_util_mac.mm',
'gfx/insets_unittest.cc',
],
'all_sources': [
@@ -105,11 +110,6 @@
'gfx/font_list_unittest.cc',
'gfx/font_unittest.cc',
'gfx/image/image_mac_unittest.mm',
- 'gfx/image/image_skia_unittest.cc',
- 'gfx/image/image_unittest.cc',
- 'gfx/image/image_unittest_util.cc',
- 'gfx/image/image_unittest_util.h',
- 'gfx/image/image_unittest_util_mac.mm',
'gfx/image/image_util_unittest.cc',
'gfx/rect_unittest.cc',
'gfx/render_text_unittest.cc',
@@ -133,9 +133,12 @@
'base/ime/ime_unittests.gypi',
],
}, { # OS=="ios"
- 'sources' : ['<@(_common_sources)'],
- 'dependencies' : [
- '../testing/gtest.gyp:gtest_main',
+ 'sources' : [
+ '<@(_common_sources)',
+ # TODO(rohitrao): Get ui/test/test_suite.cc and
+ # ui/test/run_all_unittests.cc compiling on iOS and remove this
+ # line.
+ '../base/test/run_all_unittests.cc',
],
}],
['OS == "win"', {