diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt index 6ea0bde144..f7cf111b17 100644 --- a/RELEASE_NOTES.txt +++ b/RELEASE_NOTES.txt @@ -10,6 +10,7 @@ This file includes a list of high level updates for each milestone release. * Remove isRectContour and ksNestedFillRects from public * Start to move nested SkPath types (e.g. Direction, Verb) up to root level in SkPathTypes.h * Remove Vulkan/Metal float32 RGBA texture support + * Add SkColorInfo. It's dimensionless SkImageInfo. Milestone 79 diff --git a/include/core/SkImageInfo.h b/include/core/SkImageInfo.h index 8054aed95a..46b5fbde06 100644 --- a/include/core/SkImageInfo.h +++ b/include/core/SkImageInfo.h @@ -186,6 +186,102 @@ enum SkYUVColorSpace { kLastEnum_SkYUVColorSpace = kIdentity_SkYUVColorSpace, //!< last valid value }; +/** \struct SkColorInfo + Describes pixel and encoding. SkImageInfo can be created from SkColorInfo by + providing dimensions. + + It encodes how pixel bits describe alpha, transparency; color components red, blue, + and green; and SkColorSpace, the range and linearity of colors. +*/ +class SK_API SkColorInfo { +public: + /** Creates an SkColorInfo with kUnknown_SkColorType, kUnknown_SkAlphaType, + and no SkColorSpace. + + @return empty SkImageInfo + */ + SkColorInfo() = default; + + /** Creates SkColorInfo from SkColorType ct, SkAlphaType at, and optionally SkColorSpace cs. + + If SkColorSpace cs is nullptr and SkColorInfo is part of drawing source: SkColorSpace + defaults to sRGB, mapping into SkSurface SkColorSpace. + + Parameters are not validated to see if their values are legal, or that the + combination is supported. + @return created SkColorInfo + */ + SkColorInfo(SkColorType ct, SkAlphaType at, sk_sp cs) + : fColorSpace(std::move(cs)), fColorType(ct), fAlphaType(at) {} + + SkColorInfo(const SkColorInfo&) = default; + SkColorInfo(SkColorInfo&&) = default; + + SkColorInfo& operator=(const SkColorInfo&) = default; + SkColorInfo& operator=(SkColorInfo&&) = default; + + SkColorSpace* colorSpace() const { return fColorSpace.get(); } + sk_sp refColorSpace() const { return fColorSpace; } + SkColorType colorType() const { return fColorType; } + SkAlphaType alphaType() const { return fAlphaType; } + + bool isOpaque() const { return SkAlphaTypeIsOpaque(fAlphaType); } + + bool gammaCloseToSRGB() const { return fColorSpace && fColorSpace->gammaCloseToSRGB(); } + + /** Does other represent the same color type, alpha type, and color space? */ + bool operator==(const SkColorInfo& other) const { + return fColorType == other.fColorType && fAlphaType == other.fAlphaType && + SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get()); + } + + /** Does other represent a different color type, alpha type, or color space? */ + bool operator!=(const SkColorInfo& other) const { return !(*this == other); } + + /** Creates SkColorInfo with same SkColorType, SkColorSpace, with SkAlphaType set + to newAlphaType. + + Created SkColorInfo contains newAlphaType even if it is incompatible with + SkColorType, in which case SkAlphaType in SkColorInfo is ignored. + */ + SkColorInfo makeAlphaType(SkAlphaType newAlphaType) const { + return SkColorInfo(this->colorType(), newAlphaType, this->refColorSpace()); + } + + /** Creates new SkColorInfo with same SkAlphaType, SkColorSpace, with SkColorType + set to newColorType. + */ + SkColorInfo makeColorType(SkColorType newColorType) const { + return SkColorInfo(newColorType, this->alphaType(), this->refColorSpace()); + } + + /** Creates SkColorInfo with same SkAlphaType, SkColorType, with SkColorSpace + set to cs. cs may be nullptr. + */ + SkColorInfo makeColorSpace(sk_sp cs) const { + return SkColorInfo(this->colorType(), this->alphaType(), std::move(cs)); + } + + /** Returns number of bytes per pixel required by SkColorType. + Returns zero if colorType() is kUnknown_SkColorType. + + @return bytes in pixel + */ + int bytesPerPixel() const; + + /** Returns bit shift converting row bytes to row pixels. + Returns zero for kUnknown_SkColorType. + + @return one of: 0, 1, 2, 3, 4; left shift to convert pixels to bytes + */ + int shiftPerPixel() const; + +private: + sk_sp fColorSpace; + SkColorType fColorType = kUnknown_SkColorType; + SkAlphaType fAlphaType = kUnknown_SkAlphaType; +}; + /** \struct SkImageInfo Describes pixel dimensions and encoding. SkBitmap, SkImage, PixMap, and SkSurface can be created from SkImageInfo. SkImageInfo can be retrieved from SkBitmap and @@ -204,12 +300,7 @@ public: @return empty SkImageInfo */ - SkImageInfo() - : fColorSpace(nullptr) - , fDimensions{0, 0} - , fColorType(kUnknown_SkColorType) - , fAlphaType(kUnknown_SkAlphaType) - {} + SkImageInfo() = default; /** Creates SkImageInfo from integral dimensions width and height, SkColorType ct, SkAlphaType at, and optionally SkColorSpace cs. @@ -235,11 +326,28 @@ public: */ static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at, sk_sp cs = nullptr) { - return SkImageInfo({width, height}, ct, at, std::move(cs)); + return SkImageInfo({width, height}, {ct, at, std::move(cs)}); } static SkImageInfo Make(SkISize dimensions, SkColorType ct, SkAlphaType at, sk_sp cs = nullptr) { - return SkImageInfo(dimensions, ct, at, std::move(cs)); + return SkImageInfo(dimensions, {ct, at, std::move(cs)}); + } + + /** Creates SkImageInfo from integral dimensions and SkColorInfo colorInfo, + + Parameters are not validated to see if their values are legal, or that the + combination is supported. + + @param dimensions pixel column and row count; must be zeros or greater + @param SkColorInfo the pixel encoding consisting of SkColorType, SkAlphaType, and + SkColorSpace (which may be nullptr) + @return created SkImageInfo + */ + static SkImageInfo Make(SkISize dimensions, const SkColorInfo& colorInfo) { + return SkImageInfo(dimensions, colorInfo); + } + static SkImageInfo Make(SkISize dimensions, SkColorInfo&& colorInfo) { + return SkImageInfo(dimensions, std::move(colorInfo)); } /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType, @@ -371,7 +479,7 @@ public: @return SkColorType */ - SkColorType colorType() const { return fColorType; } + SkColorType colorType() const { return fColorInfo.colorType(); } /** Returns SkAlphaType, one of: kUnknown_SkAlphaType, kOpaque_SkAlphaType, kPremul_SkAlphaType, @@ -379,14 +487,14 @@ public: @return SkAlphaType */ - SkAlphaType alphaType() const { return fAlphaType; } + SkAlphaType alphaType() const { return fColorInfo.alphaType(); } /** Returns SkColorSpace, the range of colors. The reference count of SkColorSpace is unchanged. The returned SkColorSpace is immutable. @return SkColorSpace, or nullptr */ - SkColorSpace* colorSpace() const { return fColorSpace.get(); } + SkColorSpace* colorSpace() const { return fColorInfo.colorSpace(); } /** Returns smart pointer to SkColorSpace, the range of colors. The smart pointer tracks the number of objects sharing this SkColorSpace reference so the memory @@ -396,7 +504,7 @@ public: @return SkColorSpace wrapped in a smart pointer */ - sk_sp refColorSpace() const { return fColorSpace; } + sk_sp refColorSpace() const { return fColorInfo.refColorSpace(); } /** Returns if SkImageInfo describes an empty area of pixels by checking if either width or height is zero or smaller. @@ -405,6 +513,11 @@ public: */ bool isEmpty() const { return fDimensions.isEmpty(); } + /** Returns the dimensionless SkColorInfo that represents the same color type, + alpha type, and color space as this SkImageInfo. + */ + const SkColorInfo& colorInfo() const { return fColorInfo; } + /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their alpha value is implicitly or explicitly 1.0. If true, and all pixels are not opaque, Skia may draw incorrectly. @@ -414,9 +527,7 @@ public: @return true if SkAlphaType is kOpaque_SkAlphaType */ - bool isOpaque() const { - return SkAlphaTypeIsOpaque(fAlphaType); - } + bool isOpaque() const { return fColorInfo.isOpaque(); } /** Returns SkISize { width(), height() }. @@ -436,9 +547,7 @@ public: @return true if SkColorSpace gamma is approximately the same as sRGB */ - bool gammaCloseToSRGB() const { - return fColorSpace && fColorSpace->gammaCloseToSRGB(); - } + bool gammaCloseToSRGB() const { return fColorInfo.gammaCloseToSRGB(); } /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType, with dimensions set to width and height. @@ -448,7 +557,7 @@ public: @return created SkImageInfo */ SkImageInfo makeWH(int newWidth, int newHeight) const { - return Make(newWidth, newHeight, fColorType, fAlphaType, fColorSpace); + return Make({newWidth, newHeight}, fColorInfo); } /** Creates SkImageInfo with same SkColorType, SkColorSpace, width, and height, @@ -463,7 +572,7 @@ public: @return created SkImageInfo */ SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const { - return Make(this->width(), this->height(), fColorType, newAlphaType, fColorSpace); + return Make(fDimensions, fColorInfo.makeAlphaType(newAlphaType)); } /** Creates SkImageInfo with same SkAlphaType, SkColorSpace, width, and height, @@ -477,7 +586,7 @@ public: @return created SkImageInfo */ SkImageInfo makeColorType(SkColorType newColorType) const { - return Make(this->width(), this->height(), newColorType, fAlphaType, fColorSpace); + return Make(fDimensions, fColorInfo.makeColorType(newColorType)); } /** Creates SkImageInfo with same SkAlphaType, SkColorType, width, and height, @@ -487,7 +596,7 @@ public: @return created SkImageInfo */ SkImageInfo makeColorSpace(sk_sp cs) const { - return Make(this->width(), this->height(), fColorType, fAlphaType, std::move(cs)); + return Make(fDimensions, fColorInfo.makeColorSpace(std::move(cs))); } /** Returns number of bytes per pixel required by SkColorType. @@ -495,14 +604,14 @@ public: @return bytes in pixel */ - int bytesPerPixel() const; + int bytesPerPixel() const { return fColorInfo.bytesPerPixel(); } /** Returns bit shift converting row bytes to row pixels. Returns zero for kUnknown_SkColorType. @return one of: 0, 1, 2, 3; left shift to convert pixels to bytes */ - int shiftPerPixel() const; + int shiftPerPixel() const { return fColorInfo.shiftPerPixel(); } /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit @@ -545,9 +654,7 @@ public: @return true if SkImageInfo equals other */ bool operator==(const SkImageInfo& other) const { - return fDimensions == other.fDimensions && - fColorType == other.fColorType && fAlphaType == other.fAlphaType && - SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get()); + return fDimensions == other.fDimensions && fColorInfo == other.fColorInfo; } /** Compares SkImageInfo with other, and returns true if width, height, SkColorType, @@ -605,12 +712,7 @@ public: /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType, a width and height of zero, and no SkColorSpace. */ - void reset() { - fColorSpace = nullptr; - fDimensions = {0, 0}; - fColorType = kUnknown_SkColorType; - fAlphaType = kUnknown_SkAlphaType; - } + void reset() { *this = {}; } /** Asserts if internal values are illegal or inconsistent. Only available if SK_DEBUG is defined at compile time. @@ -618,17 +720,14 @@ public: SkDEBUGCODE(void validate() const;) private: - sk_sp fColorSpace; - SkISize fDimensions; - SkColorType fColorType; - SkAlphaType fAlphaType; + SkColorInfo fColorInfo; + SkISize fDimensions = {0, 0}; - SkImageInfo(SkISize dimensions, SkColorType ct, SkAlphaType at, sk_sp cs) - : fColorSpace(std::move(cs)) - , fDimensions(dimensions) - , fColorType(ct) - , fAlphaType(at) - {} + SkImageInfo(SkISize dimensions, const SkColorInfo& colorInfo) + : fColorInfo(colorInfo), fDimensions(dimensions) {} + + SkImageInfo(SkISize dimensions, SkColorInfo&& colorInfo) + : fColorInfo(std::move(colorInfo)), fDimensions(dimensions) {} }; #endif diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp index 3cf72d0c54..83ecc0c799 100644 --- a/src/core/SkBitmap.cpp +++ b/src/core/SkBitmap.cpp @@ -628,14 +628,3 @@ bool SkBitmap::peekPixels(SkPixmap* pmap) const { } return false; } - -/////////////////////////////////////////////////////////////////////////////// - -#ifdef SK_DEBUG -void SkImageInfo::validate() const { - SkASSERT(fDimensions.width() >= 0); - SkASSERT(fDimensions.height() >= 0); - SkASSERT(SkColorTypeIsValid(fColorType)); - SkASSERT(SkAlphaTypeIsValid(fAlphaType)); -} -#endif diff --git a/src/core/SkImageInfo.cpp b/src/core/SkImageInfo.cpp index e1a834787e..f033bb16ef 100644 --- a/src/core/SkImageInfo.cpp +++ b/src/core/SkImageInfo.cpp @@ -41,9 +41,11 @@ bool SkColorTypeIsAlwaysOpaque(SkColorType ct) { /////////////////////////////////////////////////////////////////////////////////////////////////// -int SkImageInfo::bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); } +int SkColorInfo::bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); } -int SkImageInfo::shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); } +int SkColorInfo::shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); } + +/////////////////////////////////////////////////////////////////////////////////////////////////// size_t SkImageInfo::computeOffset(int x, int y, size_t rowBytes) const { SkASSERT((unsigned)x < (unsigned)this->width()); @@ -62,9 +64,18 @@ size_t SkImageInfo::computeByteSize(size_t rowBytes) const { } SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) { - return SkImageInfo({width, height}, kN32_SkColorType, at, SkColorSpace::MakeSRGB()); + return SkImageInfo({width, height}, {kN32_SkColorType, at, SkColorSpace::MakeSRGB()}); } +#ifdef SK_DEBUG +void SkImageInfo::validate() const { + SkASSERT(fDimensions.width() >= 0); + SkASSERT(fDimensions.height() >= 0); + SkASSERT(SkColorTypeIsValid(this->colorType())); + SkASSERT(SkAlphaTypeIsValid(this->alphaType())); +} +#endif + bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType, SkAlphaType* canonical) { switch (colorType) { diff --git a/src/gpu/GrBitmapTextureMaker.cpp b/src/gpu/GrBitmapTextureMaker.cpp index 42eaa415f5..5fbfcf107b 100644 --- a/src/gpu/GrBitmapTextureMaker.cpp +++ b/src/gpu/GrBitmapTextureMaker.cpp @@ -17,14 +17,9 @@ #include "src/gpu/GrSurfaceContext.h" #include "src/gpu/SkGr.h" -static GrColorInfo make_info(const SkBitmap& bm) { - return GrColorInfo(SkColorTypeToGrColorType(bm.colorType()), bm.alphaType(), - bm.refColorSpace()); -} - GrBitmapTextureMaker::GrBitmapTextureMaker(GrRecordingContext* context, const SkBitmap& bitmap, bool useDecal) - : INHERITED(context, bitmap.width(), bitmap.height(), make_info(bitmap), useDecal) + : INHERITED(context, bitmap.width(), bitmap.height(), bitmap.info().colorInfo(), useDecal) , fBitmap(bitmap) { if (!bitmap.isVolatile()) { SkIPoint origin = bitmap.pixelRefOrigin(); diff --git a/src/gpu/GrColorInfo.cpp b/src/gpu/GrColorInfo.cpp index d5efec4db7..a6cc9be008 100644 --- a/src/gpu/GrColorInfo.cpp +++ b/src/gpu/GrColorInfo.cpp @@ -13,6 +13,11 @@ GrColorInfo::GrColorInfo( GrColorType colorType, SkAlphaType alphaType, sk_sp colorSpace) : fColorSpace(std::move(colorSpace)), fColorType(colorType), fAlphaType(alphaType) {} +GrColorInfo::GrColorInfo(const SkColorInfo& ci) + : GrColorInfo(SkColorTypeToGrColorType(ci.colorType()), + ci.alphaType(), + ci.refColorSpace()) {} + GrColorSpaceXform* GrColorInfo::colorSpaceXformFromSRGB() const { // TODO: Make this atomic if we start accessing this on multiple threads. if (!fInitializedColorSpaceXformFromSRGB) { diff --git a/src/gpu/GrColorInfo.h b/src/gpu/GrColorInfo.h index 4f5f594b23..ba95bf3b95 100644 --- a/src/gpu/GrColorInfo.h +++ b/src/gpu/GrColorInfo.h @@ -20,6 +20,7 @@ class GrColorInfo { public: GrColorInfo() = default; GrColorInfo(GrColorType, SkAlphaType, sk_sp); + /* implicit */ GrColorInfo(const SkColorInfo&); bool isLinearlyBlended() const { return fColorSpace && fColorSpace->gammaIsLinear(); } diff --git a/src/gpu/GrImageInfo.h b/src/gpu/GrImageInfo.h index e2f1330d72..800d3f433f 100644 --- a/src/gpu/GrImageInfo.h +++ b/src/gpu/GrImageInfo.h @@ -16,11 +16,8 @@ class GrImageInfo { public: GrImageInfo() = default; - // not explicit - GrImageInfo(const SkImageInfo& info) - : fColorInfo(SkColorTypeToGrColorType(info.colorType()), info.alphaType(), - info.refColorSpace()) - , fDimensions(info.dimensions()) {} + /* implicit */ GrImageInfo(const SkImageInfo& info) + : fColorInfo(info.colorInfo()), fDimensions(info.dimensions()) {} GrImageInfo(GrColorType ct, SkAlphaType at, sk_sp cs, int w, int h) : fColorInfo(ct, at, std::move(cs)), fDimensions{w,h} {} diff --git a/src/gpu/GrImageTextureMaker.cpp b/src/gpu/GrImageTextureMaker.cpp index b315bdbbd1..13ca46dad3 100644 --- a/src/gpu/GrImageTextureMaker.cpp +++ b/src/gpu/GrImageTextureMaker.cpp @@ -13,15 +13,10 @@ #include "src/image/SkImage_GpuYUVA.h" #include "src/image/SkImage_Lazy.h" -static GrColorInfo make_info(const SkImage*& image) { - return GrColorInfo(SkColorTypeToGrColorType(image->colorType()), - image->alphaType(), - image->refColorSpace()); -} - GrImageTextureMaker::GrImageTextureMaker(GrRecordingContext* context, const SkImage* client, SkImage::CachingHint chint, bool useDecal) - : INHERITED(context, client->width(), client->height(), make_info(client), useDecal) + : INHERITED(context, client->width(), client->height(), client->imageInfo().colorInfo(), + useDecal) , fImage(static_cast(client)) , fCachingHint(chint) { SkASSERT(client->isLazyGenerated()); @@ -48,7 +43,8 @@ void GrImageTextureMaker::makeCopyKey(const CopyParams& stretch, GrUniqueKey* pa GrYUVAImageTextureMaker::GrYUVAImageTextureMaker(GrContext* context, const SkImage* client, bool useDecal) - : INHERITED(context, client->width(), client->height(), make_info(client), useDecal) + : INHERITED(context, client->width(), client->height(), client->imageInfo().colorInfo(), + useDecal) , fImage(static_cast(client)) { SkASSERT(as_IB(client)->isYUVA()); GrMakeKeyFromImageID(&fOriginalKey, client->uniqueID(),