1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <Cocoa/Cocoa.h>
7 #include "base/logging.h"
8 #include "base/mac/scoped_nsobject.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "ui/gfx/image/image.h"
11 #include "ui/gfx/image/image_png_rep.h"
12 #include "ui/gfx/image/image_skia.h"
13 #include "ui/gfx/image/image_skia_util_mac.h"
14 #include "ui/gfx/image/image_unittest_util.h"
18 // Returns true if the structure of |ns_image| matches the structure
19 // described by |width|, |height|, and |scales|.
20 // The structure matches if:
21 // - |ns_image| is not nil.
22 // - |ns_image| has NSImageReps of |scales|.
23 // - Each of the NSImageReps has a pixel size of [|ns_image| size] *
25 bool NSImageStructureMatches(
29 const std::vector<float>& scales) {
31 [ns_image size].width != width ||
32 [ns_image size].height != height ||
33 [ns_image representations].count != scales.size()) {
37 for (size_t i = 0; i < scales.size(); ++i) {
38 float scale = scales[i];
39 bool found_match = false;
40 for (size_t j = 0; j < [ns_image representations].count; ++j) {
41 NSImageRep* ns_image_rep = [[ns_image representations] objectAtIndex:j];
43 [ns_image_rep pixelsWide] == width * scale &&
44 [ns_image_rep pixelsHigh] == height * scale) {
55 void BitmapImageRep(int width, int height,
56 NSBitmapImageRep** image_rep) {
57 *image_rep = [[[NSBitmapImageRep alloc]
58 initWithBitmapDataPlanes:NULL
65 colorSpaceName:NSDeviceRGBColorSpace
70 unsigned char* image_rep_data = [*image_rep bitmapData];
71 for (int i = 0; i < width * height * 3; ++i)
72 image_rep_data[i] = 255;
75 class ImageMacTest : public testing::Test {
78 gfx::ImageSkia::SetSupportedScales(gfx::test::Get1xAnd2xScales());
81 virtual ~ImageMacTest() {
85 DISALLOW_COPY_AND_ASSIGN(ImageMacTest);
88 namespace gt = gfx::test;
90 TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
91 const int kWidth1x = 10;
92 const int kHeight1x = 12;
93 const int kWidth2x = 20;
94 const int kHeight2x = 24;
96 NSBitmapImageRep* ns_image_rep1;
97 BitmapImageRep(kWidth1x, kHeight1x, &ns_image_rep1);
98 NSBitmapImageRep* ns_image_rep2;
99 BitmapImageRep(kWidth2x, kHeight2x, &ns_image_rep2);
100 base::scoped_nsobject<NSImage> ns_image(
101 [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
102 [ns_image addRepresentation:ns_image_rep1];
103 [ns_image addRepresentation:ns_image_rep2];
105 gfx::Image image(ns_image.release());
107 EXPECT_EQ(1u, image.RepresentationCount());
109 const gfx::ImageSkia* image_skia = image.ToImageSkia();
111 std::vector<float> scales;
112 scales.push_back(1.0f);
113 scales.push_back(2.0f);
114 EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
117 // ToImageSkia should create a second representation.
118 EXPECT_EQ(2u, image.RepresentationCount());
121 // Test that convertng to an ImageSkia from an NSImage with scale factors
122 // other than 1x and 2x results in an ImageSkia with scale factors 1x and
124 TEST_F(ImageMacTest, UnalignedMultiResolutionNSImageToImageSkia) {
125 const int kWidth1x = 10;
126 const int kHeight1x= 12;
127 const int kWidth4x = 40;
128 const int kHeight4x = 48;
130 NSBitmapImageRep* ns_image_rep4;
131 BitmapImageRep(kWidth4x, kHeight4x, &ns_image_rep4);
132 base::scoped_nsobject<NSImage> ns_image(
133 [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
134 [ns_image addRepresentation:ns_image_rep4];
136 gfx::Image image(ns_image.release());
138 EXPECT_EQ(1u, image.RepresentationCount());
140 const gfx::ImageSkia* image_skia = image.ToImageSkia();
142 std::vector<float> scales;
143 scales.push_back(1.0f);
144 scales.push_back(2.0f);
145 EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
148 // ToImageSkia should create a second representation.
149 EXPECT_EQ(2u, image.RepresentationCount());
152 TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
153 const int kWidth1x = 10;
154 const int kHeight1x= 12;
155 const int kWidth2x = 20;
156 const int kHeight2x = 24;
158 gfx::ImageSkia image_skia;
159 image_skia.AddRepresentation(gfx::ImageSkiaRep(
160 gt::CreateBitmap(kWidth1x, kHeight1x), 1.0f));
161 image_skia.AddRepresentation(gfx::ImageSkiaRep(
162 gt::CreateBitmap(kWidth2x, kHeight2x), 2.0f));
164 gfx::Image image(image_skia);
166 EXPECT_EQ(1u, image.RepresentationCount());
167 EXPECT_EQ(2u, image.ToImageSkia()->image_reps().size());
169 NSImage* ns_image = image.ToNSImage();
171 std::vector<float> scales;
172 scales.push_back(1.0f);
173 scales.push_back(2.0f);
174 EXPECT_TRUE(NSImageStructureMatches(ns_image, kWidth1x, kHeight1x, scales));
176 // Request for NSImage* should create a second representation.
177 EXPECT_EQ(2u, image.RepresentationCount());
180 TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
181 const int kSize1x = 25;
182 const int kSize2x = 50;
184 scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
185 scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
186 std::vector<gfx::ImagePNGRep> image_png_reps;
187 image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
188 image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, 2.0f));
190 gfx::Image image(image_png_reps);
192 NSImage* ns_image = image.ToNSImage();
193 std::vector<float> scales;
194 scales.push_back(1.0f);
195 scales.push_back(2.0f);
196 EXPECT_TRUE(NSImageStructureMatches(ns_image, kSize1x, kSize1x, scales));
198 // Converting from PNG to NSImage should not go through ImageSkia.
199 EXPECT_FALSE(image.HasRepresentation(gfx::Image::kImageRepSkia));
201 // Convert to ImageSkia to check pixel contents of NSImageReps.
202 gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
203 EXPECT_TRUE(gt::IsEqual(bytes1x,
204 image_skia.GetRepresentation(1.0f).sk_bitmap()));
205 EXPECT_TRUE(gt::IsEqual(bytes2x,
206 image_skia.GetRepresentation(2.0f).sk_bitmap()));