aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkBitmap.h3
-rw-r--r--samplecode/SampleDitherBitmap.cpp27
-rw-r--r--src/core/SkBitmap.cpp2
-rw-r--r--src/core/SkBitmapProcShader.cpp18
-rw-r--r--src/core/SkBlitter.cpp14
-rw-r--r--src/core/SkColorTable.cpp8
-rw-r--r--tests/BitmapCopyTest.cpp52
-rw-r--r--xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj8
8 files changed, 110 insertions, 22 deletions
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 3c04a310a9..1c16b780e2 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -508,6 +508,9 @@ public:
*/
void setFlags(unsigned flags);
+ bool isOpaque() const { return (fFlags & kColorsAreOpaque_Flag) != 0; }
+ void setIsOpaque(bool isOpaque);
+
/** Returns the number of colors in the table.
*/
int count() const { return fCount; }
diff --git a/samplecode/SampleDitherBitmap.cpp b/samplecode/SampleDitherBitmap.cpp
index bd604cf84c..35816a213a 100644
--- a/samplecode/SampleDitherBitmap.cpp
+++ b/samplecode/SampleDitherBitmap.cpp
@@ -10,7 +10,7 @@ static SkBitmap make_bitmap() {
SkPMColor* c = ctable->lockColors();
for (int i = 0; i < 256; i++) {
- c[i] = SkPackARGB32(0xFF, 0, 0, i);
+ c[i] = SkPackARGB32(0xFF, i, 0, 0);
}
ctable->unlockColors(true);
bm.setConfig(SkBitmap::kIndex8_Config, 256, 32);
@@ -51,12 +51,31 @@ protected:
canvas->drawColor(0xFFDDDDDD);
}
+ static void setBitmapOpaque(SkBitmap* bm, bool isOpaque) {
+ SkAutoLockPixels alp(*bm); // needed for ctable
+ bm->setIsOpaque(isOpaque);
+ SkColorTable* ctable = bm->getColorTable();
+ if (ctable) {
+ ctable->setIsOpaque(isOpaque);
+ }
+ }
+
static void draw2(SkCanvas* canvas, const SkBitmap& bm) {
SkPaint paint;
-
- canvas->drawBitmap(bm, 0, 0, &paint);
+ SkBitmap bitmap(bm);
+
+ setBitmapOpaque(&bitmap, false);
+ paint.setDither(false);
+ canvas->drawBitmap(bitmap, 0, 0, &paint);
+ paint.setDither(true);
+ canvas->drawBitmap(bitmap, 0, SkIntToScalar(bm.height() + 10), &paint);
+
+ setBitmapOpaque(&bitmap, true);
+ SkScalar x = SkIntToScalar(bm.width() + 10);
+ paint.setDither(false);
+ canvas->drawBitmap(bitmap, x, 0, &paint);
paint.setDither(true);
- canvas->drawBitmap(bm, 0, SkIntToScalar(bm.height() + 10), &paint);
+ canvas->drawBitmap(bitmap, x, SkIntToScalar(bm.height() + 10), &paint);
}
virtual void onDraw(SkCanvas* canvas) {
diff --git a/src/core/SkBitmap.cpp b/src/core/SkBitmap.cpp
index d87f001ed8..9478faef52 100644
--- a/src/core/SkBitmap.cpp
+++ b/src/core/SkBitmap.cpp
@@ -793,6 +793,8 @@ bool SkBitmap::copyTo(SkBitmap* dst, Config dstConfig, Allocator* alloc) const {
canvas.drawBitmap(*this, 0, 0, &paint);
}
+ tmp.setIsOpaque(this->isOpaque());
+
dst->swap(tmp);
return true;
}
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 7eb8ea148b..353388b74c 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -102,19 +102,19 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
}
// update fFlags
- fFlags = 0;
+ uint32_t flags = 0;
if (bitmapIsOpaque && (255 == this->getPaintAlpha())) {
- fFlags |= kOpaqueAlpha_Flag;
+ flags |= kOpaqueAlpha_Flag;
}
switch (fState.fBitmap->config()) {
case SkBitmap::kRGB_565_Config:
- fFlags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
+ flags |= (kHasSpan16_Flag | kIntrinsicly16_Flag);
break;
case SkBitmap::kIndex8_Config:
case SkBitmap::kARGB_8888_Config:
if (bitmapIsOpaque) {
- fFlags |= kHasSpan16_Flag;
+ flags |= kHasSpan16_Flag;
}
break;
case SkBitmap::kA8_Config:
@@ -123,11 +123,19 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
break;
}
+ if (paint.isDither()) {
+ // gradients can auto-dither in their 16bit sampler, but we don't so
+ // we clear the flag here
+ flags &= ~kHasSpan16_Flag;
+ }
+
// if we're only 1-pixel heigh, and we don't rotate, then we can claim this
if (1 == fState.fBitmap->height() &&
only_scale_and_translate(this->getTotalInverse())) {
- fFlags |= kConstInY_Flag;
+ flags |= kConstInY_Flag;
}
+
+ fFlags = flags;
return true;
}
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index faf29c1712..e60887e588 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -896,16 +896,8 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
((SkPaint*)&paint)->setShader(shader)->unref();
}
- bool doDither = paint.isDither();
-
- if (shader)
- {
- if (!shader->setContext(device, paint, matrix))
- return SkNEW(SkNullBlitter);
-
- // disable dither if our shader is natively 16bit (no need to upsample)
- if (shader->getFlags() & SkShader::kIntrinsicly16_Flag)
- doDither = false;
+ if (shader && !shader->setContext(device, paint, matrix)) {
+ return SkNEW(SkNullBlitter);
}
switch (device.getConfig()) {
@@ -929,7 +921,7 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
{
if (mode)
SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Xfermode_Blitter, storage, storageSize, (device, paint));
- else if (SkShader::CanCallShadeSpan16(shader->getFlags()) && !doDither)
+ else if (shader->canCallShadeSpan16())
SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader16_Blitter, storage, storageSize, (device, paint));
else
SK_PLACEMENT_NEW_ARGS(blitter, SkRGB16_Shader_Blitter, storage, storageSize, (device, paint));
diff --git a/src/core/SkColorTable.cpp b/src/core/SkColorTable.cpp
index 41e6895fff..308287c1ea 100644
--- a/src/core/SkColorTable.cpp
+++ b/src/core/SkColorTable.cpp
@@ -132,6 +132,14 @@ const uint16_t* SkColorTable::lock16BitCache()
return f16BitCache;
}
+void SkColorTable::setIsOpaque(bool isOpaque) {
+ if (isOpaque) {
+ fFlags |= kColorsAreOpaque_Flag;
+ } else {
+ fFlags &= ~kColorsAreOpaque_Flag;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
diff --git a/tests/BitmapCopyTest.cpp b/tests/BitmapCopyTest.cpp
index e54cde3319..2ae7b0af50 100644
--- a/tests/BitmapCopyTest.cpp
+++ b/tests/BitmapCopyTest.cpp
@@ -11,6 +11,57 @@ static const char* gConfigName[] = {
"None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
};
+static void report_opaqueness(skiatest::Reporter* reporter, const SkBitmap& src,
+ const SkBitmap& dst) {
+ SkString str;
+ str.printf("src %s opaque:%d, dst %s opaque:%d",
+ gConfigName[src.config()], src.isOpaque(),
+ gConfigName[dst.config()], dst.isOpaque());
+ reporter->reportFailed(str);
+}
+
+static bool canHaveAlpha(SkBitmap::Config config) {
+ return config != SkBitmap::kRGB_565_Config;
+}
+
+// copyTo() should preserve isOpaque when it makes sense
+static void test_isOpaque(skiatest::Reporter* reporter, const SkBitmap& src,
+ SkBitmap::Config dstConfig) {
+ SkBitmap bitmap(src);
+ SkBitmap dst;
+
+ // we need the lock so that we get a valid colorTable (when available)
+ SkAutoLockPixels alp(bitmap);
+ SkColorTable* ctable = bitmap.getColorTable();
+ unsigned ctableFlags = ctable ? ctable->getFlags() : 0;
+
+ if (canHaveAlpha(bitmap.config()) && canHaveAlpha(dstConfig)) {
+ bitmap.setIsOpaque(false);
+ if (ctable) {
+ ctable->setFlags(ctableFlags & ~SkColorTable::kColorsAreOpaque_Flag);
+ }
+ REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig));
+ REPORTER_ASSERT(reporter, dst.config() == dstConfig);
+ if (bitmap.isOpaque() != dst.isOpaque()) {
+ report_opaqueness(reporter, bitmap, dst);
+ }
+ }
+
+ bitmap.setIsOpaque(true);
+ if (ctable) {
+ ctable->setFlags(ctableFlags | SkColorTable::kColorsAreOpaque_Flag);
+ }
+ REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig));
+ REPORTER_ASSERT(reporter, dst.config() == dstConfig);
+ if (bitmap.isOpaque() != dst.isOpaque()) {
+ report_opaqueness(reporter, bitmap, dst);
+ }
+
+ if (ctable) {
+ ctable->setFlags(ctableFlags);
+ }
+}
+
static void init_src(const SkBitmap& bitmap) {
SkAutoLockPixels lock(bitmap);
if (bitmap.getPixels()) {
@@ -83,6 +134,7 @@ static void TestBitmapCopy(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, src.width() == dst.width());
REPORTER_ASSERT(reporter, src.height() == dst.height());
REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig);
+ test_isOpaque(reporter, src, dst.config());
if (src.config() == dst.config()) {
SkAutoLockPixels srcLock(src);
SkAutoLockPixels dstLock(dst);
diff --git a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
index 654f361795..3edf0e461f 100644
--- a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
+++ b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
@@ -47,7 +47,6 @@
0057785F0FF17CCC00582CD9 /* SampleMipMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2794C04E0FE72903009AD112 /* SampleMipMap.cpp */; };
005778B40FF5616F00582CD9 /* SampleShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 003145310FB9B48F00B10956 /* SampleShapes.cpp */; };
005E92DC0FF08507008965B9 /* SampleFilter2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0041CE290F00A12400695E8C /* SampleFilter2.cpp */; };
- 005E92DE0FF0850E008965B9 /* SampleFillType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0041CE270F00A12400695E8C /* SampleFillType.cpp */; };
005E92E00FF08512008965B9 /* SampleFilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0041CE280F00A12400695E8C /* SampleFilter.cpp */; };
007A7CB30F01658C00A2D6EE /* SamplePicture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CA40F01658C00A2D6EE /* SamplePicture.cpp */; };
007A7CB40F01658C00A2D6EE /* SamplePoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CA50F01658C00A2D6EE /* SamplePoints.cpp */; };
@@ -71,6 +70,8 @@
00A7295D0FD8397600D5051F /* SampleAll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F6740FCCCB01002BD8B4 /* SampleAll.cpp */; };
00AF77B00FE2EA2D007F9650 /* SampleTestGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A729630FD93ED600D5051F /* SampleTestGL.cpp */; };
00AF787E0FE94433007F9650 /* SamplePath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00003C640EFC22A8000FF73A /* SamplePath.cpp */; };
+ 00AF9B18103CD5EB00CBBCB3 /* SampleDitherBitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00AF9B17103CD5EB00CBBCB3 /* SampleDitherBitmap.cpp */; };
+ 00C1B809103857A400FA5948 /* SampleFillType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0041CE270F00A12400695E8C /* SampleFillType.cpp */; };
00F53F480FFCFC4D003FA70A /* SampleGradients.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00C55DA00F8552DC000CAC09 /* SampleGradients.cpp */; };
00FF39140FC6ED2C00915187 /* SampleEffects.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FF39130FC6ED2C00915187 /* SampleEffects.cpp */; };
0156F80407C56A3000C6122B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0156F80307C56A3000C6122B /* Foundation.framework */; };
@@ -197,6 +198,7 @@
00A7282D0FD43D3700D5051F /* SkMovie.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkMovie.cpp; path = ../../src/images/SkMovie.cpp; sourceTree = SOURCE_ROOT; };
00A7282E0FD43D3700D5051F /* SkMovie_gif.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkMovie_gif.cpp; path = ../../src/images/SkMovie_gif.cpp; sourceTree = SOURCE_ROOT; };
00A729630FD93ED600D5051F /* SampleTestGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTestGL.cpp; path = ../../samplecode/SampleTestGL.cpp; sourceTree = SOURCE_ROOT; };
+ 00AF9B17103CD5EB00CBBCB3 /* SampleDitherBitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleDitherBitmap.cpp; path = ../../samplecode/SampleDitherBitmap.cpp; sourceTree = SOURCE_ROOT; };
00C55DA00F8552DC000CAC09 /* SampleGradients.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleGradients.cpp; path = ../../samplecode/SampleGradients.cpp; sourceTree = SOURCE_ROOT; };
00D6B5CB0F72DC4300C466B9 /* SampleFuzz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFuzz.cpp; path = ../../samplecode/SampleFuzz.cpp; sourceTree = SOURCE_ROOT; };
00FF39130FC6ED2C00915187 /* SampleEffects.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleEffects.cpp; path = ../../samplecode/SampleEffects.cpp; sourceTree = SOURCE_ROOT; };
@@ -277,6 +279,7 @@
0041CE250F00A12400695E8C /* SampleEmboss.cpp */,
0041CE260F00A12400695E8C /* SampleEncode.cpp */,
0041CE270F00A12400695E8C /* SampleFillType.cpp */,
+ 00AF9B17103CD5EB00CBBCB3 /* SampleDitherBitmap.cpp */,
0041CE280F00A12400695E8C /* SampleFilter.cpp */,
0041CE290F00A12400695E8C /* SampleFilter2.cpp */,
0041CE2A0F00A12400695E8C /* SampleFontCache.cpp */,
@@ -568,13 +571,14 @@
00AF787E0FE94433007F9650 /* SamplePath.cpp in Sources */,
0088C1160FEC311C00CE52F5 /* SampleXfermodes.cpp in Sources */,
005E92DC0FF08507008965B9 /* SampleFilter2.cpp in Sources */,
- 005E92DE0FF0850E008965B9 /* SampleFillType.cpp in Sources */,
005E92E00FF08512008965B9 /* SampleFilter.cpp in Sources */,
0057785F0FF17CCC00582CD9 /* SampleMipMap.cpp in Sources */,
005778B40FF5616F00582CD9 /* SampleShapes.cpp in Sources */,
00F53F480FFCFC4D003FA70A /* SampleGradients.cpp in Sources */,
27005D16100903C100E275B6 /* SampleLines.cpp in Sources */,
27005D5F10095B2B00E275B6 /* SampleCircle.cpp in Sources */,
+ 00C1B809103857A400FA5948 /* SampleFillType.cpp in Sources */,
+ 00AF9B18103CD5EB00CBBCB3 /* SampleDitherBitmap.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};