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 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 DrawForContainer(builder.Context().Canvas(), flags, container_size, zoom, | 348 DrawForContainer(builder.Context().Canvas(), flags, container_size, zoom, |
349 tile, src_rect, url); | 349 tile, src_rect, url); |
350 } | 350 } |
351 sk_sp<PaintRecord> record = builder.EndRecording(); | 351 sk_sp<PaintRecord> record = builder.EndRecording(); |
352 | 352 |
353 SkMatrix pattern_transform; | 353 SkMatrix pattern_transform; |
354 pattern_transform.setTranslate(phase.X() + spaced_tile.X(), | 354 pattern_transform.setTranslate(phase.X() + spaced_tile.X(), |
355 phase.Y() + spaced_tile.Y()); | 355 phase.Y() + spaced_tile.Y()); |
356 | 356 |
357 PaintFlags flags; | 357 PaintFlags flags; |
358 flags.setShader(MakePaintShaderRecord(record, SkShader::kRepeat_TileMode, | 358 flags.setShader( |
359 SkShader::kRepeat_TileMode, | 359 MakePaintShaderRecord(record, spaced_tile, SkShader::kRepeat_TileMode, |
360 &pattern_transform, nullptr)); | 360 SkShader::kRepeat_TileMode, &pattern_transform)); |
361 // If the shader could not be instantiated (e.g. non-invertible matrix), | 361 // If the shader could not be instantiated (e.g. non-invertible matrix), |
362 // draw transparent. | 362 // draw transparent. |
363 // Note: we can't simply bail, because of arbitrary blend mode. | 363 // Note: we can't simply bail, because of arbitrary blend mode. |
364 if (!flags.getShader()) | 364 if (!flags.getShader()) |
365 flags.setColor(SK_ColorTRANSPARENT); | 365 flags.setColor(SK_ColorTRANSPARENT); |
366 | 366 |
367 flags.setBlendMode(composite_op); | 367 flags.setBlendMode(composite_op); |
368 flags.setColorFilter(sk_ref_sp(context.GetColorFilter())); | 368 flags.setColorFilter(sk_ref_sp(context.GetColorFilter())); |
369 context.DrawRect(dst_rect, flags); | 369 context.DrawRect(dst_rect, flags); |
370 } | 370 } |
371 | 371 |
372 sk_sp<SkImage> SVGImage::ImageForCurrentFrameForContainer( | 372 sk_sp<SkImage> SVGImage::ImageForCurrentFrameForContainer( |
373 const KURL& url, | 373 const KURL& url, |
374 const IntSize& container_size) { | 374 const IntSize& container_size) { |
375 if (!page_) | 375 if (!page_) |
376 return nullptr; | 376 return nullptr; |
377 | 377 |
378 const FloatRect container_rect((FloatPoint()), FloatSize(container_size)); | 378 const FloatRect container_rect((FloatPoint()), FloatSize(container_size)); |
379 | 379 |
380 PaintRecorder recorder; | 380 PaintRecorder recorder; |
381 PaintCanvas* canvas = recorder.beginRecording(container_rect); | 381 PaintCanvas* canvas = recorder.beginRecording(container_rect); |
382 DrawForContainer(canvas, PaintFlags(), container_rect.Size(), 1, | 382 DrawForContainer(canvas, PaintFlags(), container_rect.Size(), 1, |
383 container_rect, container_rect, url); | 383 container_rect, container_rect, url); |
384 | 384 |
385 return SkImage::MakeFromPicture( | 385 return SkImage::MakeFromPicture( |
386 ToSkPicture(recorder.finishRecordingAsPicture()), | 386 ToSkPicture(recorder.finishRecordingAsPicture(), container_rect), |
387 SkISize::Make(container_size.Width(), container_size.Height()), nullptr, | 387 SkISize::Make(container_size.Width(), container_size.Height()), nullptr, |
388 nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()); | 388 nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()); |
389 } | 389 } |
390 | 390 |
391 static bool DrawNeedsLayer(const PaintFlags& flags) { | 391 static bool DrawNeedsLayer(const PaintFlags& flags) { |
392 if (SkColorGetA(flags.getColor()) < 255) | 392 if (SkColorGetA(flags.getColor()) < 255) |
393 return true; | 393 return true; |
394 return !flags.isSrcOver(); | 394 return !flags.isSrcOver(); |
395 } | 395 } |
396 | 396 |
397 bool SVGImage::ApplyShaderInternal(PaintFlags& flags, | 397 bool SVGImage::ApplyShaderInternal(PaintFlags& flags, |
398 const SkMatrix& local_matrix, | 398 const SkMatrix& local_matrix, |
399 const KURL& url) { | 399 const KURL& url) { |
400 const FloatSize size(ContainerSize()); | 400 const IntSize size(ContainerSize()); |
401 if (size.IsEmpty()) | 401 if (size.IsEmpty()) |
402 return false; | 402 return false; |
403 | 403 |
404 FloatRect float_bounds(FloatPoint(), size); | 404 IntRect bounds(IntPoint(), size); |
405 const SkRect bounds(float_bounds); | |
406 | 405 |
407 flags.setShader(MakePaintShaderRecord( | 406 flags.setShader(MakePaintShaderRecord( |
408 PaintRecordForCurrentFrame(float_bounds, url), SkShader::kRepeat_TileMode, | 407 PaintRecordForCurrentFrame(bounds, url), bounds, |
409 SkShader::kRepeat_TileMode, &local_matrix, &bounds)); | 408 SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &local_matrix)); |
410 | 409 |
411 // Animation is normally refreshed in draw() impls, which we don't reach when | 410 // Animation is normally refreshed in draw() impls, which we don't reach when |
412 // painting via shaders. | 411 // painting via shaders. |
413 StartAnimation(); | 412 StartAnimation(); |
414 | 413 |
415 return true; | 414 return true; |
416 } | 415 } |
417 | 416 |
418 bool SVGImage::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) { | 417 bool SVGImage::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) { |
419 return ApplyShaderInternal(flags, local_matrix, KURL()); | 418 return ApplyShaderInternal(flags, local_matrix, KURL()); |
(...skipping 24 matching lines...) Expand all Loading... |
444 const FloatRect& src_rect, | 443 const FloatRect& src_rect, |
445 RespectImageOrientationEnum should_respect_image_orientation, | 444 RespectImageOrientationEnum should_respect_image_orientation, |
446 ImageClampingMode clamp_mode) { | 445 ImageClampingMode clamp_mode) { |
447 if (!page_) | 446 if (!page_) |
448 return; | 447 return; |
449 | 448 |
450 DrawInternal(canvas, flags, dst_rect, src_rect, | 449 DrawInternal(canvas, flags, dst_rect, src_rect, |
451 should_respect_image_orientation, clamp_mode, KURL()); | 450 should_respect_image_orientation, clamp_mode, KURL()); |
452 } | 451 } |
453 | 452 |
454 sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(const FloatRect& bounds, | 453 sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(const IntRect& bounds, |
455 const KURL& url, | 454 const KURL& url, |
456 PaintCanvas* canvas) { | 455 PaintCanvas* canvas) { |
457 DCHECK(page_); | 456 DCHECK(page_); |
458 FrameView* view = ToLocalFrame(page_->MainFrame())->View(); | 457 FrameView* view = ToLocalFrame(page_->MainFrame())->View(); |
459 view->Resize(ContainerSize()); | 458 view->Resize(ContainerSize()); |
460 | 459 |
461 // Always call processUrlFragment, even if the url is empty, because | 460 // Always call processUrlFragment, even if the url is empty, because |
462 // there may have been a previous url/fragment that needs to be reset. | 461 // there may have been a previous url/fragment that needs to be reset. |
463 view->ProcessUrlFragment(url); | 462 view->ProcessUrlFragment(url); |
464 | 463 |
465 // If the image was reset, we need to rewind the timeline back to 0. This | 464 // If the image was reset, we need to rewind the timeline back to 0. This |
466 // needs to be done before painting, or else we wouldn't get the correct | 465 // needs to be done before painting, or else we wouldn't get the correct |
467 // reset semantics (we'd paint the "last" frame rather than the one at | 466 // reset semantics (we'd paint the "last" frame rather than the one at |
468 // time=0.) The reason we do this here and not in resetAnimation() is to | 467 // time=0.) The reason we do this here and not in resetAnimation() is to |
469 // avoid setting timers from the latter. | 468 // avoid setting timers from the latter. |
470 FlushPendingTimelineRewind(); | 469 FlushPendingTimelineRewind(); |
471 | 470 |
472 IntRect int_bounds(EnclosingIntRect(bounds)); | 471 PaintRecordBuilder builder(bounds, nullptr, nullptr, paint_controller_.get()); |
473 PaintRecordBuilder builder(int_bounds, nullptr, nullptr, | |
474 paint_controller_.get()); | |
475 | 472 |
476 view->UpdateAllLifecyclePhasesExceptPaint(); | 473 view->UpdateAllLifecyclePhasesExceptPaint(); |
477 view->Paint(builder.Context(), CullRect(int_bounds)); | 474 view->Paint(builder.Context(), CullRect(bounds)); |
478 DCHECK(!view->NeedsLayout()); | 475 DCHECK(!view->NeedsLayout()); |
479 | 476 |
480 if (canvas) { | 477 if (canvas) { |
481 builder.EndRecording(*canvas); | 478 builder.EndRecording(*canvas); |
482 return nullptr; | 479 return nullptr; |
483 } | 480 } |
484 return builder.EndRecording(); | 481 return builder.EndRecording(); |
485 } | 482 } |
486 | 483 |
487 void SVGImage::DrawInternal(PaintCanvas* canvas, | 484 void SVGImage::DrawInternal(PaintCanvas* canvas, |
(...skipping 17 matching lines...) Expand all Loading... |
505 FloatSize top_left_offset(src_rect.Location().X() * scale.Width(), | 502 FloatSize top_left_offset(src_rect.Location().X() * scale.Width(), |
506 src_rect.Location().Y() * scale.Height()); | 503 src_rect.Location().Y() * scale.Height()); |
507 FloatPoint dest_offset = dst_rect.Location() - top_left_offset; | 504 FloatPoint dest_offset = dst_rect.Location() - top_left_offset; |
508 AffineTransform transform = | 505 AffineTransform transform = |
509 AffineTransform::Translation(dest_offset.X(), dest_offset.Y()); | 506 AffineTransform::Translation(dest_offset.X(), dest_offset.Y()); |
510 transform.Scale(scale.Width(), scale.Height()); | 507 transform.Scale(scale.Width(), scale.Height()); |
511 | 508 |
512 canvas->save(); | 509 canvas->save(); |
513 canvas->clipRect(EnclosingIntRect(dst_rect)); | 510 canvas->clipRect(EnclosingIntRect(dst_rect)); |
514 canvas->concat(AffineTransformToSkMatrix(transform)); | 511 canvas->concat(AffineTransformToSkMatrix(transform)); |
515 PaintRecordForCurrentFrame(src_rect, url, canvas); | 512 PaintRecordForCurrentFrame(EnclosingIntRect(src_rect), url, canvas); |
516 canvas->restore(); | 513 canvas->restore(); |
517 } | 514 } |
518 | 515 |
519 // Start any (SMIL) animations if needed. This will restart or continue | 516 // Start any (SMIL) animations if needed. This will restart or continue |
520 // animations if preceded by calls to resetAnimation or stopAnimation | 517 // animations if preceded by calls to resetAnimation or stopAnimation |
521 // respectively. | 518 // respectively. |
522 StartAnimation(); | 519 StartAnimation(); |
523 } | 520 } |
524 | 521 |
525 LayoutReplaced* SVGImage::EmbeddedReplacedContent() const { | 522 LayoutReplaced* SVGImage::EmbeddedReplacedContent() const { |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 | 781 |
785 NOTREACHED(); | 782 NOTREACHED(); |
786 return kSizeAvailable; | 783 return kSizeAvailable; |
787 } | 784 } |
788 | 785 |
789 String SVGImage::FilenameExtension() const { | 786 String SVGImage::FilenameExtension() const { |
790 return "svg"; | 787 return "svg"; |
791 } | 788 } |
792 | 789 |
793 } // namespace blink | 790 } // namespace blink |
OLD | NEW |