• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4
5#include <Cocoa/Cocoa.h>
6
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"
15
16namespace {
17
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] *
24//   scale.
25bool NSImageStructureMatches(
26    NSImage* ns_image,
27    int width,
28    int height,
29    const std::vector<float>& scales) {
30  if (!ns_image ||
31      [ns_image size].width != width ||
32      [ns_image size].height != height ||
33      [ns_image representations].count != scales.size()) {
34    return false;
35  }
36
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];
42      if (ns_image_rep &&
43          [ns_image_rep pixelsWide] == width * scale &&
44          [ns_image_rep pixelsHigh] == height * scale) {
45        found_match = true;
46        break;
47      }
48    }
49    if (!found_match)
50      return false;
51  }
52  return true;
53}
54
55void BitmapImageRep(int width, int height,
56     NSBitmapImageRep** image_rep) {
57  *image_rep = [[[NSBitmapImageRep alloc]
58      initWithBitmapDataPlanes:NULL
59                    pixelsWide:width
60                   pixelsHigh:height
61                bitsPerSample:8
62              samplesPerPixel:3
63                     hasAlpha:NO
64                     isPlanar:NO
65               colorSpaceName:NSDeviceRGBColorSpace
66                 bitmapFormat:0
67                  bytesPerRow:0
68                 bitsPerPixel:0]
69      autorelease];
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;
73}
74
75class ImageMacTest : public testing::Test {
76 public:
77  ImageMacTest() {
78    gfx::ImageSkia::SetSupportedScales(gfx::test::Get1xAnd2xScales());
79  }
80
81  virtual ~ImageMacTest() {
82  }
83
84 private:
85  DISALLOW_COPY_AND_ASSIGN(ImageMacTest);
86};
87
88namespace gt = gfx::test;
89
90TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
91  const int kWidth1x = 10;
92  const int kHeight1x = 12;
93  const int kWidth2x = 20;
94  const int kHeight2x = 24;
95
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];
104
105  gfx::Image image(ns_image.release());
106
107  EXPECT_EQ(1u, image.RepresentationCount());
108
109  const gfx::ImageSkia* image_skia = image.ToImageSkia();
110
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,
115                                            scales));
116
117  // ToImageSkia should create a second representation.
118  EXPECT_EQ(2u, image.RepresentationCount());
119}
120
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
123// 2x;
124TEST_F(ImageMacTest, UnalignedMultiResolutionNSImageToImageSkia) {
125  const int kWidth1x = 10;
126  const int kHeight1x= 12;
127  const int kWidth4x = 40;
128  const int kHeight4x = 48;
129
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];
135
136  gfx::Image image(ns_image.release());
137
138  EXPECT_EQ(1u, image.RepresentationCount());
139
140  const gfx::ImageSkia* image_skia = image.ToImageSkia();
141
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,
146                                            scales));
147
148  // ToImageSkia should create a second representation.
149  EXPECT_EQ(2u, image.RepresentationCount());
150}
151
152TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
153  const int kWidth1x = 10;
154  const int kHeight1x= 12;
155  const int kWidth2x = 20;
156  const int kHeight2x = 24;
157
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));
163
164  gfx::Image image(image_skia);
165
166  EXPECT_EQ(1u, image.RepresentationCount());
167  EXPECT_EQ(2u, image.ToImageSkia()->image_reps().size());
168
169  NSImage* ns_image = image.ToNSImage();
170
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));
175
176  // Request for NSImage* should create a second representation.
177  EXPECT_EQ(2u, image.RepresentationCount());
178}
179
180TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
181  const int kSize1x = 25;
182  const int kSize2x = 50;
183
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));
189
190  gfx::Image image(image_png_reps);
191
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));
197
198  // Converting from PNG to NSImage should not go through ImageSkia.
199  EXPECT_FALSE(image.HasRepresentation(gfx::Image::kImageRepSkia));
200
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()));
207}
208
209} // namespace
210