Chromium Code Reviews| 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 |