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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 return FloatSize(solutionWidth, defaultObjectSize.height()); | 223 return FloatSize(solutionWidth, defaultObjectSize.height()); |
224 | 224 |
225 float solutionHeight = resolveHeightForRatio( | 225 float solutionHeight = resolveHeightForRatio( |
226 defaultObjectSize.width(), intrinsicSizingInfo.aspectRatio); | 226 defaultObjectSize.width(), intrinsicSizingInfo.aspectRatio); |
227 return FloatSize(defaultObjectSize.width(), solutionHeight); | 227 return FloatSize(defaultObjectSize.width(), solutionHeight); |
228 } | 228 } |
229 | 229 |
230 return defaultObjectSize; | 230 return defaultObjectSize; |
231 } | 231 } |
232 | 232 |
233 void SVGImage::drawForContainer(PaintCanvas* canvas, | 233 template <typename Func> |
234 const PaintFlags& flags, | 234 void SVGImage::forContainer(const FloatSize& containerSize, Func&& func) { |
235 const FloatSize containerSize, | |
236 float zoom, | |
237 const FloatRect& dstRect, | |
238 const FloatRect& srcRect, | |
239 const KURL& url) { | |
240 if (!m_page) | 235 if (!m_page) |
241 return; | 236 return; |
242 | 237 |
243 // Temporarily disable the image observer to prevent changeInRect() calls due | 238 // Temporarily disable the image observer to prevent changeInRect() calls due |
244 // re-laying out the image. | 239 // re-laying out the image. |
245 ImageObserverDisabler imageObserverDisabler(this); | 240 ImageObserverDisabler imageObserverDisabler(this); |
246 | 241 |
247 IntSize roundedContainerSize = roundedIntSize(containerSize); | 242 IntSize roundedContainerSize = roundedIntSize(containerSize); |
248 | 243 |
249 if (SVGSVGElement* rootElement = svgRootElement(m_page.get())) { | 244 if (SVGSVGElement* rootElement = svgRootElement(m_page.get())) { |
250 if (LayoutSVGRoot* layoutObject = | 245 if (LayoutSVGRoot* layoutObject = |
251 toLayoutSVGRoot(rootElement->layoutObject())) | 246 toLayoutSVGRoot(rootElement->layoutObject())) |
252 layoutObject->setContainerSize(roundedContainerSize); | 247 layoutObject->setContainerSize(roundedContainerSize); |
253 } | 248 } |
254 | 249 |
255 FloatRect scaledSrc = srcRect; | 250 func(FloatSize(roundedContainerSize.width() / containerSize.width(), |
256 scaledSrc.scale(1 / zoom); | 251 roundedContainerSize.height() / containerSize.height())); |
| 252 } |
257 | 253 |
258 // Compensate for the container size rounding by adjusting the source rect. | 254 void SVGImage::drawForContainer(PaintCanvas* canvas, |
259 FloatSize adjustedSrcSize = scaledSrc.size(); | 255 const PaintFlags& flags, |
260 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), | 256 const FloatSize& containerSize, |
261 roundedContainerSize.height() / containerSize.height()); | 257 float zoom, |
262 scaledSrc.setSize(adjustedSrcSize); | 258 const FloatRect& dstRect, |
| 259 const FloatRect& srcRect, |
| 260 const KURL& url) { |
| 261 forContainer(containerSize, [&](const FloatSize& residualScale) { |
| 262 FloatRect scaledSrc = srcRect; |
| 263 scaledSrc.scale(1 / zoom); |
263 | 264 |
264 drawInternal(canvas, flags, dstRect, scaledSrc, DoNotRespectImageOrientation, | 265 // Compensate for the container size rounding by adjusting the source rect. |
265 ClampImageToSourceRect, url); | 266 FloatSize adjustedSrcSize = scaledSrc.size(); |
| 267 adjustedSrcSize.scale(residualScale.width(), residualScale.height()); |
| 268 scaledSrc.setSize(adjustedSrcSize); |
| 269 |
| 270 drawInternal(canvas, flags, dstRect, scaledSrc, |
| 271 DoNotRespectImageOrientation, ClampImageToSourceRect, url); |
| 272 }); |
266 } | 273 } |
267 | 274 |
268 sk_sp<SkImage> SVGImage::imageForCurrentFrame() { | 275 sk_sp<SkImage> SVGImage::imageForCurrentFrame() { |
269 return imageForCurrentFrameForContainer(KURL(), size()); | 276 return imageForCurrentFrameForContainer(KURL(), size()); |
270 } | 277 } |
271 | 278 |
272 void SVGImage::drawPatternForContainer(GraphicsContext& context, | 279 void SVGImage::drawPatternForContainer(GraphicsContext& context, |
273 const FloatSize containerSize, | 280 const FloatSize containerSize, |
274 float zoom, | 281 float zoom, |
275 const FloatRect& srcRect, | 282 const FloatRect& srcRect, |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 SkISize::Make(containerSize.width(), containerSize.height()), nullptr, | 355 SkISize::Make(containerSize.width(), containerSize.height()), nullptr, |
349 nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()); | 356 nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()); |
350 } | 357 } |
351 | 358 |
352 static bool drawNeedsLayer(const PaintFlags& flags) { | 359 static bool drawNeedsLayer(const PaintFlags& flags) { |
353 if (SkColorGetA(flags.getColor()) < 255) | 360 if (SkColorGetA(flags.getColor()) < 255) |
354 return true; | 361 return true; |
355 return !flags.isSrcOver(); | 362 return !flags.isSrcOver(); |
356 } | 363 } |
357 | 364 |
| 365 bool SVGImage::applyShaderInternal(PaintFlags& flags, |
| 366 const SkMatrix& localMatrix, |
| 367 const KURL& url) { |
| 368 const FloatSize size(containerSize()); |
| 369 if (size.isEmpty()) |
| 370 return false; |
| 371 |
| 372 const FloatRect bounds(FloatPoint(), size); |
| 373 flags.setShader(SkShader::MakePictureShader( |
| 374 paintRecordForCurrentFrame(bounds, bounds, url), |
| 375 SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &localMatrix, |
| 376 nullptr)); |
| 377 |
| 378 // Animation is normally refreshed in draw() impls, which we don't reach when |
| 379 // painting via shaders. |
| 380 startAnimation(); |
| 381 |
| 382 return true; |
| 383 } |
| 384 |
| 385 bool SVGImage::applyShader(PaintFlags& flags, const SkMatrix& localMatrix) { |
| 386 return applyShaderInternal(flags, localMatrix, KURL()); |
| 387 } |
| 388 |
| 389 bool SVGImage::applyShaderForContainer(const FloatSize& containerSize, |
| 390 float zoom, |
| 391 const KURL& url, |
| 392 PaintFlags& flags, |
| 393 const SkMatrix& localMatrix) { |
| 394 bool result = false; |
| 395 forContainer(containerSize, [&](const FloatSize& residualScale) { |
| 396 // Compensate for the container size rounding. |
| 397 auto adjustedLocalMatrix = localMatrix; |
| 398 adjustedLocalMatrix.preScale(zoom * residualScale.width(), |
| 399 zoom * residualScale.height()); |
| 400 |
| 401 result = applyShaderInternal(flags, adjustedLocalMatrix, url); |
| 402 }); |
| 403 |
| 404 return result; |
| 405 } |
| 406 |
358 void SVGImage::draw(PaintCanvas* canvas, | 407 void SVGImage::draw(PaintCanvas* canvas, |
359 const PaintFlags& flags, | 408 const PaintFlags& flags, |
360 const FloatRect& dstRect, | 409 const FloatRect& dstRect, |
361 const FloatRect& srcRect, | 410 const FloatRect& srcRect, |
362 RespectImageOrientationEnum shouldRespectImageOrientation, | 411 RespectImageOrientationEnum shouldRespectImageOrientation, |
363 ImageClampingMode clampMode) { | 412 ImageClampingMode clampMode) { |
364 if (!m_page) | 413 if (!m_page) |
365 return; | 414 return; |
366 | 415 |
367 drawInternal(canvas, flags, dstRect, srcRect, shouldRespectImageOrientation, | 416 drawInternal(canvas, flags, dstRect, srcRect, shouldRespectImageOrientation, |
368 clampMode, KURL()); | 417 clampMode, KURL()); |
369 } | 418 } |
370 | 419 |
371 void SVGImage::drawInternal(PaintCanvas* canvas, | 420 sk_sp<PaintRecord> SVGImage::paintRecordForCurrentFrame( |
372 const PaintFlags& flags, | 421 const FloatRect& srcRect, |
373 const FloatRect& dstRect, | 422 const FloatRect& dstRect, |
374 const FloatRect& srcRect, | 423 const KURL& url) { |
375 RespectImageOrientationEnum, | |
376 ImageClampingMode, | |
377 const KURL& url) { | |
378 DCHECK(m_page); | 424 DCHECK(m_page); |
379 FrameView* view = toLocalFrame(m_page->mainFrame())->view(); | 425 FrameView* view = toLocalFrame(m_page->mainFrame())->view(); |
380 view->resize(containerSize()); | 426 view->resize(containerSize()); |
381 | 427 |
382 // Always call processUrlFragment, even if the url is empty, because | 428 // Always call processUrlFragment, even if the url is empty, because |
383 // there may have been a previous url/fragment that needs to be reset. | 429 // there may have been a previous url/fragment that needs to be reset. |
384 view->processUrlFragment(url); | 430 view->processUrlFragment(url); |
385 | 431 |
386 // If the image was reset, we need to rewind the timeline back to 0. This | 432 // If the image was reset, we need to rewind the timeline back to 0. This |
387 // needs to be done before painting, or else we wouldn't get the correct | 433 // needs to be done before painting, or else we wouldn't get the correct |
(...skipping 29 matching lines...) Expand all Loading... |
417 AffineTransform transform = | 463 AffineTransform transform = |
418 AffineTransform::translation(destOffset.x(), destOffset.y()); | 464 AffineTransform::translation(destOffset.x(), destOffset.y()); |
419 transform.scale(scale.width(), scale.height()); | 465 transform.scale(scale.width(), scale.height()); |
420 TransformRecorder transformRecorder(builder.context(), builder, transform); | 466 TransformRecorder transformRecorder(builder.context(), builder, transform); |
421 | 467 |
422 view->updateAllLifecyclePhasesExceptPaint(); | 468 view->updateAllLifecyclePhasesExceptPaint(); |
423 view->paint(builder.context(), CullRect(enclosingIntRect(srcRect))); | 469 view->paint(builder.context(), CullRect(enclosingIntRect(srcRect))); |
424 DCHECK(!view->needsLayout()); | 470 DCHECK(!view->needsLayout()); |
425 } | 471 } |
426 | 472 |
| 473 return builder.endRecording(); |
| 474 } |
| 475 |
| 476 void SVGImage::drawInternal(PaintCanvas* canvas, |
| 477 const PaintFlags& flags, |
| 478 const FloatRect& dstRect, |
| 479 const FloatRect& srcRect, |
| 480 RespectImageOrientationEnum, |
| 481 ImageClampingMode, |
| 482 const KURL& url) { |
427 { | 483 { |
428 PaintCanvasAutoRestore ar(canvas, false); | 484 PaintCanvasAutoRestore ar(canvas, false); |
429 if (drawNeedsLayer(flags)) { | 485 if (drawNeedsLayer(flags)) { |
430 SkRect layerRect = dstRect; | 486 SkRect layerRect = dstRect; |
431 canvas->saveLayer(&layerRect, &flags); | 487 canvas->saveLayer(&layerRect, &flags); |
432 } | 488 } |
433 sk_sp<PaintRecord> recording = builder.endRecording(); | 489 |
434 canvas->drawPicture(recording.get()); | 490 canvas->drawPicture(paintRecordForCurrentFrame(srcRect, dstRect, url)); |
435 } | 491 } |
436 | 492 |
437 // Start any (SMIL) animations if needed. This will restart or continue | 493 // Start any (SMIL) animations if needed. This will restart or continue |
438 // animations if preceded by calls to resetAnimation or stopAnimation | 494 // animations if preceded by calls to resetAnimation or stopAnimation |
439 // respectively. | 495 // respectively. |
440 startAnimation(); | 496 startAnimation(); |
441 } | 497 } |
442 | 498 |
443 LayoutReplaced* SVGImage::embeddedReplacedContent() const { | 499 LayoutReplaced* SVGImage::embeddedReplacedContent() const { |
444 SVGSVGElement* rootElement = svgRootElement(m_page.get()); | 500 SVGSVGElement* rootElement = svgRootElement(m_page.get()); |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
658 } | 714 } |
659 | 715 |
660 return m_page ? SizeAvailable : SizeUnavailable; | 716 return m_page ? SizeAvailable : SizeUnavailable; |
661 } | 717 } |
662 | 718 |
663 String SVGImage::filenameExtension() const { | 719 String SVGImage::filenameExtension() const { |
664 return "svg"; | 720 return "svg"; |
665 } | 721 } |
666 | 722 |
667 } // namespace blink | 723 } // namespace blink |
OLD | NEW |