Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp

Issue 2753633003: Implement SVGImage::applyShader() (Closed)
Patch Set: rebaseline Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698