Merge latest Skia into master (2 commits)
https://skia.googlesource.com/skia.git/+log/20ece3a..a2cedff
Test: Presubmit checks will test this change.
Change-Id: I6a830535fb52cc174ff9c07cd3136388361dc141
diff --git a/gm/gaussianedge.cpp b/gm/gaussianedge.cpp
index 7a45118..eca8495 100644
--- a/gm/gaussianedge.cpp
+++ b/gm/gaussianedge.cpp
@@ -6,8 +6,9 @@
*/
#include "gm.h"
-#include "SkRRect.h"
+#include "SkColorFilter.h"
#include "SkGaussianEdgeShader.h"
+#include "SkRRect.h"
//#define VIZ 1
@@ -118,8 +119,10 @@
SkPaint basePaint;
basePaint.setAntiAlias(true);
- basePaint.setShader(SkGaussianEdgeShader::Make());
basePaint.setColor(SkColorSetARGB(255, (4 * blurRad) >> 8, (4 * blurRad) & 0xff, 0));
+ basePaint.setShader(SkGaussianEdgeShader::Make());
+ basePaint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorRED,
+ SkBlendMode::kModulate));
//----
paints[0] = basePaint;
diff --git a/gn/effects.gni b/gn/effects.gni
index 3ae4ebe..cc2b8ed 100644
--- a/gn/effects.gni
+++ b/gn/effects.gni
@@ -40,6 +40,7 @@
"$_src/effects/SkEmbossMaskFilter.cpp",
"$_src/effects/SkImageSource.cpp",
"$_src/effects/SkGaussianEdgeShader.cpp",
+ "$_src/effects/SkGaussianEdgeShader.h",
"$_src/effects/SkHighContrastFilter.cpp",
"$_src/effects/SkLayerDrawLooper.cpp",
"$_src/effects/SkLayerRasterizer.cpp",
@@ -106,7 +107,6 @@
"$_include/effects/SkDiscretePathEffect.h",
"$_include/effects/SkDisplacementMapEffect.h",
"$_include/effects/SkDropShadowImageFilter.h",
- "$_include/effects/SkGaussianEdgeShader.h",
"$_include/effects/SkGradientShader.h",
"$_include/effects/SkImageSource.h",
"$_include/effects/SkLayerDrawLooper.h",
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 700dbc2..fd25a23 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -657,7 +657,9 @@
* This is logically the same as creating a bitmap around src, and calling readPixels on it
* with this bitmap as the dst.
*/
- bool writePixels(const SkPixmap& src, int dstX, int dstY);
+ bool writePixels(const SkPixmap& src, int dstX, int dstY) {
+ return this->writePixels(src, dstX, dstY, SkTransferFunctionBehavior::kRespect);
+ }
bool writePixels(const SkPixmap& src) {
return this->writePixels(src, 0, 0);
}
@@ -777,6 +779,8 @@
uint32_t fRowBytes;
uint8_t fFlags;
+ bool writePixels(const SkPixmap& src, int x, int y, SkTransferFunctionBehavior behavior);
+
/* Unreference any pixelrefs or colortables
*/
void freePixels();
@@ -785,6 +789,7 @@
static void WriteRawPixels(SkWriteBuffer*, const SkBitmap&);
static bool ReadRawPixels(SkReadBuffer*, SkBitmap*);
+ friend class SkImage_Raster;
friend class SkReadBuffer; // unflatten, rawpixels
friend class SkBinaryWriteBuffer; // rawpixels
friend struct SkBitmapProcState;
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index 4a55e1a..0a999ce 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -709,7 +709,8 @@
return this->readPixels(dst.info(), dst.writable_addr(), dst.rowBytes(), srcX, srcY);
}
-bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY) {
+bool SkBitmap::writePixels(const SkPixmap& src, int dstX, int dstY,
+ SkTransferFunctionBehavior behavior) {
SkAutoPixmapUnlock dst;
if (!this->requestLock(&dst)) {
return false;
@@ -727,7 +728,7 @@
void* dstPixels = this->getAddr(rec.fX, rec.fY);
const SkImageInfo dstInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height());
SkConvertPixels(dstInfo, dstPixels, this->rowBytes(), rec.fInfo, rec.fPixels, rec.fRowBytes,
- src.ctable());
+ src.ctable(), behavior);
return true;
}
@@ -848,7 +849,8 @@
}
const SkPixmap& pmap = apl.pixmap();
SkConvertPixels(SkImageInfo::MakeA8(pmap.width(), pmap.height()), alpha, alphaRowBytes,
- pmap.info(), pmap.addr(), pmap.rowBytes(), pmap.ctable());
+ pmap.info(), pmap.addr(), pmap.rowBytes(), pmap.ctable(),
+ SkTransferFunctionBehavior::kRespect);
return true;
}
diff --git a/src/core/SkConvertPixels.cpp b/src/core/SkConvertPixels.cpp
index 787acb9..b919f5d 100644
--- a/src/core/SkConvertPixels.cpp
+++ b/src/core/SkConvertPixels.cpp
@@ -5,7 +5,7 @@
* found in the LICENSE file.
*/
-#include "SkColorSpaceXform.h"
+#include "SkColorSpaceXform_Base.h"
#include "SkColorSpaceXformPriv.h"
#include "SkColorTable.h"
#include "SkConvertPixels.h"
@@ -87,9 +87,13 @@
}
// Fast Path 3: Color space xform.
-static inline bool optimized_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo) {
- if (kUnpremul_SkAlphaType == dstInfo.alphaType() && kPremul_SkAlphaType == srcInfo.alphaType())
- {
+static inline bool optimized_color_xform(const SkImageInfo& dstInfo, const SkImageInfo& srcInfo,
+ SkTransferFunctionBehavior behavior) {
+ // Unpremultiplication is unsupported by SkColorSpaceXform. Note that if |src| is non-linearly
+ // premultiplied, we're always going to have to unpremultiply before doing anything.
+ if (kPremul_SkAlphaType == srcInfo.alphaType() &&
+ (kUnpremul_SkAlphaType == dstInfo.alphaType() ||
+ SkTransferFunctionBehavior::kIgnore == behavior)) {
return false;
}
@@ -115,7 +119,7 @@
static inline void apply_color_xform(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
const SkImageInfo& srcInfo, const void* srcPixels,
- size_t srcRB) {
+ size_t srcRB, SkTransferFunctionBehavior behavior) {
SkColorSpaceXform::ColorFormat dstFormat = select_xform_format(dstInfo.colorType());
SkColorSpaceXform::ColorFormat srcFormat = select_xform_format(srcInfo.colorType());
SkAlphaType xformAlpha;
@@ -142,8 +146,8 @@
break;
}
- std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(srcInfo.colorSpace(),
- dstInfo.colorSpace());
+ std::unique_ptr<SkColorSpaceXform> xform =
+ SkColorSpaceXform_Base::New(srcInfo.colorSpace(), dstInfo.colorSpace(), behavior);
SkASSERT(xform);
for (int y = 0; y < dstInfo.height(); y++) {
@@ -158,14 +162,14 @@
template <typename T>
void do_index8(const SkImageInfo& dstInfo, T* dstPixels, size_t dstRB,
const SkImageInfo& srcInfo, const uint8_t* srcPixels, size_t srcRB,
- SkColorTable* ctable) {
+ SkColorTable* ctable, SkTransferFunctionBehavior behavior) {
T dstCTable[256];
int count = ctable->count();
SkImageInfo srcInfo8888 = srcInfo.makeColorType(kN32_SkColorType).makeWH(count, 1);
SkImageInfo dstInfoCT = dstInfo.makeWH(count, 1);
size_t rowBytes = count * sizeof(T);
SkConvertPixels(dstInfoCT, dstCTable, rowBytes, srcInfo8888, ctable->readColors(), rowBytes,
- nullptr);
+ nullptr, behavior);
for (int y = 0; y < dstInfo.height(); y++) {
for (int x = 0; x < dstInfo.width(); x++) {
@@ -178,21 +182,25 @@
void convert_from_index8(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
const SkImageInfo& srcInfo, const uint8_t* srcPixels, size_t srcRB,
- SkColorTable* ctable) {
+ SkColorTable* ctable, SkTransferFunctionBehavior behavior) {
switch (dstInfo.colorType()) {
case kAlpha_8_SkColorType:
- do_index8(dstInfo, (uint8_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ do_index8(dstInfo, (uint8_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
+ behavior);
break;
case kRGB_565_SkColorType:
case kARGB_4444_SkColorType:
- do_index8(dstInfo, (uint16_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ do_index8(dstInfo, (uint16_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
+ behavior);
break;
case kRGBA_8888_SkColorType:
case kBGRA_8888_SkColorType:
- do_index8(dstInfo, (uint32_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ do_index8(dstInfo, (uint32_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
+ behavior);
break;
case kRGBA_F16_SkColorType:
- do_index8(dstInfo, (uint64_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable);
+ do_index8(dstInfo, (uint64_t*) dstPixels, dstRB, srcInfo, srcPixels, srcRB, ctable,
+ behavior);
break;
default:
SkASSERT(false);
@@ -267,7 +275,7 @@
// Default: Use the pipeline.
static void convert_with_pipeline(const SkImageInfo& dstInfo, void* dstRow, size_t dstRB,
const SkImageInfo& srcInfo, const void* srcRow, size_t srcRB,
- bool isColorAware) {
+ bool isColorAware, SkTransferFunctionBehavior behavior) {
SkRasterPipeline pipeline;
switch (srcInfo.colorType()) {
case kRGBA_8888_SkColorType:
@@ -294,6 +302,12 @@
break;
}
+ SkAlphaType premulState = srcInfo.alphaType();
+ if (kPremul_SkAlphaType == premulState && SkTransferFunctionBehavior::kIgnore == behavior) {
+ pipeline.append(SkRasterPipeline::unpremul);
+ premulState = kUnpremul_SkAlphaType;
+ }
+
if (isColorAware && srcInfo.gammaCloseToSRGB()) {
pipeline.append_from_srgb(srcInfo.alphaType());
}
@@ -304,18 +318,32 @@
dstInfo.colorSpace()));
}
- SkAlphaType sat = srcInfo.alphaType();
SkAlphaType dat = dstInfo.alphaType();
- if (sat == kPremul_SkAlphaType && dat == kUnpremul_SkAlphaType) {
- pipeline.append(SkRasterPipeline::unpremul);
- } else if (sat == kUnpremul_SkAlphaType && dat == kPremul_SkAlphaType) {
- pipeline.append(SkRasterPipeline::premul);
+ if (SkTransferFunctionBehavior::kRespect == behavior) {
+ if (kPremul_SkAlphaType == premulState && kUnpremul_SkAlphaType == dat) {
+ pipeline.append(SkRasterPipeline::unpremul);
+ premulState = kUnpremul_SkAlphaType;
+ } else if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat) {
+ pipeline.append(SkRasterPipeline::premul);
+ premulState = kPremul_SkAlphaType;
+ }
}
if (isColorAware && dstInfo.gammaCloseToSRGB()) {
pipeline.append(SkRasterPipeline::to_srgb);
}
+ if (kUnpremul_SkAlphaType == premulState && kPremul_SkAlphaType == dat &&
+ SkTransferFunctionBehavior::kIgnore == behavior)
+ {
+ pipeline.append(SkRasterPipeline::premul);
+ premulState = kPremul_SkAlphaType;
+ }
+
+ // The final premul state must equal the dst alpha type. Note that if we are "converting"
+ // opaque to another alpha type, there's no need to worry about multiplication.
+ SkASSERT(premulState == dat || kOpaque_SkAlphaType == srcInfo.alphaType());
+
switch (dstInfo.colorType()) {
case kRGBA_8888_SkColorType:
pipeline.append(SkRasterPipeline::store_8888, &dstRow);
@@ -349,7 +377,7 @@
void SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB,
const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRB,
- SkColorTable* ctable) {
+ SkColorTable* ctable, SkTransferFunctionBehavior behavior) {
SkASSERT(dstInfo.dimensions() == srcInfo.dimensions());
SkASSERT(SkImageInfoValidConversion(dstInfo, srcInfo));
@@ -369,8 +397,8 @@
}
// Fast Path 3: Color space xform.
- if (isColorAware && optimized_color_xform(dstInfo, srcInfo)) {
- apply_color_xform(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB);
+ if (isColorAware && optimized_color_xform(dstInfo, srcInfo, behavior)) {
+ apply_color_xform(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, behavior);
return;
}
@@ -378,7 +406,7 @@
if (kIndex_8_SkColorType == srcInfo.colorType()) {
SkASSERT(ctable);
convert_from_index8(dstInfo, dstPixels, dstRB, srcInfo, (const uint8_t*) srcPixels, srcRB,
- ctable);
+ ctable, behavior);
return;
}
@@ -389,5 +417,6 @@
}
// Default: Use the pipeline.
- convert_with_pipeline(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware);
+ convert_with_pipeline(dstInfo, dstPixels, dstRB, srcInfo, srcPixels, srcRB, isColorAware,
+ behavior);
}
diff --git a/src/core/SkConvertPixels.h b/src/core/SkConvertPixels.h
index aa641e5..c825d84 100644
--- a/src/core/SkConvertPixels.h
+++ b/src/core/SkConvertPixels.h
@@ -15,7 +15,7 @@
void SkConvertPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes,
- SkColorTable* srcCTable = nullptr);
+ SkColorTable* srcCTable, SkTransferFunctionBehavior behavior);
static inline void SkRectMemcpy(void* dst, size_t dstRB, const void* src, size_t srcRB,
size_t bytesPerRow, int rowCount) {
diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp
index 62dda16..7eac6c4 100644
--- a/src/core/SkPixmap.cpp
+++ b/src/core/SkPixmap.cpp
@@ -98,7 +98,7 @@
const void* srcPixels = this->addr(rec.fX, rec.fY);
const SkImageInfo srcInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height());
SkConvertPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels, this->rowBytes(),
- this->ctable());
+ this->ctable(), SkTransferFunctionBehavior::kRespect);
return true;
}
diff --git a/include/effects/SkGaussianEdgeShader.h b/src/effects/SkGaussianEdgeShader.h
similarity index 100%
rename from include/effects/SkGaussianEdgeShader.h
rename to src/effects/SkGaussianEdgeShader.h
diff --git a/src/image/SkImage_Raster.cpp b/src/image/SkImage_Raster.cpp
index 30262dd..547bdbf 100644
--- a/src/image/SkImage_Raster.cpp
+++ b/src/image/SkImage_Raster.cpp
@@ -374,7 +374,9 @@
src.setColorSpace(SkColorSpace::MakeSRGB());
}
- SkAssertResult(dst.writePixels(src));
+ // Use kIgnore for transfer function behavior. This is used by the SkColorSpaceXformCanvas,
+ // which wants to pre-xform the inputs but ignore the transfer function on blends.
+ SkAssertResult(dst.writePixels(src, 0, 0, SkTransferFunctionBehavior::kIgnore));
dst.setImmutable();
return SkImage::MakeFromBitmap(dst);
}
diff --git a/src/ports/SkGlobalInitialization_default.cpp b/src/ports/SkGlobalInitialization_default.cpp
index 97d3b67..df4dde3 100644
--- a/src/ports/SkGlobalInitialization_default.cpp
+++ b/src/ports/SkGlobalInitialization_default.cpp
@@ -23,8 +23,7 @@
#include "SkDisplacementMapEffect.h"
#include "SkDropShadowImageFilter.h"
#include "../../src/effects/SkEmbossMaskFilter.h"
-#include "SkGaussianEdgeShader.h"
-#include "SkRRectsGaussianEdgeMaskFilter.h"
+#include "../../src/effects/SkGaussianEdgeShader.h"
#include "SkGradientShader.h"
#include "SkHighContrastFilter.h"
#include "SkImageSource.h"
@@ -44,6 +43,7 @@
#include "SkPaintImageFilter.h"
#include "SkPerlinNoiseShader.h"
#include "SkPictureImageFilter.h"
+#include "SkRRectsGaussianEdgeMaskFilter.h"
#include "SkTableColorFilter.h"
#include "SkTileImageFilter.h"
#include "SkXfermodeImageFilter.h"