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());
82 DISALLOW_COPY_AND_ASSIGN(ImageMacTest);
85 namespace gt = gfx::test;
87 TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
88 const int kWidth1x = 10;
89 const int kHeight1x = 12;
90 const int kWidth2x = 20;
91 const int kHeight2x = 24;
93 NSBitmapImageRep* ns_image_rep1;
94 BitmapImageRep(kWidth1x, kHeight1x, &ns_image_rep1);
95 NSBitmapImageRep* ns_image_rep2;
96 BitmapImageRep(kWidth2x, kHeight2x, &ns_image_rep2);
97 base::scoped_nsobject<NSImage> ns_image(
98 [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
99 [ns_image addRepresentation:ns_image_rep1];
100 [ns_image addRepresentation:ns_image_rep2];
102 gfx::Image image(ns_image.release());
104 EXPECT_EQ(1u, image.RepresentationCount());
106 const gfx::ImageSkia* image_skia = image.ToImageSkia();
108 std::vector<float> scales;
109 scales.push_back(1.0f);
110 scales.push_back(2.0f);
111 EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
114 // ToImageSkia should create a second representation.
115 EXPECT_EQ(2u, image.RepresentationCount());
118 // Test that convertng to an ImageSkia from an NSImage with scale factors
119 // other than 1x and 2x results in an ImageSkia with scale factors 1x and
121 TEST_F(ImageMacTest, UnalignedMultiResolutionNSImageToImageSkia) {
122 const int kWidth1x = 10;
123 const int kHeight1x= 12;
124 const int kWidth4x = 40;
125 const int kHeight4x = 48;
127 NSBitmapImageRep* ns_image_rep4;
128 BitmapImageRep(kWidth4x, kHeight4x, &ns_image_rep4);
129 base::scoped_nsobject<NSImage> ns_image(
130 [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
131 [ns_image addRepresentation:ns_image_rep4];
133 gfx::Image image(ns_image.release());
135 EXPECT_EQ(1u, image.RepresentationCount());
137 const gfx::ImageSkia* image_skia = image.ToImageSkia();
139 std::vector<float> scales;
140 scales.push_back(1.0f);
141 scales.push_back(2.0f);
142 EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
145 // ToImageSkia should create a second representation.
146 EXPECT_EQ(2u, image.RepresentationCount());
149 TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
150 const int kWidth1x = 10;
151 const int kHeight1x= 12;
152 const int kWidth2x = 20;
153 const int kHeight2x = 24;
155 gfx::ImageSkia image_skia;
156 image_skia.AddRepresentation(gfx::ImageSkiaRep(
157 gt::CreateBitmap(kWidth1x, kHeight1x), 1.0f));
158 image_skia.AddRepresentation(gfx::ImageSkiaRep(
159 gt::CreateBitmap(kWidth2x, kHeight2x), 2.0f));
161 gfx::Image image(image_skia);
163 EXPECT_EQ(1u, image.RepresentationCount());
164 EXPECT_EQ(2u, image.ToImageSkia()->image_reps().size());
166 NSImage* ns_image = image.ToNSImage();
168 std::vector<float> scales;
169 scales.push_back(1.0f);
170 scales.push_back(2.0f);
171 EXPECT_TRUE(NSImageStructureMatches(ns_image, kWidth1x, kHeight1x, scales));
173 // Request for NSImage* should create a second representation.
174 EXPECT_EQ(2u, image.RepresentationCount());
177 TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
178 const int kSize1x = 25;
179 const int kSize2x = 50;
181 scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
182 scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
183 std::vector<gfx::ImagePNGRep> image_png_reps;
184 image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, 1.0f));
185 image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, 2.0f));
187 gfx::Image image(image_png_reps);
189 NSImage* ns_image = image.ToNSImage();
190 std::vector<float> scales;
191 scales.push_back(1.0f);
192 scales.push_back(2.0f);
193 EXPECT_TRUE(NSImageStructureMatches(ns_image, kSize1x, kSize1x, scales));
195 // Converting from PNG to NSImage should not go through ImageSkia.
196 EXPECT_FALSE(image.HasRepresentation(gfx::Image::kImageRepSkia));
198 // Convert to ImageSkia to check pixel contents of NSImageReps.
199 gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
200 EXPECT_TRUE(gt::IsEqual(bytes1x,
201 image_skia.GetRepresentation(1.0f).sk_bitmap()));
202 EXPECT_TRUE(gt::IsEqual(bytes2x,
203 image_skia.GetRepresentation(2.0f).sk_bitmap()));