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