From 169a0ed50a5e451711c341795572e7177a540a24 Mon Sep 17 00:00:00 2001 From: "mike@reedtribe.org" Date: Tue, 11 Feb 2014 02:20:17 +0000 Subject: SkBitmap now really stores SkImageInfo -- config is just a ruse (edited) clone of https://codereview.chromium.org/159173004/ Review URL: https://codereview.chromium.org/159463003 git-svn-id: http://skia.googlecode.com/svn/trunk@13391 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkBitmap.h | 114 ++++++++++++++++++++++++--------------------- include/core/SkImageInfo.h | 48 +++++++++++++++++-- 2 files changed, 105 insertions(+), 57 deletions(-) (limited to 'include/core') diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h index 87d4649228..ad47dfadf4 100644 --- a/include/core/SkBitmap.h +++ b/include/core/SkBitmap.h @@ -79,10 +79,42 @@ public: // This method is not exported to java. void swap(SkBitmap& other); + /////////////////////////////////////////////////////////////////////////// + + const SkImageInfo& info() const { return fInfo; } + + int width() const { return fInfo.fWidth; } + int height() const { return fInfo.fHeight; } + SkColorType colorType() const { return fInfo.fColorType; } + SkAlphaType alphaType() const { return fInfo.fAlphaType; } + + /** Return the number of bytes per pixel based on the config. If the config + does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned. + */ + int bytesPerPixel() const { return fInfo.bytesPerPixel(); } + + /** Return the rowbytes expressed as a number of pixels (like width and + height). Note, for 1-byte per pixel configs like kA8_Config, this will + return the same as rowBytes(). Is undefined for configs that are less + than 1-byte per pixel (e.g. kA1_Config) + */ + int rowBytesAsPixels() const { + return fRowBytes >> this->shiftPerPixel(); + } + + /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for + 2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0 + for configs that are not at least 1-byte per pixel (e.g. kA1_Config + or kNo_Config) + */ + int shiftPerPixel() const { return this->bytesPerPixel() >> 1; } + + /////////////////////////////////////////////////////////////////////////// + /** Return true iff the bitmap has empty dimensions. * Hey! Before you use this, see if you really want to know drawsNothing() instead. */ - bool empty() const { return 0 == fWidth || 0 == fHeight; } + bool empty() const { return fInfo.isEmpty(); } /** Return true iff the bitmap has no pixelref. Note: this can return true even if the * dimensions of the bitmap are > 0 (see empty()). @@ -95,41 +127,14 @@ public: bool drawsNothing() const { return this->empty() || this->isNull(); } /** Return the config for the bitmap. */ - Config config() const { return (Config)fConfig; } + Config config() const; SK_ATTR_DEPRECATED("use config()") Config getConfig() const { return this->config(); } - /** Return the bitmap's width, in pixels. */ - int width() const { return fWidth; } - - /** Return the bitmap's height, in pixels. */ - int height() const { return fHeight; } - /** Return the number of bytes between subsequent rows of the bitmap. */ size_t rowBytes() const { return fRowBytes; } - /** Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for - 2-bytes per pixel configs, 2 for 4-bytes per pixel configs). Return 0 - for configs that are not at least 1-byte per pixel (e.g. kA1_Config - or kNo_Config) - */ - int shiftPerPixel() const { return fBytesPerPixel >> 1; } - - /** Return the number of bytes per pixel based on the config. If the config - does not have at least 1 byte per (e.g. kA1_Config) then 0 is returned. - */ - int bytesPerPixel() const { return fBytesPerPixel; } - - /** Return the rowbytes expressed as a number of pixels (like width and - height). Note, for 1-byte per pixel configs like kA8_Config, this will - return the same as rowBytes(). Is undefined for configs that are less - than 1-byte per pixel (e.g. kA1_Config) - */ - int rowBytesAsPixels() const { return fRowBytes >> (fBytesPerPixel >> 1); } - - SkAlphaType alphaType() const { return (SkAlphaType)fAlphaType; } - /** * Set the bitmap's alphaType, returning true on success. If false is * returned, then the specified new alphaType is incompatible with the @@ -149,19 +154,19 @@ public: Note this truncates the result to 32bits. Call getSize64() to detect if the real size exceeds 32bits. */ - size_t getSize() const { return fHeight * fRowBytes; } + size_t getSize() const { return fInfo.fHeight * fRowBytes; } /** Return the number of bytes from the pointer returned by getPixels() to the end of the allocated space in the buffer. Required in cases where extractSubset has been called. */ - size_t getSafeSize() const ; + size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); } /** * Return the full size of the bitmap, in bytes. */ int64_t computeSize64() const { - return sk_64_mul(fHeight, fRowBytes); + return sk_64_mul(fInfo.fHeight, fRowBytes); } /** @@ -170,7 +175,7 @@ public: * than computeSize64() if there is any rowbytes padding beyond the width. */ int64_t computeSafeSize64() const { - return ComputeSafeSize64((Config)fConfig, fWidth, fHeight, fRowBytes); + return fInfo.getSafeSize64(fRowBytes); } /** Returns true if this bitmap is marked as immutable, meaning that the @@ -304,11 +309,18 @@ public: void* context); /** - * If the bitmap's config can be represented as SkImageInfo, return true, - * and if info is not-null, set it to the bitmap's info. If it cannot be - * represented as SkImageInfo, return false and ignore the info parameter. + * DEPRECATED: call info(). */ - bool asImageInfo(SkImageInfo* info) const; + bool asImageInfo(SkImageInfo* info) const { + // compatibility: return false for kUnknown + if (kUnknown_SkColorType == this->colorType()) { + return false; + } + if (info) { + *info = this->info(); + } + return true; + } /** Use this to assign a new pixel address for an existing bitmap. This will automatically release any pixelref previously installed. Only call @@ -450,8 +462,8 @@ public: */ GrTexture* getTexture() const; - /** Return the bitmap's colortable, if it uses one (i.e. fConfig is - kIndex8_Config) and the pixels are locked. + /** Return the bitmap's colortable, if it uses one (i.e. colorType is + Index_8) and the pixels are locked. Otherwise returns NULL. Does not affect the colortable's reference count. */ @@ -742,13 +754,11 @@ private: #endif }; + SkImageInfo fInfo; + uint32_t fRowBytes; - uint32_t fWidth; - uint32_t fHeight; - uint8_t fConfig; - uint8_t fAlphaType; + uint8_t fFlags; - uint8_t fBytesPerPixel; // based on config void internalErase(const SkIRect&, U8CPU a, U8CPU r, U8CPU g, U8CPU b)const; @@ -860,29 +870,29 @@ private: inline uint32_t* SkBitmap::getAddr32(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kARGB_8888_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kARGB_8888_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); return (uint32_t*)((char*)fPixels + y * fRowBytes + (x << 2)); } inline uint16_t* SkBitmap::getAddr16(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kRGB_565_Config || fConfig == kARGB_4444_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kRGB_565_Config || this->config() == kARGB_4444_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); return (uint16_t*)((char*)fPixels + y * fRowBytes + (x << 1)); } inline uint8_t* SkBitmap::getAddr8(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kA8_Config || fConfig == kIndex8_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kA8_Config || this->config() == kIndex8_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); return (uint8_t*)fPixels + y * fRowBytes + x; } inline SkPMColor SkBitmap::getIndex8Color(int x, int y) const { SkASSERT(fPixels); - SkASSERT(fConfig == kIndex8_Config); - SkASSERT((unsigned)x < fWidth && (unsigned)y < fHeight); + SkASSERT(this->config() == kIndex8_Config); + SkASSERT((unsigned)x < (unsigned)this->width() && (unsigned)y < (unsigned)this->height()); SkASSERT(fColorTable); return (*fColorTable)[*((const uint8_t*)fPixels + y * fRowBytes + x)]; } diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h index 722ff27437..73b8b8c12c 100644 --- a/include/core/SkImageInfo.h +++ b/include/core/SkImageInfo.h @@ -8,7 +8,7 @@ #ifndef SkImageInfo_DEFINED #define SkImageInfo_DEFINED -#include "SkTypes.h" +#include "SkMath.h" #include "SkSize.h" class SkWriteBuffer; @@ -59,12 +59,17 @@ static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) { return (unsigned)at <= kOpaque_SkAlphaType; } +static inline bool SkAlphaTypeIsValid(unsigned value) { + return value <= kLastEnum_SkAlphaType; +} + /////////////////////////////////////////////////////////////////////////////// /** * Describes how to interpret the components of a pixel. */ enum SkColorType { + kUnknown_SkColorType, kAlpha_8_SkColorType, kRGB_565_SkColorType, kARGB_4444_SkColorType, @@ -85,6 +90,7 @@ enum SkColorType { static int SkColorTypeBytesPerPixel(SkColorType ct) { static const uint8_t gSize[] = { + 0, // Unknown 1, // Alpha_8 2, // RGB_565 2, // ARGB_4444 @@ -99,6 +105,14 @@ static int SkColorTypeBytesPerPixel(SkColorType ct) { return gSize[ct]; } +static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) { + return width * SkColorTypeBytesPerPixel(ct); +} + +static inline bool SkColorTypeIsValid(unsigned value) { + return value <= kLastEnum_SkColorType; +} + /////////////////////////////////////////////////////////////////////////////// /** @@ -159,18 +173,31 @@ struct SkImageInfo { return info; } + int width() const { return fWidth; } + int height() const { return fHeight; } + SkColorType colorType() const { return fColorType; } + SkAlphaType alphaType() const { return fAlphaType; } + + bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; } + bool isOpaque() const { return SkAlphaTypeIsOpaque(fAlphaType); } + SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); } + int bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); } + uint64_t minRowBytes64() const { + return sk_64_mul(fWidth, this->bytesPerPixel()); + } + size_t minRowBytes() const { - return fWidth * this->bytesPerPixel(); + return (size_t)this->minRowBytes64(); } - + bool operator==(const SkImageInfo& other) const { return 0 == memcmp(this, &other, sizeof(other)); } @@ -181,12 +208,23 @@ struct SkImageInfo { void unflatten(SkReadBuffer&); void flatten(SkWriteBuffer&) const; - size_t getSafeSize(size_t rowBytes) const { + int64_t getSafeSize64(size_t rowBytes) const { if (0 == fHeight) { return 0; } - return (fHeight - 1) * rowBytes + fWidth * this->bytesPerPixel(); + return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel(); } + + size_t getSafeSize(size_t rowBytes) const { + return (size_t)this->getSafeSize64(rowBytes); + } + + bool validRowBytes(size_t rowBytes) const { + uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel()); + return rowBytes >= rb; + } + + SkDEBUGCODE(void validate() const;) }; #endif -- cgit v1.2.3