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   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