1 /*
2  * Copyright 2015 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/SkYUVAIndex.h"
9 #include "src/codec/SkCodecImageGenerator.h"
10 #include "src/core/SkPixmapPriv.h"
11 
MakeFromEncodedCodec(sk_sp<SkData> data)12 std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(sk_sp<SkData> data) {
13     auto codec = SkCodec::MakeFromData(data);
14     if (nullptr == codec) {
15         return nullptr;
16     }
17 
18     return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), data));
19 }
20 
21 std::unique_ptr<SkImageGenerator>
MakeFromCodec(std::unique_ptr<SkCodec> codec)22 SkCodecImageGenerator::MakeFromCodec(std::unique_ptr<SkCodec> codec) {
23     return codec
24         ? std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), nullptr))
25         : nullptr;
26 }
27 
adjust_info(SkCodec * codec)28 static SkImageInfo adjust_info(SkCodec* codec) {
29     SkImageInfo info = codec->getInfo();
30     if (kUnpremul_SkAlphaType == info.alphaType()) {
31         info = info.makeAlphaType(kPremul_SkAlphaType);
32     }
33     if (SkPixmapPriv::ShouldSwapWidthHeight(codec->getOrigin())) {
34         info = SkPixmapPriv::SwapWidthHeight(info);
35     }
36     return info;
37 }
38 
SkCodecImageGenerator(std::unique_ptr<SkCodec> codec,sk_sp<SkData> data)39 SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec, sk_sp<SkData> data)
40     : INHERITED(adjust_info(codec.get()))
41     , fCodec(std::move(codec))
42     , fData(std::move(data))
43 {}
44 
onRefEncodedData()45 sk_sp<SkData> SkCodecImageGenerator::onRefEncodedData() {
46     return fData;
47 }
48 
getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,const SkCodec::Options * options)49 bool SkCodecImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const SkCodec::Options* options) {
50     SkPixmap dst(info, pixels, rowBytes);
51 
52     auto decode = [this, options](const SkPixmap& pm) {
53         SkCodec::Result result = fCodec->getPixels(pm, options);
54         switch (result) {
55             case SkCodec::kSuccess:
56             case SkCodec::kIncompleteInput:
57             case SkCodec::kErrorInInput:
58                 return true;
59             default:
60                 return false;
61         }
62     };
63 
64     return SkPixmapPriv::Orient(dst, fCodec->getOrigin(), decode);
65 }
66 
onGetPixels(const SkImageInfo & requestInfo,void * requestPixels,size_t requestRowBytes,const Options & options)67 bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
68                                         size_t requestRowBytes, const Options& options) {
69     return this->getPixels(requestInfo, requestPixels, requestRowBytes, nullptr);
70 }
71 
onQueryYUVAInfo(const SkYUVAPixmapInfo::SupportedDataTypes & supportedDataTypes,SkYUVAPixmapInfo * yuvaPixmapInfo) const72 bool SkCodecImageGenerator::onQueryYUVAInfo(
73         const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
74         SkYUVAPixmapInfo* yuvaPixmapInfo) const {
75     return fCodec->queryYUVAInfo(supportedDataTypes, yuvaPixmapInfo);
76 }
77 
onGetYUVAPlanes(const SkYUVAPixmaps & yuvaPixmaps)78 bool SkCodecImageGenerator::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
79     switch (fCodec->getYUVAPlanes(yuvaPixmaps)) {
80         case SkCodec::kSuccess:
81         case SkCodec::kIncompleteInput:
82         case SkCodec::kErrorInInput:
83             return true;
84         default:
85             return false;
86     }
87 }
88 
getScaledDimensions(float desiredScale) const89 SkISize SkCodecImageGenerator::getScaledDimensions(float desiredScale) const {
90     SkISize size = fCodec->getScaledDimensions(desiredScale);
91     if (SkPixmapPriv::ShouldSwapWidthHeight(fCodec->getOrigin())) {
92         std::swap(size.fWidth, size.fHeight);
93     }
94     return size;
95 }
96