• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkImage.h"
9 #include "SkImageGenerator.h"
10 #include "SkNextID.h"
11 
SkImageGenerator(const SkImageInfo & info,uint32_t uniqueID)12 SkImageGenerator::SkImageGenerator(const SkImageInfo& info, uint32_t uniqueID)
13     : fInfo(info)
14     , fUniqueID(kNeedNewImageUniqueID == uniqueID ? SkNextID::ImageID() : uniqueID)
15 {}
16 
getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes,SkPMColor ctable[],int * ctableCount)17 bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
18                                  SkPMColor ctable[], int* ctableCount) {
19     if (kUnknown_SkColorType == info.colorType()) {
20         return false;
21     }
22     if (nullptr == pixels) {
23         return false;
24     }
25     if (rowBytes < info.minRowBytes()) {
26         return false;
27     }
28 
29     if (kIndex_8_SkColorType == info.colorType()) {
30         if (nullptr == ctable || nullptr == ctableCount) {
31             return false;
32         }
33     } else {
34         if (ctableCount) {
35             *ctableCount = 0;
36         }
37         ctableCount = nullptr;
38         ctable = nullptr;
39     }
40 
41     const bool success = this->onGetPixels(info, pixels, rowBytes, ctable, ctableCount);
42     if (success && ctableCount) {
43         SkASSERT(*ctableCount >= 0 && *ctableCount <= 256);
44     }
45     return success;
46 }
47 
getPixels(const SkImageInfo & info,void * pixels,size_t rowBytes)48 bool SkImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes) {
49     SkASSERT(kIndex_8_SkColorType != info.colorType());
50     if (kIndex_8_SkColorType == info.colorType()) {
51         return false;
52     }
53     return this->getPixels(info, pixels, rowBytes, nullptr, nullptr);
54 }
55 
queryYUV8(SkYUVSizeInfo * sizeInfo,SkYUVColorSpace * colorSpace) const56 bool SkImageGenerator::queryYUV8(SkYUVSizeInfo* sizeInfo, SkYUVColorSpace* colorSpace) const {
57     SkASSERT(sizeInfo);
58 
59     return this->onQueryYUV8(sizeInfo, colorSpace);
60 }
61 
getYUV8Planes(const SkYUVSizeInfo & sizeInfo,void * planes[3])62 bool SkImageGenerator::getYUV8Planes(const SkYUVSizeInfo& sizeInfo, void* planes[3]) {
63     SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth >= 0);
64     SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight >= 0);
65     SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU].fWidth >= 0);
66     SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kU].fHeight >= 0);
67     SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kV].fWidth >= 0);
68     SkASSERT(sizeInfo.fSizes[SkYUVSizeInfo::kV].fHeight >= 0);
69     SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kY] >=
70             (size_t) sizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth);
71     SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kU] >=
72             (size_t) sizeInfo.fSizes[SkYUVSizeInfo::kU].fWidth);
73     SkASSERT(sizeInfo.fWidthBytes[SkYUVSizeInfo::kV] >=
74             (size_t) sizeInfo.fSizes[SkYUVSizeInfo::kV].fWidth);
75     SkASSERT(planes && planes[0] && planes[1] && planes[2]);
76 
77     return this->onGetYUV8Planes(sizeInfo, planes);
78 }
79 
80 #if SK_SUPPORT_GPU
81 #include "GrTextureProxy.h"
82 
generateTexture(GrContext * ctx,const SkImageInfo & info,const SkIPoint & origin)83 sk_sp<GrTextureProxy> SkImageGenerator::generateTexture(GrContext* ctx, const SkImageInfo& info,
84                                                         const SkIPoint& origin) {
85     SkIRect srcRect = SkIRect::MakeXYWH(origin.x(), origin.y(), info.width(), info.height());
86     if (!SkIRect::MakeWH(fInfo.width(), fInfo.height()).contains(srcRect)) {
87         return nullptr;
88     }
89     return this->onGenerateTexture(ctx, info, origin);
90 }
91 
onGenerateTexture(GrContext *,const SkImageInfo &,const SkIPoint &)92 sk_sp<GrTextureProxy> SkImageGenerator::onGenerateTexture(GrContext*, const SkImageInfo&,
93                                                           const SkIPoint&) {
94     return nullptr;
95 }
96 #endif
97 
98 /////////////////////////////////////////////////////////////////////////////////////////////
99 
onRefEncodedData(GrContext * ctx)100 SkData* SkImageGenerator::onRefEncodedData(GrContext* ctx) {
101     return nullptr;
102 }
103 
onGetPixels(const SkImageInfo & info,void * dst,size_t rb,SkPMColor * colors,int * colorCount)104 bool SkImageGenerator::onGetPixels(const SkImageInfo& info, void* dst, size_t rb,
105                                    SkPMColor* colors, int* colorCount) {
106     return false;
107 }
108 
109 ///////////////////////////////////////////////////////////////////////////////////////////////////
110 
111 #include "SkBitmap.h"
112 #include "SkColorTable.h"
113 
reset_and_return_false(SkBitmap * bitmap)114 static bool reset_and_return_false(SkBitmap* bitmap) {
115     bitmap->reset();
116     return false;
117 }
118 
tryGenerateBitmap(SkBitmap * bitmap,const SkImageInfo & info,SkBitmap::Allocator * allocator)119 bool SkImageGenerator::tryGenerateBitmap(SkBitmap* bitmap, const SkImageInfo& info,
120                                          SkBitmap::Allocator* allocator) {
121     if (0 == info.getSafeSize(info.minRowBytes())) {
122         return false;
123     }
124     if (!bitmap->setInfo(info)) {
125         return reset_and_return_false(bitmap);
126     }
127 
128     SkPMColor ctStorage[256];
129     memset(ctStorage, 0xFF, sizeof(ctStorage)); // init with opaque-white for the moment
130     sk_sp<SkColorTable> ctable(new SkColorTable(ctStorage, 256));
131     if (!bitmap->tryAllocPixels(allocator, ctable.get())) {
132         // SkResourceCache's custom allcator can'thandle ctables, so it may fail on
133         // kIndex_8_SkColorTable.
134         // https://bug.skia.org/4355
135 #if 1
136         // ignore the allocator, and see if we can succeed without it
137         if (!bitmap->tryAllocPixels(nullptr, ctable.get())) {
138             return reset_and_return_false(bitmap);
139         }
140 #else
141         // this is the up-scale technique, not fully debugged, but we keep it here at the moment
142         // to remind ourselves that this might be better than ignoring the allocator.
143 
144         info = SkImageInfo::MakeN32(info.width(), info.height(), info.alphaType());
145         if (!bitmap->setInfo(info)) {
146             return reset_and_return_false(bitmap);
147         }
148         // we pass nullptr for the ctable arg, since we are now explicitly N32
149         if (!bitmap->tryAllocPixels(allocator, nullptr)) {
150             return reset_and_return_false(bitmap);
151         }
152 #endif
153     }
154 
155     bitmap->lockPixels();
156     if (!bitmap->getPixels()) {
157         return reset_and_return_false(bitmap);
158     }
159 
160     int ctCount = 0;
161     if (!this->getPixels(bitmap->info(), bitmap->getPixels(), bitmap->rowBytes(),
162                          ctStorage, &ctCount)) {
163         return reset_and_return_false(bitmap);
164     }
165 
166     if (ctCount > 0) {
167         SkASSERT(kIndex_8_SkColorType == bitmap->colorType());
168         // we and bitmap should be owners
169         SkASSERT(!ctable->unique());
170 
171         // Now we need to overwrite the ctable we built earlier, with the correct colors.
172         // This does mean that we may have made the table too big, but that cannot be avoided
173         // until we can change SkImageGenerator's API to return us the ctable *before* we have to
174         // allocate space for all the pixels.
175         ctable->dangerous_overwriteColors(ctStorage, ctCount);
176     } else {
177         SkASSERT(kIndex_8_SkColorType != bitmap->colorType());
178         // we should be the only owner
179         SkASSERT(ctable->unique());
180     }
181     return true;
182 }
183 
184 #include "SkGraphics.h"
185 
186 static SkGraphics::ImageGeneratorFromEncodedDataFactory gFactory;
187 
188 SkGraphics::ImageGeneratorFromEncodedDataFactory
SetImageGeneratorFromEncodedDataFactory(ImageGeneratorFromEncodedDataFactory factory)189 SkGraphics::SetImageGeneratorFromEncodedDataFactory(ImageGeneratorFromEncodedDataFactory factory)
190 {
191     ImageGeneratorFromEncodedDataFactory prev = gFactory;
192     gFactory = factory;
193     return prev;
194 }
195 
MakeFromEncoded(sk_sp<SkData> data)196 std::unique_ptr<SkImageGenerator> SkImageGenerator::MakeFromEncoded(sk_sp<SkData> data) {
197     if (!data) {
198         return nullptr;
199     }
200     if (gFactory) {
201         if (std::unique_ptr<SkImageGenerator> generator = gFactory(data)) {
202             return generator;
203         }
204     }
205     return SkImageGenerator::MakeFromEncodedImpl(std::move(data));
206 }
207