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 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
136 SkTSwap(fColorTable, other.fColorTable); | 136 SkTSwap(fColorTable, other.fColorTable); |
137 SkTSwap(fPixelRef, other.fPixelRef); | 137 SkTSwap(fPixelRef, other.fPixelRef); |
138 SkTSwap(fPixelRefOffset, other.fPixelRefOffset); | 138 SkTSwap(fPixelRefOffset, other.fPixelRefOffset); |
139 SkTSwap(fPixelLockCount, other.fPixelLockCount); | 139 SkTSwap(fPixelLockCount, other.fPixelLockCount); |
140 SkTSwap(fMipMap, other.fMipMap); | 140 SkTSwap(fMipMap, other.fMipMap); |
141 SkTSwap(fPixels, other.fPixels); | 141 SkTSwap(fPixels, other.fPixels); |
142 SkTSwap(fRowBytes, other.fRowBytes); | 142 SkTSwap(fRowBytes, other.fRowBytes); |
143 SkTSwap(fWidth, other.fWidth); | 143 SkTSwap(fWidth, other.fWidth); |
144 SkTSwap(fHeight, other.fHeight); | 144 SkTSwap(fHeight, other.fHeight); |
145 SkTSwap(fConfig, other.fConfig); | 145 SkTSwap(fConfig, other.fConfig); |
146 SkTSwap(fAlphaType, other.fAlphaType); | |
146 SkTSwap(fFlags, other.fFlags); | 147 SkTSwap(fFlags, other.fFlags); |
147 SkTSwap(fBytesPerPixel, other.fBytesPerPixel); | 148 SkTSwap(fBytesPerPixel, other.fBytesPerPixel); |
148 | 149 |
149 SkDEBUGCODE(this->validate();) | 150 SkDEBUGCODE(this->validate();) |
150 } | 151 } |
151 | 152 |
152 void SkBitmap::reset() { | 153 void SkBitmap::reset() { |
153 this->freePixels(); | 154 this->freePixels(); |
154 sk_bzero(this, sizeof(*this)); | 155 sk_bzero(this, sizeof(*this)); |
155 } | 156 } |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
259 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); | 260 SkIntToScalar(fWidth), SkIntToScalar(fHeight)); |
260 } | 261 } |
261 | 262 |
262 void SkBitmap::getBounds(SkIRect* bounds) const { | 263 void SkBitmap::getBounds(SkIRect* bounds) const { |
263 SkASSERT(bounds); | 264 SkASSERT(bounds); |
264 bounds->set(0, 0, fWidth, fHeight); | 265 bounds->set(0, 0, fWidth, fHeight); |
265 } | 266 } |
266 | 267 |
267 /////////////////////////////////////////////////////////////////////////////// | 268 /////////////////////////////////////////////////////////////////////////////// |
268 | 269 |
269 void SkBitmap::setConfig(Config c, int width, int height, size_t rowBytes) { | 270 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes, |
270 this->freePixels(); | 271 SkAlphaType alphaType) { |
271 | |
272 if ((width | height) < 0) { | 272 if ((width | height) < 0) { |
273 goto err; | 273 goto ERROR; |
274 } | 274 } |
275 | |
276 if (rowBytes == 0) { | 275 if (rowBytes == 0) { |
277 rowBytes = SkBitmap::ComputeRowBytes(c, width); | 276 rowBytes = SkBitmap::ComputeRowBytes(config, width); |
278 if (0 == rowBytes && kNo_Config != c) { | 277 if (0 == rowBytes && kNo_Config != config) { |
279 goto err; | 278 goto ERROR; |
280 } | 279 } |
281 } | 280 } |
282 | 281 |
283 fConfig = SkToU8(c); | 282 // check for legal/supported config+alphaType combinations |
283 // | |
284 switch (config) { | |
scroggo
2013/10/18 20:04:34
Thiis comment still holds - can this call setAlpha
reed1
2013/10/18 21:37:35
Done.
| |
285 case kNo_Config: | |
286 alphaType = kIgnore_SkAlphaType; // canonicalize | |
287 break; | |
288 case kA1_Config: | |
289 case kA8_Config: | |
290 if (kUnpremul_SkAlphaType == alphaType) { | |
291 alphaType = kPremul_SkAlphaType; | |
292 } | |
293 // fall-through | |
294 case kIndex8_Config: | |
295 case kARGB_4444_Config: | |
296 case kARGB_8888_Config: | |
297 if (kIgnore_SkAlphaType == alphaType) { | |
298 goto ERROR; // not supported yet | |
299 } | |
300 break; | |
301 case kRGB_565_Config: | |
302 alphaType = kOpaque_SkAlphaType; // canonicalize | |
303 break; | |
304 } | |
305 | |
306 this->freePixels(); | |
307 | |
308 fConfig = SkToU8(config); | |
309 fAlphaType = SkToU8(alphaType); | |
284 fWidth = width; | 310 fWidth = width; |
285 fHeight = height; | 311 fHeight = height; |
286 fRowBytes = SkToU32(rowBytes); | 312 fRowBytes = SkToU32(rowBytes); |
287 | 313 |
288 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); | 314 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config); |
289 | 315 |
290 SkDEBUGCODE(this->validate();) | 316 SkDEBUGCODE(this->validate();) |
291 return; | 317 return true; |
292 | 318 |
293 // if we got here, we had an error, so we reset the bitmap to empty | 319 // if we got here, we had an error, so we reset the bitmap to empty |
294 err: | 320 ERROR: |
295 this->reset(); | 321 this->reset(); |
322 return false; | |
323 } | |
324 | |
325 void SkBitmap::setAlphaType(SkAlphaType alphaType) { | |
326 // check for legal/supported config+alphaType combinations | |
327 // | |
328 switch (this->config()) { | |
329 case kNo_Config: | |
330 alphaType = kIgnore_SkAlphaType; // canonicalize | |
331 break; | |
332 case kA1_Config: | |
333 case kA8_Config: | |
334 if (kUnpremul_SkAlphaType == alphaType) { | |
335 alphaType = kPremul_SkAlphaType; | |
336 } | |
337 // fall-through | |
338 case kIndex8_Config: | |
339 case kARGB_4444_Config: | |
340 case kARGB_8888_Config: | |
341 if (kIgnore_SkAlphaType == alphaType) { | |
342 SkDEBUGFAIL("bad alphaType for existing config"); | |
343 return; | |
344 } | |
345 break; | |
346 case kRGB_565_Config: | |
347 alphaType = kOpaque_SkAlphaType; // canonicalize | |
348 break; | |
349 } | |
350 | |
351 fAlphaType = SkToU8(alphaType); | |
296 } | 352 } |
297 | 353 |
298 void SkBitmap::updatePixelsFromRef() const { | 354 void SkBitmap::updatePixelsFromRef() const { |
299 if (NULL != fPixelRef) { | 355 if (NULL != fPixelRef) { |
300 if (fPixelLockCount > 0) { | 356 if (fPixelLockCount > 0) { |
301 SkASSERT(fPixelRef->isLocked()); | 357 SkASSERT(fPixelRef->isLocked()); |
302 | 358 |
303 void* p = fPixelRef->pixels(); | 359 void* p = fPixelRef->pixels(); |
304 if (NULL != p) { | 360 if (NULL != p) { |
305 p = (char*)p + fPixelRefOffset; | 361 p = (char*)p + fPixelRefOffset; |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
517 } | 573 } |
518 | 574 |
519 void SkBitmap::setImmutable() { | 575 void SkBitmap::setImmutable() { |
520 if (fPixelRef) { | 576 if (fPixelRef) { |
521 fPixelRef->setImmutable(); | 577 fPixelRef->setImmutable(); |
522 } else { | 578 } else { |
523 fFlags |= kImageIsImmutable_Flag; | 579 fFlags |= kImageIsImmutable_Flag; |
524 } | 580 } |
525 } | 581 } |
526 | 582 |
527 bool SkBitmap::isOpaque() const { | |
528 switch (fConfig) { | |
529 case kNo_Config: | |
530 return true; | |
531 | |
532 case kA1_Config: | |
533 case kA8_Config: | |
534 case kARGB_4444_Config: | |
535 case kARGB_8888_Config: | |
536 return (fFlags & kImageIsOpaque_Flag) != 0; | |
537 | |
538 case kIndex8_Config: { | |
539 bool isOpaque; | |
540 | |
541 this->lockPixels(); | |
542 isOpaque = fColorTable && fColorTable->isOpaque(); | |
543 this->unlockPixels(); | |
544 return isOpaque; | |
545 } | |
546 | |
547 case kRGB_565_Config: | |
548 return true; | |
549 | |
550 default: | |
551 SkDEBUGFAIL("unknown bitmap config pased to isOpaque"); | |
552 return false; | |
553 } | |
554 } | |
555 | |
556 void SkBitmap::setIsOpaque(bool isOpaque) { | |
557 /* we record this regardless of fConfig, though it is ignored in | |
558 isOpaque() for configs that can't support per-pixel alpha. | |
559 */ | |
560 if (isOpaque) { | |
561 fFlags |= kImageIsOpaque_Flag; | |
562 } else { | |
563 fFlags &= ~kImageIsOpaque_Flag; | |
564 } | |
565 } | |
566 | |
567 bool SkBitmap::isVolatile() const { | 583 bool SkBitmap::isVolatile() const { |
568 return (fFlags & kImageIsVolatile_Flag) != 0; | 584 return (fFlags & kImageIsVolatile_Flag) != 0; |
569 } | 585 } |
570 | 586 |
571 void SkBitmap::setIsVolatile(bool isVolatile) { | 587 void SkBitmap::setIsVolatile(bool isVolatile) { |
572 if (isVolatile) { | 588 if (isVolatile) { |
573 fFlags |= kImageIsVolatile_Flag; | 589 fFlags |= kImageIsVolatile_Flag; |
574 } else { | 590 } else { |
575 fFlags &= ~kImageIsVolatile_Flag; | 591 fFlags &= ~kImageIsVolatile_Flag; |
576 } | 592 } |
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
951 srcRect.set(0, 0, this->width(), this->height()); | 967 srcRect.set(0, 0, this->width(), this->height()); |
952 if (!r.intersect(srcRect, subset)) { | 968 if (!r.intersect(srcRect, subset)) { |
953 return false; // r is empty (i.e. no intersection) | 969 return false; // r is empty (i.e. no intersection) |
954 } | 970 } |
955 | 971 |
956 if (fPixelRef->getTexture() != NULL) { | 972 if (fPixelRef->getTexture() != NULL) { |
957 // Do a deep copy | 973 // Do a deep copy |
958 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); | 974 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); |
959 if (pixelRef != NULL) { | 975 if (pixelRef != NULL) { |
960 SkBitmap dst; | 976 SkBitmap dst; |
961 dst.setConfig(this->config(), subset.width(), subset.height()); | 977 dst.setConfig(this->config(), subset.width(), subset.height(), 0, |
978 this->alphaType()); | |
962 dst.setIsVolatile(this->isVolatile()); | 979 dst.setIsVolatile(this->isVolatile()); |
963 dst.setIsOpaque(this->isOpaque()); | |
964 dst.setPixelRef(pixelRef)->unref(); | 980 dst.setPixelRef(pixelRef)->unref(); |
965 SkDEBUGCODE(dst.validate()); | 981 SkDEBUGCODE(dst.validate()); |
966 result->swap(dst); | 982 result->swap(dst); |
967 return true; | 983 return true; |
968 } | 984 } |
969 } | 985 } |
970 | 986 |
971 // If the upper left of the rectangle was outside the bounds of this SkBitma p, we should have | 987 // If the upper left of the rectangle was outside the bounds of this SkBitma p, we should have |
972 // exited above. | 988 // exited above. |
973 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width( ))); | 989 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width( ))); |
974 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height( ))); | 990 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height( ))); |
975 | 991 |
976 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); | 992 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); |
977 if (SUB_OFFSET_FAILURE == offset) { | 993 if (SUB_OFFSET_FAILURE == offset) { |
978 return false; // config not supported | 994 return false; // config not supported |
979 } | 995 } |
980 | 996 |
981 SkBitmap dst; | 997 SkBitmap dst; |
982 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes()); | 998 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(), |
999 this->alphaType()); | |
983 dst.setIsVolatile(this->isVolatile()); | 1000 dst.setIsVolatile(this->isVolatile()); |
984 dst.setIsOpaque(this->isOpaque()); | |
985 | 1001 |
986 if (fPixelRef) { | 1002 if (fPixelRef) { |
987 // share the pixelref with a custom offset | 1003 // share the pixelref with a custom offset |
988 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); | 1004 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); |
989 } | 1005 } |
990 SkDEBUGCODE(dst.validate();) | 1006 SkDEBUGCODE(dst.validate();) |
991 | 1007 |
992 // we know we're good, so commit to result | 1008 // we know we're good, so commit to result |
993 result->swap(dst); | 1009 result->swap(dst); |
994 return true; | 1010 return true; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1063 } | 1079 } |
1064 } | 1080 } |
1065 | 1081 |
1066 // we lock this now, since we may need its colortable | 1082 // we lock this now, since we may need its colortable |
1067 SkAutoLockPixels srclock(*src); | 1083 SkAutoLockPixels srclock(*src); |
1068 if (!src->readyToDraw()) { | 1084 if (!src->readyToDraw()) { |
1069 return false; | 1085 return false; |
1070 } | 1086 } |
1071 | 1087 |
1072 SkBitmap tmpDst; | 1088 SkBitmap tmpDst; |
1073 tmpDst.setConfig(dstConfig, src->width(), src->height()); | 1089 tmpDst.setConfig(dstConfig, src->width(), src->height(), 0, |
1090 src->alphaType()); | |
1074 | 1091 |
1075 // allocate colortable if srcConfig == kIndex8_Config | 1092 // allocate colortable if srcConfig == kIndex8_Config |
1076 SkColorTable* ctable = (dstConfig == kIndex8_Config) ? | 1093 SkColorTable* ctable = (dstConfig == kIndex8_Config) ? |
1077 new SkColorTable(*src->getColorTable()) : NULL; | 1094 new SkColorTable(*src->getColorTable()) : NULL; |
1078 SkAutoUnref au(ctable); | 1095 SkAutoUnref au(ctable); |
1079 if (!tmpDst.allocPixels(alloc, ctable)) { | 1096 if (!tmpDst.allocPixels(alloc, ctable)) { |
1080 return false; | 1097 return false; |
1081 } | 1098 } |
1082 | 1099 |
1083 if (!tmpDst.readyToDraw()) { | 1100 if (!tmpDst.readyToDraw()) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1123 // TODO: switch the allocation of tmpDst to call sk_calloc_throw | 1140 // TODO: switch the allocation of tmpDst to call sk_calloc_throw |
1124 tmpDst.eraseColor(SK_ColorTRANSPARENT); | 1141 tmpDst.eraseColor(SK_ColorTRANSPARENT); |
1125 | 1142 |
1126 SkCanvas canvas(tmpDst); | 1143 SkCanvas canvas(tmpDst); |
1127 SkPaint paint; | 1144 SkPaint paint; |
1128 | 1145 |
1129 paint.setDither(true); | 1146 paint.setDither(true); |
1130 canvas.drawBitmap(*src, 0, 0, &paint); | 1147 canvas.drawBitmap(*src, 0, 0, &paint); |
1131 } | 1148 } |
1132 | 1149 |
1133 tmpDst.setIsOpaque(src->isOpaque()); | |
1134 | |
1135 dst->swap(tmpDst); | 1150 dst->swap(tmpDst); |
1136 return true; | 1151 return true; |
1137 } | 1152 } |
1138 | 1153 |
1139 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { | 1154 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { |
1140 if (!this->canCopyTo(dstConfig)) { | 1155 if (!this->canCopyTo(dstConfig)) { |
1141 return false; | 1156 return false; |
1142 } | 1157 } |
1143 | 1158 |
1144 // If we have a PixelRef, and it supports deep copy, use it. | 1159 // If we have a PixelRef, and it supports deep copy, use it. |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1572 enum { | 1587 enum { |
1573 SERIALIZE_PIXELTYPE_NONE, | 1588 SERIALIZE_PIXELTYPE_NONE, |
1574 SERIALIZE_PIXELTYPE_REF_DATA | 1589 SERIALIZE_PIXELTYPE_REF_DATA |
1575 }; | 1590 }; |
1576 | 1591 |
1577 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { | 1592 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { |
1578 buffer.writeInt(fWidth); | 1593 buffer.writeInt(fWidth); |
1579 buffer.writeInt(fHeight); | 1594 buffer.writeInt(fHeight); |
1580 buffer.writeInt(fRowBytes); | 1595 buffer.writeInt(fRowBytes); |
1581 buffer.writeInt(fConfig); | 1596 buffer.writeInt(fConfig); |
1582 buffer.writeBool(this->isOpaque()); | 1597 buffer.writeInt(fAlphaType); |
1583 | 1598 |
1584 if (fPixelRef) { | 1599 if (fPixelRef) { |
1585 if (fPixelRef->getFactory()) { | 1600 if (fPixelRef->getFactory()) { |
1586 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); | 1601 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); |
1587 buffer.writeUInt(SkToU32(fPixelRefOffset)); | 1602 buffer.writeUInt(SkToU32(fPixelRefOffset)); |
1588 buffer.writeFlattenable(fPixelRef); | 1603 buffer.writeFlattenable(fPixelRef); |
1589 return; | 1604 return; |
1590 } | 1605 } |
1591 // if we get here, we can't record the pixels | 1606 // if we get here, we can't record the pixels |
1592 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); | 1607 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); |
1593 } else { | 1608 } else { |
1594 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); | 1609 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); |
1595 } | 1610 } |
1596 } | 1611 } |
1597 | 1612 |
1598 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { | 1613 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { |
1599 this->reset(); | 1614 this->reset(); |
1600 | 1615 |
1601 int width = buffer.readInt(); | 1616 int width = buffer.readInt(); |
1602 int height = buffer.readInt(); | 1617 int height = buffer.readInt(); |
1603 int rowBytes = buffer.readInt(); | 1618 int rowBytes = buffer.readInt(); |
1604 int config = buffer.readInt(); | 1619 int config = buffer.readInt(); |
1620 int alphaType = buffer.readInt(); | |
1605 | 1621 |
1606 this->setConfig((Config)config, width, height, rowBytes); | 1622 this->setConfig((Config)config, width, height, rowBytes, (SkAlphaType)alphaT ype); |
1607 this->setIsOpaque(buffer.readBool()); | |
1608 | 1623 |
1609 int reftype = buffer.readInt(); | 1624 int reftype = buffer.readInt(); |
1610 switch (reftype) { | 1625 switch (reftype) { |
1611 case SERIALIZE_PIXELTYPE_REF_DATA: { | 1626 case SERIALIZE_PIXELTYPE_REF_DATA: { |
1612 size_t offset = buffer.readUInt(); | 1627 size_t offset = buffer.readUInt(); |
1613 SkPixelRef* pr = buffer.readPixelRef(); | 1628 SkPixelRef* pr = buffer.readPixelRef(); |
1614 SkSafeUnref(this->setPixelRef(pr, offset)); | 1629 SkSafeUnref(this->setPixelRef(pr, offset)); |
1615 break; | 1630 break; |
1616 } | 1631 } |
1617 case SERIALIZE_PIXELTYPE_NONE: | 1632 case SERIALIZE_PIXELTYPE_NONE: |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1693 if (NULL != uri) { | 1708 if (NULL != uri) { |
1694 str->appendf(" uri:\"%s\"", uri); | 1709 str->appendf(" uri:\"%s\"", uri); |
1695 } else { | 1710 } else { |
1696 str->appendf(" pixelref:%p", pr); | 1711 str->appendf(" pixelref:%p", pr); |
1697 } | 1712 } |
1698 } | 1713 } |
1699 | 1714 |
1700 str->append(")"); | 1715 str->append(")"); |
1701 } | 1716 } |
1702 #endif | 1717 #endif |
OLD | NEW |