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

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 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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698