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 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 DrawForContainer(builder.Context().Canvas(), flags, container_size, zoom, | 336 DrawForContainer(builder.Context().Canvas(), flags, container_size, zoom, |
337 tile, src_rect, url); | 337 tile, src_rect, url); |
338 } | 338 } |
339 sk_sp<PaintRecord> record = builder.EndRecording(); | 339 sk_sp<PaintRecord> record = builder.EndRecording(); |
340 | 340 |
341 SkMatrix pattern_transform; | 341 SkMatrix pattern_transform; |
342 pattern_transform.setTranslate(phase.X() + spaced_tile.X(), | 342 pattern_transform.setTranslate(phase.X() + spaced_tile.X(), |
343 phase.Y() + spaced_tile.Y()); | 343 phase.Y() + spaced_tile.Y()); |
344 | 344 |
345 PaintFlags flags; | 345 PaintFlags flags; |
346 flags.setShader(MakePaintShaderRecord(record, SkShader::kRepeat_TileMode, | 346 flags.setShader( |
347 SkShader::kRepeat_TileMode, | 347 MakePaintShaderRecord(record, spaced_tile, SkShader::kRepeat_TileMode, |
348 &pattern_transform, nullptr)); | 348 SkShader::kRepeat_TileMode, &pattern_transform)); |
349 // If the shader could not be instantiated (e.g. non-invertible matrix), | 349 // If the shader could not be instantiated (e.g. non-invertible matrix), |
350 // draw transparent. | 350 // draw transparent. |
351 // Note: we can't simply bail, because of arbitrary blend mode. | 351 // Note: we can't simply bail, because of arbitrary blend mode. |
352 if (!flags.getShader()) | 352 if (!flags.getShader()) |
353 flags.setColor(SK_ColorTRANSPARENT); | 353 flags.setColor(SK_ColorTRANSPARENT); |
354 | 354 |
355 flags.setBlendMode(composite_op); | 355 flags.setBlendMode(composite_op); |
356 flags.setColorFilter(sk_ref_sp(context.GetColorFilter())); | 356 flags.setColorFilter(sk_ref_sp(context.GetColorFilter())); |
357 context.DrawRect(dst_rect, flags); | 357 context.DrawRect(dst_rect, flags); |
358 } | 358 } |
359 | 359 |
360 sk_sp<SkImage> SVGImage::ImageForCurrentFrameForContainer( | 360 sk_sp<SkImage> SVGImage::ImageForCurrentFrameForContainer( |
361 const KURL& url, | 361 const KURL& url, |
362 const IntSize& container_size) { | 362 const IntSize& container_size) { |
363 if (!page_) | 363 if (!page_) |
364 return nullptr; | 364 return nullptr; |
365 | 365 |
366 const FloatRect container_rect((FloatPoint()), FloatSize(container_size)); | 366 const FloatRect container_rect((FloatPoint()), FloatSize(container_size)); |
367 | 367 |
368 PaintRecorder recorder; | 368 PaintRecorder recorder; |
369 PaintCanvas* canvas = recorder.beginRecording(container_rect); | 369 PaintCanvas* canvas = recorder.beginRecording(container_rect); |
370 DrawForContainer(canvas, PaintFlags(), container_rect.Size(), 1, | 370 DrawForContainer(canvas, PaintFlags(), container_rect.Size(), 1, |
371 container_rect, container_rect, url); | 371 container_rect, container_rect, url); |
372 | 372 |
373 return SkImage::MakeFromPicture( | 373 return SkImage::MakeFromPicture( |
374 ToSkPicture(recorder.finishRecordingAsPicture()), | 374 ToSkPicture(recorder.finishRecordingAsPicture(), container_rect), |
375 SkISize::Make(container_size.Width(), container_size.Height()), nullptr, | 375 SkISize::Make(container_size.Width(), container_size.Height()), nullptr, |
376 nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()); | 376 nullptr, SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()); |
377 } | 377 } |
378 | 378 |
379 static bool DrawNeedsLayer(const PaintFlags& flags) { | 379 static bool DrawNeedsLayer(const PaintFlags& flags) { |
380 if (SkColorGetA(flags.getColor()) < 255) | 380 if (SkColorGetA(flags.getColor()) < 255) |
381 return true; | 381 return true; |
382 return !flags.isSrcOver(); | 382 return !flags.isSrcOver(); |
383 } | 383 } |
384 | 384 |
385 bool SVGImage::ApplyShaderInternal(PaintFlags& flags, | 385 bool SVGImage::ApplyShaderInternal(PaintFlags& flags, |
386 const SkMatrix& local_matrix, | 386 const SkMatrix& local_matrix, |
387 const KURL& url) { | 387 const KURL& url) { |
388 const FloatSize size(ContainerSize()); | 388 const IntSize size(ContainerSize()); |
389 if (size.IsEmpty()) | 389 if (size.IsEmpty()) |
390 return false; | 390 return false; |
391 | 391 |
392 FloatRect float_bounds(FloatPoint(), size); | 392 IntRect bounds(IntPoint(), size); |
393 const SkRect bounds(float_bounds); | |
394 | 393 |
395 flags.setShader(MakePaintShaderRecord( | 394 flags.setShader(MakePaintShaderRecord( |
396 PaintRecordForCurrentFrame(float_bounds, url), SkShader::kRepeat_TileMode, | 395 PaintRecordForCurrentFrame(bounds, url), bounds, |
397 SkShader::kRepeat_TileMode, &local_matrix, &bounds)); | 396 SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &local_matrix)); |
398 | 397 |
399 // Animation is normally refreshed in draw() impls, which we don't reach when | 398 // Animation is normally refreshed in draw() impls, which we don't reach when |
400 // painting via shaders. | 399 // painting via shaders. |
401 StartAnimation(); | 400 StartAnimation(); |
402 | 401 |
403 return true; | 402 return true; |
404 } | 403 } |
405 | 404 |
406 bool SVGImage::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) { | 405 bool SVGImage::ApplyShader(PaintFlags& flags, const SkMatrix& local_matrix) { |
407 return ApplyShaderInternal(flags, local_matrix, KURL()); | 406 return ApplyShaderInternal(flags, local_matrix, KURL()); |
(...skipping 24 matching lines...) Expand all Loading... |
432 const FloatRect& src_rect, | 431 const FloatRect& src_rect, |
433 RespectImageOrientationEnum should_respect_image_orientation, | 432 RespectImageOrientationEnum should_respect_image_orientation, |
434 ImageClampingMode clamp_mode) { | 433 ImageClampingMode clamp_mode) { |
435 if (!page_) | 434 if (!page_) |
436 return; | 435 return; |
437 | 436 |
438 DrawInternal(canvas, flags, dst_rect, src_rect, | 437 DrawInternal(canvas, flags, dst_rect, src_rect, |
439 should_respect_image_orientation, clamp_mode, KURL()); | 438 should_respect_image_orientation, clamp_mode, KURL()); |
440 } | 439 } |
441 | 440 |
442 sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(const FloatRect& bounds, | 441 sk_sp<PaintRecord> SVGImage::PaintRecordForCurrentFrame(const IntRect& bounds, |
443 const KURL& url, | 442 const KURL& url, |
444 PaintCanvas* canvas) { | 443 PaintCanvas* canvas) { |
445 DCHECK(page_); | 444 DCHECK(page_); |
446 FrameView* view = ToLocalFrame(page_->MainFrame())->View(); | 445 FrameView* view = ToLocalFrame(page_->MainFrame())->View(); |
447 view->Resize(ContainerSize()); | 446 view->Resize(ContainerSize()); |
448 | 447 |
449 // Always call processUrlFragment, even if the url is empty, because | 448 // Always call processUrlFragment, even if the url is empty, because |
450 // there may have been a previous url/fragment that needs to be reset. | 449 // there may have been a previous url/fragment that needs to be reset. |
451 view->ProcessUrlFragment(url); | 450 view->ProcessUrlFragment(url); |
452 | 451 |
453 // If the image was reset, we need to rewind the timeline back to 0. This | 452 // If the image was reset, we need to rewind the timeline back to 0. This |
454 // needs to be done before painting, or else we wouldn't get the correct | 453 // needs to be done before painting, or else we wouldn't get the correct |
455 // reset semantics (we'd paint the "last" frame rather than the one at | 454 // reset semantics (we'd paint the "last" frame rather than the one at |
456 // time=0.) The reason we do this here and not in resetAnimation() is to | 455 // time=0.) The reason we do this here and not in resetAnimation() is to |
457 // avoid setting timers from the latter. | 456 // avoid setting timers from the latter. |
458 FlushPendingTimelineRewind(); | 457 FlushPendingTimelineRewind(); |
459 | 458 |
460 IntRect int_bounds(EnclosingIntRect(bounds)); | 459 PaintRecordBuilder builder(bounds, nullptr, nullptr, paint_controller_.get()); |
461 PaintRecordBuilder builder(int_bounds, nullptr, nullptr, | |
462 paint_controller_.get()); | |
463 | 460 |
464 view->UpdateAllLifecyclePhasesExceptPaint(); | 461 view->UpdateAllLifecyclePhasesExceptPaint(); |
465 view->Paint(builder.Context(), CullRect(int_bounds)); | 462 view->Paint(builder.Context(), CullRect(bounds)); |
466 DCHECK(!view->NeedsLayout()); | 463 DCHECK(!view->NeedsLayout()); |
467 | 464 |
468 if (canvas) { | 465 if (canvas) { |
469 builder.EndRecording(*canvas); | 466 builder.EndRecording(*canvas); |
470 return nullptr; | 467 return nullptr; |
471 } | 468 } |
472 return builder.EndRecording(); | 469 return builder.EndRecording(); |
473 } | 470 } |
474 | 471 |
475 void SVGImage::DrawInternal(PaintCanvas* canvas, | 472 void SVGImage::DrawInternal(PaintCanvas* canvas, |
(...skipping 17 matching lines...) Expand all Loading... |
493 FloatSize top_left_offset(src_rect.Location().X() * scale.Width(), | 490 FloatSize top_left_offset(src_rect.Location().X() * scale.Width(), |
494 src_rect.Location().Y() * scale.Height()); | 491 src_rect.Location().Y() * scale.Height()); |
495 FloatPoint dest_offset = dst_rect.Location() - top_left_offset; | 492 FloatPoint dest_offset = dst_rect.Location() - top_left_offset; |
496 AffineTransform transform = | 493 AffineTransform transform = |
497 AffineTransform::Translation(dest_offset.X(), dest_offset.Y()); | 494 AffineTransform::Translation(dest_offset.X(), dest_offset.Y()); |
498 transform.Scale(scale.Width(), scale.Height()); | 495 transform.Scale(scale.Width(), scale.Height()); |
499 | 496 |
500 canvas->save(); | 497 canvas->save(); |
501 canvas->clipRect(EnclosingIntRect(dst_rect)); | 498 canvas->clipRect(EnclosingIntRect(dst_rect)); |
502 canvas->concat(AffineTransformToSkMatrix(transform)); | 499 canvas->concat(AffineTransformToSkMatrix(transform)); |
503 PaintRecordForCurrentFrame(src_rect, url, canvas); | 500 PaintRecordForCurrentFrame(EnclosingIntRect(src_rect), url, canvas); |
504 canvas->restore(); | 501 canvas->restore(); |
505 } | 502 } |
506 | 503 |
507 // Start any (SMIL) animations if needed. This will restart or continue | 504 // Start any (SMIL) animations if needed. This will restart or continue |
508 // animations if preceded by calls to resetAnimation or stopAnimation | 505 // animations if preceded by calls to resetAnimation or stopAnimation |
509 // respectively. | 506 // respectively. |
510 StartAnimation(); | 507 StartAnimation(); |
511 } | 508 } |
512 | 509 |
513 LayoutReplaced* SVGImage::EmbeddedReplacedContent() const { | 510 LayoutReplaced* SVGImage::EmbeddedReplacedContent() const { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 | 756 |
760 NOTREACHED(); | 757 NOTREACHED(); |
761 return kSizeAvailable; | 758 return kSizeAvailable; |
762 } | 759 } |
763 | 760 |
764 String SVGImage::FilenameExtension() const { | 761 String SVGImage::FilenameExtension() const { |
765 return "svg"; | 762 return "svg"; |
766 } | 763 } |
767 | 764 |
768 } // namespace blink | 765 } // namespace blink |
OLD | NEW |