Index: third_party/WebKit/Source/platform/graphics/Image.cpp |
diff --git a/third_party/WebKit/Source/platform/graphics/Image.cpp b/third_party/WebKit/Source/platform/graphics/Image.cpp |
index e06cf388b158dacdb761e8cd8c8d2473160bf96d..020d270c4bd7b6d94ee4d162228212bb8b19fd09 100644 |
--- a/third_party/WebKit/Source/platform/graphics/Image.cpp |
+++ b/third_party/WebKit/Source/platform/graphics/Image.cpp |
@@ -37,8 +37,11 @@ |
#include "platform/geometry/FloatRect.h" |
#include "platform/geometry/FloatSize.h" |
#include "platform/graphics/BitmapImage.h" |
+#include "platform/graphics/ColorSpaceFilter.h" |
+#include "platform/graphics/ColorSpaceProfile.h" |
#include "platform/graphics/DeferredImageDecoder.h" |
#include "platform/graphics/GraphicsContext.h" |
+#include "platform/graphics/GraphicsScreen.h" |
#include "public/platform/Platform.h" |
#include "public/platform/WebData.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
@@ -184,30 +187,32 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const Flo |
startAnimation(); |
} |
-namespace { |
- |
-PassRefPtr<SkShader> createPatternShader(const SkImage* image, const SkMatrix& shaderMatrix, |
- const SkPaint& paint, const FloatSize& spacing) |
+static PassRefPtr<SkShader> createPatternShader(const SkImage* image, SkPaint* paint, const SkMatrix& shaderMatrix, const FloatSize& spacing) |
{ |
if (spacing.isZero()) |
return adoptRef(image->newShader(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &shaderMatrix)); |
- // Arbitrary tiling is currently only supported for SkPictureShader - so we use it instead |
- // of a plain bitmap shader to implement spacing. |
- const SkRect tileRect = SkRect::MakeWH( |
- image->width() + spacing.width(), |
- image->height() + spacing.height()); |
+ // Arbitrary tiling is currently only supported for SkPictureShader so use it, instead |
+ // of a plain bitmap shader, to implement spacing (CSS background-repeat: space). |
+ SkRect tileRect = SkRect::MakeWH(image->width() + spacing.width(), image->height() + spacing.height()); |
SkPictureRecorder recorder; |
SkCanvas* canvas = recorder.beginRecording(tileRect); |
- canvas->drawImage(image, 0, 0, &paint); |
+ canvas->drawImage(image, 0, 0, paint); |
RefPtr<const SkPicture> picture = adoptRef(recorder.endRecordingAsPicture()); |
- return adoptRef(SkShader::CreatePictureShader( |
- picture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &shaderMatrix, nullptr)); |
+ // Remove any color filter from callers paint: it is applied when drawing the SkPicture |
+ // shader so clearing it here prevents caller from applying the filter twice. |
+ if (paint->getColorFilter()) |
+ paint->setColorFilter(nullptr); |
+ |
+ return adoptRef(SkShader::CreatePictureShader(picture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &shaderMatrix, nullptr)); |
} |
-} // anonymous namespace |
+inline PassRefPtr<ColorSpaceProfile> sourceColorProfile(Image* image) |
+{ |
+ return image->isBitmapImage() ? toBitmapImage(image)->colorProfile() : nullptr; |
+} |
void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, const FloatSize& scale, |
const FloatPoint& phase, SkXfermode::Mode compositeOp, const FloatRect& destRect, const IntSize& repeatSpacing) |
@@ -244,18 +249,45 @@ void Image::drawPattern(GraphicsContext* context, const FloatRect& floatSrcRect, |
if (!image) |
return; |
- { |
- SkPaint paint = context->fillPaint(); |
- paint.setColor(SK_ColorBLACK); |
- paint.setXfermodeMode(compositeOp); |
- paint.setFilterQuality(context->computeFilterQuality(this, destRect, normSrcRect)); |
- paint.setAntiAlias(context->shouldAntialias()); |
- RefPtr<SkShader> shader = createPatternShader(image.get(), localMatrix, paint, |
- FloatSize(repeatSpacing.width() / scale.width(), repeatSpacing.height() / scale.height())); |
- paint.setShader(shader.get()); |
- context->drawRect(destRect, paint); |
+ RefPtr<SkColorFilter> colorTransform; |
+ if (RefPtr<ColorSpaceProfile> source = sourceColorProfile(this)) { |
+ // Tagged images (those that have a color profile) are drawn color-correct on supported platforms. |
+ RefPtr<ColorSpaceProfile> screen = screenColorProfile(currentScreenId()); |
+ if (!context->colorFilter()) // http://crbug.com/542498 |
+ colorTransform = createColorSpaceFilter(source.get(), screen.get()); |
+ RELEASE_ASSERT(currentScreenId()); |
+ } else { |
+ // For sRGB assumed images: easy, just interpolate the sRGB color profile here as the src profile? |
+ // FIXME: untagged images should be drawn from sRGB color space, per CSS2.1 onwards, a change that |
+ // would also require that all CSS content, including <canvas>, be drawn from sRGB space to match, |
+ // and the same for plugins (Flash, NaCl) which don't define their color space at all, <video> and |
+ // OOPIF, and so on ... |
} |
+ SkPaint paint = context->fillPaint(); |
+ paint.setColor(SK_ColorBLACK); |
+ paint.setXfermodeMode(compositeOp); |
+ paint.setFilterQuality(context->computeFilterQuality(this, destRect, normSrcRect)); |
+ paint.setAntiAlias(context->shouldAntialias()); |
+ |
+ // BoxPainter background paint can set a luminance color filter on the context. Add it to the paint if |
+ // present: see layout test css3/masking/mask-luminance-png.html and http://crbug.com/542498 |
+ if (context->colorFilter()) { |
+ fprintf(stderr, "Image::drawPattern color filter\n"); |
+ paint.setColorFilter(context->colorFilter()); |
+ fflush(stderr); |
+ } else if (colorTransform.get()) { |
+ fprintf(stderr, "Image::drawPattern color transform key [%s]\n", colorSpaceFilterKey(colorTransform.get()).latin1().data()); |
+ paint.setColorFilter(colorTransform.get()); |
+ fflush(stderr); |
+ } |
+ |
+ FloatSize spacing = FloatSize(repeatSpacing.width() / scale.width(), repeatSpacing.height() / scale.height()); |
+ RefPtr<SkShader> shader = createPatternShader(image.get(), &paint, localMatrix, spacing); |
+ paint.setShader(shader.get()); |
+ |
+ context->drawRect(destRect, paint); |
+ |
if (currentFrameIsLazyDecoded()) |
PlatformInstrumentation::didDrawLazyPixelRef(imageID); |
} |