| Index: Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| diff --git a/Source/core/html/canvas/CanvasRenderingContext2D.cpp b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| index b2701331d1dffccff104b5be49378965be011792..ebea8be080f6001be01a558970448f699f7c5bb0 100644
|
| --- a/Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| +++ b/Source/core/html/canvas/CanvasRenderingContext2D.cpp
|
| @@ -1191,6 +1191,25 @@ static inline FloatRect normalizeRect(const FloatRect& rect)
|
| max(rect.height(), -rect.height()));
|
| }
|
|
|
| +static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* srcRect, FloatRect* dstRect)
|
| +{
|
| + if (imageRect.contains(*srcRect))
|
| + return;
|
| +
|
| + // Compute the src to dst transform
|
| + FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect->size().height() / srcRect->size().height());
|
| + FloatPoint scaledSrcLocation = srcRect->location();
|
| + scaledSrcLocation.scale(scale.width(), scale.height());
|
| + FloatSize offset = dstRect->location() - scaledSrcLocation;
|
| +
|
| + srcRect->intersect(imageRect);
|
| +
|
| + // To clip the destination rectangle in the same proportion, transform the clipped src rect
|
| + *dstRect = *srcRect;
|
| + dstRect->scale(scale.width(), scale.height());
|
| + dstRect->move(offset);
|
| +}
|
| +
|
| void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const BlendMode& blendMode)
|
| {
|
| if (!image)
|
| @@ -1272,9 +1291,11 @@ void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap,
|
| ec = IndexSizeError;
|
| return;
|
| }
|
| - if (!imageRect.contains(normalizedSrcRect))
|
| + if (!imageRect.intersects(normalizedSrcRect))
|
| return;
|
|
|
| + clipRectsToImageRect(imageRect, &normalizedSrcRect, &actualDstRect);
|
| +
|
| Image* imageForRendering = bitmap->bitmapImage();
|
|
|
| drawImageInternal(imageForRendering, normalizedSrcRect, actualDstRect, state().m_globalComposite, state().m_globalBlend);
|
| @@ -1340,9 +1361,11 @@ void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec
|
| ec = IndexSizeError;
|
| return;
|
| }
|
| - if (!imageRect.contains(normalizedSrcRect))
|
| + if (!imageRect.intersects(normalizedSrcRect))
|
| return;
|
|
|
| + clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect);
|
| +
|
| CachedImage* cachedImage = image->cachedImage();
|
| if (!cachedImage)
|
| return;
|
| @@ -1400,9 +1423,14 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
|
|
|
| ec = 0;
|
|
|
| - if (!srcCanvasRect.contains(normalizeRect(srcRect)) || !dstRect.width() || !dstRect.height())
|
| + FloatRect normalizedSrcRect = normalizeRect(srcRect);
|
| + FloatRect normalizedDstRect = normalizeRect(dstRect);
|
| +
|
| + if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height())
|
| return;
|
|
|
| + clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect);
|
| +
|
| GraphicsContext* c = drawingContext();
|
| if (!c)
|
| return;
|
| @@ -1423,19 +1451,19 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
|
| if (!isAccelerated() || !sourceContext || !sourceContext->isAccelerated() || !sourceContext->is2d())
|
| sourceCanvas->makeRenderingResultsAvailable();
|
|
|
| - if (rectContainsCanvas(dstRect)) {
|
| - c->drawImageBuffer(buffer, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend);
|
| + if (rectContainsCanvas(normalizedDstRect)) {
|
| + c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend);
|
| didDrawEntireCanvas();
|
| } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
|
| - fullCanvasCompositedDrawImage(buffer, dstRect, srcRect, state().m_globalComposite);
|
| + fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite);
|
| didDrawEntireCanvas();
|
| } else if (state().m_globalComposite == CompositeCopy) {
|
| clearCanvas();
|
| - c->drawImageBuffer(buffer, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend);
|
| + c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend);
|
| didDrawEntireCanvas();
|
| } else {
|
| - c->drawImageBuffer(buffer, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend);
|
| - didDraw(dstRect);
|
| + c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state().m_globalComposite, state().m_globalBlend);
|
| + didDraw(normalizedDstRect);
|
| }
|
| }
|
|
|
| @@ -1486,9 +1514,14 @@ void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec
|
| return;
|
| }
|
|
|
| - if (!videoRect.contains(normalizeRect(srcRect)) || !dstRect.width() || !dstRect.height())
|
| + FloatRect normalizedSrcRect = normalizeRect(srcRect);
|
| + FloatRect normalizedDstRect = normalizeRect(dstRect);
|
| +
|
| + if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() || !normalizedDstRect.height())
|
| return;
|
|
|
| + clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect);
|
| +
|
| GraphicsContext* c = drawingContext();
|
| if (!c)
|
| return;
|
| @@ -1498,10 +1531,10 @@ void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec
|
| checkOrigin(video);
|
|
|
| GraphicsContextStateSaver stateSaver(*c);
|
| - c->clip(dstRect);
|
| - c->translate(dstRect.x(), dstRect.y());
|
| - c->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()));
|
| - c->translate(-srcRect.x(), -srcRect.y());
|
| + c->clip(normalizedDstRect);
|
| + c->translate(normalizedDstRect.x(), normalizedDstRect.y());
|
| + c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), normalizedDstRect.height() / normalizedSrcRect.height()));
|
| + c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y());
|
| video->paintCurrentFrameInContext(c, IntRect(IntPoint(), size(video)));
|
| stateSaver.restore();
|
| didDraw(dstRect);
|
|
|