Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(516)

Unified Diff: Source/core/html/HTMLCanvasElement.cpp

Issue 758493004: canvas: make a temporary buffer when a context doesn't exist. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/html/HTMLCanvasElement.cpp
diff --git a/Source/core/html/HTMLCanvasElement.cpp b/Source/core/html/HTMLCanvasElement.cpp
index 7bc778110214f91b55eb0f5bd5b810742368f521..e8de8040d614344c71647283aae9ae7321b58ae4 100644
--- a/Source/core/html/HTMLCanvasElement.cpp
+++ b/Source/core/html/HTMLCanvasElement.cpp
@@ -46,6 +46,7 @@
#include "core/rendering/RenderLayer.h"
#include "platform/MIMETypeRegistry.h"
#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/graphics/BitmapImage.h"
#include "platform/graphics/Canvas2DImageBufferSurface.h"
#include "platform/graphics/GraphicsContextStateSaver.h"
#include "platform/graphics/ImageBuffer.h"
@@ -76,15 +77,12 @@ const int MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
//In Skia, we will also limit width/height to 32767.
const int MaxSkiaDim = 32767; // Maximum width/height in CSS pixels.
-bool canCreateImageBuffer(const IntSize& deviceSize)
+PassRefPtr<Image> createTransparentImage(const IntSize& size)
{
- if (deviceSize.width() * deviceSize.height() > MaxCanvasArea)
- return false;
- if (deviceSize.width() > MaxSkiaDim || deviceSize.height() > MaxSkiaDim)
- return false;
- if (!deviceSize.width() || !deviceSize.height())
- return false;
- return true;
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(size.width(), size.height());
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ return BitmapImage::create(NativeImageSkia::create(bitmap));
}
} // namespace
@@ -354,21 +352,21 @@ bool HTMLCanvasElement::paintsIntoCanvasBuffer() const
void HTMLCanvasElement::paint(GraphicsContext* context, const LayoutRect& r)
{
- if (m_context) {
- if (!paintsIntoCanvasBuffer() && !document().printing())
- return;
- m_context->paintRenderingResultsToCanvas(FrontBuffer);
- }
-
- if (hasImageBuffer()) {
- CompositeOperator compositeOperator = !m_context || m_context->hasAlpha() ? CompositeSourceOver : CompositeCopy;
- context->drawImageBuffer(buffer(), pixelSnappedIntRect(r), 0, compositeOperator);
- } else {
+ if (!m_context)
+ return;
+ if (!paintsIntoCanvasBuffer() && !document().printing())
+ return;
+ if (!canCreateImageBuffer()) {
Justin Novosad 2014/11/27 00:49:31 I disagree with this part. We should not create an
dshwang 2014/11/27 15:12:11 Thank you for explaining. I rollback this code in
// When alpha is false, we should draw to opaque black.
- if (m_context && !m_context->hasAlpha())
+ if (!m_context->hasAlpha())
context->fillRect(FloatRect(r), Color(0, 0, 0));
+ return;
}
+ m_context->paintRenderingResultsToCanvas(FrontBuffer);
+ CompositeOperator compositeOperator = m_context->hasAlpha() ? CompositeSourceOver : CompositeCopy;
+ context->drawImageBuffer(buffer(), pixelSnappedIntRect(r), 0, compositeOperator);
+
if (is3D())
toWebGLRenderingContext(m_context.get())->markLayerComposited();
}
@@ -410,7 +408,7 @@ const AtomicString HTMLCanvasElement::imageSourceURL() const
String HTMLCanvasElement::toDataURLInternal(const String& mimeType, const double* quality, SourceDrawingBuffer sourceBuffer) const
{
- if (m_size.isEmpty() || !canCreateImageBuffer(size()))
+ if (!canCreateImageBuffer())
return String("data:,");
String encodingMimeType = toEncodingMimeType(mimeType);
@@ -555,7 +553,7 @@ PassOwnPtr<ImageBufferSurface> HTMLCanvasElement::createImageBufferSurface(const
void HTMLCanvasElement::createImageBuffer()
{
createImageBufferInternal();
- if (m_didFailToCreateImageBuffer && m_context && m_context->is2d())
+ if (m_didFailToCreateImageBuffer && m_context->is2d())
toCanvasRenderingContext2D(m_context.get())->loseContext();
}
@@ -567,7 +565,7 @@ void HTMLCanvasElement::createImageBufferInternal()
m_didFailToCreateImageBuffer = true;
m_imageBufferIsClear = true;
- if (!canCreateImageBuffer(size()))
+ if (!canCreateImageBuffer())
return;
int msaaSampleCount;
@@ -609,6 +607,17 @@ void HTMLCanvasElement::createImageBufferInternal()
setNeedsCompositingUpdate();
}
+bool HTMLCanvasElement::canCreateImageBuffer() const
+{
+ if (m_size.isEmpty())
+ return false;
+ if (m_size.width() * m_size.height() > MaxCanvasArea)
+ return false;
+ if (m_size.width() > MaxSkiaDim || m_size.height() > MaxSkiaDim)
+ return false;
+ return true;
+}
+
void HTMLCanvasElement::notifySurfaceInvalid()
{
if (m_context && m_context->is2d()) {
@@ -664,6 +673,7 @@ GraphicsContext* HTMLCanvasElement::existingDrawingContext() const
ImageBuffer* HTMLCanvasElement::buffer() const
{
+ ASSERT(m_context);
dshwang 2014/11/26 21:36:54 It means that we can move imageBuffer to CanvasRen
if (!hasImageBuffer() && !m_didFailToCreateImageBuffer)
const_cast<HTMLCanvasElement*>(this)->createImageBuffer();
return m_imageBuffer.get();
@@ -671,23 +681,29 @@ ImageBuffer* HTMLCanvasElement::buffer() const
void HTMLCanvasElement::ensureUnacceleratedImageBuffer()
{
+ ASSERT(m_context);
if ((hasImageBuffer() && !m_imageBuffer->isAccelerated()) || m_didFailToCreateImageBuffer)
return;
discardImageBuffer();
- OpacityMode opacityMode = !m_context || m_context->hasAlpha() ? NonOpaque : Opaque;
+ OpacityMode opacityMode = m_context->hasAlpha() ? NonOpaque : Opaque;
m_imageBuffer = ImageBuffer::create(size(), opacityMode);
m_didFailToCreateImageBuffer = !m_imageBuffer;
}
-Image* HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer) const
+PassRefPtr<Image> HTMLCanvasElement::copiedImage(SourceDrawingBuffer sourceBuffer) const
{
+ if (!canCreateImageBuffer())
+ return nullptr;
+ if (!m_context)
+ return createTransparentImage(size());
+
if (!m_copiedImage && buffer()) {
if (m_context && m_context->is3d())
m_context->paintRenderingResultsToCanvas(sourceBuffer);
m_copiedImage = buffer()->copyImage(CopyBackingStore, Unscaled);
updateExternallyAllocatedMemory();
}
- return m_copiedImage.get();
+ return m_copiedImage;
}
void HTMLCanvasElement::discardImageBuffer()
@@ -744,29 +760,31 @@ PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(SourceImageMode mod
return nullptr;
}
- if (!buffer()) {
+ if (!canCreateImageBuffer()) {
*status = InvalidSourceImageStatus;
return nullptr;
}
- if (m_context && m_context->is3d()) {
+ if (!m_context) {
+ *status = NormalSourceImageStatus;
+ return createTransparentImage(size());
+ }
+
+ if (m_context->is3d()) {
m_context->paintRenderingResultsToCanvas(BackBuffer);
*status = ExternalSourceImageStatus;
// can't create SkImage from WebGLImageBufferSurface (contains only SkBitmap)
- return m_imageBuffer->copyImage(DontCopyBackingStore, Unscaled);
+ return buffer()->copyImage(DontCopyBackingStore, Unscaled);
Justin Novosad 2014/11/27 00:49:31 Here: not safe to assume buffer is non-null
dshwang 2014/11/27 15:12:11 Yes, true In next patch set, above "if statement"
}
- RefPtr<SkImage> image = m_imageBuffer->newImageSnapshot();
+ RefPtr<SkImage> image = buffer()->newImageSnapshot();
Justin Novosad 2014/11/27 00:49:30 here too
if (image) {
*status = NormalSourceImageStatus;
-
return StaticBitmapImage::create(image.release());
}
-
*status = InvalidSourceImageStatus;
-
return nullptr;
}

Powered by Google App Engine
This is Rietveld 408576698