• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // Because the unit tests for gfx::Image are spread across multiple
6 // implementation files, this header contains the reusable components.
7 
8 #include "ui/gfx/image/image_unittest_util.h"
9 
10 #include <cmath>
11 
12 #include "base/memory/scoped_ptr.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "ui/gfx/codec/png_codec.h"
16 #include "ui/gfx/image/image_skia.h"
17 
18 #if defined(TOOLKIT_GTK)
19 #include <gtk/gtk.h>
20 #include "ui/gfx/gtk_util.h"
21 #elif defined(OS_IOS)
22 #include "base/mac/foundation_util.h"
23 #include "base/mac/scoped_cftyperef.h"
24 #include "skia/ext/skia_utils_ios.h"
25 #elif defined(OS_MACOSX)
26 #include "base/mac/mac_util.h"
27 #include "skia/ext/skia_utils_mac.h"
28 #endif
29 
30 namespace gfx {
31 namespace test {
32 
33 namespace {
34 
ColorComponentsClose(SkColor component1,SkColor component2)35 bool ColorComponentsClose(SkColor component1, SkColor component2) {
36   int c1 = static_cast<int>(component1);
37   int c2 = static_cast<int>(component2);
38   return std::abs(c1 - c2) <= 40;
39 }
40 
ColorsClose(SkColor color1,SkColor color2)41 bool ColorsClose(SkColor color1, SkColor color2) {
42   // Be tolerant of floating point rounding and lossy color space conversions.
43   return ColorComponentsClose(SkColorGetR(color1), SkColorGetR(color2)) &&
44          ColorComponentsClose(SkColorGetG(color1), SkColorGetG(color2)) &&
45          ColorComponentsClose(SkColorGetB(color1), SkColorGetB(color2)) &&
46          ColorComponentsClose(SkColorGetA(color1), SkColorGetA(color2));
47 }
48 
49 }  // namespace
50 
Get1xAnd2xScales()51 std::vector<float> Get1xAnd2xScales() {
52   std::vector<float> scales;
53   scales.push_back(1.0f);
54   scales.push_back(2.0f);
55   return scales;
56 }
57 
CreateBitmap(int width,int height)58 const SkBitmap CreateBitmap(int width, int height) {
59   SkBitmap bitmap;
60   bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
61   bitmap.allocPixels();
62   bitmap.eraseRGB(0, 255, 0);
63   return bitmap;
64 }
65 
CreateImageSkia(int width,int height)66 gfx::ImageSkia CreateImageSkia(int width, int height) {
67   return gfx::ImageSkia::CreateFrom1xBitmap(CreateBitmap(width, height));
68 }
69 
CreatePNGBytes(int edge_size)70 scoped_refptr<base::RefCountedMemory> CreatePNGBytes(int edge_size) {
71   SkBitmap bitmap = CreateBitmap(edge_size, edge_size);
72   scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes());
73   PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bytes->data());
74   return bytes;
75 }
76 
CreateImage()77 gfx::Image CreateImage() {
78   return CreateImage(100, 50);
79 }
80 
CreateImage(int width,int height)81 gfx::Image CreateImage(int width, int height) {
82   return gfx::Image::CreateFrom1xBitmap(CreateBitmap(width, height));
83 }
84 
IsEqual(const gfx::Image & img1,const gfx::Image & img2)85 bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) {
86   std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps();
87   gfx::ImageSkia image_skia2 = img2.AsImageSkia();
88   if (image_skia2.image_reps().size() != img1_reps.size())
89     return false;
90 
91   for (size_t i = 0; i < img1_reps.size(); ++i) {
92     float scale = img1_reps[i].scale();
93     const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
94     if (image_rep2.scale() != scale ||
95         !IsEqual(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap())) {
96       return false;
97     }
98   }
99   return true;
100 }
101 
IsEqual(const SkBitmap & bmp1,const SkBitmap & bmp2)102 bool IsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) {
103   if (bmp1.isNull() && bmp2.isNull())
104     return true;
105 
106   if (bmp1.width() != bmp2.width() ||
107       bmp1.height() != bmp2.height() ||
108       bmp1.config() != SkBitmap::kARGB_8888_Config ||
109       bmp2.config() != SkBitmap::kARGB_8888_Config) {
110     return false;
111   }
112 
113   SkAutoLockPixels lock1(bmp1);
114   SkAutoLockPixels lock2(bmp2);
115   if (!bmp1.getPixels() || !bmp2.getPixels())
116     return false;
117 
118   for (int y = 0; y < bmp1.height(); ++y) {
119     for (int x = 0; x < bmp1.width(); ++x) {
120       if (!ColorsClose(bmp1.getColor(x,y), bmp2.getColor(x,y)))
121         return false;
122     }
123   }
124 
125   return true;
126 }
127 
IsEqual(const scoped_refptr<base::RefCountedMemory> & bytes,const SkBitmap & bitmap)128 bool IsEqual(const scoped_refptr<base::RefCountedMemory>& bytes,
129              const SkBitmap& bitmap) {
130   SkBitmap decoded;
131   if (!bytes.get() ||
132       !PNGCodec::Decode(bytes->front(), bytes->size(), &decoded)) {
133     return bitmap.isNull();
134   }
135 
136   return IsEqual(bitmap, decoded);
137 }
138 
CheckImageIndicatesPNGDecodeFailure(const gfx::Image & image)139 void CheckImageIndicatesPNGDecodeFailure(const gfx::Image& image) {
140   SkBitmap bitmap = image.AsBitmap();
141   EXPECT_FALSE(bitmap.isNull());
142   EXPECT_LE(16, bitmap.width());
143   EXPECT_LE(16, bitmap.height());
144   SkAutoLockPixels auto_lock(bitmap);
145   CheckColors(bitmap.getColor(10, 10), SK_ColorRED);
146 }
147 
ImageSkiaStructureMatches(const gfx::ImageSkia & image_skia,int width,int height,const std::vector<float> & scales)148 bool ImageSkiaStructureMatches(
149     const gfx::ImageSkia& image_skia,
150     int width,
151     int height,
152     const std::vector<float>& scales) {
153   if (image_skia.isNull() ||
154       image_skia.width() != width ||
155       image_skia.height() != height ||
156       image_skia.image_reps().size() != scales.size()) {
157     return false;
158   }
159 
160   for (size_t i = 0; i < scales.size(); ++i) {
161     gfx::ImageSkiaRep image_rep =
162         image_skia.GetRepresentation(scales[i]);
163     if (image_rep.is_null() || image_rep.scale() != scales[i])
164       return false;
165 
166     if (image_rep.pixel_width() != static_cast<int>(width * scales[i]) ||
167         image_rep.pixel_height() != static_cast<int>(height * scales[i])) {
168       return false;
169     }
170   }
171   return true;
172 }
173 
IsEmpty(const gfx::Image & image)174 bool IsEmpty(const gfx::Image& image) {
175   const SkBitmap& bmp = *image.ToSkBitmap();
176   return bmp.isNull() ||
177          (bmp.width() == 0 && bmp.height() == 0);
178 }
179 
CreatePlatformImage()180 PlatformImage CreatePlatformImage() {
181   const SkBitmap bitmap(CreateBitmap(25, 25));
182 #if defined(OS_IOS)
183   float scale = ImageSkia::GetMaxSupportedScale();
184 
185   base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
186       CGColorSpaceCreateDeviceRGB());
187   UIImage* image =
188       gfx::SkBitmapToUIImageWithColorSpace(bitmap, scale, color_space);
189   base::mac::NSObjectRetain(image);
190   return image;
191 #elif defined(OS_MACOSX)
192   NSImage* image = gfx::SkBitmapToNSImage(bitmap);
193   base::mac::NSObjectRetain(image);
194   return image;
195 #elif defined(TOOLKIT_GTK)
196   return gfx::GdkPixbufFromSkBitmap(bitmap);
197 #else
198   return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
199 #endif
200 }
201 
GetPlatformRepresentationType()202 gfx::Image::RepresentationType GetPlatformRepresentationType() {
203 #if defined(OS_IOS)
204   return gfx::Image::kImageRepCocoaTouch;
205 #elif defined(OS_MACOSX)
206   return gfx::Image::kImageRepCocoa;
207 #elif defined(TOOLKIT_GTK)
208   return gfx::Image::kImageRepGdk;
209 #else
210   return gfx::Image::kImageRepSkia;
211 #endif
212 }
213 
ToPlatformType(const gfx::Image & image)214 PlatformImage ToPlatformType(const gfx::Image& image) {
215 #if defined(OS_IOS)
216   return image.ToUIImage();
217 #elif defined(OS_MACOSX)
218   return image.ToNSImage();
219 #elif defined(TOOLKIT_GTK)
220   return image.ToGdkPixbuf();
221 #else
222   return image.AsImageSkia();
223 #endif
224 }
225 
CopyPlatformType(const gfx::Image & image)226 PlatformImage CopyPlatformType(const gfx::Image& image) {
227 #if defined(OS_IOS)
228   return image.CopyUIImage();
229 #elif defined(OS_MACOSX)
230   return image.CopyNSImage();
231 #elif defined(TOOLKIT_GTK)
232   return image.CopyGdkPixbuf();
233 #else
234   return image.AsImageSkia();
235 #endif
236 }
237 
238 #if defined(OS_MACOSX)
239 // Defined in image_unittest_util_mac.mm.
240 #elif defined(TOOLKIT_GTK)
GetPlatformImageColor(PlatformImage image,int x,int y)241 SkColor GetPlatformImageColor(PlatformImage image, int x, int y) {
242   int n_channels = gdk_pixbuf_get_n_channels(image);
243   int rowstride = gdk_pixbuf_get_rowstride(image);
244   guchar* gdk_pixels = gdk_pixbuf_get_pixels(image);
245 
246   guchar* pixel = gdk_pixels + (y * rowstride) + (x * n_channels);
247   guchar alpha = gdk_pixbuf_get_has_alpha(image) ? pixel[3] : 255;
248   return SkColorSetARGB(alpha, pixel[0], pixel[1], pixel[2]);
249 }
250 #else
GetPlatformImageColor(PlatformImage image,int x,int y)251 SkColor GetPlatformImageColor(PlatformImage image, int x, int y) {
252   SkBitmap bitmap = *image.bitmap();
253   SkAutoLockPixels auto_lock(bitmap);
254   return bitmap.getColor(x, y);
255 }
256 #endif
257 
CheckColors(SkColor color1,SkColor color2)258 void CheckColors(SkColor color1, SkColor color2) {
259   EXPECT_TRUE(ColorsClose(color1, color2));
260 }
261 
CheckIsTransparent(SkColor color)262 void CheckIsTransparent(SkColor color) {
263   EXPECT_LT(SkColorGetA(color) / 255.0, 0.05);
264 }
265 
IsPlatformImageValid(PlatformImage image)266 bool IsPlatformImageValid(PlatformImage image) {
267 #if defined(OS_MACOSX) || defined(TOOLKIT_GTK)
268   return image != NULL;
269 #else
270   return !image.isNull();
271 #endif
272 }
273 
PlatformImagesEqual(PlatformImage image1,PlatformImage image2)274 bool PlatformImagesEqual(PlatformImage image1, PlatformImage image2) {
275 #if defined(OS_MACOSX) || defined(TOOLKIT_GTK)
276   return image1 == image2;
277 #else
278   return image1.BackedBySameObjectAs(image2);
279 #endif
280 }
281 
282 }  // namespace test
283 }  // namespace gfx
284