Home | History | Annotate | Download | only in image
      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 <Cocoa/Cocoa.h>
      6 
      7 #include "base/logging.h"
      8 #include "base/mac/scoped_nsobject.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 #include "ui/gfx/image/image.h"
     11 #include "ui/gfx/image/image_png_rep.h"
     12 #include "ui/gfx/image/image_skia.h"
     13 #include "ui/gfx/image/image_skia_util_mac.h"
     14 #include "ui/gfx/image/image_unittest_util.h"
     15 
     16 namespace {
     17 
     18 // Returns true if the structure of |ns_image| matches the structure
     19 // described by |width|, |height|, and |scale_factors|.
     20 // The structure matches if:
     21 // - |ns_image| is not nil.
     22 // - |ns_image| has NSImageReps of |scale_factors|.
     23 // - Each of the NSImageReps has a pixel size of [|ns_image| size] *
     24 //   scale_factor.
     25 bool NSImageStructureMatches(
     26     NSImage* ns_image,
     27     int width,
     28     int height,
     29     const std::vector<ui::ScaleFactor>& scale_factors) {
     30   if (!ns_image ||
     31       [ns_image size].width != width ||
     32       [ns_image size].height != height ||
     33       [ns_image representations].count != scale_factors.size()) {
     34     return false;
     35   }
     36 
     37   for (size_t i = 0; i < scale_factors.size(); ++i) {
     38     float scale = ui::GetScaleFactorScale(scale_factors[i]);
     39     bool found_match = false;
     40     for (size_t j = 0; j < [ns_image representations].count; ++j) {
     41       NSImageRep* ns_image_rep = [[ns_image representations] objectAtIndex:j];
     42       if (ns_image_rep &&
     43           [ns_image_rep pixelsWide] == width * scale &&
     44           [ns_image_rep pixelsHigh] == height * scale) {
     45         found_match = true;
     46         break;
     47       }
     48     }
     49     if (!found_match)
     50       return false;
     51   }
     52   return true;
     53 }
     54 
     55 void BitmapImageRep(int width, int height,
     56      NSBitmapImageRep** image_rep) {
     57   *image_rep = [[[NSBitmapImageRep alloc]
     58       initWithBitmapDataPlanes:NULL
     59                     pixelsWide:width
     60                    pixelsHigh:height
     61                 bitsPerSample:8
     62               samplesPerPixel:3
     63                      hasAlpha:NO
     64                      isPlanar:NO
     65                colorSpaceName:NSDeviceRGBColorSpace
     66                  bitmapFormat:0
     67                   bytesPerRow:0
     68                  bitsPerPixel:0]
     69       autorelease];
     70   unsigned char* image_rep_data = [*image_rep bitmapData];
     71   for (int i = 0; i < width * height * 3; ++i)
     72     image_rep_data[i] = 255;
     73 }
     74 
     75 class ImageMacTest : public testing::Test {
     76  public:
     77   ImageMacTest()
     78       : supported_scale_factors_(gfx::test::Get1xAnd2xScaleFactors()) {
     79   }
     80 
     81   virtual ~ImageMacTest() {
     82   }
     83 
     84  private:
     85   ui::test::ScopedSetSupportedScaleFactors supported_scale_factors_;
     86 
     87   DISALLOW_COPY_AND_ASSIGN(ImageMacTest);
     88 };
     89 
     90 namespace gt = gfx::test;
     91 
     92 TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
     93   const int kWidth1x = 10;
     94   const int kHeight1x = 12;
     95   const int kWidth2x = 20;
     96   const int kHeight2x = 24;
     97 
     98   NSBitmapImageRep* ns_image_rep1;
     99   BitmapImageRep(kWidth1x, kHeight1x, &ns_image_rep1);
    100   NSBitmapImageRep* ns_image_rep2;
    101   BitmapImageRep(kWidth2x, kHeight2x, &ns_image_rep2);
    102   base::scoped_nsobject<NSImage> ns_image(
    103       [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
    104   [ns_image addRepresentation:ns_image_rep1];
    105   [ns_image addRepresentation:ns_image_rep2];
    106 
    107   gfx::Image image(ns_image.release());
    108 
    109   EXPECT_EQ(1u, image.RepresentationCount());
    110 
    111   const gfx::ImageSkia* image_skia = image.ToImageSkia();
    112 
    113   std::vector<ui::ScaleFactor> scale_factors;
    114   scale_factors.push_back(ui::SCALE_FACTOR_100P);
    115   scale_factors.push_back(ui::SCALE_FACTOR_200P);
    116   EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
    117                                             scale_factors));
    118 
    119   // ToImageSkia should create a second representation.
    120   EXPECT_EQ(2u, image.RepresentationCount());
    121 }
    122 
    123 // Test that convertng to an ImageSkia from an NSImage with scale factors
    124 // other than 1x and 2x results in an ImageSkia with scale factors 1x and
    125 // 2x;
    126 TEST_F(ImageMacTest, UnalignedMultiResolutionNSImageToImageSkia) {
    127   const int kWidth1x = 10;
    128   const int kHeight1x= 12;
    129   const int kWidth4x = 40;
    130   const int kHeight4x = 48;
    131 
    132   NSBitmapImageRep* ns_image_rep4;
    133   BitmapImageRep(kWidth4x, kHeight4x, &ns_image_rep4);
    134   base::scoped_nsobject<NSImage> ns_image(
    135       [[NSImage alloc] initWithSize:NSMakeSize(kWidth1x, kHeight1x)]);
    136   [ns_image addRepresentation:ns_image_rep4];
    137 
    138   gfx::Image image(ns_image.release());
    139 
    140   EXPECT_EQ(1u, image.RepresentationCount());
    141 
    142   const gfx::ImageSkia* image_skia = image.ToImageSkia();
    143 
    144   std::vector<ui::ScaleFactor> scale_factors;
    145   scale_factors.push_back(ui::SCALE_FACTOR_100P);
    146   scale_factors.push_back(ui::SCALE_FACTOR_200P);
    147   EXPECT_TRUE(gt::ImageSkiaStructureMatches(*image_skia, kWidth1x, kHeight1x,
    148                                             scale_factors));
    149 
    150   // ToImageSkia should create a second representation.
    151   EXPECT_EQ(2u, image.RepresentationCount());
    152 }
    153 
    154 TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
    155   const int kWidth1x = 10;
    156   const int kHeight1x= 12;
    157   const int kWidth2x = 20;
    158   const int kHeight2x = 24;
    159 
    160   gfx::ImageSkia image_skia;
    161   image_skia.AddRepresentation(gfx::ImageSkiaRep(
    162       gt::CreateBitmap(kWidth1x, kHeight1x), ui::SCALE_FACTOR_100P));
    163   image_skia.AddRepresentation(gfx::ImageSkiaRep(
    164       gt::CreateBitmap(kWidth2x, kHeight2x), ui::SCALE_FACTOR_200P));
    165 
    166   gfx::Image image(image_skia);
    167 
    168   EXPECT_EQ(1u, image.RepresentationCount());
    169   EXPECT_EQ(2u, image.ToImageSkia()->image_reps().size());
    170 
    171   NSImage* ns_image = image.ToNSImage();
    172 
    173   std::vector<ui::ScaleFactor> scale_factors;
    174   scale_factors.push_back(ui::SCALE_FACTOR_100P);
    175   scale_factors.push_back(ui::SCALE_FACTOR_200P);
    176   EXPECT_TRUE(NSImageStructureMatches(ns_image, kWidth1x, kHeight1x,
    177                                       scale_factors));
    178 
    179   // Request for NSImage* should create a second representation.
    180   EXPECT_EQ(2u, image.RepresentationCount());
    181 }
    182 
    183 TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
    184   const int kSize1x = 25;
    185   const int kSize2x = 50;
    186 
    187   scoped_refptr<base::RefCountedMemory> bytes1x = gt::CreatePNGBytes(kSize1x);
    188   scoped_refptr<base::RefCountedMemory> bytes2x = gt::CreatePNGBytes(kSize2x);
    189   std::vector<gfx::ImagePNGRep> image_png_reps;
    190   image_png_reps.push_back(gfx::ImagePNGRep(bytes1x, ui::SCALE_FACTOR_100P));
    191   image_png_reps.push_back(gfx::ImagePNGRep(bytes2x, ui::SCALE_FACTOR_200P));
    192 
    193   gfx::Image image(image_png_reps);
    194 
    195   NSImage* ns_image = image.ToNSImage();
    196   std::vector<ui::ScaleFactor> scale_factors;
    197   scale_factors.push_back(ui::SCALE_FACTOR_100P);
    198   scale_factors.push_back(ui::SCALE_FACTOR_200P);
    199   EXPECT_TRUE(NSImageStructureMatches(ns_image, kSize1x, kSize1x,
    200                                       scale_factors));
    201 
    202   // Converting from PNG to NSImage should not go through ImageSkia.
    203   EXPECT_FALSE(image.HasRepresentation(gfx::Image::kImageRepSkia));
    204 
    205   // Convert to ImageSkia to check pixel contents of NSImageReps.
    206   gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
    207   EXPECT_TRUE(gt::IsEqual(bytes1x,
    208       image_skia.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap()));
    209   EXPECT_TRUE(gt::IsEqual(bytes2x,
    210       image_skia.GetRepresentation(ui::SCALE_FACTOR_200P).sk_bitmap()));
    211 }
    212 
    213 } // namespace
    214