1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2023 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkCodec.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkEncodedImageFormat.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkPngDecoder.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkAutoMalloc.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkSwizzlePriv.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkOSPath.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommandLineFlags.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommonFlags.h"
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker #include <map>
29*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
30*c8dee2aaSAndroid Build Coastguard Worker #include <string>
31*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker DEFINE_string(pngCodecGMImages,
34*c8dee2aaSAndroid Build Coastguard Worker "",
35*c8dee2aaSAndroid Build Coastguard Worker "Zero or more images or directories where to find PNG images to test with "
36*c8dee2aaSAndroid Build Coastguard Worker "PNGCodecGM. Directories are scanned non-recursively. All files are assumed to be "
37*c8dee2aaSAndroid Build Coastguard Worker "PNG images.");
38*c8dee2aaSAndroid Build Coastguard Worker DEFINE_string(pngCodecDecodeMode,
39*c8dee2aaSAndroid Build Coastguard Worker "",
40*c8dee2aaSAndroid Build Coastguard Worker "One of \"get-all-pixels\", \"incremental\" or \"zero-init\".");
41*c8dee2aaSAndroid Build Coastguard Worker DEFINE_string(pngCodecDstColorType,
42*c8dee2aaSAndroid Build Coastguard Worker "",
43*c8dee2aaSAndroid Build Coastguard Worker "One of \"force-grayscale\", "
44*c8dee2aaSAndroid Build Coastguard Worker "\"force-nonnative-premul-color\" or \"get-from-canvas\".");
45*c8dee2aaSAndroid Build Coastguard Worker DEFINE_string(pngCodecDstAlphaType, "", "One of \"premul\" or \"unpremul\".");
46*c8dee2aaSAndroid Build Coastguard Worker
sk_color_type_to_str(SkColorType colorType)47*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* sk_color_type_to_str(SkColorType colorType) {
48*c8dee2aaSAndroid Build Coastguard Worker switch (colorType) {
49*c8dee2aaSAndroid Build Coastguard Worker case kUnknown_SkColorType:
50*c8dee2aaSAndroid Build Coastguard Worker return "kUnknown_SkColorType";
51*c8dee2aaSAndroid Build Coastguard Worker case kAlpha_8_SkColorType:
52*c8dee2aaSAndroid Build Coastguard Worker return "kAlpha_8_SkColorType";
53*c8dee2aaSAndroid Build Coastguard Worker case kRGB_565_SkColorType:
54*c8dee2aaSAndroid Build Coastguard Worker return "kRGB_565_SkColorType";
55*c8dee2aaSAndroid Build Coastguard Worker case kARGB_4444_SkColorType:
56*c8dee2aaSAndroid Build Coastguard Worker return "kARGB_4444_SkColorType";
57*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_8888_SkColorType:
58*c8dee2aaSAndroid Build Coastguard Worker return "kRGBA_8888_SkColorType";
59*c8dee2aaSAndroid Build Coastguard Worker case kRGB_888x_SkColorType:
60*c8dee2aaSAndroid Build Coastguard Worker return "kRGB_888x_SkColorType";
61*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_8888_SkColorType:
62*c8dee2aaSAndroid Build Coastguard Worker return "kBGRA_8888_SkColorType";
63*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_1010102_SkColorType:
64*c8dee2aaSAndroid Build Coastguard Worker return "kRGBA_1010102_SkColorType";
65*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_1010102_SkColorType:
66*c8dee2aaSAndroid Build Coastguard Worker return "kBGRA_1010102_SkColorType";
67*c8dee2aaSAndroid Build Coastguard Worker case kRGB_101010x_SkColorType:
68*c8dee2aaSAndroid Build Coastguard Worker return "kRGB_101010x_SkColorType";
69*c8dee2aaSAndroid Build Coastguard Worker case kBGR_101010x_SkColorType:
70*c8dee2aaSAndroid Build Coastguard Worker return "kBGR_101010x_SkColorType";
71*c8dee2aaSAndroid Build Coastguard Worker case kBGR_101010x_XR_SkColorType:
72*c8dee2aaSAndroid Build Coastguard Worker return "kBGR_101010x_XR_SkColorType";
73*c8dee2aaSAndroid Build Coastguard Worker case kGray_8_SkColorType:
74*c8dee2aaSAndroid Build Coastguard Worker return "kGray_8_SkColorType";
75*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16Norm_SkColorType:
76*c8dee2aaSAndroid Build Coastguard Worker return "kRGBA_F16Norm_SkColorType";
77*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16_SkColorType:
78*c8dee2aaSAndroid Build Coastguard Worker return "kRGBA_F16_SkColorType";
79*c8dee2aaSAndroid Build Coastguard Worker case kRGB_F16F16F16x_SkColorType:
80*c8dee2aaSAndroid Build Coastguard Worker return "kRGB_F16F16F16x_SkColorType";
81*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F32_SkColorType:
82*c8dee2aaSAndroid Build Coastguard Worker return "kRGBA_F32_SkColorType";
83*c8dee2aaSAndroid Build Coastguard Worker case kR8G8_unorm_SkColorType:
84*c8dee2aaSAndroid Build Coastguard Worker return "kR8G8_unorm_SkColorType";
85*c8dee2aaSAndroid Build Coastguard Worker case kA16_float_SkColorType:
86*c8dee2aaSAndroid Build Coastguard Worker return "kA16_float_SkColorType";
87*c8dee2aaSAndroid Build Coastguard Worker case kR16G16_float_SkColorType:
88*c8dee2aaSAndroid Build Coastguard Worker return "kR16G16_float_SkColorType";
89*c8dee2aaSAndroid Build Coastguard Worker case kA16_unorm_SkColorType:
90*c8dee2aaSAndroid Build Coastguard Worker return "kA16_unorm_SkColorType";
91*c8dee2aaSAndroid Build Coastguard Worker case kR16G16_unorm_SkColorType:
92*c8dee2aaSAndroid Build Coastguard Worker return "kR16G16_unorm_SkColorType";
93*c8dee2aaSAndroid Build Coastguard Worker case kR16G16B16A16_unorm_SkColorType:
94*c8dee2aaSAndroid Build Coastguard Worker return "kR16G16B16A16_unorm_SkColorType";
95*c8dee2aaSAndroid Build Coastguard Worker case kSRGBA_8888_SkColorType:
96*c8dee2aaSAndroid Build Coastguard Worker return "kSRGBA_8888_SkColorType";
97*c8dee2aaSAndroid Build Coastguard Worker case kR8_unorm_SkColorType:
98*c8dee2aaSAndroid Build Coastguard Worker return "kR8_unorm_SkColorType";
99*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_10x6_SkColorType:
100*c8dee2aaSAndroid Build Coastguard Worker return "kRGBA_10x6_SkColorType";
101*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_10101010_XR_SkColorType:
102*c8dee2aaSAndroid Build Coastguard Worker return "kBGRA_10101010_XR_SkColorType";
103*c8dee2aaSAndroid Build Coastguard Worker }
104*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
105*c8dee2aaSAndroid Build Coastguard Worker }
106*c8dee2aaSAndroid Build Coastguard Worker
sk_alpha_type_to_str(SkAlphaType alphaType)107*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* sk_alpha_type_to_str(SkAlphaType alphaType) {
108*c8dee2aaSAndroid Build Coastguard Worker switch (alphaType) {
109*c8dee2aaSAndroid Build Coastguard Worker case kUnknown_SkAlphaType:
110*c8dee2aaSAndroid Build Coastguard Worker return "kUnknown_SkAlphaType";
111*c8dee2aaSAndroid Build Coastguard Worker case kOpaque_SkAlphaType:
112*c8dee2aaSAndroid Build Coastguard Worker return "kOpaque_SkAlphaType";
113*c8dee2aaSAndroid Build Coastguard Worker case kPremul_SkAlphaType:
114*c8dee2aaSAndroid Build Coastguard Worker return "kPremul_SkAlphaType";
115*c8dee2aaSAndroid Build Coastguard Worker case kUnpremul_SkAlphaType:
116*c8dee2aaSAndroid Build Coastguard Worker return "kUnpremul_SkAlphaType";
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker
121*c8dee2aaSAndroid Build Coastguard Worker struct DecodeResult {
122*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec;
123*c8dee2aaSAndroid Build Coastguard Worker std::string errorMsg;
124*c8dee2aaSAndroid Build Coastguard Worker };
125*c8dee2aaSAndroid Build Coastguard Worker
decode(std::string path)126*c8dee2aaSAndroid Build Coastguard Worker static DecodeResult decode(std::string path) {
127*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
128*c8dee2aaSAndroid Build Coastguard Worker if (!encoded) {
129*c8dee2aaSAndroid Build Coastguard Worker return {.errorMsg = SkStringPrintf("Could not read \"%s\".", path.c_str()).c_str()};
130*c8dee2aaSAndroid Build Coastguard Worker }
131*c8dee2aaSAndroid Build Coastguard Worker SkCodec::Result result;
132*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec = SkPngDecoder::Decode(SkMemoryStream::Make(encoded), &result);
133*c8dee2aaSAndroid Build Coastguard Worker if (result != SkCodec::Result::kSuccess) {
134*c8dee2aaSAndroid Build Coastguard Worker return {.errorMsg = SkStringPrintf("Could not create codec for \"%s\": %s.",
135*c8dee2aaSAndroid Build Coastguard Worker path.c_str(),
136*c8dee2aaSAndroid Build Coastguard Worker SkCodec::ResultToString(result))
137*c8dee2aaSAndroid Build Coastguard Worker .c_str()};
138*c8dee2aaSAndroid Build Coastguard Worker }
139*c8dee2aaSAndroid Build Coastguard Worker return {.codec = std::move(codec)};
140*c8dee2aaSAndroid Build Coastguard Worker }
141*c8dee2aaSAndroid Build Coastguard Worker
142*c8dee2aaSAndroid Build Coastguard Worker // This GM implements the PNG-related behaviors found in DM's CodecSrc class. It takes a single
143*c8dee2aaSAndroid Build Coastguard Worker // image as an argument and applies the same logic as CodecSrc.
144*c8dee2aaSAndroid Build Coastguard Worker //
145*c8dee2aaSAndroid Build Coastguard Worker // See the CodecSrc class here:
146*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.h#158.
147*c8dee2aaSAndroid Build Coastguard Worker class PNGCodecGM : public skiagm::GM {
148*c8dee2aaSAndroid Build Coastguard Worker public:
149*c8dee2aaSAndroid Build Coastguard Worker // Based on CodecSrc::Mode.
150*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.h#160
151*c8dee2aaSAndroid Build Coastguard Worker enum class DecodeMode {
152*c8dee2aaSAndroid Build Coastguard Worker kGetAllPixels,
153*c8dee2aaSAndroid Build Coastguard Worker kIncremental,
154*c8dee2aaSAndroid Build Coastguard Worker kZeroInit,
155*c8dee2aaSAndroid Build Coastguard Worker };
156*c8dee2aaSAndroid Build Coastguard Worker
157*c8dee2aaSAndroid Build Coastguard Worker // Based on CodecSrc::DstColorType.
158*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.h#172
159*c8dee2aaSAndroid Build Coastguard Worker enum class DstColorType {
160*c8dee2aaSAndroid Build Coastguard Worker kForceGrayscale,
161*c8dee2aaSAndroid Build Coastguard Worker kForceNonNativePremulColor,
162*c8dee2aaSAndroid Build Coastguard Worker kGetFromCanvas,
163*c8dee2aaSAndroid Build Coastguard Worker };
164*c8dee2aaSAndroid Build Coastguard Worker
DecodeModeToString(DecodeMode decodeMode)165*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* DecodeModeToString(DecodeMode decodeMode) {
166*c8dee2aaSAndroid Build Coastguard Worker switch (decodeMode) {
167*c8dee2aaSAndroid Build Coastguard Worker case DecodeMode::kGetAllPixels:
168*c8dee2aaSAndroid Build Coastguard Worker return "kGetAllPixels";
169*c8dee2aaSAndroid Build Coastguard Worker case DecodeMode::kIncremental:
170*c8dee2aaSAndroid Build Coastguard Worker return "kIncremental";
171*c8dee2aaSAndroid Build Coastguard Worker case DecodeMode::kZeroInit:
172*c8dee2aaSAndroid Build Coastguard Worker return "kZeroInit";
173*c8dee2aaSAndroid Build Coastguard Worker }
174*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
175*c8dee2aaSAndroid Build Coastguard Worker }
176*c8dee2aaSAndroid Build Coastguard Worker
DstColorTypeToString(DstColorType dstColorType)177*c8dee2aaSAndroid Build Coastguard Worker static constexpr const char* DstColorTypeToString(DstColorType dstColorType) {
178*c8dee2aaSAndroid Build Coastguard Worker switch (dstColorType) {
179*c8dee2aaSAndroid Build Coastguard Worker case DstColorType::kForceGrayscale:
180*c8dee2aaSAndroid Build Coastguard Worker return "kForceGrayscale";
181*c8dee2aaSAndroid Build Coastguard Worker case DstColorType::kForceNonNativePremulColor:
182*c8dee2aaSAndroid Build Coastguard Worker return "kForceNonNativePremulColor";
183*c8dee2aaSAndroid Build Coastguard Worker case DstColorType::kGetFromCanvas:
184*c8dee2aaSAndroid Build Coastguard Worker return "kGetFromCanvas";
185*c8dee2aaSAndroid Build Coastguard Worker }
186*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
187*c8dee2aaSAndroid Build Coastguard Worker }
188*c8dee2aaSAndroid Build Coastguard Worker
189*c8dee2aaSAndroid Build Coastguard Worker // Based on DM's CodecSrc::CodecSrc().
190*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.cpp#371
PNGCodecGM(std::string path,DecodeMode decodeMode,DstColorType dstColorType,SkAlphaType dstAlphaType)191*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM(std::string path,
192*c8dee2aaSAndroid Build Coastguard Worker DecodeMode decodeMode,
193*c8dee2aaSAndroid Build Coastguard Worker DstColorType dstColorType,
194*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType dstAlphaType)
195*c8dee2aaSAndroid Build Coastguard Worker : skiagm::GM()
196*c8dee2aaSAndroid Build Coastguard Worker , fPath(path)
197*c8dee2aaSAndroid Build Coastguard Worker , fDecodeMode(decodeMode)
198*c8dee2aaSAndroid Build Coastguard Worker , fDstColorType(dstColorType)
199*c8dee2aaSAndroid Build Coastguard Worker , fDstAlphaType(dstAlphaType) {}
200*c8dee2aaSAndroid Build Coastguard Worker
isBazelOnly() const201*c8dee2aaSAndroid Build Coastguard Worker bool isBazelOnly() const override {
202*c8dee2aaSAndroid Build Coastguard Worker // This GM class overlaps with DM's CodecSrc and related sources.
203*c8dee2aaSAndroid Build Coastguard Worker return true;
204*c8dee2aaSAndroid Build Coastguard Worker }
205*c8dee2aaSAndroid Build Coastguard Worker
getGoldKeys() const206*c8dee2aaSAndroid Build Coastguard Worker std::map<std::string, std::string> getGoldKeys() const override {
207*c8dee2aaSAndroid Build Coastguard Worker return std::map<std::string, std::string>{
208*c8dee2aaSAndroid Build Coastguard Worker {"name", getName().c_str()},
209*c8dee2aaSAndroid Build Coastguard Worker {"source_type", "image"},
210*c8dee2aaSAndroid Build Coastguard Worker {"decode_mode", DecodeModeToString(fDecodeMode)},
211*c8dee2aaSAndroid Build Coastguard Worker {"dst_color_type", DstColorTypeToString(fDstColorType)},
212*c8dee2aaSAndroid Build Coastguard Worker {"dst_alpha_type", sk_alpha_type_to_str(fDstAlphaType)},
213*c8dee2aaSAndroid Build Coastguard Worker };
214*c8dee2aaSAndroid Build Coastguard Worker }
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker protected:
217*c8dee2aaSAndroid Build Coastguard Worker // Based on CodecSrc::name().
218*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.cpp#828
getName() const219*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
220*c8dee2aaSAndroid Build Coastguard Worker SkString name = SkOSPath::Basename(fPath.c_str());
221*c8dee2aaSAndroid Build Coastguard Worker return name;
222*c8dee2aaSAndroid Build Coastguard Worker }
223*c8dee2aaSAndroid Build Coastguard Worker
224*c8dee2aaSAndroid Build Coastguard Worker // Based on CodecSrc::size().
225*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.cpp#803
getISize()226*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override {
227*c8dee2aaSAndroid Build Coastguard Worker DecodeResult decodeResult = decode(fPath);
228*c8dee2aaSAndroid Build Coastguard Worker if (decodeResult.errorMsg != "") {
229*c8dee2aaSAndroid Build Coastguard Worker return {0, 0};
230*c8dee2aaSAndroid Build Coastguard Worker }
231*c8dee2aaSAndroid Build Coastguard Worker return decodeResult.codec->dimensions();
232*c8dee2aaSAndroid Build Coastguard Worker }
233*c8dee2aaSAndroid Build Coastguard Worker
234*c8dee2aaSAndroid Build Coastguard Worker // Based on CodecSrc::draw().
235*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.cpp#450
onDraw(SkCanvas * canvas,SkString * errorMsg)236*c8dee2aaSAndroid Build Coastguard Worker DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
237*c8dee2aaSAndroid Build Coastguard Worker DecodeResult decodeResult = decode(fPath);
238*c8dee2aaSAndroid Build Coastguard Worker if (decodeResult.errorMsg != "") {
239*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = decodeResult.errorMsg.c_str();
240*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kFail;
241*c8dee2aaSAndroid Build Coastguard Worker }
242*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec = std::move(decodeResult.codec);
243*c8dee2aaSAndroid Build Coastguard Worker
244*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo decodeInfo = codec->getInfo();
245*c8dee2aaSAndroid Build Coastguard Worker if (*errorMsg = validateCanvasColorTypeAndGetDecodeInfo(&decodeInfo,
246*c8dee2aaSAndroid Build Coastguard Worker canvas->imageInfo().colorType());
247*c8dee2aaSAndroid Build Coastguard Worker *errorMsg != SkString()) {
248*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kFail;
249*c8dee2aaSAndroid Build Coastguard Worker }
250*c8dee2aaSAndroid Build Coastguard Worker
251*c8dee2aaSAndroid Build Coastguard Worker SkISize size = codec->dimensions();
252*c8dee2aaSAndroid Build Coastguard Worker decodeInfo = decodeInfo.makeDimensions(size);
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker const int bpp = decodeInfo.bytesPerPixel();
255*c8dee2aaSAndroid Build Coastguard Worker const size_t rowBytes = size.width() * bpp;
256*c8dee2aaSAndroid Build Coastguard Worker const size_t safeSize = decodeInfo.computeByteSize(rowBytes);
257*c8dee2aaSAndroid Build Coastguard Worker SkAutoMalloc pixels(safeSize);
258*c8dee2aaSAndroid Build Coastguard Worker
259*c8dee2aaSAndroid Build Coastguard Worker SkCodec::Options options;
260*c8dee2aaSAndroid Build Coastguard Worker if (DecodeMode::kZeroInit == fDecodeMode) {
261*c8dee2aaSAndroid Build Coastguard Worker memset(pixels.get(), 0, size.height() * rowBytes);
262*c8dee2aaSAndroid Build Coastguard Worker options.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
263*c8dee2aaSAndroid Build Coastguard Worker }
264*c8dee2aaSAndroid Build Coastguard Worker
265*c8dee2aaSAndroid Build Coastguard Worker // For codec srcs, we want the "draw" step to be a memcpy. Any interesting color space or
266*c8dee2aaSAndroid Build Coastguard Worker // color format conversions should be performed by the codec. Sometimes the output of the
267*c8dee2aaSAndroid Build Coastguard Worker // decode will be in an interesting color space. On our srgb and f16 backends, we need to
268*c8dee2aaSAndroid Build Coastguard Worker // "pretend" that the color space is standard sRGB to avoid triggering color conversion
269*c8dee2aaSAndroid Build Coastguard Worker // at draw time.
270*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo bitmapInfo = decodeInfo.makeColorSpace(SkColorSpace::MakeSRGB());
271*c8dee2aaSAndroid Build Coastguard Worker
272*c8dee2aaSAndroid Build Coastguard Worker if (kRGBA_8888_SkColorType == decodeInfo.colorType() ||
273*c8dee2aaSAndroid Build Coastguard Worker kBGRA_8888_SkColorType == decodeInfo.colorType()) {
274*c8dee2aaSAndroid Build Coastguard Worker bitmapInfo = bitmapInfo.makeColorType(kN32_SkColorType);
275*c8dee2aaSAndroid Build Coastguard Worker }
276*c8dee2aaSAndroid Build Coastguard Worker
277*c8dee2aaSAndroid Build Coastguard Worker switch (fDecodeMode) {
278*c8dee2aaSAndroid Build Coastguard Worker case DecodeMode::kZeroInit:
279*c8dee2aaSAndroid Build Coastguard Worker case DecodeMode::kGetAllPixels: {
280*c8dee2aaSAndroid Build Coastguard Worker switch (codec->getPixels(decodeInfo, pixels.get(), rowBytes, &options)) {
281*c8dee2aaSAndroid Build Coastguard Worker case SkCodec::kSuccess:
282*c8dee2aaSAndroid Build Coastguard Worker // We consider these to be valid, since we should still decode what is
283*c8dee2aaSAndroid Build Coastguard Worker // available.
284*c8dee2aaSAndroid Build Coastguard Worker case SkCodec::kErrorInInput:
285*c8dee2aaSAndroid Build Coastguard Worker case SkCodec::kIncompleteInput:
286*c8dee2aaSAndroid Build Coastguard Worker break;
287*c8dee2aaSAndroid Build Coastguard Worker default:
288*c8dee2aaSAndroid Build Coastguard Worker // Everything else is considered a failure.
289*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = SkStringPrintf("Couldn't getPixels %s.", fPath.c_str());
290*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kFail;
291*c8dee2aaSAndroid Build Coastguard Worker }
292*c8dee2aaSAndroid Build Coastguard Worker
293*c8dee2aaSAndroid Build Coastguard Worker drawToCanvas(canvas, bitmapInfo, pixels.get(), rowBytes);
294*c8dee2aaSAndroid Build Coastguard Worker break;
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker case DecodeMode::kIncremental: {
297*c8dee2aaSAndroid Build Coastguard Worker void* dst = pixels.get();
298*c8dee2aaSAndroid Build Coastguard Worker uint32_t height = decodeInfo.height();
299*c8dee2aaSAndroid Build Coastguard Worker if (SkCodec::kSuccess ==
300*c8dee2aaSAndroid Build Coastguard Worker codec->startIncrementalDecode(decodeInfo, dst, rowBytes, &options)) {
301*c8dee2aaSAndroid Build Coastguard Worker int rowsDecoded;
302*c8dee2aaSAndroid Build Coastguard Worker auto result = codec->incrementalDecode(&rowsDecoded);
303*c8dee2aaSAndroid Build Coastguard Worker if (SkCodec::kIncompleteInput == result || SkCodec::kErrorInInput == result) {
304*c8dee2aaSAndroid Build Coastguard Worker codec->fillIncompleteImage(decodeInfo,
305*c8dee2aaSAndroid Build Coastguard Worker dst,
306*c8dee2aaSAndroid Build Coastguard Worker rowBytes,
307*c8dee2aaSAndroid Build Coastguard Worker SkCodec::kNo_ZeroInitialized,
308*c8dee2aaSAndroid Build Coastguard Worker height,
309*c8dee2aaSAndroid Build Coastguard Worker rowsDecoded);
310*c8dee2aaSAndroid Build Coastguard Worker }
311*c8dee2aaSAndroid Build Coastguard Worker } else {
312*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "Could not start incremental decode";
313*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kFail;
314*c8dee2aaSAndroid Build Coastguard Worker }
315*c8dee2aaSAndroid Build Coastguard Worker drawToCanvas(canvas, bitmapInfo, dst, rowBytes);
316*c8dee2aaSAndroid Build Coastguard Worker break;
317*c8dee2aaSAndroid Build Coastguard Worker }
318*c8dee2aaSAndroid Build Coastguard Worker default:
319*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
320*c8dee2aaSAndroid Build Coastguard Worker *errorMsg = "Invalid fDecodeMode";
321*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kFail;
322*c8dee2aaSAndroid Build Coastguard Worker }
323*c8dee2aaSAndroid Build Coastguard Worker return DrawResult::kOk;
324*c8dee2aaSAndroid Build Coastguard Worker }
325*c8dee2aaSAndroid Build Coastguard Worker
326*c8dee2aaSAndroid Build Coastguard Worker private:
327*c8dee2aaSAndroid Build Coastguard Worker // Checks that the canvas color type, destination color and alpha types and input image
328*c8dee2aaSAndroid Build Coastguard Worker // constitute an interesting test case, and constructs the SkImageInfo to use when decoding the
329*c8dee2aaSAndroid Build Coastguard Worker // image.
330*c8dee2aaSAndroid Build Coastguard Worker //
331*c8dee2aaSAndroid Build Coastguard Worker // Based on DM's get_decode_info() function.
332*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.cpp#398
validateCanvasColorTypeAndGetDecodeInfo(SkImageInfo * decodeInfo,SkColorType canvasColorType)333*c8dee2aaSAndroid Build Coastguard Worker SkString validateCanvasColorTypeAndGetDecodeInfo(SkImageInfo* decodeInfo,
334*c8dee2aaSAndroid Build Coastguard Worker SkColorType canvasColorType) {
335*c8dee2aaSAndroid Build Coastguard Worker switch (fDstColorType) {
336*c8dee2aaSAndroid Build Coastguard Worker case DstColorType::kForceGrayscale:
337*c8dee2aaSAndroid Build Coastguard Worker if (kRGB_565_SkColorType == canvasColorType) {
338*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf(
339*c8dee2aaSAndroid Build Coastguard Worker "canvas color type %s and destination color type %s are redundant",
340*c8dee2aaSAndroid Build Coastguard Worker sk_color_type_to_str(canvasColorType),
341*c8dee2aaSAndroid Build Coastguard Worker DstColorTypeToString(fDstColorType));
342*c8dee2aaSAndroid Build Coastguard Worker }
343*c8dee2aaSAndroid Build Coastguard Worker *decodeInfo = decodeInfo->makeColorType(kGray_8_SkColorType);
344*c8dee2aaSAndroid Build Coastguard Worker break;
345*c8dee2aaSAndroid Build Coastguard Worker
346*c8dee2aaSAndroid Build Coastguard Worker case DstColorType::kForceNonNativePremulColor:
347*c8dee2aaSAndroid Build Coastguard Worker if (kRGB_565_SkColorType == canvasColorType ||
348*c8dee2aaSAndroid Build Coastguard Worker kRGBA_F16_SkColorType == canvasColorType) {
349*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf(
350*c8dee2aaSAndroid Build Coastguard Worker "canvas color type %s and destination color type %s are redundant",
351*c8dee2aaSAndroid Build Coastguard Worker sk_color_type_to_str(canvasColorType),
352*c8dee2aaSAndroid Build Coastguard Worker DstColorTypeToString(fDstColorType));
353*c8dee2aaSAndroid Build Coastguard Worker }
354*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_PMCOLOR_IS_RGBA
355*c8dee2aaSAndroid Build Coastguard Worker *decodeInfo = decodeInfo->makeColorType(kBGRA_8888_SkColorType);
356*c8dee2aaSAndroid Build Coastguard Worker #else
357*c8dee2aaSAndroid Build Coastguard Worker *decodeInfo = decodeInfo->makeColorType(kRGBA_8888_SkColorType);
358*c8dee2aaSAndroid Build Coastguard Worker #endif
359*c8dee2aaSAndroid Build Coastguard Worker break;
360*c8dee2aaSAndroid Build Coastguard Worker
361*c8dee2aaSAndroid Build Coastguard Worker case DstColorType::kGetFromCanvas:
362*c8dee2aaSAndroid Build Coastguard Worker if (kRGB_565_SkColorType == canvasColorType &&
363*c8dee2aaSAndroid Build Coastguard Worker kOpaque_SkAlphaType != decodeInfo->alphaType()) {
364*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf(
365*c8dee2aaSAndroid Build Coastguard Worker "image \"%s\" has alpha type %s; this is incompatible with with "
366*c8dee2aaSAndroid Build Coastguard Worker "canvas color type %s and destination color type %s",
367*c8dee2aaSAndroid Build Coastguard Worker fPath.c_str(),
368*c8dee2aaSAndroid Build Coastguard Worker sk_alpha_type_to_str(decodeInfo->alphaType()),
369*c8dee2aaSAndroid Build Coastguard Worker sk_color_type_to_str(canvasColorType),
370*c8dee2aaSAndroid Build Coastguard Worker DstColorTypeToString(fDstColorType));
371*c8dee2aaSAndroid Build Coastguard Worker }
372*c8dee2aaSAndroid Build Coastguard Worker *decodeInfo = decodeInfo->makeColorType(canvasColorType);
373*c8dee2aaSAndroid Build Coastguard Worker break;
374*c8dee2aaSAndroid Build Coastguard Worker
375*c8dee2aaSAndroid Build Coastguard Worker default:
376*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
377*c8dee2aaSAndroid Build Coastguard Worker }
378*c8dee2aaSAndroid Build Coastguard Worker
379*c8dee2aaSAndroid Build Coastguard Worker *decodeInfo = decodeInfo->makeAlphaType(fDstAlphaType);
380*c8dee2aaSAndroid Build Coastguard Worker return SkString();
381*c8dee2aaSAndroid Build Coastguard Worker }
382*c8dee2aaSAndroid Build Coastguard Worker
383*c8dee2aaSAndroid Build Coastguard Worker // Based on DM's draw_to_canvas() function.
384*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.cpp#432
drawToCanvas(SkCanvas * canvas,const SkImageInfo & info,void * pixels,size_t rowBytes,SkScalar left=0,SkScalar top=0)385*c8dee2aaSAndroid Build Coastguard Worker void drawToCanvas(SkCanvas* canvas,
386*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& info,
387*c8dee2aaSAndroid Build Coastguard Worker void* pixels,
388*c8dee2aaSAndroid Build Coastguard Worker size_t rowBytes,
389*c8dee2aaSAndroid Build Coastguard Worker SkScalar left = 0,
390*c8dee2aaSAndroid Build Coastguard Worker SkScalar top = 0) {
391*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
392*c8dee2aaSAndroid Build Coastguard Worker bitmap.installPixels(info, pixels, rowBytes);
393*c8dee2aaSAndroid Build Coastguard Worker swapRbIfNecessary(bitmap);
394*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(bitmap.asImage(), left, top);
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker
397*c8dee2aaSAndroid Build Coastguard Worker // Allows us to test decodes to non-native 8888.
398*c8dee2aaSAndroid Build Coastguard Worker //
399*c8dee2aaSAndroid Build Coastguard Worker // Based on DM's swap_rb_if_necessary function.
400*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DMSrcSink.cpp#387
swapRbIfNecessary(SkBitmap & bitmap)401*c8dee2aaSAndroid Build Coastguard Worker void swapRbIfNecessary(SkBitmap& bitmap) {
402*c8dee2aaSAndroid Build Coastguard Worker if (DstColorType::kForceNonNativePremulColor != fDstColorType) {
403*c8dee2aaSAndroid Build Coastguard Worker return;
404*c8dee2aaSAndroid Build Coastguard Worker }
405*c8dee2aaSAndroid Build Coastguard Worker
406*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < bitmap.height(); y++) {
407*c8dee2aaSAndroid Build Coastguard Worker uint32_t* row = (uint32_t*)bitmap.getAddr(0, y);
408*c8dee2aaSAndroid Build Coastguard Worker SkOpts::RGBA_to_BGRA(row, row, bitmap.width());
409*c8dee2aaSAndroid Build Coastguard Worker }
410*c8dee2aaSAndroid Build Coastguard Worker }
411*c8dee2aaSAndroid Build Coastguard Worker
412*c8dee2aaSAndroid Build Coastguard Worker std::string fPath;
413*c8dee2aaSAndroid Build Coastguard Worker DecodeMode fDecodeMode;
414*c8dee2aaSAndroid Build Coastguard Worker DstColorType fDstColorType;
415*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType fDstAlphaType;
416*c8dee2aaSAndroid Build Coastguard Worker };
417*c8dee2aaSAndroid Build Coastguard Worker
418*c8dee2aaSAndroid Build Coastguard Worker // Registers GMs with zero or more PNGCodecGM instances for the given image. Returns a non-empty,
419*c8dee2aaSAndroid Build Coastguard Worker // human-friendly error message in the case of errors.
420*c8dee2aaSAndroid Build Coastguard Worker //
421*c8dee2aaSAndroid Build Coastguard Worker // Based on DM's push_codec_srcs() function. It only covers "simple" codecs (lines 740-834).
422*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DM.cpp#740
423*c8dee2aaSAndroid Build Coastguard Worker //
424*c8dee2aaSAndroid Build Coastguard Worker // Specifically, this function does not capture any behaviors found in the following DM classes:
425*c8dee2aaSAndroid Build Coastguard Worker //
426*c8dee2aaSAndroid Build Coastguard Worker // - AndroidCodecSrc
427*c8dee2aaSAndroid Build Coastguard Worker // - BRDSrc
428*c8dee2aaSAndroid Build Coastguard Worker // - ImageGenSrc
429*c8dee2aaSAndroid Build Coastguard Worker //
430*c8dee2aaSAndroid Build Coastguard Worker // TODO(lovisolo): Implement the above sources as GMs (if necessary).
registerGMsForImage(std::string path,PNGCodecGM::DecodeMode decodeMode,PNGCodecGM::DstColorType dstColorType,SkAlphaType dstAlphaType)431*c8dee2aaSAndroid Build Coastguard Worker static std::string registerGMsForImage(std::string path,
432*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM::DecodeMode decodeMode,
433*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM::DstColorType dstColorType,
434*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType dstAlphaType) {
435*c8dee2aaSAndroid Build Coastguard Worker DecodeResult decodeResult = decode(path);
436*c8dee2aaSAndroid Build Coastguard Worker if (decodeResult.errorMsg != "") {
437*c8dee2aaSAndroid Build Coastguard Worker return decodeResult.errorMsg;
438*c8dee2aaSAndroid Build Coastguard Worker }
439*c8dee2aaSAndroid Build Coastguard Worker
440*c8dee2aaSAndroid Build Coastguard Worker if (dstColorType == PNGCodecGM::DstColorType::kForceGrayscale &&
441*c8dee2aaSAndroid Build Coastguard Worker decodeResult.codec->getInfo().colorType() != kGray_8_SkColorType) {
442*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf(
443*c8dee2aaSAndroid Build Coastguard Worker "image \"%s\" has color type %s; this is incompatible with the given "
444*c8dee2aaSAndroid Build Coastguard Worker "dstColorType argument: %s (expected image color type: %s)",
445*c8dee2aaSAndroid Build Coastguard Worker path.c_str(),
446*c8dee2aaSAndroid Build Coastguard Worker sk_color_type_to_str(decodeResult.codec->getInfo().colorType()),
447*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM::DstColorTypeToString(PNGCodecGM::DstColorType::kForceGrayscale),
448*c8dee2aaSAndroid Build Coastguard Worker sk_color_type_to_str(kGray_8_SkColorType))
449*c8dee2aaSAndroid Build Coastguard Worker .c_str();
450*c8dee2aaSAndroid Build Coastguard Worker }
451*c8dee2aaSAndroid Build Coastguard Worker
452*c8dee2aaSAndroid Build Coastguard Worker if (dstAlphaType == kUnpremul_SkAlphaType &&
453*c8dee2aaSAndroid Build Coastguard Worker decodeResult.codec->getInfo().alphaType() == kOpaque_SkAlphaType) {
454*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf(
455*c8dee2aaSAndroid Build Coastguard Worker "image \"%s\" has alpha type %s; this is incompatible with the given "
456*c8dee2aaSAndroid Build Coastguard Worker "dstAlphaType argument: %s",
457*c8dee2aaSAndroid Build Coastguard Worker path.c_str(),
458*c8dee2aaSAndroid Build Coastguard Worker sk_alpha_type_to_str(kOpaque_SkAlphaType),
459*c8dee2aaSAndroid Build Coastguard Worker sk_alpha_type_to_str(kUnpremul_SkAlphaType))
460*c8dee2aaSAndroid Build Coastguard Worker .c_str();
461*c8dee2aaSAndroid Build Coastguard Worker }
462*c8dee2aaSAndroid Build Coastguard Worker
463*c8dee2aaSAndroid Build Coastguard Worker skiagm::Register(new PNGCodecGM(path, decodeMode, dstColorType, dstAlphaType));
464*c8dee2aaSAndroid Build Coastguard Worker return "";
465*c8dee2aaSAndroid Build Coastguard Worker }
466*c8dee2aaSAndroid Build Coastguard Worker
467*c8dee2aaSAndroid Build Coastguard Worker // Returns a non-empty message in the case of errors.
parse_and_validate_flags(PNGCodecGM::DecodeMode * decodeMode,PNGCodecGM::DstColorType * dstColorType,SkAlphaType * dstAlphaType)468*c8dee2aaSAndroid Build Coastguard Worker static std::string parse_and_validate_flags(PNGCodecGM::DecodeMode* decodeMode,
469*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM::DstColorType* dstColorType,
470*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType* dstAlphaType) {
471*c8dee2aaSAndroid Build Coastguard Worker skia_private::THashMap<SkString, PNGCodecGM::DecodeMode> decodeModeValues = {
472*c8dee2aaSAndroid Build Coastguard Worker {SkString("get-all-pixels"), PNGCodecGM::DecodeMode::kGetAllPixels},
473*c8dee2aaSAndroid Build Coastguard Worker {SkString("incremental"), PNGCodecGM::DecodeMode::kIncremental},
474*c8dee2aaSAndroid Build Coastguard Worker {SkString("zero-init"), PNGCodecGM::DecodeMode::kZeroInit},
475*c8dee2aaSAndroid Build Coastguard Worker };
476*c8dee2aaSAndroid Build Coastguard Worker if (SkString errorMsg = FLAGS_pngCodecDecodeMode.parseAndValidate(
477*c8dee2aaSAndroid Build Coastguard Worker "--pngCodecDecodeMode", decodeModeValues, decodeMode);
478*c8dee2aaSAndroid Build Coastguard Worker errorMsg != SkString()) {
479*c8dee2aaSAndroid Build Coastguard Worker return errorMsg.c_str();
480*c8dee2aaSAndroid Build Coastguard Worker }
481*c8dee2aaSAndroid Build Coastguard Worker
482*c8dee2aaSAndroid Build Coastguard Worker skia_private::THashMap<SkString, PNGCodecGM::DstColorType> dstColorTypeValues = {
483*c8dee2aaSAndroid Build Coastguard Worker {SkString("get-from-canvas"), PNGCodecGM::DstColorType::kGetFromCanvas},
484*c8dee2aaSAndroid Build Coastguard Worker {SkString("force-grayscale"), PNGCodecGM::DstColorType::kForceGrayscale},
485*c8dee2aaSAndroid Build Coastguard Worker {SkString("force-nonnative-premul-color"),
486*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM::DstColorType::kForceNonNativePremulColor},
487*c8dee2aaSAndroid Build Coastguard Worker };
488*c8dee2aaSAndroid Build Coastguard Worker if (SkString errorMsg = FLAGS_pngCodecDstColorType.parseAndValidate(
489*c8dee2aaSAndroid Build Coastguard Worker "--pngCodecDstColorType", dstColorTypeValues, dstColorType);
490*c8dee2aaSAndroid Build Coastguard Worker errorMsg != SkString()) {
491*c8dee2aaSAndroid Build Coastguard Worker return errorMsg.c_str();
492*c8dee2aaSAndroid Build Coastguard Worker }
493*c8dee2aaSAndroid Build Coastguard Worker
494*c8dee2aaSAndroid Build Coastguard Worker skia_private::THashMap<SkString, SkAlphaType> dstAlphaTypeValues = {
495*c8dee2aaSAndroid Build Coastguard Worker {SkString("premul"), kPremul_SkAlphaType},
496*c8dee2aaSAndroid Build Coastguard Worker {SkString("unpremul"), kUnpremul_SkAlphaType},
497*c8dee2aaSAndroid Build Coastguard Worker };
498*c8dee2aaSAndroid Build Coastguard Worker if (SkString errorMsg = FLAGS_pngCodecDstAlphaType.parseAndValidate(
499*c8dee2aaSAndroid Build Coastguard Worker "--pngCodecDstAlphaType", dstAlphaTypeValues, dstAlphaType);
500*c8dee2aaSAndroid Build Coastguard Worker errorMsg != SkString()) {
501*c8dee2aaSAndroid Build Coastguard Worker return errorMsg.c_str();
502*c8dee2aaSAndroid Build Coastguard Worker }
503*c8dee2aaSAndroid Build Coastguard Worker
504*c8dee2aaSAndroid Build Coastguard Worker return "";
505*c8dee2aaSAndroid Build Coastguard Worker }
506*c8dee2aaSAndroid Build Coastguard Worker
507*c8dee2aaSAndroid Build Coastguard Worker // Registers one PNGCodecGM instance for each image passed via the --pngCodecGMImages flag, which
508*c8dee2aaSAndroid Build Coastguard Worker // can take files and directories. Directories are scanned non-recursively.
509*c8dee2aaSAndroid Build Coastguard Worker //
510*c8dee2aaSAndroid Build Coastguard Worker // Based on DM's gather_srcs() function.
511*c8dee2aaSAndroid Build Coastguard Worker // https://skia.googlesource.com/skia/+/ce49fc71bc7cc25244020cd3e64764a6d08e54fb/dm/DM.cpp#953
__anonb277b3f40102() 512*c8dee2aaSAndroid Build Coastguard Worker DEF_GM_REGISTERER_FN([]() -> std::string {
513*c8dee2aaSAndroid Build Coastguard Worker // Parse flags.
514*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM::DecodeMode decodeMode;
515*c8dee2aaSAndroid Build Coastguard Worker PNGCodecGM::DstColorType dstColorType;
516*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType dstAlphaType;
517*c8dee2aaSAndroid Build Coastguard Worker if (std::string errorMsg = parse_and_validate_flags(&decodeMode, &dstColorType, &dstAlphaType);
518*c8dee2aaSAndroid Build Coastguard Worker errorMsg != "") {
519*c8dee2aaSAndroid Build Coastguard Worker return errorMsg;
520*c8dee2aaSAndroid Build Coastguard Worker }
521*c8dee2aaSAndroid Build Coastguard Worker
522*c8dee2aaSAndroid Build Coastguard Worker // Collect images.
523*c8dee2aaSAndroid Build Coastguard Worker skia_private::TArray<SkString> images;
524*c8dee2aaSAndroid Build Coastguard Worker if (!CommonFlags::CollectImages(FLAGS_pngCodecGMImages, &images)) {
525*c8dee2aaSAndroid Build Coastguard Worker return "Failed to collect images.";
526*c8dee2aaSAndroid Build Coastguard Worker }
527*c8dee2aaSAndroid Build Coastguard Worker
528*c8dee2aaSAndroid Build Coastguard Worker // Register one GM per image.
529*c8dee2aaSAndroid Build Coastguard Worker for (const SkString& image : images) {
530*c8dee2aaSAndroid Build Coastguard Worker if (std::string errorMsg =
531*c8dee2aaSAndroid Build Coastguard Worker registerGMsForImage(image.c_str(), decodeMode, dstColorType, dstAlphaType);
532*c8dee2aaSAndroid Build Coastguard Worker errorMsg != "") {
533*c8dee2aaSAndroid Build Coastguard Worker return errorMsg;
534*c8dee2aaSAndroid Build Coastguard Worker }
535*c8dee2aaSAndroid Build Coastguard Worker }
536*c8dee2aaSAndroid Build Coastguard Worker
537*c8dee2aaSAndroid Build Coastguard Worker return "";
538*c8dee2aaSAndroid Build Coastguard Worker });
539