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

Unified Diff: Source/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 907453003: Move overdraw tracking code from GraphicsContext to CanvasRenderingContext2D (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: adding missing test file Created 5 years, 10 months 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/canvas/CanvasRenderingContext2D.cpp
diff --git a/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
index 9f3346a862e6e8964aa072a165c91ade2dd36a4f..440f70848a547f891dbe15a18935402f8d46b9b6 100644
--- a/Source/core/html/canvas/CanvasRenderingContext2D.cpp
+++ b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
@@ -283,6 +283,7 @@ CanvasRenderingContext2D::State::State()
, m_unparsedFont(defaultFont)
, m_realizedFont(false)
, m_hasClip(false)
+ , m_hasComplexClip(false)
{
}
@@ -313,6 +314,7 @@ CanvasRenderingContext2D::State::State(const State& other, ClipListCopyMode mode
, m_font(other.m_font)
, m_realizedFont(other.m_realizedFont)
, m_hasClip(other.m_hasClip)
+ , m_hasComplexClip(other.m_hasComplexClip)
{
if (mode == CopyClipList) {
m_clipList = other.m_clipList;
@@ -355,6 +357,7 @@ CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons
m_font = other.m_font;
m_realizedFont = other.m_realizedFont;
m_hasClip = other.m_hasClip;
+ m_hasComplexClip = other.m_hasComplexClip;
m_clipList = other.m_clipList;
if (m_realizedFont)
@@ -1122,7 +1125,7 @@ void CanvasRenderingContext2D::clipInternal(const Path& path, const String& wind
c->clipPath(skPath, SkRegion::kIntersect_Op, m_clipAntialiasing == AntiAliased);
if (!skPath.isRect(0))
- drawingContext()->setHasComplexClip();
+ modifiableState().m_hasComplexClip = true;
modifiableState().m_hasClip = true;
}
@@ -1236,31 +1239,25 @@ void CanvasRenderingContext2D::clearRect(float x, float y, float width, float he
{
if (!validateRectForCanvas(x, y, width, height))
return;
- GraphicsContext* context = drawingContext();
- if (!context)
- return;
- if (!state().m_invertibleCTM)
- return;
- FloatRect rect(x, y, width, height);
- FloatRect dirtyRect;
- if (!computeDirtyRect(rect, &dirtyRect))
+ GraphicsContext* c = drawingContext();
+ if (!c)
return;
- context->clearShadow();
- context->setAlphaAsFloat(1);
- context->setCompositeOperation(SkXfermode::kSrcOver_Mode);
+ c->clearShadow();
+ c->setAlphaAsFloat(1);
+ c->setCompositeOperation(SkXfermode::kClear_Mode);
- context->clearRect(rect);
- if (m_hitRegionManager)
- m_hitRegionManager->removeHitRegionsInRect(rect, state().m_transform);
+ fillRect(x, y, width, height);
applyShadow(DrawShadowAndForeground);
- context->setAlphaAsFloat(state().m_globalAlpha);
- context->setCompositeOperation(state().m_globalComposite);
+ c->setAlphaAsFloat(state().m_globalAlpha);
+ c->setCompositeOperation(state().m_globalComposite);
- validateStateStack();
- didDraw(dirtyRect);
+ if (m_hitRegionManager) {
+ FloatRect rect(x, y, width, height);
+ m_hitRegionManager->removeHitRegionsInRect(rect, state().m_transform);
Ken Russell (switch to Gerrit) 2015/02/11 10:11:44 Why was the check removed above of whether the sta
Justin Novosad 2015/02/11 18:59:54 Good catch, my thinking was that we already check
+ }
dshwang 2015/02/11 08:37:52 why didDraw is removed?
Justin Novosad 2015/02/11 18:59:54 didDraw is taken care of by fillRect now. I'll add
}
// FIXME(crbug.com/425531): Funtional.h cannot handle override function signature.
@@ -1297,6 +1294,7 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei
FloatRect rect(x, y, width, height);
if (rectContainsTransformedRect(rect, clipBounds)) {
+ checkOverdraw(rect, &c->fillPaint(), NoImage, ClipFill);
c->fillRect(rect);
didDraw(clipBounds);
} else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
@@ -1304,7 +1302,7 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei
didDraw(clipBounds);
} else if (state().m_globalComposite == SkXfermode::kSrc_Mode) {
clearCanvas();
- c->clearShadow();
+ c->clearShadow(); // Takes care of signaling the overdraw
c->fillRect(rect);
applyShadow(DrawShadowAndForeground);
didDraw(clipBounds);
@@ -1425,7 +1423,7 @@ void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour
CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
FloatSize sourceRectSize = imageSourceInternal->sourceSize();
FloatSize destRectSize = imageSourceInternal->defaultDestinationSize();
- drawImageInternal(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, destRectSize.width(), destRectSize.height(), exceptionState);
+ drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, destRectSize.width(), destRectSize.height(), exceptionState);
}
void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource,
@@ -1433,7 +1431,7 @@ void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour
{
CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
FloatSize sourceRectSize = imageSourceInternal->sourceSize();
- drawImageInternal(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, width, height, exceptionState);
+ drawImage(imageSourceInternal, 0, 0, sourceRectSize.width(), sourceRectSize.height(), x, y, width, height, exceptionState);
}
void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSource,
@@ -1441,7 +1439,7 @@ void CanvasRenderingContext2D::drawImage(const CanvasImageSourceUnion& imageSour
float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
{
CanvasImageSource* imageSourceInternal = toImageSourceInternal(imageSource);
- drawImageInternal(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionState);
+ drawImage(imageSourceInternal, sx, sy, sw, sh, dx, dy, dw, dh, exceptionState);
}
static void drawVideo(SkCanvas* c, GraphicsContext* gc, CanvasImageSource* imageSource, FloatRect srcRect, FloatRect dstRect)
@@ -1465,7 +1463,7 @@ static void drawImageOnContext(SkCanvas* c, GraphicsContext* gc, CanvasImageSour
}
}
-void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource,
+void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
float sx, float sy, float sw, float sh,
float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
{
@@ -1518,13 +1516,14 @@ void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource,
canvas()->buffer()->willAccessPixels();
if (rectContainsTransformedRect(dstRect, clipBounds)) {
+ checkOverdraw(dstRect, &c->fillPaint(), imageSource->isOpaque() ? OpaqueImage : NonOpaqueImage, ClipFill);
drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect, dstRect);
didDraw(clipBounds);
} else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
fullCanvasCompositedDraw(bind(&drawImageOnContext, drawingCanvas(), c, imageSource, image.get(), srcRect, dstRect));
didDraw(clipBounds);
} else if (state().m_globalComposite == SkXfermode::kSrc_Mode) {
- clearCanvas();
+ clearCanvas(); // takes care of signaling an overdraw
drawImageOnContext(drawingCanvas(), c, imageSource, image.get(), srcRect, dstRect);
didDraw(clipBounds);
} else {
@@ -1551,6 +1550,7 @@ void CanvasRenderingContext2D::clearCanvas()
if (!c)
return;
+ checkOverdraw(canvasRect, 0, NoImage, ClipFill);
c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK);
}
@@ -1791,6 +1791,8 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy,
IntRect sourceRect(destRect);
sourceRect.move(-destOffset);
+ checkOverdraw(destRect, 0, NoImage, UntransformedUnclippedFill);
+
buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width(), data->height()), sourceRect, IntPoint(destOffset));
didDraw(destRect);
@@ -2382,4 +2384,71 @@ unsigned CanvasRenderingContext2D::hitRegionsCount() const
return 0;
}
+void CanvasRenderingContext2D::checkOverdraw(const SkRect& rect, const SkPaint* paint, ImageType imageType, DrawType drawType)
+{
+ SkCanvas* c = drawingCanvas();
+ if (!c || !canvas()->buffer()->isRecording())
Stephen Chennney 2015/02/11 14:33:20 There's a lot of implicit non-null here. As writte
Justin Novosad 2015/02/11 18:59:54 Those checks are taken care of in drawingCanvas().
Stephen Chennney 2015/02/11 19:29:47 OK.
+ return;
+
+ SkRect deviceRect;
+ if (drawType == UntransformedUnclippedFill) {
+ deviceRect = rect;
+ } else {
+ ASSERT(drawType == ClipFill);
+ if (state().m_hasComplexClip)
+ return;
+
+ SkIRect skIBounds;
+ if (!c->getClipDeviceBounds(&skIBounds))
+ return;
+ deviceRect = SkRect::Make(skIBounds);
+ }
+
+ const SkImageInfo& imageInfo = c->imageInfo();
+ if (!deviceRect.contains(SkRect::MakeWH(imageInfo.width(), imageInfo.height())))
+ return;
+
+ bool isSourceOver = true;
+ unsigned alpha = 0xFF;
+ if (paint) {
+ if (paint->getLooper() || paint->getImageFilter() || paint->getMaskFilter())
+ return;
+
+ SkXfermode* xfermode = paint->getXfermode();
+ if (xfermode) {
+ SkXfermode::Mode mode;
+ if (xfermode->asMode(&mode)) {
+ isSourceOver = mode == SkXfermode::kSrcOver_Mode;
+ if (!isSourceOver && mode != SkXfermode::kSrc_Mode && mode != SkXfermode::kClear_Mode)
+ return; // The code below only knows how to handle Src, SrcOver, and Clear
+ } else {
+ // unknown xfermode
+ ASSERT_NOT_REACHED();
+ return;
+ }
+ }
+
+ alpha = paint->getAlpha();
+
+ if (isSourceOver && imageType == NoImage) {
+ SkShader* shader = paint->getShader();
+ if (shader) {
+ if (shader->isOpaque() && alpha == 0xFF)
+ canvas()->buffer()->willOverwriteCanvas();
+ return;
+ }
+ }
+ }
+
+ if (isSourceOver) {
+ // With source over, we need to certify that alpha == 0xFF for all pixels
+ if (imageType == NonOpaqueImage)
+ return;
+ if (alpha < 0xFF)
+ return;
+ }
+
+ canvas()->buffer()->willOverwriteCanvas();
+}
+
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698