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