skia_utils_mac_unittest.mm 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  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. #include "skia/ext/skia_utils_mac.h"
  5. #import <AppKit/AppKit.h>
  6. #include "base/mac/foundation_util.h"
  7. #include "base/mac/mac_util.h"
  8. #include "base/mac/scoped_nsobject.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. #include "third_party/skia/include/core/SkColorSpace.h"
  11. #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
  12. namespace {
  13. class SkiaUtilsMacTest : public testing::Test {
  14. public:
  15. enum class TestColor {
  16. kRed,
  17. kBlue,
  18. };
  19. enum class ColorType {
  20. k24Bit, // kN32_SkColorType
  21. k16Bit, // kARGB_4444_SkColorType
  22. };
  23. // Creates a test bitmap of the specified color and color type.
  24. SkBitmap CreateSkBitmap(int width,
  25. int height,
  26. TestColor test_color,
  27. ColorType color_type);
  28. // Creates a red image.
  29. NSImage* CreateNSImage(int width, int height);
  30. // Checks that the given bitmap rep is actually the correct color.
  31. void TestImageRep(NSBitmapImageRep* image_rep, TestColor test_color);
  32. // Checks that the given bitmap is red.
  33. void TestSkBitmap(const SkBitmap& bitmap);
  34. // Tests `SkBitmapToNSImageWithColorSpace` for a specific combination of color
  35. // and color type. Creates a bitmap with `CreateSkBitmap`, converts it into an
  36. // `NSImage`, then tests it with `TestImageRep`.
  37. void ShapeHelper(int width,
  38. int height,
  39. TestColor test_color,
  40. ColorType color_type);
  41. };
  42. SkBitmap SkiaUtilsMacTest::CreateSkBitmap(int width,
  43. int height,
  44. TestColor test_color,
  45. ColorType color_type) {
  46. SkColorType sk_color_type = color_type == ColorType::k24Bit
  47. ? kN32_SkColorType
  48. : kARGB_4444_SkColorType;
  49. SkImageInfo info =
  50. SkImageInfo::Make(width, height, sk_color_type, kPremul_SkAlphaType,
  51. SkColorSpace::MakeSRGB());
  52. SkBitmap bitmap;
  53. bitmap.allocPixels(info);
  54. if (test_color == TestColor::kRed)
  55. bitmap.eraseARGB(0xff, 0xff, 0, 0);
  56. else
  57. bitmap.eraseARGB(0xff, 0, 0, 0xff);
  58. return bitmap;
  59. }
  60. NSImage* SkiaUtilsMacTest::CreateNSImage(int width, int height) {
  61. // An `NSBitmapImageRep` can only be created with a handful of named color
  62. // spaces, and sRGB isn't one. Do a retagging after creation to switch it.
  63. base::scoped_nsobject<NSBitmapImageRep> initial_bitmap(
  64. [[NSBitmapImageRep alloc]
  65. initWithBitmapDataPlanes:nil
  66. pixelsWide:width
  67. pixelsHigh:height
  68. bitsPerSample:8
  69. samplesPerPixel:4
  70. hasAlpha:YES
  71. isPlanar:NO
  72. colorSpaceName:NSCalibratedRGBColorSpace
  73. bitmapFormat:0
  74. bytesPerRow:4 * width
  75. bitsPerPixel:32]);
  76. NSBitmapImageRep* bitmap = [initial_bitmap
  77. bitmapImageRepByRetaggingWithColorSpace:NSColorSpace.sRGBColorSpace];
  78. {
  79. gfx::ScopedNSGraphicsContextSaveGState scopedGState;
  80. [NSGraphicsContext
  81. setCurrentContext:[NSGraphicsContext
  82. graphicsContextWithBitmapImageRep:bitmap]];
  83. CGFloat comps[] = {1.0, 0.0, 0.0, 1.0};
  84. NSColor* color = [NSColor colorWithColorSpace:NSColorSpace.sRGBColorSpace
  85. components:comps
  86. count:4];
  87. [color set];
  88. NSRectFill(NSMakeRect(0, 0, width, height));
  89. }
  90. base::scoped_nsobject<NSImage> image(
  91. [[NSImage alloc] initWithSize:NSMakeSize(width, height)]);
  92. [image addRepresentation:bitmap];
  93. return [image.release() autorelease];
  94. }
  95. void SkiaUtilsMacTest::TestImageRep(NSBitmapImageRep* image_rep,
  96. TestColor test_color) {
  97. // Get the color of a pixel and make sure it looks fine.
  98. int x = image_rep.size.width > 17 ? 17 : 0;
  99. int y = image_rep.size.height > 17 ? 17 : 0;
  100. NSColor* color = [image_rep colorAtX:x y:y];
  101. ASSERT_EQ(4, color.numberOfComponents);
  102. CGFloat color_components[4];
  103. [color getComponents:color_components];
  104. const CGFloat& red = color_components[0];
  105. const CGFloat& green = color_components[1];
  106. const CGFloat& blue = color_components[2];
  107. const CGFloat& alpha = color_components[3];
  108. // Be a little tolerant of floating point rounding, maybe, but everything is
  109. // done in SRGB so there should be no color space conversion affecting things.
  110. if (test_color == TestColor::kRed) {
  111. EXPECT_GT(red, 0.9995);
  112. EXPECT_LT(blue, 0.0005);
  113. } else {
  114. EXPECT_LT(red, 0.0005);
  115. EXPECT_GT(blue, 0.9995);
  116. }
  117. EXPECT_LT(green, 0.0005);
  118. EXPECT_GT(alpha, 0.9995);
  119. }
  120. void SkiaUtilsMacTest::TestSkBitmap(const SkBitmap& bitmap) {
  121. int x = bitmap.width() > 17 ? 17 : 0;
  122. int y = bitmap.height() > 17 ? 17 : 0;
  123. SkColor color = bitmap.getColor(x, y);
  124. EXPECT_EQ(255u, SkColorGetR(color));
  125. EXPECT_EQ(0u, SkColorGetB(color));
  126. EXPECT_EQ(0u, SkColorGetG(color));
  127. EXPECT_EQ(255u, SkColorGetA(color));
  128. }
  129. void SkiaUtilsMacTest::ShapeHelper(int width,
  130. int height,
  131. TestColor test_color,
  132. ColorType color_type) {
  133. SkBitmap bitmap(CreateSkBitmap(width, height, test_color, color_type));
  134. // Confirm size
  135. NSImage* image = skia::SkBitmapToNSImageWithColorSpace(
  136. bitmap, base::mac::GetSRGBColorSpace());
  137. EXPECT_DOUBLE_EQ(image.size.width, (CGFloat)width);
  138. EXPECT_DOUBLE_EQ(image.size.height, (CGFloat)height);
  139. EXPECT_TRUE(image.representations.count == 1);
  140. EXPECT_TRUE([image.representations.lastObject
  141. isKindOfClass:[NSBitmapImageRep class]]);
  142. TestImageRep(base::mac::ObjCCastStrict<NSBitmapImageRep>(
  143. image.representations.lastObject),
  144. test_color);
  145. }
  146. TEST_F(SkiaUtilsMacTest, BitmapToNSImage_RedSquare64x64) {
  147. ShapeHelper(64, 64, TestColor::kRed, ColorType::k24Bit);
  148. }
  149. TEST_F(SkiaUtilsMacTest, BitmapToNSImage_BlueRectangle199x19) {
  150. ShapeHelper(199, 19, TestColor::kBlue, ColorType::k24Bit);
  151. }
  152. TEST_F(SkiaUtilsMacTest, BitmapToNSImage_BlueRectangle444) {
  153. ShapeHelper(200, 200, TestColor::kBlue, ColorType::k16Bit);
  154. }
  155. TEST_F(SkiaUtilsMacTest, BitmapToNSBitmapImageRep_BlueRectangle20x30) {
  156. int width = 20;
  157. int height = 30;
  158. SkBitmap bitmap(
  159. CreateSkBitmap(width, height, TestColor::kBlue, ColorType::k24Bit));
  160. NSBitmapImageRep* imageRep = skia::SkBitmapToNSBitmapImageRepWithColorSpace(
  161. bitmap, base::mac::GetSRGBColorSpace());
  162. EXPECT_DOUBLE_EQ(width, imageRep.size.width);
  163. EXPECT_DOUBLE_EQ(height, imageRep.size.height);
  164. TestImageRep(imageRep, TestColor::kBlue);
  165. }
  166. TEST_F(SkiaUtilsMacTest, NSImageRepToSkBitmap) {
  167. int width = 10;
  168. int height = 15;
  169. NSImage* image = CreateNSImage(width, height);
  170. EXPECT_EQ(1u, image.representations.count);
  171. NSBitmapImageRep* imageRep = base::mac::ObjCCastStrict<NSBitmapImageRep>(
  172. image.representations.lastObject);
  173. SkBitmap bitmap(skia::NSImageRepToSkBitmapWithColorSpace(
  174. imageRep, image.size, false, base::mac::GetSRGBColorSpace()));
  175. TestSkBitmap(bitmap);
  176. }
  177. } // namespace