OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2008 The Android Open Source Project | 3 * Copyright 2008 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkBitmap.h" | 10 #include "SkBitmap.h" |
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 HeapAllocator stdalloc; | 406 HeapAllocator stdalloc; |
407 | 407 |
408 if (NULL == allocator) { | 408 if (NULL == allocator) { |
409 allocator = &stdalloc; | 409 allocator = &stdalloc; |
410 } | 410 } |
411 return allocator->allocPixelRef(this, ctable); | 411 return allocator->allocPixelRef(this, ctable); |
412 } | 412 } |
413 | 413 |
414 /////////////////////////////////////////////////////////////////////////////// | 414 /////////////////////////////////////////////////////////////////////////////// |
415 | 415 |
416 bool SkBitmap::allocPixels(const SkImageInfo& info, SkPixelRefFactory* factory, | 416 bool SkBitmap::allocPixels(const SkImageInfo& requestedInfo, SkPixelRefFactory*
factory, |
417 SkColorTable* ctable) { | 417 SkColorTable* ctable) { |
418 if (kIndex_8_SkColorType == info.fColorType && NULL == ctable) { | 418 if (kIndex_8_SkColorType == requestedInfo.fColorType && NULL == ctable) { |
419 return reset_return_false(this); | 419 return reset_return_false(this); |
420 } | 420 } |
421 if (!this->setInfo(info)) { | 421 if (!this->setInfo(requestedInfo)) { |
422 return reset_return_false(this); | 422 return reset_return_false(this); |
423 } | 423 } |
424 | 424 |
| 425 // setInfo may have corrected info (e.g. 565 is always opaque). |
| 426 const SkImageInfo& correctedInfo = this->info(); |
| 427 |
425 SkMallocPixelRef::PRFactory defaultFactory; | 428 SkMallocPixelRef::PRFactory defaultFactory; |
426 if (NULL == factory) { | 429 if (NULL == factory) { |
427 factory = &defaultFactory; | 430 factory = &defaultFactory; |
428 } | 431 } |
429 | 432 |
430 SkPixelRef* pr = factory->create(info, ctable); | 433 SkPixelRef* pr = factory->create(correctedInfo, ctable); |
431 if (NULL == pr) { | 434 if (NULL == pr) { |
432 return reset_return_false(this); | 435 return reset_return_false(this); |
433 } | 436 } |
434 this->setPixelRef(pr)->unref(); | 437 this->setPixelRef(pr)->unref(); |
435 | 438 |
436 // TODO: lockPixels could/should return bool or void*/NULL | 439 // TODO: lockPixels could/should return bool or void*/NULL |
437 this->lockPixels(); | 440 this->lockPixels(); |
438 if (NULL == this->getPixels()) { | 441 if (NULL == this->getPixels()) { |
439 return reset_return_false(this); | 442 return reset_return_false(this); |
440 } | 443 } |
441 return true; | 444 return true; |
442 } | 445 } |
443 | 446 |
444 bool SkBitmap::installPixels(const SkImageInfo& info, void* pixels, size_t rb, S
kColorTable* ct, | 447 bool SkBitmap::installPixels(const SkImageInfo& requestedInfo, void* pixels, siz
e_t rb, |
445 void (*releaseProc)(void* addr, void* context), voi
d* context) { | 448 SkColorTable* ct, void (*releaseProc)(void* addr, v
oid* context), |
446 if (!this->setInfo(info, rb)) { | 449 void* context) { |
| 450 if (!this->setInfo(requestedInfo, rb)) { |
447 this->reset(); | 451 this->reset(); |
448 return false; | 452 return false; |
449 } | 453 } |
450 | 454 |
451 SkPixelRef* pr = SkMallocPixelRef::NewWithProc(info, rb, ct, pixels, release
Proc, context); | 455 // setInfo may have corrected info (e.g. 565 is always opaque). |
| 456 const SkImageInfo& correctedInfo = this->info(); |
| 457 |
| 458 SkPixelRef* pr = SkMallocPixelRef::NewWithProc(correctedInfo, rb, ct, pixels
, releaseProc, |
| 459 context); |
452 if (!pr) { | 460 if (!pr) { |
453 this->reset(); | 461 this->reset(); |
454 return false; | 462 return false; |
455 } | 463 } |
456 | 464 |
457 this->setPixelRef(pr)->unref(); | 465 this->setPixelRef(pr)->unref(); |
458 | 466 |
459 // since we're already allocated, we lockPixels right away | 467 // since we're already allocated, we lockPixels right away |
460 this->lockPixels(); | 468 this->lockPixels(); |
461 SkDEBUGCODE(this->validate();) | 469 SkDEBUGCODE(this->validate();) |
(...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 | 963 |
956 // if we have a texture, first get those pixels | 964 // if we have a texture, first get those pixels |
957 SkBitmap tmpSrc; | 965 SkBitmap tmpSrc; |
958 const SkBitmap* src = this; | 966 const SkBitmap* src = this; |
959 | 967 |
960 if (fPixelRef) { | 968 if (fPixelRef) { |
961 SkIRect subset; | 969 SkIRect subset; |
962 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, | 970 subset.setXYWH(fPixelRefOrigin.fX, fPixelRefOrigin.fY, |
963 fInfo.width(), fInfo.height()); | 971 fInfo.width(), fInfo.height()); |
964 if (fPixelRef->readPixels(&tmpSrc, &subset)) { | 972 if (fPixelRef->readPixels(&tmpSrc, &subset)) { |
| 973 if (fPixelRef->info().alphaType() == kUnpremul_SkAlphaType) { |
| 974 // FIXME: The only meaningful implementation of readPixels |
| 975 // (GrPixelRef) assumes premultiplied pixels. |
| 976 return false; |
| 977 } |
965 SkASSERT(tmpSrc.width() == this->width()); | 978 SkASSERT(tmpSrc.width() == this->width()); |
966 SkASSERT(tmpSrc.height() == this->height()); | 979 SkASSERT(tmpSrc.height() == this->height()); |
967 | 980 |
968 // did we get lucky and we can just return tmpSrc? | 981 // did we get lucky and we can just return tmpSrc? |
969 if (tmpSrc.colorType() == dstColorType && NULL == alloc) { | 982 if (tmpSrc.colorType() == dstColorType && NULL == alloc) { |
970 dst->swap(tmpSrc); | 983 dst->swap(tmpSrc); |
971 // If the result is an exact copy, clone the gen ID. | 984 // If the result is an exact copy, clone the gen ID. |
972 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->inf
o()) { | 985 if (dst->pixelRef() && dst->pixelRef()->info() == fPixelRef->inf
o()) { |
973 dst->pixelRef()->cloneGenID(*fPixelRef); | 986 dst->pixelRef()->cloneGenID(*fPixelRef); |
974 } | 987 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 | 1027 |
1015 // pixelRef must be non NULL or tmpDst.readyToDraw() would have | 1028 // pixelRef must be non NULL or tmpDst.readyToDraw() would have |
1016 // returned false. | 1029 // returned false. |
1017 SkASSERT(tmpDst.pixelRef() != NULL); | 1030 SkASSERT(tmpDst.pixelRef() != NULL); |
1018 | 1031 |
1019 /* do memcpy for the same configs cases, else use drawing | 1032 /* do memcpy for the same configs cases, else use drawing |
1020 */ | 1033 */ |
1021 if (src->colorType() == dstColorType) { | 1034 if (src->colorType() == dstColorType) { |
1022 if (tmpDst.getSize() == src->getSize()) { | 1035 if (tmpDst.getSize() == src->getSize()) { |
1023 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); | 1036 memcpy(tmpDst.getPixels(), src->getPixels(), src->getSafeSize()); |
1024 SkPixelRef* pixelRef = tmpDst.pixelRef(); | |
1025 | 1037 |
1026 // In order to reach this point, we know that the width, config and | 1038 SkPixelRef* dstPixelRef = tmpDst.pixelRef(); |
1027 // rowbytes of the SkPixelRefs are the same, but it is possible for | 1039 if (dstPixelRef->info() == fPixelRef->info()) { |
1028 // the heights to differ, if this SkBitmap's height is a subset of | 1040 dstPixelRef->cloneGenID(*fPixelRef); |
1029 // fPixelRef. Only if the SkPixelRefs' heights match are we | |
1030 // guaranteed that this is an exact copy, meaning we should clone | |
1031 // the genID. | |
1032 if (pixelRef->info().fHeight == fPixelRef->info().fHeight) { | |
1033 // TODO: what to do if the two infos match, BUT | |
1034 // fPixelRef is premul and pixelRef is opaque? | |
1035 // skipping assert for now | |
1036 // https://code.google.com/p/skia/issues/detail?id=2012 | |
1037 // SkASSERT(pixelRef->info() == fPixelRef->info()); | |
1038 SkASSERT(pixelRef->info().fWidth == fPixelRef->info().fWidth); | |
1039 SkASSERT(pixelRef->info().fColorType == fPixelRef->info().fColor
Type); | |
1040 pixelRef->cloneGenID(*fPixelRef); | |
1041 } | 1041 } |
1042 } else { | 1042 } else { |
1043 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); | 1043 const char* srcP = reinterpret_cast<const char*>(src->getPixels()); |
1044 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); | 1044 char* dstP = reinterpret_cast<char*>(tmpDst.getPixels()); |
1045 // to be sure we don't read too much, only copy our logical pixels | 1045 // to be sure we don't read too much, only copy our logical pixels |
1046 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); | 1046 size_t bytesToCopy = tmpDst.width() * tmpDst.bytesPerPixel(); |
1047 for (int y = 0; y < tmpDst.height(); y++) { | 1047 for (int y = 0; y < tmpDst.height(); y++) { |
1048 memcpy(dstP, srcP, bytesToCopy); | 1048 memcpy(dstP, srcP, bytesToCopy); |
1049 srcP += src->rowBytes(); | 1049 srcP += src->rowBytes(); |
1050 dstP += tmpDst.rowBytes(); | 1050 dstP += tmpDst.rowBytes(); |
1051 } | 1051 } |
1052 } | 1052 } |
1053 } else if (kARGB_4444_SkColorType == dstColorType | 1053 } else if (kARGB_4444_SkColorType == dstColorType |
1054 && kN32_SkColorType == src->colorType()) { | 1054 && kN32_SkColorType == src->colorType()) { |
| 1055 if (src->alphaType() == kUnpremul_SkAlphaType) { |
| 1056 // Our method for converting to 4444 assumes premultiplied. |
| 1057 return false; |
| 1058 } |
1055 SkASSERT(src->height() == tmpDst.height()); | 1059 SkASSERT(src->height() == tmpDst.height()); |
1056 SkASSERT(src->width() == tmpDst.width()); | 1060 SkASSERT(src->width() == tmpDst.width()); |
1057 for (int y = 0; y < src->height(); ++y) { | 1061 for (int y = 0; y < src->height(); ++y) { |
1058 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0,
y); | 1062 SkPMColor16* SK_RESTRICT dstRow = (SkPMColor16*) tmpDst.getAddr16(0,
y); |
1059 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); | 1063 SkPMColor* SK_RESTRICT srcRow = (SkPMColor*) src->getAddr32(0, y); |
1060 DITHER_4444_SCAN(y); | 1064 DITHER_4444_SCAN(y); |
1061 for (int x = 0; x < src->width(); ++x) { | 1065 for (int x = 0; x < src->width(); ++x) { |
1062 dstRow[x] = SkDitherARGB32To4444(srcRow[x], | 1066 dstRow[x] = SkDitherARGB32To4444(srcRow[x], |
1063 DITHER_VALUE(x)); | 1067 DITHER_VALUE(x)); |
1064 } | 1068 } |
1065 } | 1069 } |
1066 } else { | 1070 } else { |
| 1071 if (tmpDst.alphaType() == kUnpremul_SkAlphaType) { |
| 1072 // We do not support drawing to unpremultiplied bitmaps. |
| 1073 return false; |
| 1074 } |
| 1075 |
1067 // Always clear the dest in case one of the blitters accesses it | 1076 // Always clear the dest in case one of the blitters accesses it |
1068 // TODO: switch the allocation of tmpDst to call sk_calloc_throw | 1077 // TODO: switch the allocation of tmpDst to call sk_calloc_throw |
1069 tmpDst.eraseColor(SK_ColorTRANSPARENT); | 1078 tmpDst.eraseColor(SK_ColorTRANSPARENT); |
1070 | 1079 |
1071 SkCanvas canvas(tmpDst); | 1080 SkCanvas canvas(tmpDst); |
1072 SkPaint paint; | 1081 SkPaint paint; |
1073 | 1082 |
1074 paint.setDither(true); | 1083 paint.setDither(true); |
1075 canvas.drawBitmap(*src, 0, 0, &paint); | 1084 canvas.drawBitmap(*src, 0, 0, &paint); |
1076 } | 1085 } |
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 /////////////////////////////////////////////////////////////////////////////// | 1485 /////////////////////////////////////////////////////////////////////////////// |
1477 | 1486 |
1478 #ifdef SK_DEBUG | 1487 #ifdef SK_DEBUG |
1479 void SkImageInfo::validate() const { | 1488 void SkImageInfo::validate() const { |
1480 SkASSERT(fWidth >= 0); | 1489 SkASSERT(fWidth >= 0); |
1481 SkASSERT(fHeight >= 0); | 1490 SkASSERT(fHeight >= 0); |
1482 SkASSERT(SkColorTypeIsValid(fColorType)); | 1491 SkASSERT(SkColorTypeIsValid(fColorType)); |
1483 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); | 1492 SkASSERT(SkAlphaTypeIsValid(fAlphaType)); |
1484 } | 1493 } |
1485 #endif | 1494 #endif |
OLD | NEW |