mac: Fix SkiaUtilsMacTest.NSImageRepToSkBitmap.
[chromium-blink-merge.git] / skia / ext / skia_utils_mac_unittest.mm
blobad505c71af8c4cfb3759fed9655ca38fe63b8271
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 "skia/ext/skia_utils_mac.h"
7 #import <AppKit/AppKit.h>
9 #include "base/mac/scoped_nsobject.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "third_party/skia/include/core/SkCanvas.h"
12 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
14 namespace {
16 class SkiaUtilsMacTest : public testing::Test {
17  public:
18   // Creates a red or blue bitmap.
19   SkBitmap CreateSkBitmap(int width, int height, bool isred, bool tfbit);
21   // Creates a red image.
22   NSImage* CreateNSImage(int width, int height);
24   // Checks that the given bitmap rep is actually red or blue.
25   void TestImageRep(NSBitmapImageRep* imageRep, bool isred);
27   // Checks that the given bitmap is red.
28   void TestSkBitmap(const SkBitmap& bitmap);
30   enum BitLockerTest {
31     TestIdentity = 0,
32     TestTranslate = 1,
33     TestClip = 2,
34     TestXClip = TestTranslate | TestClip,
35     TestNoBits = 4,
36     TestTranslateNoBits = TestTranslate | TestNoBits,
37     TestClipNoBits = TestClip | TestNoBits,
38     TestXClipNoBits = TestXClip | TestNoBits,
39   };
40   void RunBitLockerTest(BitLockerTest test);
42   // If not red, is blue.
43   // If not tfbit (twenty-four-bit), is 444.
44   void ShapeHelper(int width, int height, bool isred, bool tfbit);
47 SkBitmap SkiaUtilsMacTest::CreateSkBitmap(int width, int height,
48                                           bool isred, bool tfbit) {
49   SkColorType ct = tfbit ? kN32_SkColorType : kARGB_4444_SkColorType;
50   SkImageInfo info = SkImageInfo::Make(width, height, ct, kPremul_SkAlphaType);
52   SkBitmap bitmap;
53   bitmap.allocPixels(info);
55   if (isred)
56     bitmap.eraseARGB(0xff, 0xff, 0, 0);
57   else
58     bitmap.eraseARGB(0xff, 0, 0, 0xff);
60   return bitmap;
63 NSImage* SkiaUtilsMacTest::CreateNSImage(int width, int height) {
64   base::scoped_nsobject<NSBitmapImageRep> bitmap([[NSBitmapImageRep alloc]
65       initWithBitmapDataPlanes:nil
66                     pixelsWide:width
67                     pixelsHigh:height
68                  bitsPerSample:8
69                samplesPerPixel:4
70                       hasAlpha:YES
71                       isPlanar:NO
72                 colorSpaceName:NSCalibratedRGBColorSpace
73                   bitmapFormat:0
74                    bytesPerRow:4 * width
75                   bitsPerPixel:32]);
77   {
78     gfx::ScopedNSGraphicsContextSaveGState scopedGState;
79     [NSGraphicsContext
80         setCurrentContext:[NSGraphicsContext
81                               graphicsContextWithBitmapImageRep:bitmap]];
83     CGFloat comps[] = {1.0, 0.0, 0.0, 1.0};
84     NSColor* color =
85         [NSColor colorWithColorSpace:[NSColorSpace genericRGBColorSpace]
86                           components:comps
87                                count:4];
88     [color set];
89     NSRectFill(NSMakeRect(0, 0, width, height));
90   }
92   base::scoped_nsobject<NSImage> image(
93       [[NSImage alloc] initWithSize:NSMakeSize(width, height)]);
94   [image addRepresentation:bitmap];
96   return [image.release() autorelease];
99 void SkiaUtilsMacTest::TestImageRep(NSBitmapImageRep* imageRep, bool isred) {
100   // Get the color of a pixel and make sure it looks fine
101   int x = [imageRep size].width > 17 ? 17 : 0;
102   int y = [imageRep size].height > 17 ? 17 : 0;
103   NSColor* color = [imageRep colorAtX:x y:y];
104   CGFloat red = 0, green = 0, blue = 0, alpha = 0;
106   // SkBitmapToNSImage returns a bitmap in the calibrated color space (sRGB),
107   // while NSReadPixel returns a color in the device color space. Convert back
108   // to the calibrated color space before testing.
109   color = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
111   [color getRed:&red green:&green blue:&blue alpha:&alpha];
113   // Be tolerant of floating point rounding and lossy color space conversions.
114   if (isred) {
115     EXPECT_GT(red, 0.95);
116     EXPECT_LT(blue, 0.05);
117   } else {
118     EXPECT_LT(red, 0.05);
119     EXPECT_GT(blue, 0.95);
120   }
121   EXPECT_LT(green, 0.05);
122   EXPECT_GT(alpha, 0.95);
125 void SkiaUtilsMacTest::TestSkBitmap(const SkBitmap& bitmap) {
126   int x = bitmap.width() > 17 ? 17 : 0;
127   int y = bitmap.height() > 17 ? 17 : 0;
128   SkColor color = bitmap.getColor(x, y);
130   EXPECT_EQ(255u, SkColorGetR(color));
131   EXPECT_EQ(0u, SkColorGetB(color));
132   EXPECT_EQ(0u, SkColorGetG(color));
133   EXPECT_EQ(255u, SkColorGetA(color));
136 // setBitmapDevice has been deprecated/removed. Is this test still useful?
137 void SkiaUtilsMacTest::RunBitLockerTest(BitLockerTest test) {
138   const unsigned width = 2;
139   const unsigned height = 2;
140   const unsigned storageSize = width * height;
141   const unsigned original[] = {0xFF333333, 0xFF666666, 0xFF999999, 0xFFCCCCCC};
142   EXPECT_EQ(storageSize, sizeof(original) / sizeof(original[0]));
143   unsigned bits[storageSize];
144   memcpy(bits, original, sizeof(original));
145   SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
146   SkBitmap bitmap;
147   bitmap.installPixels(info, bits, info.minRowBytes());
149   SkCanvas canvas(bitmap);
150   if (test & TestTranslate)
151     canvas.translate(width / 2, 0);
152   if (test & TestClip) {
153     SkRect clipRect = {0, height / 2, width, height};
154     canvas.clipRect(clipRect);
155   }
156   {
157     gfx::SkiaBitLocker bitLocker(&canvas);
158     CGContextRef cgContext = bitLocker.cgContext();
159     CGColorRef testColor = CGColorGetConstantColor(kCGColorWhite);
160     CGContextSetFillColorWithColor(cgContext, testColor);
161     CGRect cgRect = {{0, 0}, {width, height}};
162     CGContextFillRect(cgContext, cgRect);
163     if (test & TestNoBits) {
164       if (test & TestClip) {
165         SkRect clipRect = {0, height / 2, width, height};
166         canvas.clipRect(clipRect);
167       }
168     }
169   }
170   const unsigned results[][storageSize] = {
171     {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, // identity
172     {0xFF333333, 0xFFFFFFFF, 0xFF999999, 0xFFFFFFFF}, // translate
173     {0xFF333333, 0xFF666666, 0xFFFFFFFF, 0xFFFFFFFF}, // clip
174     {0xFF333333, 0xFF666666, 0xFF999999, 0xFFFFFFFF}  // translate | clip
175   };
176   for (unsigned index = 0; index < storageSize; index++)
177     EXPECT_EQ(results[test & ~TestNoBits][index], bits[index]);
180 void SkiaUtilsMacTest::ShapeHelper(int width, int height,
181                                    bool isred, bool tfbit) {
182   SkBitmap thing(CreateSkBitmap(width, height, isred, tfbit));
184   // Confirm size
185   NSImage* image = gfx::SkBitmapToNSImage(thing);
186   EXPECT_DOUBLE_EQ([image size].width, (double)width);
187   EXPECT_DOUBLE_EQ([image size].height, (double)height);
189   EXPECT_TRUE([[image representations] count] == 1);
190   EXPECT_TRUE([[[image representations] lastObject]
191       isKindOfClass:[NSBitmapImageRep class]]);
192   TestImageRep([[image representations] lastObject], isred);
195 TEST_F(SkiaUtilsMacTest, BitmapToNSImage_RedSquare64x64) {
196   ShapeHelper(64, 64, true, true);
199 TEST_F(SkiaUtilsMacTest, BitmapToNSImage_BlueRectangle199x19) {
200   ShapeHelper(199, 19, false, true);
203 TEST_F(SkiaUtilsMacTest, BitmapToNSImage_BlueRectangle444) {
204   ShapeHelper(200, 200, false, false);
207 TEST_F(SkiaUtilsMacTest, BitmapToNSBitmapImageRep_BlueRectangle20x30) {
208   int width = 20;
209   int height = 30;
211   SkBitmap bitmap(CreateSkBitmap(width, height, false, true));
212   NSBitmapImageRep* imageRep = gfx::SkBitmapToNSBitmapImageRep(bitmap);
214   EXPECT_DOUBLE_EQ(width, [imageRep size].width);
215   EXPECT_DOUBLE_EQ(height, [imageRep size].height);
216   TestImageRep(imageRep, false);
219 TEST_F(SkiaUtilsMacTest, NSImageRepToSkBitmap) {
220   int width = 10;
221   int height = 15;
223   NSImage* image = CreateNSImage(width, height);
224   EXPECT_EQ(1u, [[image representations] count]);
225   NSBitmapImageRep* imageRep = [[image representations] lastObject];
226   NSColorSpace* colorSpace = [NSColorSpace genericRGBColorSpace];
227   SkBitmap bitmap(gfx::NSImageRepToSkBitmapWithColorSpace(
228       imageRep, [image size], false, [colorSpace CGColorSpace]));
229   TestSkBitmap(bitmap);
232 TEST_F(SkiaUtilsMacTest, BitLocker_Identity) {
233   RunBitLockerTest(SkiaUtilsMacTest::TestIdentity);
236 TEST_F(SkiaUtilsMacTest, BitLocker_Translate) {
237   RunBitLockerTest(SkiaUtilsMacTest::TestTranslate);
240 TEST_F(SkiaUtilsMacTest, BitLocker_Clip) {
241   RunBitLockerTest(SkiaUtilsMacTest::TestClip);
244 TEST_F(SkiaUtilsMacTest, BitLocker_XClip) {
245   RunBitLockerTest(SkiaUtilsMacTest::TestXClip);
248 TEST_F(SkiaUtilsMacTest, BitLocker_NoBits) {
249   RunBitLockerTest(SkiaUtilsMacTest::TestNoBits);
252 TEST_F(SkiaUtilsMacTest, BitLocker_TranslateNoBits) {
253   RunBitLockerTest(SkiaUtilsMacTest::TestTranslateNoBits);
256 TEST_F(SkiaUtilsMacTest, BitLocker_ClipNoBits) {
257   RunBitLockerTest(SkiaUtilsMacTest::TestClipNoBits);
260 TEST_F(SkiaUtilsMacTest, BitLocker_XClipNoBits) {
261   RunBitLockerTest(SkiaUtilsMacTest::TestXClipNoBits);
264 }  // namespace