OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCodecPriv.h" | 8 #include "SkCodecPriv.h" |
9 #include "SkScaledCodec.h" | 9 #include "SkScaledCodec.h" |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
171 } | 171 } |
172 if (sampleYPtr) { | 172 if (sampleYPtr) { |
173 *sampleYPtr = sampleY; | 173 *sampleYPtr = sampleY; |
174 } | 174 } |
175 } | 175 } |
176 | 176 |
177 // TODO: Implement subsetting in onGetPixels which works when and when not sampl ing | 177 // TODO: Implement subsetting in onGetPixels which works when and when not sampl ing |
178 | 178 |
179 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst, | 179 SkCodec::Result SkScaledCodec::onGetPixels(const SkImageInfo& requestedInfo, voi d* dst, |
180 size_t rowBytes, const Options& optio ns, | 180 size_t rowBytes, const Options& optio ns, |
181 SkPMColor ctable[], int* ctableCount) { | 181 SkPMColor ctable[], int* ctableCount, |
182 int* rowsDecoded) { | |
182 | 183 |
183 if (options.fSubset) { | 184 if (options.fSubset) { |
184 // Subsets are not supported. | 185 // Subsets are not supported. |
185 return kUnimplemented; | 186 return kUnimplemented; |
186 } | 187 } |
187 | 188 |
188 // FIXME: If no scaling/subsets are requested, we can call fCodec->getPixels . | 189 // FIXME: If no scaling/subsets are requested, we can call fCodec->getPixels . |
189 Result result = fCodec->startScanlineDecode(requestedInfo, &options, ctable, ctableCount); | 190 Result result = fCodec->startScanlineDecode(requestedInfo, &options, ctable, ctableCount); |
190 if (kSuccess == result) { | 191 if (kSuccess == result) { |
191 // native decode supported | 192 // native decode supported |
192 switch (fCodec->getScanlineOrder()) { | 193 switch (fCodec->getScanlineOrder()) { |
193 case SkCodec::kTopDown_SkScanlineOrder: | 194 case SkCodec::kTopDown_SkScanlineOrder: |
194 case SkCodec::kBottomUp_SkScanlineOrder: | 195 case SkCodec::kBottomUp_SkScanlineOrder: |
195 case SkCodec::kNone_SkScanlineOrder: | 196 case SkCodec::kNone_SkScanlineOrder: |
196 return fCodec->getScanlines(dst, requestedInfo.height(), rowByte s); | 197 if (fCodec->getScanlines(dst, requestedInfo.height(), rowBytes) != |
198 requestedInfo.height()) { | |
199 // fCodec has already handled filling uninitialized memory. | |
200 *rowsDecoded = requestedInfo.height(); | |
201 return kIncompleteInput; | |
202 } | |
203 return kSuccess; | |
197 case SkCodec::kOutOfOrder_SkScanlineOrder: { | 204 case SkCodec::kOutOfOrder_SkScanlineOrder: { |
198 for (int y = 0; y < requestedInfo.height(); y++) { | 205 for (int y = 0; y < requestedInfo.height(); y++) { |
199 int dstY = fCodec->nextScanline(); | 206 int dstY = fCodec->nextScanline(); |
200 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); | 207 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * dstY); |
201 result = fCodec->getScanlines(dstPtr, 1, rowBytes); | 208 if (1 != fCodec->getScanlines(dstPtr, 1, rowBytes)) { |
202 // FIXME (msarett): Make the SkCodec base class take care of filling | 209 *rowsDecoded = y + 1; |
scroggo
2015/10/01 14:48:32
Why is this y+1 and not y? (Same for other instanc
msarett
2015/10/01 18:14:14
The failed call to getScanlines(1) will fill the s
| |
203 // uninitialized pixels so we can return immediately on kInc ompleteInput. | 210 return kIncompleteInput; |
204 if (kSuccess != result && kIncompleteInput != result) { | |
205 return result; | |
206 } | 211 } |
207 } | 212 } |
208 return result; | 213 return kSuccess; |
209 } | 214 } |
210 } | 215 } |
211 } | 216 } |
212 | 217 |
213 if (kInvalidScale != result) { | 218 if (kInvalidScale != result) { |
214 // no scaling requested | 219 // no scaling requested |
215 return result; | 220 return result; |
216 } | 221 } |
217 | 222 |
218 // scaling requested | 223 // scaling requested |
(...skipping 15 matching lines...) Expand all Loading... | |
234 // update codec with new info | 239 // update codec with new info |
235 // FIXME: The previous call to start returned kInvalidScale. This call may | 240 // FIXME: The previous call to start returned kInvalidScale. This call may |
236 // require a rewind. (skbug.com/4284) | 241 // require a rewind. (skbug.com/4284) |
237 result = fCodec->startScanlineDecode(info, &options, ctable, ctableCount); | 242 result = fCodec->startScanlineDecode(info, &options, ctable, ctableCount); |
238 if (kSuccess != result) { | 243 if (kSuccess != result) { |
239 return result; | 244 return result; |
240 } | 245 } |
241 | 246 |
242 switch(fCodec->getScanlineOrder()) { | 247 switch(fCodec->getScanlineOrder()) { |
243 case SkCodec::kTopDown_SkScanlineOrder: { | 248 case SkCodec::kTopDown_SkScanlineOrder: { |
244 result = fCodec->skipScanlines(Y0); | 249 if (!fCodec->skipScanlines(Y0)) { |
245 if (kSuccess != result && kIncompleteInput != result) { | 250 *rowsDecoded = 0; |
246 return result; | 251 return kIncompleteInput; |
247 } | 252 } |
248 for (int y = 0; y < dstHeight; y++) { | 253 for (int y = 0; y < dstHeight; y++) { |
249 result = fCodec->getScanlines(dst, 1, rowBytes); | 254 if (1 != fCodec->getScanlines(dst, 1, rowBytes)) { |
250 if (kSuccess != result && kIncompleteInput != result) { | 255 *rowsDecoded = y + 1; |
251 return result; | 256 return kIncompleteInput; |
252 } | 257 } |
253 if (y < dstHeight - 1) { | 258 if (y < dstHeight - 1) { |
254 result = fCodec->skipScanlines(sampleY - 1); | 259 if (!fCodec->skipScanlines(sampleY - 1)) { |
255 if (kSuccess != result && kIncompleteInput != result) { | 260 *rowsDecoded = y + 1; |
256 return result; | 261 return kIncompleteInput; |
257 } | 262 } |
258 } | 263 } |
259 dst = SkTAddOffset<void>(dst, rowBytes); | 264 dst = SkTAddOffset<void>(dst, rowBytes); |
260 } | 265 } |
261 return result; | 266 return kSuccess; |
262 } | 267 } |
263 case SkCodec::kBottomUp_SkScanlineOrder: | 268 case SkCodec::kBottomUp_SkScanlineOrder: |
264 case SkCodec::kOutOfOrder_SkScanlineOrder: { | 269 case SkCodec::kOutOfOrder_SkScanlineOrder: { |
265 for (int y = 0; y < srcHeight; y++) { | 270 Result result = kSuccess; |
271 int y; | |
272 for (y = 0; y < srcHeight; y++) { | |
266 int srcY = fCodec->nextScanline(); | 273 int srcY = fCodec->nextScanline(); |
267 if (is_coord_necessary(srcY, sampleY, dstHeight)) { | 274 if (is_coord_necessary(srcY, sampleY, dstHeight)) { |
268 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_co ord(srcY, sampleY)); | 275 void* dstPtr = SkTAddOffset<void>(dst, rowBytes * get_dst_co ord(srcY, sampleY)); |
269 result = fCodec->getScanlines(dstPtr, 1, rowBytes); | 276 if (1 != fCodec->getScanlines(dstPtr, 1, rowBytes)) { |
270 if (kSuccess != result && kIncompleteInput != result) { | 277 result = kIncompleteInput; |
271 return result; | 278 break; |
272 } | 279 } |
273 } else { | 280 } else { |
274 result = fCodec->skipScanlines(1); | 281 if (!fCodec->skipScanlines(1)) { |
275 if (kSuccess != result && kIncompleteInput != result) { | 282 result = kIncompleteInput; |
276 return result; | 283 break; |
277 } | 284 } |
278 } | 285 } |
279 } | 286 } |
287 | |
288 // We handle filling uninitialized memory here instead of in the par ent class. | |
289 // The parent class does not know that we are sampling. | |
290 if (kIncompleteInput == result) { | |
291 const SkImageInfo fillInfo = requestedInfo.makeWH(requestedInfo. width(), 1); | |
292 const uint32_t fillValue = this->getFillValue(fillInfo.colorType (), | |
293 fillInfo.alphaType()); | |
294 for (; y < srcHeight; y++) { | |
295 int srcY = fCodec->nextScanline(y); | |
296 if (is_coord_necessary(srcY, sampleY, dstHeight)) { | |
297 void* dstRow = SkTAddOffset<void>(dst, | |
298 rowBytes * get_dst_coord(srcY, sampleY)); | |
299 SkSwizzler::Fill(dstRow, fillInfo, rowBytes, fillValue, | |
300 options.fZeroInitialized); | |
301 } | |
302 } | |
303 *rowsDecoded = dstHeight; | |
304 } | |
280 return result; | 305 return result; |
281 } | 306 } |
282 case SkCodec::kNone_SkScanlineOrder: { | 307 case SkCodec::kNone_SkScanlineOrder: { |
283 SkAutoMalloc storage(srcHeight * rowBytes); | 308 SkAutoMalloc storage(srcHeight * rowBytes); |
284 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); | 309 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); |
285 result = fCodec->getScanlines(storagePtr, srcHeight, rowBytes); | 310 int scanlines = (int) fCodec->getScanlines(storagePtr, srcHeight, ro wBytes); |
scroggo
2015/10/01 14:48:32
It's weird to me that getScanlines returns one typ
msarett
2015/10/01 18:14:14
Yeah I also thought this was strange.
I feel stro
scroggo
2015/10/01 20:48:57
+1 to consistency. I'm not sure why width and heig
| |
286 if (kSuccess != result && kIncompleteInput != result) { | |
287 return result; | |
288 } | |
289 storagePtr += Y0 * rowBytes; | 311 storagePtr += Y0 * rowBytes; |
290 for (int y = 0; y < dstHeight; y++) { | 312 scanlines -= Y0; |
313 int y = 0; | |
314 while(y < dstHeight && scanlines > 0) { | |
291 memcpy(dst, storagePtr, rowBytes); | 315 memcpy(dst, storagePtr, rowBytes); |
292 storagePtr += sampleY * rowBytes; | 316 storagePtr += sampleY * rowBytes; |
293 dst = SkTAddOffset<void>(dst, rowBytes); | 317 dst = SkTAddOffset<void>(dst, rowBytes); |
318 scanlines -= sampleY; | |
319 y++; | |
294 } | 320 } |
295 return result; | 321 if (y < dstHeight) { |
322 // fCodec has already handled filling uninitialized memory. | |
323 *rowsDecoded = dstHeight; | |
324 return kIncompleteInput; | |
325 } | |
326 return kSuccess; | |
296 } | 327 } |
297 default: | 328 default: |
298 SkASSERT(false); | 329 SkASSERT(false); |
299 return kUnimplemented; | 330 return kUnimplemented; |
300 } | 331 } |
301 } | 332 } |
333 | |
334 uint32_t SkScaledCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaT ype) const { | |
335 return fCodec->getFillValue(colorType, alphaType); | |
336 } | |
337 | |
338 SkCodec::SkScanlineOrder SkScaledCodec::onGetScanlineOrder() const { | |
339 return fCodec->getScanlineOrder(); | |
340 } | |
OLD | NEW |