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