Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: src/core/SkBitmap.cpp

Issue 25275004: store SkAlphaType inside SkBitmap, on road to support unpremul (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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 static bool validate_alphaType(SkBitmap::Config config, SkAlphaType alphaType,
270 this->freePixels(); 271 SkAlphaType* canonical) {
272 switch (config) {
273 case SkBitmap::kNo_Config:
274 alphaType = kIgnore_SkAlphaType;
275 break;
276 case SkBitmap::kA1_Config:
277 case SkBitmap::kA8_Config:
278 if (kUnpremul_SkAlphaType == alphaType) {
279 alphaType = kPremul_SkAlphaType;
scroggo 2014/06/10 20:11:59 Looking back at this as I write tests for Android.
280 }
281 // fall-through
282 case SkBitmap::kIndex8_Config:
283 case SkBitmap::kARGB_4444_Config:
284 case SkBitmap::kARGB_8888_Config:
285 if (kIgnore_SkAlphaType == alphaType) {
286 return false;
287 }
288 break;
289 case SkBitmap::kRGB_565_Config:
290 alphaType = kOpaque_SkAlphaType;
291 break;
292 }
293 if (canonical) {
294 *canonical = alphaType;
295 }
296 return true;
297 }
271 298
299 bool SkBitmap::setConfig(Config config, int width, int height, size_t rowBytes,
300 SkAlphaType alphaType) {
272 if ((width | height) < 0) { 301 if ((width | height) < 0) {
273 goto err; 302 goto ERROR;
274 } 303 }
275
276 if (rowBytes == 0) { 304 if (rowBytes == 0) {
277 rowBytes = SkBitmap::ComputeRowBytes(c, width); 305 rowBytes = SkBitmap::ComputeRowBytes(config, width);
278 if (0 == rowBytes && kNo_Config != c) { 306 if (0 == rowBytes && kNo_Config != config) {
279 goto err; 307 goto ERROR;
280 } 308 }
281 } 309 }
282 310
283 fConfig = SkToU8(c); 311 if (!validate_alphaType(config, alphaType, &alphaType)) {
312 goto ERROR;
313 }
314
315 this->freePixels();
316
317 fConfig = SkToU8(config);
318 fAlphaType = SkToU8(alphaType);
284 fWidth = width; 319 fWidth = width;
285 fHeight = height; 320 fHeight = height;
286 fRowBytes = SkToU32(rowBytes); 321 fRowBytes = SkToU32(rowBytes);
287 322
288 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(c); 323 fBytesPerPixel = (uint8_t)ComputeBytesPerPixel(config);
289 324
290 SkDEBUGCODE(this->validate();) 325 SkDEBUGCODE(this->validate();)
291 return; 326 return true;
292 327
293 // if we got here, we had an error, so we reset the bitmap to empty 328 // if we got here, we had an error, so we reset the bitmap to empty
294 err: 329 ERROR:
295 this->reset(); 330 this->reset();
331 return false;
332 }
333
334 bool SkBitmap::setAlphaType(SkAlphaType alphaType) {
335 if (!validate_alphaType(this->config(), alphaType, &alphaType)) {
336 return false;
337 }
338 fAlphaType = SkToU8(alphaType);
339 return true;
296 } 340 }
297 341
298 void SkBitmap::updatePixelsFromRef() const { 342 void SkBitmap::updatePixelsFromRef() const {
299 if (NULL != fPixelRef) { 343 if (NULL != fPixelRef) {
300 if (fPixelLockCount > 0) { 344 if (fPixelLockCount > 0) {
301 SkASSERT(fPixelRef->isLocked()); 345 SkASSERT(fPixelRef->isLocked());
302 346
303 void* p = fPixelRef->pixels(); 347 void* p = fPixelRef->pixels();
304 if (NULL != p) { 348 if (NULL != p) {
305 p = (char*)p + fPixelRefOffset; 349 p = (char*)p + fPixelRefOffset;
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 } 561 }
518 562
519 void SkBitmap::setImmutable() { 563 void SkBitmap::setImmutable() {
520 if (fPixelRef) { 564 if (fPixelRef) {
521 fPixelRef->setImmutable(); 565 fPixelRef->setImmutable();
522 } else { 566 } else {
523 fFlags |= kImageIsImmutable_Flag; 567 fFlags |= kImageIsImmutable_Flag;
524 } 568 }
525 } 569 }
526 570
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 { 571 bool SkBitmap::isVolatile() const {
568 return (fFlags & kImageIsVolatile_Flag) != 0; 572 return (fFlags & kImageIsVolatile_Flag) != 0;
569 } 573 }
570 574
571 void SkBitmap::setIsVolatile(bool isVolatile) { 575 void SkBitmap::setIsVolatile(bool isVolatile) {
572 if (isVolatile) { 576 if (isVolatile) {
573 fFlags |= kImageIsVolatile_Flag; 577 fFlags |= kImageIsVolatile_Flag;
574 } else { 578 } else {
575 fFlags &= ~kImageIsVolatile_Flag; 579 fFlags &= ~kImageIsVolatile_Flag;
576 } 580 }
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 srcRect.set(0, 0, this->width(), this->height()); 955 srcRect.set(0, 0, this->width(), this->height());
952 if (!r.intersect(srcRect, subset)) { 956 if (!r.intersect(srcRect, subset)) {
953 return false; // r is empty (i.e. no intersection) 957 return false; // r is empty (i.e. no intersection)
954 } 958 }
955 959
956 if (fPixelRef->getTexture() != NULL) { 960 if (fPixelRef->getTexture() != NULL) {
957 // Do a deep copy 961 // Do a deep copy
958 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset); 962 SkPixelRef* pixelRef = fPixelRef->deepCopy(this->config(), &subset);
959 if (pixelRef != NULL) { 963 if (pixelRef != NULL) {
960 SkBitmap dst; 964 SkBitmap dst;
961 dst.setConfig(this->config(), subset.width(), subset.height()); 965 dst.setConfig(this->config(), subset.width(), subset.height(), 0,
966 this->alphaType());
962 dst.setIsVolatile(this->isVolatile()); 967 dst.setIsVolatile(this->isVolatile());
963 dst.setIsOpaque(this->isOpaque());
964 dst.setPixelRef(pixelRef)->unref(); 968 dst.setPixelRef(pixelRef)->unref();
965 SkDEBUGCODE(dst.validate()); 969 SkDEBUGCODE(dst.validate());
966 result->swap(dst); 970 result->swap(dst);
967 return true; 971 return true;
968 } 972 }
969 } 973 }
970 974
971 // If the upper left of the rectangle was outside the bounds of this SkBitma p, we should have 975 // If the upper left of the rectangle was outside the bounds of this SkBitma p, we should have
972 // exited above. 976 // exited above.
973 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width( ))); 977 SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width( )));
974 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height( ))); 978 SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height( )));
975 979
976 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop); 980 size_t offset = get_sub_offset(*this, r.fLeft, r.fTop);
977 if (SUB_OFFSET_FAILURE == offset) { 981 if (SUB_OFFSET_FAILURE == offset) {
978 return false; // config not supported 982 return false; // config not supported
979 } 983 }
980 984
981 SkBitmap dst; 985 SkBitmap dst;
982 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes()); 986 dst.setConfig(this->config(), r.width(), r.height(), this->rowBytes(),
987 this->alphaType());
983 dst.setIsVolatile(this->isVolatile()); 988 dst.setIsVolatile(this->isVolatile());
984 dst.setIsOpaque(this->isOpaque());
985 989
986 if (fPixelRef) { 990 if (fPixelRef) {
987 // share the pixelref with a custom offset 991 // share the pixelref with a custom offset
988 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset); 992 dst.setPixelRef(fPixelRef, fPixelRefOffset + offset);
989 } 993 }
990 SkDEBUGCODE(dst.validate();) 994 SkDEBUGCODE(dst.validate();)
991 995
992 // we know we're good, so commit to result 996 // we know we're good, so commit to result
993 result->swap(dst); 997 result->swap(dst);
994 return true; 998 return true;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1063 } 1067 }
1064 } 1068 }
1065 1069
1066 // we lock this now, since we may need its colortable 1070 // we lock this now, since we may need its colortable
1067 SkAutoLockPixels srclock(*src); 1071 SkAutoLockPixels srclock(*src);
1068 if (!src->readyToDraw()) { 1072 if (!src->readyToDraw()) {
1069 return false; 1073 return false;
1070 } 1074 }
1071 1075
1072 SkBitmap tmpDst; 1076 SkBitmap tmpDst;
1073 tmpDst.setConfig(dstConfig, src->width(), src->height()); 1077 tmpDst.setConfig(dstConfig, src->width(), src->height(), 0,
1078 src->alphaType());
1074 1079
1075 // allocate colortable if srcConfig == kIndex8_Config 1080 // allocate colortable if srcConfig == kIndex8_Config
1076 SkColorTable* ctable = (dstConfig == kIndex8_Config) ? 1081 SkColorTable* ctable = (dstConfig == kIndex8_Config) ?
1077 new SkColorTable(*src->getColorTable()) : NULL; 1082 new SkColorTable(*src->getColorTable()) : NULL;
1078 SkAutoUnref au(ctable); 1083 SkAutoUnref au(ctable);
1079 if (!tmpDst.allocPixels(alloc, ctable)) { 1084 if (!tmpDst.allocPixels(alloc, ctable)) {
1080 return false; 1085 return false;
1081 } 1086 }
1082 1087
1083 if (!tmpDst.readyToDraw()) { 1088 if (!tmpDst.readyToDraw()) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 // TODO: switch the allocation of tmpDst to call sk_calloc_throw 1128 // TODO: switch the allocation of tmpDst to call sk_calloc_throw
1124 tmpDst.eraseColor(SK_ColorTRANSPARENT); 1129 tmpDst.eraseColor(SK_ColorTRANSPARENT);
1125 1130
1126 SkCanvas canvas(tmpDst); 1131 SkCanvas canvas(tmpDst);
1127 SkPaint paint; 1132 SkPaint paint;
1128 1133
1129 paint.setDither(true); 1134 paint.setDither(true);
1130 canvas.drawBitmap(*src, 0, 0, &paint); 1135 canvas.drawBitmap(*src, 0, 0, &paint);
1131 } 1136 }
1132 1137
1133 tmpDst.setIsOpaque(src->isOpaque());
1134
1135 dst->swap(tmpDst); 1138 dst->swap(tmpDst);
1136 return true; 1139 return true;
1137 } 1140 }
1138 1141
1139 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const { 1142 bool SkBitmap::deepCopyTo(SkBitmap* dst, Config dstConfig) const {
1140 if (!this->canCopyTo(dstConfig)) { 1143 if (!this->canCopyTo(dstConfig)) {
1141 return false; 1144 return false;
1142 } 1145 }
1143 1146
1144 // If we have a PixelRef, and it supports deep copy, use it. 1147 // If we have a PixelRef, and it supports deep copy, use it.
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
1572 enum { 1575 enum {
1573 SERIALIZE_PIXELTYPE_NONE, 1576 SERIALIZE_PIXELTYPE_NONE,
1574 SERIALIZE_PIXELTYPE_REF_DATA 1577 SERIALIZE_PIXELTYPE_REF_DATA
1575 }; 1578 };
1576 1579
1577 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const { 1580 void SkBitmap::flatten(SkFlattenableWriteBuffer& buffer) const {
1578 buffer.writeInt(fWidth); 1581 buffer.writeInt(fWidth);
1579 buffer.writeInt(fHeight); 1582 buffer.writeInt(fHeight);
1580 buffer.writeInt(fRowBytes); 1583 buffer.writeInt(fRowBytes);
1581 buffer.writeInt(fConfig); 1584 buffer.writeInt(fConfig);
1582 buffer.writeBool(this->isOpaque()); 1585 buffer.writeInt(fAlphaType);
1583 1586
1584 if (fPixelRef) { 1587 if (fPixelRef) {
1585 if (fPixelRef->getFactory()) { 1588 if (fPixelRef->getFactory()) {
1586 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA); 1589 buffer.writeInt(SERIALIZE_PIXELTYPE_REF_DATA);
1587 buffer.writeUInt(SkToU32(fPixelRefOffset)); 1590 buffer.writeUInt(SkToU32(fPixelRefOffset));
1588 buffer.writeFlattenable(fPixelRef); 1591 buffer.writeFlattenable(fPixelRef);
1589 return; 1592 return;
1590 } 1593 }
1591 // if we get here, we can't record the pixels 1594 // if we get here, we can't record the pixels
1592 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1595 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1593 } else { 1596 } else {
1594 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE); 1597 buffer.writeInt(SERIALIZE_PIXELTYPE_NONE);
1595 } 1598 }
1596 } 1599 }
1597 1600
1598 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) { 1601 void SkBitmap::unflatten(SkFlattenableReadBuffer& buffer) {
1599 this->reset(); 1602 this->reset();
1600 1603
1601 int width = buffer.readInt(); 1604 int width = buffer.readInt();
1602 int height = buffer.readInt(); 1605 int height = buffer.readInt();
1603 int rowBytes = buffer.readInt(); 1606 int rowBytes = buffer.readInt();
1604 int config = buffer.readInt(); 1607 int config = buffer.readInt();
1608 int alphaType = buffer.readInt();
1605 1609
1606 this->setConfig((Config)config, width, height, rowBytes); 1610 this->setConfig((Config)config, width, height, rowBytes, (SkAlphaType)alphaT ype);
1607 this->setIsOpaque(buffer.readBool());
1608 1611
1609 int reftype = buffer.readInt(); 1612 int reftype = buffer.readInt();
1610 switch (reftype) { 1613 switch (reftype) {
1611 case SERIALIZE_PIXELTYPE_REF_DATA: { 1614 case SERIALIZE_PIXELTYPE_REF_DATA: {
1612 size_t offset = buffer.readUInt(); 1615 size_t offset = buffer.readUInt();
1613 SkPixelRef* pr = buffer.readPixelRef(); 1616 SkPixelRef* pr = buffer.readPixelRef();
1614 SkSafeUnref(this->setPixelRef(pr, offset)); 1617 SkSafeUnref(this->setPixelRef(pr, offset));
1615 break; 1618 break;
1616 } 1619 }
1617 case SERIALIZE_PIXELTYPE_NONE: 1620 case SERIALIZE_PIXELTYPE_NONE:
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1693 if (NULL != uri) { 1696 if (NULL != uri) {
1694 str->appendf(" uri:\"%s\"", uri); 1697 str->appendf(" uri:\"%s\"", uri);
1695 } else { 1698 } else {
1696 str->appendf(" pixelref:%p", pr); 1699 str->appendf(" pixelref:%p", pr);
1697 } 1700 }
1698 } 1701 }
1699 1702
1700 str->append(")"); 1703 str->append(")");
1701 } 1704 }
1702 #endif 1705 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698