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 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 | 120 |
121 DEFINE_NODE_FACTORY(HTMLCanvasElement) | 121 DEFINE_NODE_FACTORY(HTMLCanvasElement) |
122 | 122 |
123 HTMLCanvasElement::~HTMLCanvasElement() | 123 HTMLCanvasElement::~HTMLCanvasElement() |
124 { | 124 { |
125 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_external
lyAllocatedMemory); | 125 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-m_external
lyAllocatedMemory); |
126 #if !ENABLE(OILPAN) | 126 #if !ENABLE(OILPAN) |
127 for (CanvasObserver* canvasObserver : m_observers) | 127 for (CanvasObserver* canvasObserver : m_observers) |
128 canvasObserver->canvasDestroyed(this); | 128 canvasObserver->canvasDestroyed(this); |
129 // Ensure these go away before the ImageBuffer. | 129 // Ensure these go away before the ImageBuffer. |
130 m_contextStateSaver.clear(); | |
131 m_context.clear(); | 130 m_context.clear(); |
132 #endif | 131 #endif |
133 } | 132 } |
134 | 133 |
135 void HTMLCanvasElement::parseAttribute(const QualifiedName& name, const AtomicSt
ring& value) | 134 void HTMLCanvasElement::parseAttribute(const QualifiedName& name, const AtomicSt
ring& value) |
136 { | 135 { |
137 if (name == widthAttr || name == heightAttr) | 136 if (name == widthAttr || name == heightAttr) |
138 reset(); | 137 reset(); |
139 HTMLElement::parseAttribute(name, value); | 138 HTMLElement::parseAttribute(name, value); |
140 } | 139 } |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 { | 281 { |
283 if (rect.isEmpty()) | 282 if (rect.isEmpty()) |
284 return; | 283 return; |
285 m_imageBufferIsClear = false; | 284 m_imageBufferIsClear = false; |
286 clearCopiedImage(); | 285 clearCopiedImage(); |
287 if (layoutObject()) | 286 if (layoutObject()) |
288 layoutObject()->setMayNeedPaintInvalidation(); | 287 layoutObject()->setMayNeedPaintInvalidation(); |
289 m_dirtyRect.unite(rect); | 288 m_dirtyRect.unite(rect); |
290 if (m_context && m_context->is2d() && hasImageBuffer()) | 289 if (m_context && m_context->is2d() && hasImageBuffer()) |
291 buffer()->didDraw(rect); | 290 buffer()->didDraw(rect); |
292 notifyObserversCanvasChanged(m_dirtyRect); | 291 notifyObserversCanvasChanged(rect); |
293 } | 292 } |
294 | 293 |
295 void HTMLCanvasElement::didFinalizeFrame() | 294 void HTMLCanvasElement::didFinalizeFrame() |
296 { | 295 { |
297 if (m_dirtyRect.isEmpty()) | 296 if (m_dirtyRect.isEmpty()) |
298 return; | 297 return; |
299 | 298 |
300 // Propagate the m_dirtyRect accumulated so far to the compositor | 299 // Propagate the m_dirtyRect accumulated so far to the compositor |
301 // before restarting with a blank dirty rect. | 300 // before restarting with a blank dirty rect. |
302 FloatRect srcRect(0, 0, size().width(), size().height()); | 301 FloatRect srcRect(0, 0, size().width(), size().height()); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 bool hadImageBuffer = hasImageBuffer(); | 362 bool hadImageBuffer = hasImageBuffer(); |
364 | 363 |
365 int w = getAttribute(widthAttr).toInt(&ok); | 364 int w = getAttribute(widthAttr).toInt(&ok); |
366 if (!ok || w < 0) | 365 if (!ok || w < 0) |
367 w = DefaultWidth; | 366 w = DefaultWidth; |
368 | 367 |
369 int h = getAttribute(heightAttr).toInt(&ok); | 368 int h = getAttribute(heightAttr).toInt(&ok); |
370 if (!ok || h < 0) | 369 if (!ok || h < 0) |
371 h = DefaultHeight; | 370 h = DefaultHeight; |
372 | 371 |
373 if (m_contextStateSaver) { | |
374 // Reset to the initial graphics context state. | |
375 m_contextStateSaver->restore(); | |
376 m_contextStateSaver->save(); | |
377 } | |
378 | |
379 if (m_context && m_context->is2d()) | 372 if (m_context && m_context->is2d()) |
380 toCanvasRenderingContext2D(m_context.get())->reset(); | 373 toCanvasRenderingContext2D(m_context.get())->reset(); |
381 | 374 |
382 IntSize oldSize = size(); | 375 IntSize oldSize = size(); |
383 IntSize newSize(w, h); | 376 IntSize newSize(w, h); |
384 | 377 |
385 // If the size of an existing buffer matches, we can just clear it instead o
f reallocating. | 378 // If the size of an existing buffer matches, we can just clear it instead o
f reallocating. |
386 // This optimization is only done for 2D canvases for now. | 379 // This optimization is only done for 2D canvases for now. |
387 if (hadImageBuffer && oldSize == newSize && m_context && m_context->is2d() &
& !buffer()->isRecording()) { | 380 if (hadImageBuffer && oldSize == newSize && m_context && m_context->is2d() &
& !buffer()->isRecording()) { |
388 if (!m_imageBufferIsClear) { | 381 if (!m_imageBufferIsClear) { |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 void HTMLCanvasElement::createImageBuffer() | 634 void HTMLCanvasElement::createImageBuffer() |
642 { | 635 { |
643 createImageBufferInternal(nullptr); | 636 createImageBufferInternal(nullptr); |
644 if (m_didFailToCreateImageBuffer && m_context->is2d()) | 637 if (m_didFailToCreateImageBuffer && m_context->is2d()) |
645 toCanvasRenderingContext2D(m_context.get())->loseContext(CanvasRendering
Context2D::SyntheticLostContext); | 638 toCanvasRenderingContext2D(m_context.get())->loseContext(CanvasRendering
Context2D::SyntheticLostContext); |
646 } | 639 } |
647 | 640 |
648 void HTMLCanvasElement::createImageBufferInternal(PassOwnPtr<ImageBufferSurface>
externalSurface) | 641 void HTMLCanvasElement::createImageBufferInternal(PassOwnPtr<ImageBufferSurface>
externalSurface) |
649 { | 642 { |
650 ASSERT(!m_imageBuffer); | 643 ASSERT(!m_imageBuffer); |
651 ASSERT(!m_contextStateSaver); | |
652 | 644 |
653 m_didFailToCreateImageBuffer = true; | 645 m_didFailToCreateImageBuffer = true; |
654 m_imageBufferIsClear = true; | 646 m_imageBufferIsClear = true; |
655 | 647 |
656 if (!canCreateImageBuffer(size())) | 648 if (!canCreateImageBuffer(size())) |
657 return; | 649 return; |
658 | 650 |
659 int msaaSampleCount = 0; | 651 int msaaSampleCount = 0; |
660 OwnPtr<ImageBufferSurface> surface; | 652 OwnPtr<ImageBufferSurface> surface; |
661 if (externalSurface) { | 653 if (externalSurface) { |
(...skipping 13 matching lines...) Expand all Loading... |
675 m_didFailToCreateImageBuffer = false; | 667 m_didFailToCreateImageBuffer = false; |
676 | 668 |
677 updateExternallyAllocatedMemory(); | 669 updateExternallyAllocatedMemory(); |
678 | 670 |
679 if (is3D()) { | 671 if (is3D()) { |
680 // Early out for WebGL canvases | 672 // Early out for WebGL canvases |
681 return; | 673 return; |
682 } | 674 } |
683 | 675 |
684 m_imageBuffer->setClient(this); | 676 m_imageBuffer->setClient(this); |
685 m_imageBuffer->context()->setShouldClampToSourceRect(false); | |
686 m_imageBuffer->context()->disableAntialiasingOptimizationForHairlineImages()
; | |
687 m_imageBuffer->context()->setImageInterpolationQuality(CanvasDefaultInterpol
ationQuality); | |
688 // Enabling MSAA overrides a request to disable antialiasing. This is true r
egardless of whether the | 677 // Enabling MSAA overrides a request to disable antialiasing. This is true r
egardless of whether the |
689 // rendering mode is accelerated or not. For consistency, we don't want to a
pply AA in accelerated | 678 // rendering mode is accelerated or not. For consistency, we don't want to a
pply AA in accelerated |
690 // canvases but not in unaccelerated canvases. | 679 // canvases but not in unaccelerated canvases. |
691 if (!msaaSampleCount && document().settings() && !document().settings()->ant
ialiased2dCanvasEnabled()) | 680 if (!msaaSampleCount && document().settings() && !document().settings()->ant
ialiased2dCanvasEnabled()) |
692 m_imageBuffer->context()->setShouldAntialias(false); | 681 toCanvasRenderingContext2D(m_context.get())->setShouldAntialias(false); |
693 #if ENABLE(ASSERT) | |
694 m_imageBuffer->context()->disableDestructionChecks(); // 2D canvas is allowe
d to leave context in an unfinalized state. | |
695 #endif | |
696 m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuffer-
>context())); | |
697 | 682 |
698 if (m_context) | 683 if (m_context) |
699 setNeedsCompositingUpdate(); | 684 setNeedsCompositingUpdate(); |
700 } | 685 } |
701 | 686 |
702 void HTMLCanvasElement::notifySurfaceInvalid() | 687 void HTMLCanvasElement::notifySurfaceInvalid() |
703 { | 688 { |
704 if (m_context && m_context->is2d()) { | 689 if (m_context && m_context->is2d()) { |
705 CanvasRenderingContext2D* context2d = toCanvasRenderingContext2D(m_conte
xt.get()); | 690 CanvasRenderingContext2D* context2d = toCanvasRenderingContext2D(m_conte
xt.get()); |
706 context2d->loseContext(CanvasRenderingContext2D::RealLostContext); | 691 context2d->loseContext(CanvasRenderingContext2D::RealLostContext); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 checkedExternallyAllocatedMemory *= height(); | 727 checkedExternallyAllocatedMemory *= height(); |
743 intptr_t externallyAllocatedMemory; | 728 intptr_t externallyAllocatedMemory; |
744 if (checkedExternallyAllocatedMemory.safeGet(externallyAllocatedMemory) == C
heckedState::DidOverflow) | 729 if (checkedExternallyAllocatedMemory.safeGet(externallyAllocatedMemory) == C
heckedState::DidOverflow) |
745 externallyAllocatedMemory = std::numeric_limits<intptr_t>::max(); | 730 externallyAllocatedMemory = std::numeric_limits<intptr_t>::max(); |
746 | 731 |
747 // Subtracting two intptr_t that are known to be positive will never underfl
ow. | 732 // Subtracting two intptr_t that are known to be positive will never underfl
ow. |
748 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA
llocatedMemory - m_externallyAllocatedMemory); | 733 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(externallyA
llocatedMemory - m_externallyAllocatedMemory); |
749 m_externallyAllocatedMemory = externallyAllocatedMemory; | 734 m_externallyAllocatedMemory = externallyAllocatedMemory; |
750 } | 735 } |
751 | 736 |
752 GraphicsContext* HTMLCanvasElement::drawingContext() const | |
753 { | |
754 return buffer() ? m_imageBuffer->context() : nullptr; | |
755 } | |
756 | |
757 SkCanvas* HTMLCanvasElement::drawingCanvas() const | 737 SkCanvas* HTMLCanvasElement::drawingCanvas() const |
758 { | 738 { |
759 return buffer() ? m_imageBuffer->canvas() : nullptr; | 739 return buffer() ? m_imageBuffer->canvas() : nullptr; |
760 } | 740 } |
761 | 741 |
762 SkCanvas* HTMLCanvasElement::existingDrawingCanvas() const | 742 SkCanvas* HTMLCanvasElement::existingDrawingCanvas() const |
763 { | 743 { |
764 if (!hasImageBuffer()) | 744 if (!hasImageBuffer()) |
765 return nullptr; | 745 return nullptr; |
766 | 746 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 needToUpdate |= m_context->paintRenderingResultsToCanvas(sourceBuffer); | 787 needToUpdate |= m_context->paintRenderingResultsToCanvas(sourceBuffer); |
808 if (needToUpdate && buffer()) { | 788 if (needToUpdate && buffer()) { |
809 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); | 789 m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled); |
810 updateExternallyAllocatedMemory(); | 790 updateExternallyAllocatedMemory(); |
811 } | 791 } |
812 return m_copiedImage; | 792 return m_copiedImage; |
813 } | 793 } |
814 | 794 |
815 void HTMLCanvasElement::discardImageBuffer() | 795 void HTMLCanvasElement::discardImageBuffer() |
816 { | 796 { |
817 m_contextStateSaver.clear(); // uses context owned by m_imageBuffer | |
818 m_imageBuffer.clear(); | 797 m_imageBuffer.clear(); |
819 m_dirtyRect = FloatRect(); | 798 m_dirtyRect = FloatRect(); |
820 updateExternallyAllocatedMemory(); | 799 updateExternallyAllocatedMemory(); |
821 } | 800 } |
822 | 801 |
823 void HTMLCanvasElement::clearCopiedImage() | 802 void HTMLCanvasElement::clearCopiedImage() |
824 { | 803 { |
825 if (m_copiedImage) { | 804 if (m_copiedImage) { |
826 m_copiedImage.clear(); | 805 m_copiedImage.clear(); |
827 updateExternallyAllocatedMemory(); | 806 updateExternallyAllocatedMemory(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 { | 877 { |
899 return FloatSize(width(), height()); | 878 return FloatSize(width(), height()); |
900 } | 879 } |
901 | 880 |
902 bool HTMLCanvasElement::isOpaque() const | 881 bool HTMLCanvasElement::isOpaque() const |
903 { | 882 { |
904 return m_context && !m_context->hasAlpha(); | 883 return m_context && !m_context->hasAlpha(); |
905 } | 884 } |
906 | 885 |
907 } // blink | 886 } // blink |
OLD | NEW |