Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLCanvasElement.cpp
index 8c4fd5d..88f05be 100644 (file)
@@ -28,7 +28,6 @@
 #include "config.h"
 #include "core/html/HTMLCanvasElement.h"
 
-#include <math.h>
 #include "HTMLNames.h"
 #include "RuntimeEnabledFeatures.h"
 #include "bindings/v8/ExceptionMessages.h"
@@ -53,6 +52,7 @@
 #include "platform/graphics/gpu/WebGLImageBufferSurface.h"
 #include "platform/transforms/AffineTransform.h"
 #include "public/platform/Platform.h"
+#include <math.h>
 
 namespace WebCore {
 
@@ -74,7 +74,6 @@ HTMLCanvasElement::HTMLCanvasElement(Document& document)
     : HTMLElement(canvasTag, document)
     , DocumentVisibilityObserver(document)
     , m_size(DefaultWidth, DefaultHeight)
-    , m_rendererIsCanvas(false)
     , m_ignoreReset(false)
     , m_accelerationDisabled(false)
     , m_externallyAllocatedMemory(0)
@@ -85,9 +84,9 @@ HTMLCanvasElement::HTMLCanvasElement(Document& document)
     ScriptWrappable::init(this);
 }
 
-PassRefPtr<HTMLCanvasElement> HTMLCanvasElement::create(Document& document)
+PassRefPtrWillBeRawPtr<HTMLCanvasElement> HTMLCanvasElement::create(Document& document)
 {
-    return adoptRef(new HTMLCanvasElement(document));
+    return adoptRefWillBeRefCountedGarbageCollected(new HTMLCanvasElement(document));
 }
 
 HTMLCanvasElement::~HTMLCanvasElement()
@@ -97,7 +96,9 @@ HTMLCanvasElement::~HTMLCanvasElement()
     for (HashSet<CanvasObserver*>::iterator it = m_observers.begin(); it != end; ++it)
         (*it)->canvasDestroyed(this);
 
+#if !ENABLE(OILPAN)
     m_context.clear(); // Ensure this goes away before the ImageBuffer.
+#endif
 }
 
 void HTMLCanvasElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
@@ -110,12 +111,8 @@ void HTMLCanvasElement::parseAttribute(const QualifiedName& name, const AtomicSt
 RenderObject* HTMLCanvasElement::createRenderer(RenderStyle* style)
 {
     LocalFrame* frame = document().frame();
-    if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript)) {
-        m_rendererIsCanvas = true;
+    if (frame && frame->script().canExecuteScripts(NotAboutToExecuteScript))
         return new RenderHTMLCanvas(this);
-    }
-
-    m_rendererIsCanvas = false;
     return HTMLElement::createRenderer(style);
 }
 
@@ -169,19 +166,15 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
         if (!m_context) {
             blink::Platform::current()->histogramEnumeration("Canvas.ContextType", Context2d, ContextTypeCount);
             m_context = CanvasRenderingContext2D::create(this, static_cast<Canvas2DContextAttributes*>(attrs), document().inQuirksMode());
-            if (m_context)
-                scheduleLayerUpdate();
+            setNeedsCompositingUpdate();
         }
         return m_context.get();
     }
 
-    // Accept the legacy "webkit-3d" name as well as the provisional "experimental-webgl" name.
-    // Now that WebGL is ratified, we will also accept "webgl" as the context name in Chrome.
+    // Accept the the provisional "experimental-webgl" or official "webgl" context ID.
     ContextType contextType;
     bool is3dContext = true;
-    if (type == "webkit-3d")
-        contextType = ContextWebkit3d;
-    else if (type == "experimental-webgl")
+    if (type == "experimental-webgl")
         contextType = ContextExperimentalWebgl;
     else if (type == "webgl")
         contextType = ContextWebgl;
@@ -196,10 +189,8 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
         if (!m_context) {
             blink::Platform::current()->histogramEnumeration("Canvas.ContextType", contextType, ContextTypeCount);
             m_context = WebGLRenderingContext::create(this, static_cast<WebGLContextAttributes*>(attrs));
-            if (m_context) {
-                scheduleLayerUpdate();
-                updateExternallyAllocatedMemory();
-            }
+            setNeedsCompositingUpdate();
+            updateExternallyAllocatedMemory();
         }
         return m_context.get();
     }
@@ -273,7 +264,7 @@ void HTMLCanvasElement::reset()
         toWebGLRenderingContext(m_context.get())->reshape(width(), height());
 
     if (RenderObject* renderer = this->renderer()) {
-        if (m_rendererIsCanvas) {
+        if (renderer->isCanvas()) {
             if (oldSize != size()) {
                 toRenderHTMLCanvas(renderer)->canvasSizeChanged();
                 if (renderBox() && renderBox()->hasAcceleratedCompositing())
@@ -324,8 +315,12 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r)
             if (m_presentedImage)
                 context->drawImage(m_presentedImage.get(), pixelSnappedIntRect(r), compositeOperator, DoNotRespectImageOrientation);
             else
-                context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), compositeOperator, blink::WebBlendModeNormal);
+                context->drawImageBuffer(imageBuffer, pixelSnappedIntRect(r), 0, compositeOperator);
         }
+    } else {
+        // When alpha is false, we should draw to opaque black.
+        if (m_context && !m_context->hasAlpha())
+            context->fillRect(FloatRect(0, 0, width(), height()), Color(0, 0, 0));
     }
 
     if (is3D())
@@ -358,6 +353,12 @@ void HTMLCanvasElement::setSurfaceSize(const IntSize& size)
     m_didFailToCreateImageBuffer = false;
     discardImageBuffer();
     clearCopiedImage();
+    if (m_context && m_context->is2d()) {
+        CanvasRenderingContext2D* context2d = toCanvasRenderingContext2D(m_context.get());
+        if (context2d->isContextLost()) {
+            context2d->restoreContext();
+        }
+    }
 }
 
 String HTMLCanvasElement::toEncodingMimeType(const String& mimeType)
@@ -371,20 +372,20 @@ String HTMLCanvasElement::toEncodingMimeType(const String& mimeType)
     return lowercaseMimeType;
 }
 
-String HTMLCanvasElement::toDataURL(const String& mimeType, const double* quality, ExceptionState& exceptionState)
+const AtomicString HTMLCanvasElement::imageSourceURL() const
 {
-    if (!m_originClean) {
-        exceptionState.throwSecurityError("Tainted canvases may not be exported.");
-        return String();
-    }
+    return AtomicString(toDataURLInternal("image/png", 0));
+}
 
+String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double* quality) const
+{
     if (m_size.isEmpty() || !buffer())
         return String("data:,");
 
     String encodingMimeType = toEncodingMimeType(mimeType);
 
     // Try to get ImageData first, as that may avoid lossy conversions.
-    RefPtr<ImageData> imageData = getImageData();
+    RefPtrWillBeRawPtr<ImageData> imageData = getImageData();
 
     if (imageData)
         return ImageDataToDataURL(ImageDataBuffer(imageData->size(), imageData->data()), encodingMimeType, quality);
@@ -395,7 +396,17 @@ String HTMLCanvasElement::toDataURL(const String& mimeType, const double* qualit
     return buffer()->toDataURL(encodingMimeType, quality);
 }
 
-PassRefPtr<ImageData> HTMLCanvasElement::getImageData()
+String HTMLCanvasElement::toDataURL(const String& mimeType, const double* quality, ExceptionState& exceptionState) const
+{
+    if (!m_originClean) {
+        exceptionState.throwSecurityError("Tainted canvases may not be exported.");
+        return String();
+    }
+
+    return toDataURLInternal(mimeType, quality);
+}
+
+PassRefPtrWillBeRawPtr<ImageData> HTMLCanvasElement::getImageData() const
 {
     if (!m_context || !m_context->is3d())
         return nullptr;
@@ -450,6 +461,13 @@ PassOwnPtr<ImageBufferSurface> HTMLCanvasElement::createImageBufferSurface(const
 
 void HTMLCanvasElement::createImageBuffer()
 {
+    createImageBufferInternal();
+    if (m_didFailToCreateImageBuffer && m_context && m_context->is2d())
+        toCanvasRenderingContext2D(m_context.get())->loseContext();
+}
+
+void HTMLCanvasElement::createImageBufferInternal()
+{
     ASSERT(!m_imageBuffer);
     ASSERT(!m_contextStateSaver);
 
@@ -470,7 +488,9 @@ void HTMLCanvasElement::createImageBuffer()
     OwnPtr<ImageBufferSurface> surface = createImageBufferSurface(deviceSize, &msaaSampleCount);
     if (!surface->isValid())
         return;
+
     m_imageBuffer = ImageBuffer::create(surface.release());
+    m_imageBuffer->setClient(this);
 
     m_didFailToCreateImageBuffer = false;
 
@@ -481,7 +501,9 @@ void HTMLCanvasElement::createImageBuffer()
         return;
     }
 
+    m_imageBuffer->setClient(this);
     m_imageBuffer->context()->setShouldClampToSourceRect(false);
+    m_imageBuffer->context()->disableAntialiasingOptimizationForHairlineImages();
     m_imageBuffer->context()->setImageInterpolationQuality(CanvasDefaultInterpolationQuality);
     // Enabling MSAA overrides a request to disable antialiasing. This is true regardless of whether the
     // rendering mode is accelerated or not. For consistency, we don't want to apply AA in accelerated
@@ -494,9 +516,22 @@ void HTMLCanvasElement::createImageBuffer()
     m_imageBuffer->context()->setStrokeThickness(1);
     m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuffer->context()));
 
-    // Recalculate compositing requirements if acceleration state changed.
     if (m_context)
-        scheduleLayerUpdate();
+        setNeedsCompositingUpdate();
+}
+
+void HTMLCanvasElement::notifySurfaceInvalid()
+{
+    if (m_context && m_context->is2d()) {
+        CanvasRenderingContext2D* context2d = toCanvasRenderingContext2D(m_context.get());
+        context2d->loseContext();
+    }
+}
+
+void HTMLCanvasElement::trace(Visitor* visitor)
+{
+    visitor->trace(m_context);
+    HTMLElement::trace(visitor);
 }
 
 void HTMLCanvasElement::updateExternallyAllocatedMemory() const
@@ -588,6 +623,11 @@ void HTMLCanvasElement::discardImageBuffer()
     updateExternallyAllocatedMemory();
 }
 
+bool HTMLCanvasElement::hasValidImageBuffer() const
+{
+    return m_imageBuffer && m_imageBuffer->isSurfaceValid();
+}
+
 void HTMLCanvasElement::clearCopiedImage()
 {
     m_copiedImage.clear();