1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkData.h"
9 #include "SkCanvas.h"
10 
11 #include "SkGraphics.h"
12 #include "SkImageGenerator.h"
13 #include "SkImageInfoPriv.h"
14 #include "SkYUVAIndex.h"
15 #include "Test.h"
16 
17 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
18     #include "SkImageGeneratorCG.h"
19 #elif defined(SK_BUILD_FOR_WIN)
20     #include "SkImageGeneratorWIC.h"
21 #endif
22 
23 static bool gMyFactoryWasCalled;
24 
my_factory(sk_sp<SkData>)25 static std::unique_ptr<SkImageGenerator> my_factory(sk_sp<SkData>) {
26     gMyFactoryWasCalled = true;
27     return nullptr;
28 }
29 
test_imagegenerator_factory(skiatest::Reporter * reporter)30 static void test_imagegenerator_factory(skiatest::Reporter* reporter) {
31     // just need a non-empty data to test things
32     sk_sp<SkData> data(SkData::MakeWithCString("test_imagegenerator_factory"));
33 
34     gMyFactoryWasCalled = false;
35 
36     REPORTER_ASSERT(reporter, !gMyFactoryWasCalled);
37 
38     std::unique_ptr<SkImageGenerator> gen = SkImageGenerator::MakeFromEncoded(data);
39     REPORTER_ASSERT(reporter, nullptr == gen);
40     REPORTER_ASSERT(reporter, !gMyFactoryWasCalled);
41 
42     // Test is racy, in that it hopes no other thread is changing this global...
43     auto prev = SkGraphics::SetImageGeneratorFromEncodedDataFactory(my_factory);
44     gen = SkImageGenerator::MakeFromEncoded(data);
45     REPORTER_ASSERT(reporter, nullptr == gen);
46     REPORTER_ASSERT(reporter, gMyFactoryWasCalled);
47 
48     // This just verifies that the signatures match.
49 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
50     SkGraphics::SetImageGeneratorFromEncodedDataFactory(SkImageGeneratorCG::MakeFromEncodedCG);
51 #elif defined(SK_BUILD_FOR_WIN)
52     SkGraphics::SetImageGeneratorFromEncodedDataFactory(SkImageGeneratorWIC::MakeFromEncodedWIC);
53 #endif
54 
55     SkGraphics::SetImageGeneratorFromEncodedDataFactory(prev);
56 }
57 
58 class MyImageGenerator : public SkImageGenerator {
59 public:
MyImageGenerator()60     MyImageGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
61 };
62 
DEF_TEST(ImageGenerator,reporter)63 DEF_TEST(ImageGenerator, reporter) {
64     MyImageGenerator ig;
65     SkYUVASizeInfo sizeInfo;
66     sizeInfo.fSizes[0] = SkISize::Make(200, 200);
67     sizeInfo.fSizes[1] = SkISize::Make(100, 100);
68     sizeInfo.fSizes[2] = SkISize::Make( 50,  50);
69     sizeInfo.fSizes[3] = SkISize::Make( 25,  25);
70     sizeInfo.fWidthBytes[0] = 0;
71     sizeInfo.fWidthBytes[1] = 0;
72     sizeInfo.fWidthBytes[2] = 0;
73     sizeInfo.fWidthBytes[3] = 0;
74     void* planes[4] = { nullptr };
75     SkYUVAIndex yuvaIndices[4];
76     SkYUVColorSpace colorSpace;
77 
78     // Check that the YUV decoding API does not cause any crashes
79     ig.queryYUVA8(&sizeInfo, yuvaIndices, nullptr);
80     ig.queryYUVA8(&sizeInfo, yuvaIndices, &colorSpace);
81     sizeInfo.fWidthBytes[0] = 250;
82     sizeInfo.fWidthBytes[1] = 250;
83     sizeInfo.fWidthBytes[2] = 250;
84     sizeInfo.fWidthBytes[3] = 250;
85     yuvaIndices[0] = { 0, SkColorChannel::kR };
86     yuvaIndices[1] = { 1, SkColorChannel::kR };
87     yuvaIndices[2] = { 2, SkColorChannel::kR };
88     yuvaIndices[3] = { 3, SkColorChannel::kR };
89     int dummy;
90     planes[0] = planes[1] = planes[2] = planes[3] = &dummy;
91     ig.getYUVA8Planes(sizeInfo, yuvaIndices, planes);
92 
93     // Suppressed due to https://code.google.com/p/skia/issues/detail?id=4339
94     if (false) {
95         test_imagegenerator_factory(reporter);
96     }
97 }
98 
99 #include "SkAutoMalloc.h"
100 #include "SkPictureRecorder.h"
101 
make_picture()102 static sk_sp<SkPicture> make_picture() {
103     SkPictureRecorder recorder;
104     recorder.beginRecording(100, 100)->drawColor(SK_ColorRED);
105     return recorder.finishRecordingAsPicture();
106 }
107 
DEF_TEST(PictureImageGenerator,reporter)108 DEF_TEST(PictureImageGenerator, reporter) {
109     const struct {
110         SkColorType fColorType;
111         SkAlphaType fAlphaType;
112     } recs[] = {
113         { kRGBA_8888_SkColorType, kPremul_SkAlphaType },
114         { kBGRA_8888_SkColorType, kPremul_SkAlphaType },
115         { kRGBA_F16_SkColorType,  kPremul_SkAlphaType },
116         { kRGBA_F32_SkColorType,  kPremul_SkAlphaType },
117         { kRGBA_1010102_SkColorType, kPremul_SkAlphaType },
118 
119         { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType },
120         { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType },
121         { kRGBA_F16_SkColorType,  kUnpremul_SkAlphaType },
122         { kRGBA_F32_SkColorType,  kUnpremul_SkAlphaType },
123         { kRGBA_1010102_SkColorType, kUnpremul_SkAlphaType },
124     };
125 
126     auto colorspace = SkColorSpace::MakeSRGB();
127     auto picture = make_picture();
128     auto gen = SkImageGenerator::MakeFromPicture({100, 100}, picture, nullptr, nullptr,
129                                                  SkImage::BitDepth::kU8, colorspace);
130 
131     // worst case for all requests
132     SkAutoMalloc storage(100 * 100 * SkColorTypeBytesPerPixel(kRGBA_F32_SkColorType));
133 
134     for (const auto& rec : recs) {
135         SkImageInfo info = SkImageInfo::Make(100, 100, rec.fColorType, rec.fAlphaType, colorspace);
136         REPORTER_ASSERT(reporter, gen->getPixels(info, storage.get(), info.minRowBytes()));
137     }
138 }
139 
140