| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006 Eric Seidel <eric@webkit.org> | 2 * Copyright (C) 2006 Eric Seidel <eric@webkit.org> |
| 3 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. | 3 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. |
| 4 * Copyright (C) Research In Motion Limited 2011. All rights reserved. | 4 * Copyright (C) Research In Motion Limited 2011. All rights reserved. |
| 5 * | 5 * |
| 6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
| 8 * are met: | 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 #include "platform/TraceEvent.h" | 52 #include "platform/TraceEvent.h" |
| 53 #include "platform/geometry/IntRect.h" | 53 #include "platform/geometry/IntRect.h" |
| 54 #include "platform/graphics/GraphicsContext.h" | 54 #include "platform/graphics/GraphicsContext.h" |
| 55 #include "platform/graphics/ImageBuffer.h" | 55 #include "platform/graphics/ImageBuffer.h" |
| 56 #include "platform/graphics/ImageObserver.h" | 56 #include "platform/graphics/ImageObserver.h" |
| 57 #include "platform/graphics/paint/ClipRecorder.h" | 57 #include "platform/graphics/paint/ClipRecorder.h" |
| 58 #include "platform/graphics/paint/DisplayItemListContextRecorder.h" | 58 #include "platform/graphics/paint/DisplayItemListContextRecorder.h" |
| 59 #include "platform/graphics/paint/DrawingRecorder.h" | 59 #include "platform/graphics/paint/DrawingRecorder.h" |
| 60 #include "platform/graphics/paint/SkPictureBuilder.h" | 60 #include "platform/graphics/paint/SkPictureBuilder.h" |
| 61 #include "third_party/skia/include/core/SkPicture.h" | 61 #include "third_party/skia/include/core/SkPicture.h" |
| 62 #include "wtf/Optional.h" | |
| 63 #include "wtf/PassRefPtr.h" | 62 #include "wtf/PassRefPtr.h" |
| 64 | 63 |
| 65 namespace blink { | 64 namespace blink { |
| 66 | 65 |
| 67 SVGImage::SVGImage(ImageObserver* observer) | 66 SVGImage::SVGImage(ImageObserver* observer) |
| 68 : Image(observer) | 67 : Image(observer) |
| 69 { | 68 { |
| 70 } | 69 } |
| 71 | 70 |
| 72 SVGImage::~SVGImage() | 71 SVGImage::~SVGImage() |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 if (intrinsicSize.isEmpty()) | 186 if (intrinsicSize.isEmpty()) |
| 188 intrinsicSize = rootElement->currentViewBoxRect().size(); | 187 intrinsicSize = rootElement->currentViewBoxRect().size(); |
| 189 | 188 |
| 190 if (!intrinsicSize.isEmpty()) | 189 if (!intrinsicSize.isEmpty()) |
| 191 return expandedIntSize(intrinsicSize); | 190 return expandedIntSize(intrinsicSize); |
| 192 | 191 |
| 193 // As last resort, use CSS replaced element fallback size. | 192 // As last resort, use CSS replaced element fallback size. |
| 194 return IntSize(300, 150); | 193 return IntSize(300, 150); |
| 195 } | 194 } |
| 196 | 195 |
| 197 void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize contai
nerSize, float zoom, const FloatRect& dstRect, | 196 void SVGImage::drawForContainer(SkCanvas* canvas, const SkPaint& paint, const Fl
oatSize containerSize, float zoom, const FloatRect& dstRect, |
| 198 const FloatRect& srcRect, SkXfermode::Mode compositeOp) | 197 const FloatRect& srcRect) |
| 199 { | 198 { |
| 200 if (!m_page) | 199 if (!m_page) |
| 201 return; | 200 return; |
| 202 | 201 |
| 203 // Temporarily disable the image observer to prevent changeInRect() calls du
e re-laying out the image. | 202 // Temporarily disable the image observer to prevent changeInRect() calls du
e re-laying out the image. |
| 204 ImageObserverDisabler imageObserverDisabler(this); | 203 ImageObserverDisabler imageObserverDisabler(this); |
| 205 | 204 |
| 206 IntSize roundedContainerSize = roundedIntSize(containerSize); | 205 IntSize roundedContainerSize = roundedIntSize(containerSize); |
| 207 setContainerSize(roundedContainerSize); | 206 setContainerSize(roundedContainerSize); |
| 208 | 207 |
| 209 FloatRect scaledSrc = srcRect; | 208 FloatRect scaledSrc = srcRect; |
| 210 scaledSrc.scale(1 / zoom); | 209 scaledSrc.scale(1 / zoom); |
| 211 | 210 |
| 212 // Compensate for the container size rounding by adjusting the source rect. | 211 // Compensate for the container size rounding by adjusting the source rect. |
| 213 FloatSize adjustedSrcSize = scaledSrc.size(); | 212 FloatSize adjustedSrcSize = scaledSrc.size(); |
| 214 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(),
roundedContainerSize.height() / containerSize.height()); | 213 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(),
roundedContainerSize.height() / containerSize.height()); |
| 215 scaledSrc.setSize(adjustedSrcSize); | 214 scaledSrc.setSize(adjustedSrcSize); |
| 216 | 215 |
| 217 draw(context, dstRect, scaledSrc, compositeOp, DoNotRespectImageOrientation)
; | 216 draw(canvas, paint, dstRect, scaledSrc, DoNotRespectImageOrientation, ClampI
mageToSourceRect); |
| 218 } | 217 } |
| 219 | 218 |
| 220 bool SVGImage::bitmapForCurrentFrame(SkBitmap* bitmap) | 219 bool SVGImage::bitmapForCurrentFrame(SkBitmap* bitmap) |
| 221 { | 220 { |
| 222 if (!m_page) | 221 if (!m_page) |
| 223 return false; | 222 return false; |
| 224 | 223 |
| 225 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size()); | 224 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size()); |
| 226 if (!buffer) | 225 if (!buffer) |
| 227 return false; | 226 return false; |
| 228 | 227 |
| 229 drawForContainer(buffer->context(), size(), 1, rect(), rect(), SkXfermode::k
SrcOver_Mode); | 228 SkPaint paint; |
| 229 drawForContainer(buffer->canvas(), paint, size(), 1, rect(), rect()); |
| 230 | 230 |
| 231 *bitmap = buffer->bitmap(); | 231 *bitmap = buffer->bitmap(); |
| 232 return true; | 232 return true; |
| 233 } | 233 } |
| 234 | 234 |
| 235 void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize
containerSize, | 235 void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize
containerSize, |
| 236 float zoom, const FloatRect& srcRect, const FloatSize& tileScale, const Floa
tPoint& phase, | 236 float zoom, const FloatRect& srcRect, const FloatSize& tileScale, const Floa
tPoint& phase, |
| 237 SkXfermode::Mode compositeOp, const FloatRect& dstRect, | 237 SkXfermode::Mode compositeOp, const FloatRect& dstRect, |
| 238 const IntSize& repeatSpacing) | 238 const IntSize& repeatSpacing) |
| 239 { | 239 { |
| 240 // Tile adjusted for scaling/stretch. | 240 // Tile adjusted for scaling/stretch. |
| 241 FloatRect tile(srcRect); | 241 FloatRect tile(srcRect); |
| 242 tile.scale(tileScale.width(), tileScale.height()); | 242 tile.scale(tileScale.width(), tileScale.height()); |
| 243 | 243 |
| 244 // Expand the tile to account for repeat spacing. | 244 // Expand the tile to account for repeat spacing. |
| 245 FloatRect spacedTile(tile); | 245 FloatRect spacedTile(tile); |
| 246 spacedTile.expand(repeatSpacing); | 246 spacedTile.expand(repeatSpacing); |
| 247 | 247 |
| 248 SkPictureBuilder patternPicture(spacedTile); | 248 SkPictureBuilder patternPicture(spacedTile); |
| 249 { | 249 { |
| 250 DrawingRecorder patternPictureRecorder(patternPicture.context(), *this,
DisplayItem::Type::SVGImage, spacedTile); | 250 DrawingRecorder patternPictureRecorder(patternPicture.context(), *this,
DisplayItem::Type::SVGImage, spacedTile); |
| 251 if (!patternPictureRecorder.canUseCachedDrawing()) { | 251 if (!patternPictureRecorder.canUseCachedDrawing()) { |
| 252 // When generating an expanded tile, make sure we don't draw into th
e spacing area. | 252 // When generating an expanded tile, make sure we don't draw into th
e spacing area. |
| 253 if (tile != spacedTile) | 253 if (tile != spacedTile) |
| 254 patternPicture.context().clip(tile); | 254 patternPicture.context().clip(tile); |
| 255 drawForContainer(&patternPicture.context(), containerSize, zoom, til
e, srcRect, SkXfermode::kSrcOver_Mode); | 255 SkPaint paint; |
| 256 drawForContainer(patternPicture.context().canvas(), paint, container
Size, zoom, tile, srcRect); |
| 256 } | 257 } |
| 257 } | 258 } |
| 258 RefPtr<const SkPicture> tilePicture = patternPicture.endRecording(); | 259 RefPtr<const SkPicture> tilePicture = patternPicture.endRecording(); |
| 259 | 260 |
| 260 SkMatrix patternTransform; | 261 SkMatrix patternTransform; |
| 261 patternTransform.setTranslate(phase.x() + spacedTile.x(), phase.y() + spaced
Tile.y()); | 262 patternTransform.setTranslate(phase.x() + spacedTile.x(), phase.y() + spaced
Tile.y()); |
| 262 RefPtr<SkShader> patternShader = adoptRef(SkShader::CreatePictureShader( | 263 RefPtr<SkShader> patternShader = adoptRef(SkShader::CreatePictureShader( |
| 263 tilePicture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMod
e, | 264 tilePicture.get(), SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMod
e, |
| 264 &patternTransform, nullptr)); | 265 &patternTransform, nullptr)); |
| 265 | 266 |
| 266 SkPaint paint; | 267 SkPaint paint; |
| 267 paint.setShader(patternShader.get()); | 268 paint.setShader(patternShader.get()); |
| 268 paint.setXfermodeMode(compositeOp); | 269 paint.setXfermodeMode(compositeOp); |
| 269 paint.setColorFilter(context->colorFilter()); | 270 paint.setColorFilter(context->colorFilter()); |
| 270 context->drawRect(dstRect, paint); | 271 context->drawRect(dstRect, paint); |
| 271 } | 272 } |
| 272 | 273 |
| 273 void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const Fl
oatRect& srcRect, SkXfermode::Mode compositeOp, RespectImageOrientationEnum) | 274 static bool drawNeedsLayer(const SkPaint& paint) |
| 275 { |
| 276 if (SkColorGetA(paint.getColor()) < 255) |
| 277 return true; |
| 278 |
| 279 SkXfermode::Mode xfermode; |
| 280 if (SkXfermode::AsMode(paint.getXfermode(), &xfermode)) { |
| 281 if (xfermode != SkXfermode::kSrcOver_Mode) |
| 282 return true; |
| 283 } |
| 284 |
| 285 return false; |
| 286 } |
| 287 |
| 288 void SVGImage::draw(SkCanvas* canvas, const SkPaint& paint, const FloatRect& dst
Rect, const FloatRect& srcRect, RespectImageOrientationEnum, ImageClampingMode) |
| 274 { | 289 { |
| 275 if (!m_page) | 290 if (!m_page) |
| 276 return; | 291 return; |
| 277 | 292 |
| 278 float opacity = context->getNormalizedAlpha() / 255.f; | |
| 279 | |
| 280 FrameView* view = frameView(); | 293 FrameView* view = frameView(); |
| 281 view->resize(containerSize()); | 294 view->resize(containerSize()); |
| 282 | 295 |
| 283 // Always call scrollToFragment, even if the url is empty, because | 296 // Always call scrollToFragment, even if the url is empty, because |
| 284 // there may have been a previous url/fragment that needs to be reset. | 297 // there may have been a previous url/fragment that needs to be reset. |
| 285 view->scrollToFragment(m_url); | 298 view->scrollToFragment(m_url); |
| 286 | 299 |
| 300 SkPictureBuilder imagePicture(dstRect); |
| 287 { | 301 { |
| 288 DisplayItemListContextRecorder contextRecorder(*context); | 302 ClipRecorder clipRecorder(imagePicture.context(), *this, DisplayItem::Cl
ipNodeImage, LayoutRect(enclosingIntRect(dstRect))); |
| 289 GraphicsContext& paintContext = contextRecorder.context(); | |
| 290 | |
| 291 ClipRecorder clipRecorder(paintContext, *this, DisplayItem::ClipNodeImag
e, LayoutRect(enclosingIntRect(dstRect))); | |
| 292 | |
| 293 bool hasCompositing = compositeOp != SkXfermode::kSrcOver_Mode; | |
| 294 Optional<CompositingRecorder> compositingRecorder; | |
| 295 if (hasCompositing || opacity < 1) | |
| 296 compositingRecorder.emplace(paintContext, *this, compositeOp, opacit
y); | |
| 297 | 303 |
| 298 // We can only draw the entire frame, clipped to the rect we want. So co
mpute where the top left | 304 // We can only draw the entire frame, clipped to the rect we want. So co
mpute where the top left |
| 299 // of the image would be if we were drawing without clipping, and transl
ate accordingly. | 305 // of the image would be if we were drawing without clipping, and transl
ate accordingly. |
| 300 FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / sr
cRect.height()); | 306 FloatSize scale(dstRect.width() / srcRect.width(), dstRect.height() / sr
cRect.height()); |
| 301 FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.
location().y() * scale.height()); | 307 FloatSize topLeftOffset(srcRect.location().x() * scale.width(), srcRect.
location().y() * scale.height()); |
| 302 FloatPoint destOffset = dstRect.location() - topLeftOffset; | 308 FloatPoint destOffset = dstRect.location() - topLeftOffset; |
| 303 AffineTransform transform = AffineTransform::translation(destOffset.x(),
destOffset.y()); | 309 AffineTransform transform = AffineTransform::translation(destOffset.x(),
destOffset.y()); |
| 304 transform.scale(scale.width(), scale.height()); | 310 transform.scale(scale.width(), scale.height()); |
| 305 TransformRecorder transformRecorder(paintContext, *this, transform); | 311 TransformRecorder transformRecorder(imagePicture.context(), *this, trans
form); |
| 306 | 312 |
| 307 view->updateLayoutAndStyleForPainting(); | 313 view->updateLayoutAndStyleForPainting(); |
| 308 view->paint(&paintContext, enclosingIntRect(srcRect)); | 314 view->paint(&imagePicture.context(), enclosingIntRect(srcRect)); |
| 309 ASSERT(!view->needsLayout()); | 315 ASSERT(!view->needsLayout()); |
| 310 } | 316 } |
| 311 | 317 |
| 318 { |
| 319 SkAutoCanvasRestore ar(canvas, false); |
| 320 if (drawNeedsLayer(paint)) { |
| 321 SkRect layerRect = dstRect; |
| 322 canvas->saveLayer(&layerRect, &paint); |
| 323 } |
| 324 RefPtr<const SkPicture> recording = imagePicture.endRecording(); |
| 325 canvas->drawPicture(recording.get()); |
| 326 } |
| 327 |
| 312 if (imageObserver()) | 328 if (imageObserver()) |
| 313 imageObserver()->didDraw(this); | 329 imageObserver()->didDraw(this); |
| 314 | 330 |
| 315 // Start any (SMIL) animations if needed. This will restart or continue | 331 // Start any (SMIL) animations if needed. This will restart or continue |
| 316 // animations if preceded by calls to resetAnimation or stopAnimation | 332 // animations if preceded by calls to resetAnimation or stopAnimation |
| 317 // respectively. | 333 // respectively. |
| 318 startAnimation(); | 334 startAnimation(); |
| 319 } | 335 } |
| 320 | 336 |
| 321 LayoutBox* SVGImage::embeddedContentBox() const | 337 LayoutBox* SVGImage::embeddedContentBox() const |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 | 484 |
| 469 return m_page; | 485 return m_page; |
| 470 } | 486 } |
| 471 | 487 |
| 472 String SVGImage::filenameExtension() const | 488 String SVGImage::filenameExtension() const |
| 473 { | 489 { |
| 474 return "svg"; | 490 return "svg"; |
| 475 } | 491 } |
| 476 | 492 |
| 477 } | 493 } |
| OLD | NEW |