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 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); | 259 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); |
260 } | 260 } |
261 | 261 |
262 void SkBitmap::getBounds(SkIRect* bounds) const { | 262 void SkBitmap::getBounds(SkIRect* bounds) const { |
263 SkASSERT(bounds); | 263 SkASSERT(bounds); |
264 bounds->set(0, 0, fWidth, fHeight); | 264 bounds->set(0, 0, fWidth, fHeight); |
265 } | 265 } |
266 | 266 |
267 /////////////////////////////////////////////////////////////////////////////// | 267 /////////////////////////////////////////////////////////////////////////////// |
268 | 268 |
269 void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes) { | 269 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, |
270 this->freePixels(); | 270 SkAlphaType alphaType) { |
271 | |
272 if ((width | height) < 0) { | 271 if ((width | height) < 0) { |
273 goto err; | 272 goto ERROR; |
274 } | 273 } |
275 | |
276 if (rowBytes == 0) { | 274 if (rowBytes == 0) { |
277 rowBytes = SkBitmap::ComputeRowBytes(c, width); | 275 rowBytes = SkBitmap::ComputeRowBytes(config, width); |
278 if (0 == rowBytes && kNo_Config != c) { | 276 if (0 == rowBytes && kNo_Config != config) { |
279 goto err; | 277 goto ERROR; |
280 } | 278 } |
281 } | 279 } |
282 | 280 |
283 fConfig = SkToU8(c); | 281 // check for legal/supported config+alphaType combinations |
| 282 // |
| 283 switch (config) { |
| 284 case kNo_Config: |
| 285 alphaType = kIgnore_SkAlphaType; // canonicalize |
| 286 break; |
| 287 case kA1_Config: |
| 288 case kA8_Config: |
| 289 if (kUnpremul_SkAlphaType == alphaType) { |
| 290 alphaType = kPremul_SkAlphaType; |
| 291 } |
| 292 // fall-through |
| 293 case kIndex8_Config: |
| 294 case kARGB_4444_Config: |
| 295 case kARGB_8888_Config: |
| 296 if (kIgnore_SkAlphaType == alphaType) { |
| 297 goto ERROR; // not supported yet |
| 298 } |
| 299 break; |
| 300 case kRGB_565_Config: |
| 301 alphaType = kOpaque_SkAlphaType; // canonicalize |
| 302 break; |
| 303 } |
| 304 |
| 305 this->freePixels(); |
| 306 |
| 307 fConfig = SkToU8(config); |
| 308 fAlphaType = SkToU8(alphaType); |
284 fWidth = width; | 309 fWidth = width; |
285 fHeight = height; | 310 fHeight = height; |
286 fRowBytes = SkToU32(rowBytes); | 311 fRowBytes = SkToU32(rowBytes); |
287 | 312 |
288 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); | 313 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config); |
289 | 314 |
290 SkDEBUGCODE(this->validate();) | 315 SkDEBUGCODE(this->validate();) |
291 return; | 316 return true; |
292 | 317 |
293 // if we got here, we had an error, so we reset the bitmap to empty | 318 // if we got here, we had an error, so we reset the bitmap to empty |
294 err: | 319 ERROR: |
295 this->reset(); | 320 this->reset(); |
| 321 return false; |
| 322 } |
| 323 |
| 324 void SkBitmap::setAlphaType(SkAlphaType alphaType) { |
| 325 // check for legal/supported config+alphaType combinations |
| 326 // |
| 327 switch (this->config()) { |
| 328 case kNo_Config: |
| 329 alphaType = kIgnore_SkAlphaType; // canonicalize |
| 330 break; |
| 331 case kA1_Config: |
| 332 case kA8_Config: |
| 333 if (kUnpremul_SkAlphaType == alphaType) { |
| 334 alphaType = kPremul_SkAlphaType; |
| 335 } |
| 336 // fall-through |
| 337 case kIndex8_Config: |
| 338 case kARGB_4444_Config: |
| 339 case kARGB_8888_Config: |
| 340 if (kIgnore_SkAlphaType == alphaType) { |
| 341 SkDEBUGFAIL("bad alphaType for existing config"); |
| 342 return; |
| 343 } |
| 344 break; |
| 345 case kRGB_565_Config: |
| 346 alphaType = kOpaque_SkAlphaType; // canonicalize |
| 347 break; |
| 348 } |
| 349 |
| 350 fAlphaType = SkToU8(alphaType); |
296 } | 351 } |
297 | 352 |
298 void SkBitmap::updatePixelsFromRef() const { | 353 void SkBitmap::updatePixelsFromRef() const { |
299 if (NULL != fPixelRef) { | 354 if (NULL != fPixelRef) { |
300 if (fPixelLockCount > 0) { | 355 if (fPixelLockCount > 0) { |
301 SkASSERT(fPixelRef->isLocked()); | 356 SkASSERT(fPixelRef->isLocked()); |
302 | 357 |
303 void* p = fPixelRef->pixels(); | 358 void* p = fPixelRef->pixels(); |
304 if (NULL != p) { | 359 if (NULL != p) { |
305 p = (char*)p + fPixelRefOffset; | 360 p = (char*)p + fPixelRefOffset; |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 573 |
519 void SkBitmap::setImmutable() { | 574 void SkBitmap::setImmutable() { |
520 if (fPixelRef) { | 575 if (fPixelRef) { |
521 fPixelRef->setImmutable(); | 576 fPixelRef->setImmutable(); |
522 } else { | 577 } else { |
523 fFlags |= kImageIsImmutable_Flag; | 578 fFlags |= kImageIsImmutable_Flag; |
524 } | 579 } |
525 } | 580 } |
526 | 581 |
527 bool SkBitmap::isOpaque() const { | 582 bool SkBitmap::isOpaque() const { |
| 583 return kOpaque_SkAlphaType == fAlphaType || |
| 584 kIgnore_SkAlphaType == fAlphaType; |
| 585 #if 0 |
528 switch (fConfig) { | 586 switch (fConfig) { |
529 case kNo_Config: | 587 case kNo_Config: |
530 return true; | 588 return true; |
531 | 589 |
532 case kA1_Config: | 590 case kA1_Config: |
533 case kA8_Config: | 591 case kA8_Config: |
534 case kARGB_4444_Config: | 592 case kARGB_4444_Config: |
535 case kARGB_8888_Config: | 593 case kARGB_8888_Config: |
536 return (fFlags & kImageIsOpaque_Flag) != 0; | 594 return (fFlags & kImageIsOpaque_Flag) != 0; |
537 | 595 |
(...skipping 10 matching lines...) Expand all Loading... |
548 return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0; | 606 return (flags & SkColorTable::kColorsAreOpaque_Flag) != 0; |
549 } | 607 } |
550 | 608 |
551 case kRGB_565_Config: | 609 case kRGB_565_Config: |
552 return true; | 610 return true; |
553 | 611 |
554 default: | 612 default: |
555 SkDEBUGFAIL("unknown bitmap config pased to isOpaque"); | 613 SkDEBUGFAIL("unknown bitmap config pased to isOpaque"); |
556 return false; | 614 return false; |
557 } | 615 } |
| 616 #endif |
558 } | 617 } |
559 | 618 |
| 619 #if 0 |
560 void SkBitmap::setIsOpaque(bool isOpaque) { | 620 void SkBitmap::setIsOpaque(bool isOpaque) { |
561 /* we record this regardless of fConfig, though it is ignored in | 621 /* we record this regardless of fConfig, though it is ignored in |
562 isOpaque() for configs that can't support per-pixel alpha. | 622 isOpaque() for configs that can't support per-pixel alpha. |
563 */ | 623 */ |
564 if (isOpaque) { | 624 if (isOpaque) { |
565 fFlags |= kImageIsOpaque_Flag; | 625 fFlags |= kImageIsOpaque_Flag; |
566 } else { | 626 } else { |
567 fFlags &= ~kImageIsOpaque_Flag; | 627 fFlags &= ~kImageIsOpaque_Flag; |
568 } | 628 } |
569 } | 629 } |
| 630 #endif |
570 | 631 |
571 bool SkBitmap::isVolatile() const { | 632 bool SkBitmap::isVolatile() const { |
572 return (fFlags & kImageIsVolatile_Flag) != 0; | 633 return (fFlags & kImageIsVolatile_Flag) != 0; |
573 } | 634 } |
574 | 635 |
575 void SkBitmap::setIsVolatile(bool isVolatile) { | 636 void SkBitmap::setIsVolatile(bool isVolatile) { |
576 if (isVolatile) { | 637 if (isVolatile) { |
577 fFlags |= kImageIsVolatile_Flag; | 638 fFlags |= kImageIsVolatile_Flag; |
578 } else { | 639 } else { |
579 fFlags &= ~kImageIsVolatile_Flag; | 640 fFlags &= ~kImageIsVolatile_Flag; |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
955 srcRect.set(0, 0, this->width(), this->height()); | 1016 srcRect.set(0, 0, this->width(), this->height()); |
956 if (!r.intersect(srcRect, subset)) { | 1017 if (!r.intersect(srcRect, subset)) { |
957 return false; // r is empty (i.e. no intersection) | 1018 return false; // r is empty (i.e. no intersection) |
958 } | 1019 } |
959 | 1020 |
960 if (fPixelRef->getTexture() != NULL) { | 1021 if (fPixelRef->getTexture() != NULL) { |
961 // Do a deep copy | 1022 // Do a deep copy |
962 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); | 1023 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); |
963 if (pixelRef != NULL) { | 1024 if (pixelRef != NULL) { |
964 SkBitmap dst; | 1025 SkBitmap dst; |
965 dst.setConfig(this->config(), subset.width(), subset.height()); | 1026 dst.setConfig(this->config(), subset.width(), subset.height(), 0, |
| 1027 this->isOpaque() ? |
| 1028 kOpaque_SkAlphaType : kPremul_SkAlphaType); |
966 dst.setIsVolatile(this->isVolatile()); | 1029 dst.setIsVolatile(this->isVolatile()); |
967 dst.setIsOpaque(this->isOpaque()); | |
968 dst.setPixelRef(pixelRef)->unref(); | 1030 dst.setPixelRef(pixelRef)->unref(); |
969 SkDEBUGCODE(dst.validate()); | 1031 SkDEBUGCODE(dst.validate()); |
970 result->swap(dst); | 1032 result->swap(dst); |
971 return true; | 1033 return true; |
972 } | 1034 } |
973 } | 1035 } |
974 | 1036 |
975 // If the upper left of the rectangle was outside the bounds of this SkBitma
p, we should have | 1037 // If the upper left of the rectangle was outside the bounds of this SkBitma
p, we should have |
976 // exited above. | 1038 // exited above. |
977 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width(
))); | 1039 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width(
))); |
978 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height(
))); | 1040 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height(
))); |
979 | 1041 |
980 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); | 1042 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); |
981 if (SUB_OFFSET_FAILURE == offset) { | 1043 if (SUB_OFFSET_FAILURE == offset) { |
982 return false; // config not supported | 1044 return false; // config not supported |
983 } | 1045 } |
984 | 1046 |
985 SkBitmap dst; | 1047 SkBitmap dst; |
986 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes()); | 1048 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), |
| 1049 this->isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType); |
987 dst.setIsVolatile(this->isVolatile()); | 1050 dst.setIsVolatile(this->isVolatile()); |
988 dst.setIsOpaque(this->isOpaque()); | |
989 | 1051 |
990 if (fPixelRef) { | 1052 if (fPixelRef) { |
991 // share the pixelref with a custom offset | 1053 // share the pixelref with a custom offset |
992 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); | 1054 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); |
993 } | 1055 } |
994 SkDEBUGCODE(dst.validate();) | 1056 SkDEBUGCODE(dst.validate();) |
995 | 1057 |
996 // we know we're good, so commit to result | 1058 // we know we're good, so commit to result |
997 result->swap(dst); | 1059 result->swap(dst); |
998 return true; | 1060 return true; |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1128 tmpDst.eraseColor(SK_ColorTRANSPARENT); | 1190 tmpDst.eraseColor(SK_ColorTRANSPARENT); |
1129 } | 1191 } |
1130 | 1192 |
1131 SkCanvas canvas(tmpDst); | 1193 SkCanvas canvas(tmpDst); |
1132 SkPaint paint; | 1194 SkPaint paint; |
1133 | 1195 |
1134 paint.setDither(true); | 1196 paint.setDither(true); |
1135 canvas.drawBitmap(*src, 0, 0, &paint); | 1197 canvas.drawBitmap(*src, 0, 0, &paint); |
1136 } | 1198 } |
1137 | 1199 |
1138 tmpDst.setIsOpaque(src->isOpaque()); | 1200 tmpDst.setAlphaType(src->isOpaque() ? |
| 1201 kOpaque_SkAlphaType : kPremul_SkAlphaType); |
1139 | 1202 |
1140 dst->swap(tmpDst); | 1203 dst->swap(tmpDst); |
1141 return true; | 1204 return true; |
1142 } | 1205 } |
1143 | 1206 |
1144 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { | 1207 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { |
1145 if (!this->canCopyTo(dstConfig)) { | 1208 if (!this->canCopyTo(dstConfig)) { |
1146 return false; | 1209 return false; |
1147 } | 1210 } |
1148 | 1211 |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 } | 1664 } |
1602 | 1665 |
1603 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { | 1666 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { |
1604 this->reset(); | 1667 this->reset(); |
1605 | 1668 |
1606 int width = buffer.readInt(); | 1669 int width = buffer.readInt(); |
1607 int height = buffer.readInt(); | 1670 int height = buffer.readInt(); |
1608 int rowBytes = buffer.readInt(); | 1671 int rowBytes = buffer.readInt(); |
1609 int config = buffer.readInt(); | 1672 int config = buffer.readInt(); |
1610 | 1673 |
1611 this->setConfig((Config)config, width, height, rowBytes); | 1674 bool isOpaque = buffer.readBool(); |
1612 this->setIsOpaque(buffer.readBool()); | 1675 this->setConfig((Config)config, width, height, rowBytes, |
| 1676 isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); |
1613 | 1677 |
1614 int reftype = buffer.readInt(); | 1678 int reftype = buffer.readInt(); |
1615 switch (reftype) { | 1679 switch (reftype) { |
1616 case SERIALIZE_PIXELTYPE_REF_DATA: { | 1680 case SERIALIZE_PIXELTYPE_REF_DATA: { |
1617 size_t offset = buffer.readUInt(); | 1681 size_t offset = buffer.readUInt(); |
1618 SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>(); | 1682 SkPixelRef* pr = buffer.readFlattenableT<SkPixelRef>(); |
1619 SkSafeUnref(this->setPixelRef(pr, offset)); | 1683 SkSafeUnref(this->setPixelRef(pr, offset)); |
1620 break; | 1684 break; |
1621 } | 1685 } |
1622 case SERIALIZE_PIXELTYPE_NONE: | 1686 case SERIALIZE_PIXELTYPE_NONE: |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1699 if (NULL != uri) { | 1763 if (NULL != uri) { |
1700 str->appendf(" uri:\"%s\"", uri); | 1764 str->appendf(" uri:\"%s\"", uri); |
1701 } else { | 1765 } else { |
1702 str->appendf(" pixelref:%p", pr); | 1766 str->appendf(" pixelref:%p", pr); |
1703 } | 1767 } |
1704 } | 1768 } |
1705 | 1769 |
1706 str->append(")"); | 1770 str->append(")"); |
1707 } | 1771 } |
1708 #endif | 1772 #endif |
OLD | NEW |