00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef SkBitmap_DEFINED
00018 #define SkBitmap_DEFINED
00019
00020 #include "Sk64.h"
00021 #include "SkColor.h"
00022 #include "SkPoint.h"
00023 #include "SkRefCnt.h"
00024
00025 struct SkIRect;
00026 class SkColorTable;
00027 class SkPaint;
00028 class SkPixelRef;
00029 class SkRegion;
00030 class SkFlattenableReadBuffer;
00031 class SkFlattenableWriteBuffer;
00032
00040 class SkBitmap {
00041 public:
00042 class Allocator;
00043
00044 enum Config {
00045 kNo_Config,
00046 kA1_Config,
00047 kA8_Config,
00048 kIndex8_Config,
00049 kRGB_565_Config,
00050 kARGB_4444_Config,
00051 kARGB_8888_Config,
00052 kRLE_Index8_Config,
00053
00054 kConfigCount
00055 };
00056
00060 SkBitmap();
00064 SkBitmap(const SkBitmap& src);
00067 ~SkBitmap();
00068
00072 SkBitmap& operator=(const SkBitmap& src);
00075
00076 void swap(SkBitmap& other);
00077
00080 bool empty() const { return 0 == fWidth || 0 == fHeight; }
00081
00085 bool isNull() const { return NULL == fPixels && NULL == fPixelRef; }
00086
00089 Config config() const { return (Config)fConfig; }
00092 Config getConfig() const { return this->config(); }
00095 int width() const { return fWidth; }
00098 int height() const { return fHeight; }
00101 int rowBytes() const { return fRowBytes; }
00102
00108 int shiftPerPixel() const { return fBytesPerPixel >> 1; }
00109
00113 int bytesPerPixel() const { return fBytesPerPixel; }
00114
00120 int rowBytesAsPixels() const { return fRowBytes >> (fBytesPerPixel >> 1); }
00121
00124 void* getPixels() const { return fPixels; }
00125
00130 size_t getSize() const { return fHeight * fRowBytes; }
00131
00136 Sk64 getSize64() const {
00137 Sk64 size;
00138 size.setMul(fHeight, fRowBytes);
00139 return size;
00140 }
00141
00144 bool isOpaque() const;
00148 void setIsOpaque(bool);
00149
00153 void reset();
00154
00158 static int ComputeRowBytes(Config c, int width);
00159
00163 static int ComputeBytesPerPixel(Config c);
00164
00168 static int ComputeShiftPerPixel(Config c) {
00169 return ComputeBytesPerPixel(c) >> 1;
00170 }
00171
00172 static Sk64 ComputeSize64(Config, int width, int height);
00173 static size_t ComputeSize(Config, int width, int height);
00174
00179 void setConfig(Config, int width, int height, int rowBytes = 0);
00190 void setPixels(void* p, SkColorTable* ctable = NULL);
00191
00205 bool allocPixels(SkColorTable* ctable = NULL) {
00206 return this->allocPixels(NULL, ctable);
00207 }
00208
00228 bool allocPixels(Allocator* allocator, SkColorTable* ctable);
00229
00232 SkPixelRef* pixelRef() const { return fPixelRef; }
00236 size_t pixelRefOffset() const { return fPixelRefOffset; }
00241 SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset = 0);
00242
00247 void lockPixels() const;
00253 void unlockPixels() const;
00254
00259 bool readyToDraw() const {
00260 return this->getPixels() != NULL &&
00261 ((this->config() != kIndex8_Config && this->config() != kRLE_Index8_Config) ||
00262 fColorTable != NULL);
00263 }
00264
00268 SkColorTable* getColorTable() const { return fColorTable; }
00269
00275 uint32_t getGenerationID() const;
00276
00281 void notifyPixelsChanged() const;
00282
00287 void eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) const;
00293 void eraseRGB(U8CPU r, U8CPU g, U8CPU b) const {
00294 this->eraseARGB(0xFF, r, g, b);
00295 }
00300 void eraseColor(SkColor c) const {
00301 this->eraseARGB(SkColorGetA(c), SkColorGetR(c), SkColorGetG(c),
00302 SkColorGetB(c));
00303 }
00304
00324 bool scrollRect(const SkIRect* subset, int dx, int dy,
00325 SkRegion* inval = NULL) const;
00326
00336 void* getAddr(int x, int y) const;
00337
00340 inline uint32_t* getAddr32(int x, int y) const;
00343 inline uint16_t* getAddr16(int x, int y) const;
00346 inline uint8_t* getAddr8(int x, int y) const;
00350 inline uint8_t* getAddr1(int x, int y) const;
00351
00355 inline SkPMColor getIndex8Color(int x, int y) const;
00356
00368 bool extractSubset(SkBitmap* dst, const SkIRect& subset) const;
00369
00381 bool copyTo(SkBitmap* dst, Config c, Allocator* allocator = NULL) const;
00382
00386 bool canCopyTo(Config newConfig) const;
00387
00388 bool hasMipMap() const;
00389 void buildMipMap(bool forceRebuild = false);
00390 void freeMipMap();
00391
00396 int extractMipLevel(SkBitmap* dst, SkFixed sx, SkFixed sy);
00397
00398 void extractAlpha(SkBitmap* dst) const {
00399 this->extractAlpha(dst, NULL, NULL);
00400 }
00401
00402 void extractAlpha(SkBitmap* dst, const SkPaint* paint,
00403 SkIPoint* offset) const;
00404
00405 void flatten(SkFlattenableWriteBuffer&) const;
00406 void unflatten(SkFlattenableReadBuffer&);
00407
00408 SkDEBUGCODE(void validate() const;)
00409
00410 class Allocator : public SkRefCnt {
00411 public:
00419 virtual bool allocPixelRef(SkBitmap*, SkColorTable*) = 0;
00420 };
00421
00426 class HeapAllocator : public Allocator {
00427 public:
00428 virtual bool allocPixelRef(SkBitmap*, SkColorTable*);
00429 };
00430
00431 class RLEPixels {
00432 public:
00433 RLEPixels(int width, int height);
00434 virtual ~RLEPixels();
00435
00436 uint8_t* packedAtY(int y) const {
00437 SkASSERT((unsigned)y < (unsigned)fHeight);
00438 return fYPtrs[y];
00439 }
00440
00441
00442 void setPackedAtY(int y, uint8_t* addr) {
00443 SkASSERT((unsigned)y < (unsigned)fHeight);
00444 fYPtrs[y] = addr;
00445 }
00446
00447 private:
00448 uint8_t** fYPtrs;
00449 int fHeight;
00450 };
00451
00452 private:
00453 struct MipMap;
00454 mutable MipMap* fMipMap;
00455
00456 mutable SkPixelRef* fPixelRef;
00457 mutable size_t fPixelRefOffset;
00458 mutable int fPixelLockCount;
00459
00460
00461 mutable void* fPixels;
00462 mutable SkColorTable* fColorTable;
00463
00464 enum Flags {
00465 kImageIsOpaque_Flag = 0x01
00466 };
00467
00468 uint32_t fRowBytes;
00469 uint32_t fWidth;
00470 uint32_t fHeight;
00471 uint8_t fConfig;
00472 uint8_t fFlags;
00473 uint8_t fBytesPerPixel;
00474
00475
00476
00477 void freePixels();
00478 void updatePixelsFromRef() const;
00479
00480 static SkFixed ComputeMipLevel(SkFixed sx, SkFixed dy);
00481 };
00482
00488 class SkColorTable : public SkRefCnt {
00489 public:
00492 SkColorTable(const SkColorTable& src);
00496 explicit SkColorTable(int count);
00497 explicit SkColorTable(SkFlattenableReadBuffer&);
00498 SkColorTable(const SkPMColor colors[], int count);
00499 virtual ~SkColorTable();
00500
00501 enum Flags {
00502 kColorsAreOpaque_Flag = 0x01
00503 };
00506 unsigned getFlags() const { return fFlags; }
00509 void setFlags(unsigned flags);
00510
00511 bool isOpaque() const { return (fFlags & kColorsAreOpaque_Flag) != 0; }
00512 void setIsOpaque(bool isOpaque);
00513
00516 int count() const { return fCount; }
00517
00521 SkPMColor operator[](int index) const {
00522 SkASSERT(fColors != NULL && (unsigned)index < fCount);
00523 return fColors[index];
00524 }
00525
00531
00532
00533
00538 SkPMColor* lockColors() {
00539 SkDEBUGCODE(fColorLockCount += 1;)
00540 return fColors;
00541 }
00544 void unlockColors(bool changed);
00545
00551 const uint16_t* lock16BitCache();
00554 void unlock16BitCache() {
00555 SkASSERT(f16BitCacheLockCount > 0);
00556 SkDEBUGCODE(f16BitCacheLockCount -= 1);
00557 }
00558
00559 void flatten(SkFlattenableWriteBuffer&) const;
00560
00561 private:
00562 SkPMColor* fColors;
00563 uint16_t* f16BitCache;
00564 uint16_t fCount;
00565 uint8_t fFlags;
00566 SkDEBUGCODE(int fColorLockCount;)
00567 SkDEBUGCODE(int f16BitCacheLockCount;)
00568
00569 void inval16BitCache();
00570 };
00571
00572 class SkAutoLockPixels {
00573 public:
00574 SkAutoLockPixels(const SkBitmap& bitmap) : fBitmap(bitmap) {
00575 bitmap.lockPixels();
00576 }
00577 ~SkAutoLockPixels() {
00578 fBitmap.unlockPixels();
00579 }
00580
00581 private:
00582 const SkBitmap& fBitmap;
00583 };
00584
00588 class SkAutoLockColors : public SkNoncopyable {
00589 public:
00593 SkAutoLockColors() : fCTable(NULL), fColors(NULL) {}
00596 explicit SkAutoLockColors(const SkBitmap& bm) {
00597 fCTable = bm.getColorTable();
00598 fColors = fCTable ? fCTable->lockColors() : NULL;
00599 }
00602 explicit SkAutoLockColors(SkColorTable* ctable) {
00603 fCTable = ctable;
00604 fColors = ctable ? ctable->lockColors() : NULL;
00605 }
00606 ~SkAutoLockColors() {
00607 if (fCTable) {
00608 fCTable->unlockColors(false);
00609 }
00610 }
00611
00615 const SkPMColor* colors() const { return fColors; }
00616
00620 const SkPMColor* lockColors(SkColorTable* ctable) {
00621 if (fCTable) {
00622 fCTable->unlockColors(false);
00623 }
00624 fCTable = ctable;
00625 fColors = ctable ? ctable->lockColors() : NULL;
00626 return fColors;
00627 }
00628
00629 const SkPMColor* lockColors(const SkBitmap& bm) {
00630 return this->lockColors(bm.getColorTable());
00631 }
00632
00633 private:
00634 SkColorTable* fCTable;
00635 const SkPMColor* fColors;
00636 };
00637
00639
00640 inline uint32_t* SkBitmap::getAddr32(int x, int y) const {
00641 SkASSERT(fPixels);
00642 SkASSERT(fConfig == kARGB_8888_Config);
00643 SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
00644 return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2));
00645 }
00646
00647 inline uint16_t* SkBitmap::getAddr16(int x, int y) const {
00648 SkASSERT(fPixels);
00649 SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config);
00650 SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
00651 return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1));
00652 }
00653
00654 inline uint8_t* SkBitmap::getAddr8(int x, int y) const {
00655 SkASSERT(fPixels);
00656 SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config);
00657 SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
00658 return (uint8_t*)fPixels + y * fRowBytes + x;
00659 }
00660
00661 inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const {
00662 SkASSERT(fPixels);
00663 SkASSERT(fConfig == kIndex8_Config);
00664 SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
00665 SkASSERT(fColorTable);
00666 return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)];
00667 }
00668
00669
00670 inline uint8_t* SkBitmap::getAddr1(int x, int y) const {
00671 SkASSERT(fPixels);
00672 SkASSERT(fConfig == kA1_Config);
00673 SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight);
00674 return (uint8_t*)fPixels + y * fRowBytes + (x >> 3);
00675 }
00676
00677 #endif
00678