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