OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved. |
3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 3 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. | 4 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. 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 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 clearCopiedImage(); | 276 clearCopiedImage(); |
277 if (layoutObject()) | 277 if (layoutObject()) |
278 layoutObject()->setMayNeedPaintInvalidation(); | 278 layoutObject()->setMayNeedPaintInvalidation(); |
279 m_dirtyRect.unite(rect); | 279 m_dirtyRect.unite(rect); |
280 if (m_context && m_context->is2d() && hasImageBuffer()) | 280 if (m_context && m_context->is2d() && hasImageBuffer()) |
281 buffer()->didDraw(rect); | 281 buffer()->didDraw(rect); |
282 } | 282 } |
283 | 283 |
284 void HTMLCanvasElement::didFinalizeFrame() | 284 void HTMLCanvasElement::didFinalizeFrame() |
285 { | 285 { |
| 286 notifyListenersCanvasChanged(); |
| 287 |
286 if (m_dirtyRect.isEmpty()) | 288 if (m_dirtyRect.isEmpty()) |
287 return; | 289 return; |
288 | 290 |
289 // Propagate the m_dirtyRect accumulated so far to the compositor | 291 // Propagate the m_dirtyRect accumulated so far to the compositor |
290 // before restarting with a blank dirty rect. | 292 // before restarting with a blank dirty rect. |
291 FloatRect srcRect(0, 0, size().width(), size().height()); | 293 FloatRect srcRect(0, 0, size().width(), size().height()); |
292 m_dirtyRect.intersect(srcRect); | 294 m_dirtyRect.intersect(srcRect); |
293 LayoutBox* ro = layoutBox(); | 295 LayoutBox* ro = layoutBox(); |
294 // Canvas content updates do not need to be propagated as | 296 // Canvas content updates do not need to be propagated as |
295 // paint invalidations if the canvas is accelerated, since | 297 // paint invalidations if the canvas is accelerated, since |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 } | 388 } |
387 } | 389 } |
388 } | 390 } |
389 | 391 |
390 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const | 392 bool HTMLCanvasElement::paintsIntoCanvasBuffer() const |
391 { | 393 { |
392 ASSERT(m_context); | 394 ASSERT(m_context); |
393 | 395 |
394 if (!m_context->isAccelerated()) | 396 if (!m_context->isAccelerated()) |
395 return true; | 397 return true; |
396 | |
397 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) | 398 if (layoutBox() && layoutBox()->hasAcceleratedCompositing()) |
398 return false; | 399 return false; |
399 | 400 |
400 return true; | 401 return true; |
401 } | 402 } |
402 | 403 |
| 404 void HTMLCanvasElement::notifyListenersCanvasChanged() |
| 405 { |
| 406 if (!originClean()) { |
| 407 m_listeners.clear(); |
| 408 return; |
| 409 } |
| 410 |
| 411 bool listenerNeedsNewFrameCapture = false; |
| 412 for (const CanvasDrawListener* listener : m_listeners) { |
| 413 if (listener->needsNewFrame()) { |
| 414 listenerNeedsNewFrameCapture = true; |
| 415 } |
| 416 } |
| 417 |
| 418 if (listenerNeedsNewFrameCapture) { |
| 419 SourceImageStatus status; |
| 420 RefPtr<Image> sourceImage = getSourceImageForCanvas(&status, PreferNoAcc
eleration); |
| 421 if (status != NormalSourceImageStatus) |
| 422 return; |
| 423 RefPtr<SkImage> image = sourceImage->imageForCurrentFrame(); |
| 424 for (CanvasDrawListener* listener : m_listeners) { |
| 425 if (listener->needsNewFrame()) { |
| 426 listener->sendNewFrame(image); |
| 427 } |
| 428 } |
| 429 } |
| 430 |
| 431 } |
| 432 |
403 void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r) | 433 void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r) |
404 { | 434 { |
405 // FIXME: crbug.com/438240; there is a bug with the new CSS blending and com
positing feature. | 435 // FIXME: crbug.com/438240; there is a bug with the new CSS blending and com
positing feature. |
406 if (!m_context) | 436 if (!m_context) |
407 return; | 437 return; |
408 if (!paintsIntoCanvasBuffer() && !document().printing()) | 438 if (!paintsIntoCanvasBuffer() && !document().printing()) |
409 return; | 439 return; |
410 | 440 |
411 m_context->paintRenderingResultsToCanvas(FrontBuffer); | 441 m_context->paintRenderingResultsToCanvas(FrontBuffer); |
412 if (hasImageBuffer()) { | 442 if (hasImageBuffer()) { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
559 ScopedDisposal<ImageData> disposer(imageData); | 589 ScopedDisposal<ImageData> disposer(imageData); |
560 // Add a ref to keep image data alive until completion of encoding | 590 // Add a ref to keep image data alive until completion of encoding |
561 RefPtr<DOMUint8ClampedArray> imageDataRef(imageData->data()); | 591 RefPtr<DOMUint8ClampedArray> imageDataRef(imageData->data()); |
562 | 592 |
563 RefPtr<CanvasAsyncBlobCreator> asyncCreatorRef = CanvasAsyncBlobCreator::cre
ate(imageDataRef.release(), encodingMimeType, imageData->size(), callback); | 593 RefPtr<CanvasAsyncBlobCreator> asyncCreatorRef = CanvasAsyncBlobCreator::cre
ate(imageDataRef.release(), encodingMimeType, imageData->size(), callback); |
564 | 594 |
565 // TODO(xlai): Remove idle-periods version of implementation completely, htt
p://crbug.com/564218 | 595 // TODO(xlai): Remove idle-periods version of implementation completely, htt
p://crbug.com/564218 |
566 asyncCreatorRef->scheduleAsyncBlobCreation(false, quality); | 596 asyncCreatorRef->scheduleAsyncBlobCreation(false, quality); |
567 } | 597 } |
568 | 598 |
| 599 void HTMLCanvasElement::addListener(CanvasDrawListener* listener) |
| 600 { |
| 601 m_listeners.add(listener); |
| 602 } |
| 603 |
| 604 void HTMLCanvasElement::removeListener(CanvasDrawListener* listener) |
| 605 { |
| 606 m_listeners.remove(listener); |
| 607 } |
| 608 |
569 SecurityOrigin* HTMLCanvasElement::securityOrigin() const | 609 SecurityOrigin* HTMLCanvasElement::securityOrigin() const |
570 { | 610 { |
571 return document().securityOrigin(); | 611 return document().securityOrigin(); |
572 } | 612 } |
573 | 613 |
574 bool HTMLCanvasElement::originClean() const | 614 bool HTMLCanvasElement::originClean() const |
575 { | 615 { |
576 if (document().settings() && document().settings()->disableReadingFromCanvas
()) | 616 if (document().settings() && document().settings()->disableReadingFromCanvas
()) |
577 return false; | 617 return false; |
578 return m_originClean; | 618 return m_originClean; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 } | 774 } |
735 | 775 |
736 void HTMLCanvasElement::notifySurfaceInvalid() | 776 void HTMLCanvasElement::notifySurfaceInvalid() |
737 { | 777 { |
738 if (m_context && m_context->is2d()) | 778 if (m_context && m_context->is2d()) |
739 m_context->loseContext(CanvasRenderingContext::RealLostContext); | 779 m_context->loseContext(CanvasRenderingContext::RealLostContext); |
740 } | 780 } |
741 | 781 |
742 DEFINE_TRACE(HTMLCanvasElement) | 782 DEFINE_TRACE(HTMLCanvasElement) |
743 { | 783 { |
| 784 visitor->trace(m_listeners); |
744 visitor->trace(m_context); | 785 visitor->trace(m_context); |
745 DocumentVisibilityObserver::trace(visitor); | 786 DocumentVisibilityObserver::trace(visitor); |
746 HTMLElement::trace(visitor); | 787 HTMLElement::trace(visitor); |
747 } | 788 } |
748 | 789 |
749 void HTMLCanvasElement::updateExternallyAllocatedMemory() const | 790 void HTMLCanvasElement::updateExternallyAllocatedMemory() const |
750 { | 791 { |
751 int bufferCount = 0; | 792 int bufferCount = 0; |
752 if (m_imageBuffer) { | 793 if (m_imageBuffer) { |
753 bufferCount++; | 794 bufferCount++; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
950 } | 991 } |
951 return ImageBitmapSource::fulfillImageBitmap(scriptState, isPaintable() ? Im
ageBitmap::create(this, IntRect(sx, sy, sw, sh)) : nullptr); | 992 return ImageBitmapSource::fulfillImageBitmap(scriptState, isPaintable() ? Im
ageBitmap::create(this, IntRect(sx, sy, sw, sh)) : nullptr); |
952 } | 993 } |
953 | 994 |
954 bool HTMLCanvasElement::isOpaque() const | 995 bool HTMLCanvasElement::isOpaque() const |
955 { | 996 { |
956 return m_context && !m_context->hasAlpha(); | 997 return m_context && !m_context->hasAlpha(); |
957 } | 998 } |
958 | 999 |
959 } // blink | 1000 } // blink |
OLD | NEW |