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 "include/core/SkAlphaType.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColor.h"
11 #include "include/core/SkColorSpace.h"
12 #include "include/core/SkColorType.h"
13 #include "include/core/SkData.h"
14 #include "include/core/SkGraphics.h"
15 #include "include/core/SkImage.h"
16 #include "include/core/SkImageGenerator.h"
17 #include "include/core/SkImageInfo.h"
18 #include "include/core/SkPicture.h"
19 #include "include/core/SkPictureRecorder.h"
20 #include "include/core/SkRefCnt.h"
21 #include "include/core/SkYUVAInfo.h"
22 #include "include/core/SkYUVAPixmaps.h"
23 #include "src/base/SkAutoMalloc.h"
24 #include "tests/Test.h"
25 
26 #include <memory>
27 
28 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
29     #include "include/ports/SkImageGeneratorCG.h"
30 #elif defined(SK_BUILD_FOR_WIN)
31     #include "include/ports/SkImageGeneratorWIC.h"
32 #endif
33 
34 static bool gMyFactoryWasCalled;
35 
my_factory(sk_sp<SkData>)36 static std::unique_ptr<SkImageGenerator> my_factory(sk_sp<SkData>) {
37     gMyFactoryWasCalled = true;
38     return nullptr;
39 }
40 
test_imagegenerator_factory(skiatest::Reporter * reporter)41 static void test_imagegenerator_factory(skiatest::Reporter* reporter) {
42     // just need a non-empty data to test things
43     sk_sp<SkData> data(SkData::MakeWithCString("test_imagegenerator_factory"));
44 
45     gMyFactoryWasCalled = false;
46 
47     REPORTER_ASSERT(reporter, !gMyFactoryWasCalled);
48 
49     std::unique_ptr<SkImageGenerator> gen = SkImageGenerator::MakeFromEncoded(data);
50     REPORTER_ASSERT(reporter, nullptr == gen);
51     REPORTER_ASSERT(reporter, !gMyFactoryWasCalled);
52 
53     // Test is racy, in that it hopes no other thread is changing this global...
54     auto prev = SkGraphics::SetImageGeneratorFromEncodedDataFactory(my_factory);
55     gen = SkImageGenerator::MakeFromEncoded(data);
56     REPORTER_ASSERT(reporter, nullptr == gen);
57     REPORTER_ASSERT(reporter, gMyFactoryWasCalled);
58 
59     // This just verifies that the signatures match.
60 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
61     SkGraphics::SetImageGeneratorFromEncodedDataFactory(SkImageGeneratorCG::MakeFromEncodedCG);
62 #elif defined(SK_BUILD_FOR_WIN)
63     SkGraphics::SetImageGeneratorFromEncodedDataFactory(SkImageGeneratorWIC::MakeFromEncodedWIC);
64 #endif
65 
66     SkGraphics::SetImageGeneratorFromEncodedDataFactory(prev);
67 }
68 
69 class MyImageGenerator : public SkImageGenerator {
70 public:
MyImageGenerator()71     MyImageGenerator() : SkImageGenerator(SkImageInfo::MakeN32Premul(0, 0)) {}
72 };
73 
DEF_TEST(ImageGenerator,reporter)74 DEF_TEST(ImageGenerator, reporter) {
75     MyImageGenerator ig;
76     SkYUVAPixmapInfo yuvaPixmapInfo;
77 
78     // Check that the YUV decoding API does not cause any crashes
79     ig.queryYUVAInfo(SkYUVAPixmapInfo::SupportedDataTypes::All(), &yuvaPixmapInfo);
80     SkYUVAInfo yuvaInfo({250, 250},
81                         SkYUVAInfo::PlaneConfig::kY_UV,
82                         SkYUVAInfo::Subsampling::k420,
83                         kJPEG_Full_SkYUVColorSpace);
84     yuvaPixmapInfo = SkYUVAPixmapInfo(yuvaInfo,
85                                       SkYUVAPixmapInfo::DataType::kUnorm8,
86                                       /*rowBytes[]*/ nullptr);
87     SkYUVAPixmaps yuvaPixmaps = SkYUVAPixmaps::Allocate(yuvaPixmapInfo);
88     ig.getYUVAPlanes(yuvaPixmaps);
89 
90     // Suppressed due to https://code.google.com/p/skia/issues/detail?id=4339
91     if ((false)) {
92         test_imagegenerator_factory(reporter);
93     }
94 }
95 
make_picture()96 static sk_sp<SkPicture> make_picture() {
97     SkPictureRecorder recorder;
98     recorder.beginRecording(100, 100)->drawColor(SK_ColorRED);
99     return recorder.finishRecordingAsPicture();
100 }
101 
DEF_TEST(PictureImageGenerator,reporter)102 DEF_TEST(PictureImageGenerator, reporter) {
103     const struct {
104         SkColorType fColorType;
105         SkAlphaType fAlphaType;
106     } recs[] = {
107         { kRGBA_8888_SkColorType, kPremul_SkAlphaType },
108         { kBGRA_8888_SkColorType, kPremul_SkAlphaType },
109         { kRGBA_F16_SkColorType,  kPremul_SkAlphaType },
110         { kRGBA_F32_SkColorType,  kPremul_SkAlphaType },
111         { kRGBA_1010102_SkColorType, kPremul_SkAlphaType },
112 
113         { kRGBA_8888_SkColorType, kUnpremul_SkAlphaType },
114         { kBGRA_8888_SkColorType, kUnpremul_SkAlphaType },
115         { kRGBA_F16_SkColorType,  kUnpremul_SkAlphaType },
116         { kRGBA_F32_SkColorType,  kUnpremul_SkAlphaType },
117         { kRGBA_1010102_SkColorType, kUnpremul_SkAlphaType },
118     };
119 
120     auto colorspace = SkColorSpace::MakeSRGB();
121     auto picture = make_picture();
122     auto gen = SkImageGenerator::MakeFromPicture({100, 100}, picture, nullptr, nullptr,
123                                                  SkImage::BitDepth::kU8, colorspace);
124 
125     // worst case for all requests
126     SkAutoMalloc storage(100 * 100 * SkColorTypeBytesPerPixel(kRGBA_F32_SkColorType));
127 
128     for (const auto& rec : recs) {
129         SkImageInfo info = SkImageInfo::Make(100, 100, rec.fColorType, rec.fAlphaType, colorspace);
130         REPORTER_ASSERT(reporter, gen->getPixels(info, storage.get(), info.minRowBytes()));
131     }
132 }
133 
134