OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) | 2 * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) |
3 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. | 3 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 18 matching lines...) Expand all Loading... |
29 #include "platform/Length.h" | 29 #include "platform/Length.h" |
30 #include "platform/MIMETypeRegistry.h" | 30 #include "platform/MIMETypeRegistry.h" |
31 #include "platform/PlatformInstrumentation.h" | 31 #include "platform/PlatformInstrumentation.h" |
32 #include "platform/RuntimeEnabledFeatures.h" | 32 #include "platform/RuntimeEnabledFeatures.h" |
33 #include "platform/SharedBuffer.h" | 33 #include "platform/SharedBuffer.h" |
34 #include "platform/TraceEvent.h" | 34 #include "platform/TraceEvent.h" |
35 #include "platform/geometry/FloatPoint.h" | 35 #include "platform/geometry/FloatPoint.h" |
36 #include "platform/geometry/FloatRect.h" | 36 #include "platform/geometry/FloatRect.h" |
37 #include "platform/geometry/FloatSize.h" | 37 #include "platform/geometry/FloatSize.h" |
38 #include "platform/graphics/BitmapImage.h" | 38 #include "platform/graphics/BitmapImage.h" |
| 39 #include "platform/graphics/ColorSpaceFilter.h" |
| 40 #include "platform/graphics/ColorSpaceProfile.h" |
39 #include "platform/graphics/DeferredImageDecoder.h" | 41 #include "platform/graphics/DeferredImageDecoder.h" |
40 #include "platform/graphics/GraphicsContext.h" | 42 #include "platform/graphics/GraphicsContext.h" |
| 43 #include "platform/graphics/GraphicsScreen.h" |
41 #include "public/platform/Platform.h" | 44 #include "public/platform/Platform.h" |
42 #include "public/platform/WebData.h" | 45 #include "public/platform/WebData.h" |
43 #include "third_party/skia/include/core/SkCanvas.h" | 46 #include "third_party/skia/include/core/SkCanvas.h" |
44 #include "third_party/skia/include/core/SkImage.h" | 47 #include "third_party/skia/include/core/SkImage.h" |
45 #include "third_party/skia/include/core/SkPictureRecorder.h" | 48 #include "third_party/skia/include/core/SkPictureRecorder.h" |
46 #include "wtf/MainThread.h" | 49 #include "wtf/MainThread.h" |
47 #include "wtf/StdLibExtras.h" | 50 #include "wtf/StdLibExtras.h" |
48 | 51 |
49 #include <math.h> | 52 #include <math.h> |
50 | 53 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 ctxt.setImageInterpolationQuality(InterpolationLow); | 179 ctxt.setImageInterpolationQuality(InterpolationLow); |
177 drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect); | 180 drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect); |
178 ctxt.setImageInterpolationQuality(previousInterpolationQuality); | 181 ctxt.setImageInterpolationQuality(previousInterpolationQuality); |
179 } else { | 182 } else { |
180 drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect); | 183 drawPattern(ctxt, srcRect, tileScaleFactor, patternPhase, op, dstRect); |
181 } | 184 } |
182 | 185 |
183 startAnimation(); | 186 startAnimation(); |
184 } | 187 } |
185 | 188 |
186 namespace { | 189 static PassRefPtr<SkShader> createPatternShader(const SkImage* image, SkPaint* p
aint, const SkMatrix& shaderMatrix, const FloatSize& spacing) |
187 | |
188 PassRefPtr<SkShader> createPatternShader(const SkImage* image, const SkMatrix& s
haderMatrix, | |
189 const SkPaint& paint, const FloatSize& spacing) | |
190 { | 190 { |
191 if (spacing.isZero()) | 191 if (spacing.isZero()) |
192 return adoptRef(image->newShader(SkShader::kRepeat_TileMode, SkShader::k
Repeat_TileMode, &shaderMatrix)); | 192 return adoptRef(image->newShader(SkShader::kRepeat_TileMode, SkShader::k
Repeat_TileMode, &shaderMatrix)); |
193 | 193 |
194 // Arbitrary tiling is currently only supported for SkPictureShader - so we
use it instead | 194 // Arbitrary tiling is currently only supported for SkPictureShader so use i
t, instead |
195 // of a plain bitmap shader to implement spacing. | 195 // of a plain bitmap shader, to implement spacing (CSS background-repeat: sp
ace). |
196 const SkRect tileRect = SkRect::MakeWH( | 196 SkRect tileRect = SkRect::MakeWH(image->width() + spacing.width(), image->he
ight() + spacing.height()); |
197 image->width() + spacing.width(), | |
198 image->height() + spacing.height()); | |
199 | 197 |
200 SkPictureRecorder recorder; | 198 SkPictureRecorder recorder; |
201 SkCanvas* canvas = recorder.beginRecording(tileRect); | 199 SkCanvas* canvas = recorder.beginRecording(tileRect); |
202 canvas->drawImage(image, 0, 0, &paint); | 200 canvas->drawImage(image, 0, 0, paint); |
203 RefPtr<const SkPicture> picture = adoptRef(recorder.endRecordingAsPicture())
; | 201 RefPtr<const SkPicture> picture = adoptRef(recorder.endRecordingAsPicture())
; |
204 | 202 |
205 return adoptRef(SkShader::CreatePictureShader( | 203 // Remove any color filter from callers paint: it is applied when drawing th
e SkPicture |
206 picture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &
shaderMatrix, nullptr)); | 204 // shader so clearing it here prevents caller from applying the filter twice
. |
| 205 if (paint->getColorFilter()) |
| 206 paint->setColorFilter(nullptr); |
| 207 |
| 208 return adoptRef(SkShader::CreatePictureShader(picture.get(), SkShader::kRepe
at_TileMode, SkShader::kRepeat_TileMode, &shaderMatrix, nullptr)); |
207 } | 209 } |
208 | 210 |
209 } // anonymous namespace | 211 inline PassRefPtr<ColorSpaceProfile> sourceColorProfile(Image* image) |
| 212 { |
| 213 return image->isBitmapImage() ? toBitmapImage(image)->colorProfile() : nullp
tr; |
| 214 } |
210 | 215 |
211 void Image::drawPattern(GraphicsContext& context, const FloatRect& floatSrcRect,
const FloatSize& scale, | 216 void Image::drawPattern(GraphicsContext& context, const FloatRect& floatSrcRect,
const FloatSize& scale, |
212 const FloatPoint& phase, SkXfermode::Mode compositeOp, const FloatRect& dest
Rect, const FloatSize& repeatSpacing) | 217 const FloatPoint& phase, SkXfermode::Mode compositeOp, const FloatRect& dest
Rect, const FloatSize& repeatSpacing) |
213 { | 218 { |
214 TRACE_EVENT0("skia", "Image::drawPattern"); | 219 TRACE_EVENT0("skia", "Image::drawPattern"); |
215 | 220 |
216 RefPtr<SkImage> image = imageForCurrentFrame(); | 221 RefPtr<SkImage> image = imageForCurrentFrame(); |
217 if (!image) | 222 if (!image) |
218 return; | 223 return; |
219 | 224 |
220 FloatRect normSrcRect = floatSrcRect; | 225 FloatRect normSrcRect = floatSrcRect; |
221 | 226 |
222 normSrcRect.intersect(FloatRect(0, 0, image->width(), image->height())); | 227 normSrcRect.intersect(FloatRect(0, 0, image->width(), image->height())); |
223 if (destRect.isEmpty() || normSrcRect.isEmpty()) | 228 if (destRect.isEmpty() || normSrcRect.isEmpty()) |
224 return; // nothing to draw | 229 return; // nothing to draw |
225 | 230 |
226 SkMatrix localMatrix; | 231 SkMatrix localMatrix; |
227 // We also need to translate it such that the origin of the pattern is the | 232 // We also need to translate it such that the origin of the pattern is the |
228 // origin of the destination rect, which is what WebKit expects. Skia uses | 233 // origin of the destination rect, which is what WebKit expects. Skia uses |
229 // the coordinate system origin as the base for the pattern. If WebKit wants | 234 // the coordinate system origin as the base for the pattern. If WebKit wants |
230 // a shifted image, it will shift it from there using the localMatrix. | 235 // a shifted image, it will shift it from there using the localMatrix. |
231 const float adjustedX = phase.x() + normSrcRect.x() * scale.width(); | 236 const float adjustedX = phase.x() + normSrcRect.x() * scale.width(); |
232 const float adjustedY = phase.y() + normSrcRect.y() * scale.height(); | 237 const float adjustedY = phase.y() + normSrcRect.y() * scale.height(); |
233 localMatrix.setTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjuste
dY)); | 238 localMatrix.setTranslate(SkFloatToScalar(adjustedX), SkFloatToScalar(adjuste
dY)); |
234 | 239 |
235 // Because no resizing occurred, the shader transform should be | 240 // Because no resizing occurred, the shader transform should be |
236 // set to the pattern's transform, which just includes scale. | 241 // set to the pattern's transform, which just includes scale. |
237 localMatrix.preScale(scale.width(), scale.height()); | 242 localMatrix.preScale(scale.width(), scale.height()); |
238 | 243 |
239 // Fetch this now as subsetting may swap the image. | 244 // Fetch the image ID now since subsetting may swap the image. |
240 auto imageID = image->uniqueID(); | 245 auto imageID = image->uniqueID(); |
241 | |
242 image = adoptRef(image->newSubset(enclosingIntRect(normSrcRect))); | 246 image = adoptRef(image->newSubset(enclosingIntRect(normSrcRect))); |
243 if (!image) | 247 if (!image) |
244 return; | 248 return; |
245 | 249 |
246 { | 250 RefPtr<SkColorFilter> colorTransform; |
247 SkPaint paint = context.fillPaint(); | 251 if (RefPtr<ColorSpaceProfile> source = sourceColorProfile(this)) { |
248 paint.setColor(SK_ColorBLACK); | 252 // Tagged images (those that have a color profile) are drawn color-corre
ct on supported platforms. |
249 paint.setXfermodeMode(compositeOp); | 253 RefPtr<ColorSpaceProfile> target = screenColorProfile(currentScreenId())
; |
250 paint.setFilterQuality(context.computeFilterQuality(this, destRect, norm
SrcRect)); | 254 if (!context.colorFilter()) // http://crbug.com/542498 |
251 paint.setAntiAlias(context.shouldAntialias()); | 255 colorTransform = createColorSpaceFilter(source.get(), target.get()); |
252 RefPtr<SkShader> shader = createPatternShader(image.get(), localMatrix,
paint, | 256 RELEASE_ASSERT(currentScreenId()); |
253 FloatSize(repeatSpacing.width() / scale.width(), repeatSpacing.heigh
t() / scale.height())); | |
254 paint.setShader(shader.get()); | |
255 context.drawRect(destRect, paint); | |
256 } | 257 } |
257 | 258 |
| 259 SkPaint paint = context.fillPaint(); |
| 260 paint.setColor(SK_ColorBLACK); |
| 261 paint.setXfermodeMode(compositeOp); |
| 262 paint.setFilterQuality(context.computeFilterQuality(this, destRect, normSrcR
ect)); |
| 263 paint.setAntiAlias(context.shouldAntialias()); |
| 264 |
| 265 // BoxPainter background paint can set a luminance color filter on the conte
xt. Add it to the paint if |
| 266 // present: see layout test css3/masking/mask-luminance-png.html and http://
crbug.com/542498 |
| 267 if (context.colorFilter()) { |
| 268 fprintf(stderr, "Image::drawPattern color filter\n"); |
| 269 paint.setColorFilter(context.colorFilter()); |
| 270 fflush(stderr); |
| 271 } else if (colorTransform.get()) { |
| 272 fprintf(stderr, "Image::drawPattern color transform key [%s]\n", colorSp
aceFilterKey(colorTransform.get()).latin1().data()); |
| 273 paint.setColorFilter(colorTransform.get()); |
| 274 fflush(stderr); |
| 275 } |
| 276 |
| 277 FloatSize spacing = FloatSize(repeatSpacing.width() / scale.width(), repeatS
pacing.height() / scale.height()); |
| 278 RefPtr<SkShader> shader = createPatternShader(image.get(), &paint, localMatr
ix, spacing); |
| 279 paint.setShader(shader.get()); |
| 280 |
| 281 context.drawRect(destRect, paint); |
| 282 |
258 if (currentFrameIsLazyDecoded()) | 283 if (currentFrameIsLazyDecoded()) |
259 PlatformInstrumentation::didDrawLazyPixelRef(imageID); | 284 PlatformInstrumentation::didDrawLazyPixelRef(imageID); |
260 } | 285 } |
261 | 286 |
262 void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsic
Height, FloatSize& intrinsicRatio) | 287 void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsic
Height, FloatSize& intrinsicRatio) |
263 { | 288 { |
264 intrinsicRatio = FloatSize(size()); | 289 intrinsicRatio = FloatSize(size()); |
265 intrinsicWidth = Length(intrinsicRatio.width(), Fixed); | 290 intrinsicWidth = Length(intrinsicRatio.width(), Fixed); |
266 intrinsicHeight = Length(intrinsicRatio.height(), Fixed); | 291 intrinsicHeight = Length(intrinsicRatio.height(), Fixed); |
267 } | 292 } |
268 | 293 |
269 PassRefPtr<Image> Image::imageForDefaultFrame() | 294 PassRefPtr<Image> Image::imageForDefaultFrame() |
270 { | 295 { |
271 RefPtr<Image> image(this); | 296 RefPtr<Image> image(this); |
272 | 297 |
273 return image.release(); | 298 return image.release(); |
274 } | 299 } |
275 | 300 |
276 bool Image::isTextureBacked() | 301 bool Image::isTextureBacked() |
277 { | 302 { |
278 RefPtr<SkImage> image = imageForCurrentFrame(); | 303 RefPtr<SkImage> image = imageForCurrentFrame(); |
279 return image ? image->isTextureBacked() : false; | 304 return image ? image->isTextureBacked() : false; |
280 } | 305 } |
281 | 306 |
282 } // namespace blink | 307 } // namespace blink |
OLD | NEW |