Home | History | Annotate | Download | only in ext
      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