|  | /* | 
|  | * Copyright 2015 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #ifndef SkPixmap_DEFINED | 
|  | #define SkPixmap_DEFINED | 
|  |  | 
|  | #include "SkColor.h" | 
|  | #include "SkFilterQuality.h" | 
|  | #include "SkImageInfo.h" | 
|  |  | 
|  | #ifdef SK_SUPPORT_LEGACY_COLORTABLE | 
|  | class SkColorTable; | 
|  | #endif | 
|  | class SkData; | 
|  | struct SkMask; | 
|  |  | 
|  | /** | 
|  | *  Pairs SkImageInfo with actual pixels and rowbytes. This class does not try to manage the | 
|  | *  lifetime of the pixel memory (nor the colortable if provided). | 
|  | */ | 
|  | class SK_API SkPixmap { | 
|  | public: | 
|  | SkPixmap() | 
|  | : fPixels(NULL), fRowBytes(0), fInfo(SkImageInfo::MakeUnknown(0, 0)) | 
|  | {} | 
|  |  | 
|  | SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes) | 
|  | : fPixels(addr), fRowBytes(rowBytes), fInfo(info) | 
|  | {} | 
|  |  | 
|  | void reset(); | 
|  | void reset(const SkImageInfo& info, const void* addr, size_t rowBytes); | 
|  | void reset(const SkImageInfo& info) { | 
|  | this->reset(info, NULL, 0); | 
|  | } | 
|  |  | 
|  | // overrides the colorspace in the SkImageInfo of the pixmap | 
|  | void setColorSpace(sk_sp<SkColorSpace>); | 
|  |  | 
|  | /** | 
|  | *  If supported, set this pixmap to point to the pixels in the specified mask and return true. | 
|  | *  On failure, return false and set this pixmap to empty. | 
|  | */ | 
|  | bool SK_WARN_UNUSED_RESULT reset(const SkMask&); | 
|  |  | 
|  | /** | 
|  | *  Computes the intersection of area and this pixmap. If that intersection is non-empty, | 
|  | *  set subset to that intersection and return true. | 
|  | * | 
|  | *  On failure, return false and ignore the subset parameter. | 
|  | */ | 
|  | bool SK_WARN_UNUSED_RESULT extractSubset(SkPixmap* subset, const SkIRect& area) const; | 
|  |  | 
|  | const SkImageInfo& info() const { return fInfo; } | 
|  | size_t rowBytes() const { return fRowBytes; } | 
|  | const void* addr() const { return fPixels; } | 
|  |  | 
|  | int width() const { return fInfo.width(); } | 
|  | int height() const { return fInfo.height(); } | 
|  | SkColorType colorType() const { return fInfo.colorType(); } | 
|  | SkAlphaType alphaType() const { return fInfo.alphaType(); } | 
|  | SkColorSpace* colorSpace() const { return fInfo.colorSpace(); } | 
|  | bool isOpaque() const { return fInfo.isOpaque(); } | 
|  |  | 
|  | SkIRect bounds() const { return SkIRect::MakeWH(this->width(), this->height()); } | 
|  |  | 
|  | /** | 
|  | *  Return the rowbytes expressed as a number of pixels (like width and height). | 
|  | */ | 
|  | int rowBytesAsPixels() const { return int(fRowBytes >> this->shiftPerPixel()); } | 
|  |  | 
|  | /** | 
|  | *  Return the shift amount per pixel (i.e. 0 for 1-byte per pixel, 1 for 2-bytes per pixel | 
|  | *  colortypes, 2 for 4-bytes per pixel colortypes). Return 0 for kUnknown_SkColorType. | 
|  | */ | 
|  | int shiftPerPixel() const { return fInfo.shiftPerPixel(); } | 
|  |  | 
|  | uint64_t getSize64() const { return sk_64_mul(fInfo.height(), fRowBytes); } | 
|  | uint64_t getSafeSize64() const { return fInfo.getSafeSize64(fRowBytes); } | 
|  | size_t getSafeSize() const { return fInfo.getSafeSize(fRowBytes); } | 
|  |  | 
|  | /** | 
|  | *  This will brute-force return true if all of the pixels in the pixmap | 
|  | *  are opaque. If there are no pixels, or encounters an error, returns false. | 
|  | */ | 
|  | bool computeIsOpaque() const; | 
|  |  | 
|  | /** | 
|  | *  Converts the pixel at the specified coordinate to an unpremultiplied | 
|  | *  SkColor. Note: this ignores any SkColorSpace information, and may return | 
|  | *  lower precision data than is actually in the pixel. Alpha only | 
|  | *  colortypes (e.g. kAlpha_8_SkColorType) return black with the appropriate | 
|  | *  alpha set.  The value is undefined for kUnknown_SkColorType or if x or y | 
|  | *  are out of bounds, or if the pixtap does not have any pixels. | 
|  | */ | 
|  | SkColor getColor(int x, int y) const; | 
|  |  | 
|  | const void* addr(int x, int y) const { | 
|  | return (const char*)fPixels + fInfo.computeOffset(x, y, fRowBytes); | 
|  | } | 
|  | const uint8_t* addr8() const { | 
|  | SkASSERT(1 == SkColorTypeBytesPerPixel(fInfo.colorType())); | 
|  | return reinterpret_cast<const uint8_t*>(fPixels); | 
|  | } | 
|  | const uint16_t* addr16() const { | 
|  | SkASSERT(2 == SkColorTypeBytesPerPixel(fInfo.colorType())); | 
|  | return reinterpret_cast<const uint16_t*>(fPixels); | 
|  | } | 
|  | const uint32_t* addr32() const { | 
|  | SkASSERT(4 == SkColorTypeBytesPerPixel(fInfo.colorType())); | 
|  | return reinterpret_cast<const uint32_t*>(fPixels); | 
|  | } | 
|  | const uint64_t* addr64() const { | 
|  | SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType())); | 
|  | return reinterpret_cast<const uint64_t*>(fPixels); | 
|  | } | 
|  | const uint16_t* addrF16() const { | 
|  | SkASSERT(8 == SkColorTypeBytesPerPixel(fInfo.colorType())); | 
|  | SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType()); | 
|  | return reinterpret_cast<const uint16_t*>(fPixels); | 
|  | } | 
|  |  | 
|  | // Offset by the specified x,y coordinates | 
|  |  | 
|  | const uint8_t* addr8(int x, int y) const { | 
|  | SkASSERT((unsigned)x < (unsigned)fInfo.width()); | 
|  | SkASSERT((unsigned)y < (unsigned)fInfo.height()); | 
|  | return (const uint8_t*)((const char*)this->addr8() + y * fRowBytes + (x << 0)); | 
|  | } | 
|  | const uint16_t* addr16(int x, int y) const { | 
|  | SkASSERT((unsigned)x < (unsigned)fInfo.width()); | 
|  | SkASSERT((unsigned)y < (unsigned)fInfo.height()); | 
|  | return (const uint16_t*)((const char*)this->addr16() + y * fRowBytes + (x << 1)); | 
|  | } | 
|  | const uint32_t* addr32(int x, int y) const { | 
|  | SkASSERT((unsigned)x < (unsigned)fInfo.width()); | 
|  | SkASSERT((unsigned)y < (unsigned)fInfo.height()); | 
|  | return (const uint32_t*)((const char*)this->addr32() + y * fRowBytes + (x << 2)); | 
|  | } | 
|  | const uint64_t* addr64(int x, int y) const { | 
|  | SkASSERT((unsigned)x < (unsigned)fInfo.width()); | 
|  | SkASSERT((unsigned)y < (unsigned)fInfo.height()); | 
|  | return (const uint64_t*)((const char*)this->addr64() + y * fRowBytes + (x << 3)); | 
|  | } | 
|  | const uint16_t* addrF16(int x, int y) const { | 
|  | SkASSERT(kRGBA_F16_SkColorType == fInfo.colorType()); | 
|  | return reinterpret_cast<const uint16_t*>(this->addr64(x, y)); | 
|  | } | 
|  |  | 
|  | // Writable versions | 
|  |  | 
|  | void* writable_addr() const { return const_cast<void*>(fPixels); } | 
|  | void* writable_addr(int x, int y) const { | 
|  | return const_cast<void*>(this->addr(x, y)); | 
|  | } | 
|  | uint8_t* writable_addr8(int x, int y) const { | 
|  | return const_cast<uint8_t*>(this->addr8(x, y)); | 
|  | } | 
|  | uint16_t* writable_addr16(int x, int y) const { | 
|  | return const_cast<uint16_t*>(this->addr16(x, y)); | 
|  | } | 
|  | uint32_t* writable_addr32(int x, int y) const { | 
|  | return const_cast<uint32_t*>(this->addr32(x, y)); | 
|  | } | 
|  | uint64_t* writable_addr64(int x, int y) const { | 
|  | return const_cast<uint64_t*>(this->addr64(x, y)); | 
|  | } | 
|  | uint16_t* writable_addrF16(int x, int y) const { | 
|  | return reinterpret_cast<uint16_t*>(writable_addr64(x, y)); | 
|  | } | 
|  |  | 
|  | // copy methods | 
|  |  | 
|  | bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, | 
|  | int srcX, int srcY, SkTransferFunctionBehavior behavior) const; | 
|  | bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes) const { | 
|  | return this->readPixels(dstInfo, dstPixels, dstRowBytes, 0, 0); | 
|  | } | 
|  | bool readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, | 
|  | int srcY) const { | 
|  | return this->readPixels(dstInfo, dstPixels, dstRowBytes, srcX, srcY, | 
|  | SkTransferFunctionBehavior::kRespect); | 
|  | } | 
|  | bool readPixels(const SkPixmap& dst, int srcX, int srcY) const { | 
|  | return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY); | 
|  | } | 
|  | bool readPixels(const SkPixmap& dst) const { | 
|  | return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), 0, 0); | 
|  | } | 
|  |  | 
|  | /** | 
|  | *  Copy the pixels from this pixmap into the dst pixmap, converting as needed into dst's | 
|  | *  colortype/alphatype. If the conversion cannot be performed, false is returned. | 
|  | * | 
|  | *  If dst's dimensions differ from the src dimension, the image will be scaled, applying the | 
|  | *  specified filter-quality. | 
|  | */ | 
|  | bool scalePixels(const SkPixmap& dst, SkFilterQuality) const; | 
|  |  | 
|  | /** | 
|  | *  Returns true if pixels were written to (e.g. if colorType is kUnknown_SkColorType, this | 
|  | *  will return false). If subset does not intersect the bounds of this pixmap, returns false. | 
|  | */ | 
|  | bool erase(SkColor, const SkIRect& subset) const; | 
|  |  | 
|  | bool erase(SkColor color) const { return this->erase(color, this->bounds()); } | 
|  | bool erase(const SkColor4f&, const SkIRect* subset = nullptr) const; | 
|  |  | 
|  | #ifdef SK_SUPPORT_LEGACY_COLORTABLE | 
|  | SkPixmap(const SkImageInfo& info, const void* addr, size_t rowBytes, SkColorTable*) | 
|  | : fPixels(addr), fRowBytes(rowBytes), fInfo(info) | 
|  | {} | 
|  | void reset(const SkImageInfo& info, const void* addr, size_t rowBytes, | 
|  | SkColorTable*) { | 
|  | this->reset(info, addr, rowBytes); | 
|  | } | 
|  | SkColorTable* ctable() const { return nullptr; } | 
|  | #endif | 
|  |  | 
|  | private: | 
|  | const void*     fPixels; | 
|  | size_t          fRowBytes; | 
|  | SkImageInfo     fInfo; | 
|  | }; | 
|  |  | 
|  | #endif |