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

Side by Side Diff: Source/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 19267027: Fixing src rectangle clipping with drawImage (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: retry without video Created 7 years, 5 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 unified diff | Download patch
« no previous file with comments | « LayoutTests/virtual/gpu/canvas/philip/tests/2d.drawImage.outsidesource-expected.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
8 * Copyright (C) 2012 Intel Corporation. All rights reserved. 8 * Copyright (C) 2012 Intel Corporation. All rights reserved.
9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
10 * 10 *
(...skipping 1173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1184 } 1184 }
1185 1185
1186 static inline FloatRect normalizeRect(const FloatRect& rect) 1186 static inline FloatRect normalizeRect(const FloatRect& rect)
1187 { 1187 {
1188 return FloatRect(min(rect.x(), rect.maxX()), 1188 return FloatRect(min(rect.x(), rect.maxX()),
1189 min(rect.y(), rect.maxY()), 1189 min(rect.y(), rect.maxY()),
1190 max(rect.width(), -rect.width()), 1190 max(rect.width(), -rect.width()),
1191 max(rect.height(), -rect.height())); 1191 max(rect.height(), -rect.height()));
1192 } 1192 }
1193 1193
1194 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect)
1195 {
1196 if (imageRect.contains(*srcRect))
1197 return;
1198
1199 // Compute the src to dst transform
1200 FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect-> size().height() / srcRect->size().height());
1201 FloatPoint scaledSrcLocation = srcRect->location();
1202 scaledSrcLocation.scale(scale.width(), scale.height());
1203 FloatSize offset = dstRect->location() - scaledSrcLocation;
1204
1205 srcRect->intersect(imageRect);
1206
1207 // To clip the destination rectangle in the same proportion, transform the c lipped src rect
1208 *dstRect = *srcRect;
1209 dstRect->scale(scale.width(), scale.height());
1210 dstRect->move(offset);
1211 }
1212
1194 void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const BlendMode& blendMode) 1213 void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const BlendMode& blendMode)
1195 { 1214 {
1196 if (!image) 1215 if (!image)
1197 return; 1216 return;
1198 1217
1199 GraphicsContext* c = drawingContext(); 1218 GraphicsContext* c = drawingContext();
1200 if (!c) 1219 if (!c)
1201 return; 1220 return;
1202 if (!state().m_invertibleCTM) 1221 if (!state().m_invertibleCTM)
1203 return; 1222 return;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1265 FloatRect normalizedDstRect = normalizeRect(dstRect); 1284 FloatRect normalizedDstRect = normalizeRect(dstRect);
1266 FloatRect actualDstRect(FloatPoint(bitmap->bitmapOffset()), bitmap->bitmapSi ze()); 1285 FloatRect actualDstRect(FloatPoint(bitmap->bitmapOffset()), bitmap->bitmapSi ze());
1267 actualDstRect.scale(normalizedDstRect.width() / bitmap->width(), normalizedD stRect.height() / bitmap->height()); 1286 actualDstRect.scale(normalizedDstRect.width() / bitmap->width(), normalizedD stRect.height() / bitmap->height());
1268 actualDstRect.moveBy(normalizedDstRect.location()); 1287 actualDstRect.moveBy(normalizedDstRect.location());
1269 1288
1270 FloatRect imageRect = FloatRect(FloatPoint(), bitmap->bitmapSize()); 1289 FloatRect imageRect = FloatRect(FloatPoint(), bitmap->bitmapSize());
1271 if (!srcRect.width() || !srcRect.height()) { 1290 if (!srcRect.width() || !srcRect.height()) {
1272 ec = IndexSizeError; 1291 ec = IndexSizeError;
1273 return; 1292 return;
1274 } 1293 }
1275 if (!imageRect.contains(normalizedSrcRect)) 1294 if (!imageRect.intersects(normalizedSrcRect))
1276 return; 1295 return;
1277 1296
1297 clipRectsToImageRect(imageRect, &normalizedSrcRect, &actualDstRect);
1298
1278 Image* imageForRendering = bitmap->bitmapImage(); 1299 Image* imageForRendering = bitmap->bitmapImage();
1279 1300
1280 drawImageInternal(imageForRendering, normalizedSrcRect, actualDstRect, state ().m_globalComposite, state().m_globalBlend); 1301 drawImageInternal(imageForRendering, normalizedSrcRect, actualDstRect, state ().m_globalComposite, state().m_globalBlend);
1281 } 1302 }
1282 1303
1283 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionCode& ec) 1304 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionCode& ec)
1284 { 1305 {
1285 if (!image) { 1306 if (!image) {
1286 ec = TypeMismatchError; 1307 ec = TypeMismatchError;
1287 return; 1308 return;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1333 return; 1354 return;
1334 1355
1335 FloatRect normalizedSrcRect = normalizeRect(srcRect); 1356 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1336 FloatRect normalizedDstRect = normalizeRect(dstRect); 1357 FloatRect normalizedDstRect = normalizeRect(dstRect);
1337 1358
1338 FloatRect imageRect = FloatRect(FloatPoint(), size(image)); 1359 FloatRect imageRect = FloatRect(FloatPoint(), size(image));
1339 if (!srcRect.width() || !srcRect.height()) { 1360 if (!srcRect.width() || !srcRect.height()) {
1340 ec = IndexSizeError; 1361 ec = IndexSizeError;
1341 return; 1362 return;
1342 } 1363 }
1343 if (!imageRect.contains(normalizedSrcRect)) 1364 if (!imageRect.intersects(normalizedSrcRect))
1344 return; 1365 return;
1345 1366
1367 clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect);
1368
1346 CachedImage* cachedImage = image->cachedImage(); 1369 CachedImage* cachedImage = image->cachedImage();
1347 if (!cachedImage) 1370 if (!cachedImage)
1348 return; 1371 return;
1349 1372
1350 checkOrigin(image); 1373 checkOrigin(image);
1351 1374
1352 Image* imageForRendering = cachedImage->imageForRenderer(image->renderer()); 1375 Image* imageForRendering = cachedImage->imageForRenderer(image->renderer());
1353 1376
1354 // For images that depend on an unavailable container size, we need to fall back to the intrinsic 1377 // For images that depend on an unavailable container size, we need to fall back to the intrinsic
1355 // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage 1378 // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1393 return; 1416 return;
1394 } 1417 }
1395 1418
1396 if (!srcRect.width() || !srcRect.height()) { 1419 if (!srcRect.width() || !srcRect.height()) {
1397 ec = IndexSizeError; 1420 ec = IndexSizeError;
1398 return; 1421 return;
1399 } 1422 }
1400 1423
1401 ec = 0; 1424 ec = 0;
1402 1425
1403 if (!srcCanvasRect.contains(normalizeRect(srcRect)) || !dstRect.width() || ! dstRect.height()) 1426 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1427 FloatRect normalizedDstRect = normalizeRect(dstRect);
1428
1429 if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width () || !normalizedDstRect.height())
1404 return; 1430 return;
1405 1431
1432 clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect);
1433
1406 GraphicsContext* c = drawingContext(); 1434 GraphicsContext* c = drawingContext();
1407 if (!c) 1435 if (!c)
1408 return; 1436 return;
1409 if (!state().m_invertibleCTM) 1437 if (!state().m_invertibleCTM)
1410 return; 1438 return;
1411 1439
1412 // FIXME: Do this through platform-independent GraphicsContext API. 1440 // FIXME: Do this through platform-independent GraphicsContext API.
1413 ImageBuffer* buffer = sourceCanvas->buffer(); 1441 ImageBuffer* buffer = sourceCanvas->buffer();
1414 if (!buffer) 1442 if (!buffer)
1415 return; 1443 return;
1416 1444
1417 checkOrigin(sourceCanvas); 1445 checkOrigin(sourceCanvas);
1418 1446
1419 // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable() 1447 // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable()
1420 // as that will do a readback to software. 1448 // as that will do a readback to software.
1421 CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext(); 1449 CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext();
1422 // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible. 1450 // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible.
1423 if (!isAccelerated() || !sourceContext || !sourceContext->isAccelerated() || !sourceContext->is2d()) 1451 if (!isAccelerated() || !sourceContext || !sourceContext->isAccelerated() || !sourceContext->is2d())
1424 sourceCanvas->makeRenderingResultsAvailable(); 1452 sourceCanvas->makeRenderingResultsAvailable();
1425 1453
1426 if (rectContainsCanvas(dstRect)) { 1454 if (rectContainsCanvas(normalizedDstRect)) {
1427 c->drawImageBuffer(buffer, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend); 1455 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend);
1428 didDrawEntireCanvas(); 1456 didDrawEntireCanvas();
1429 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { 1457 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
1430 fullCanvasCompositedDrawImage(buffer, dstRect, srcRect, state().m_global Composite); 1458 fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRe ct, state().m_globalComposite);
1431 didDrawEntireCanvas(); 1459 didDrawEntireCanvas();
1432 } else if (state().m_globalComposite == CompositeCopy) { 1460 } else if (state().m_globalComposite == CompositeCopy) {
1433 clearCanvas(); 1461 clearCanvas();
1434 c->drawImageBuffer(buffer, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend); 1462 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend);
1435 didDrawEntireCanvas(); 1463 didDrawEntireCanvas();
1436 } else { 1464 } else {
1437 c->drawImageBuffer(buffer, dstRect, srcRect, state().m_globalComposite, state().m_globalBlend); 1465 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend);
1438 didDraw(dstRect); 1466 didDraw(normalizedDstRect);
1439 } 1467 }
1440 } 1468 }
1441 1469
1442 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionCode& ec) 1470 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionCode& ec)
1443 { 1471 {
1444 if (!video) { 1472 if (!video) {
1445 ec = TypeMismatchError; 1473 ec = TypeMismatchError;
1446 return; 1474 return;
1447 } 1475 }
1448 IntSize s = size(video); 1476 IntSize s = size(video);
(...skipping 30 matching lines...) Expand all
1479 1507
1480 if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readySta te() == HTMLMediaElement::HAVE_METADATA) 1508 if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readySta te() == HTMLMediaElement::HAVE_METADATA)
1481 return; 1509 return;
1482 1510
1483 FloatRect videoRect = FloatRect(FloatPoint(), size(video)); 1511 FloatRect videoRect = FloatRect(FloatPoint(), size(video));
1484 if (!srcRect.width() || !srcRect.height()) { 1512 if (!srcRect.width() || !srcRect.height()) {
1485 ec = IndexSizeError; 1513 ec = IndexSizeError;
1486 return; 1514 return;
1487 } 1515 }
1488 1516
1489 if (!videoRect.contains(normalizeRect(srcRect)) || !dstRect.width() || !dstR ect.height()) 1517 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1518 FloatRect normalizedDstRect = normalizeRect(dstRect);
1519
1520 if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() | | !normalizedDstRect.height())
1490 return; 1521 return;
1491 1522
1523 clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect);
1524
1492 GraphicsContext* c = drawingContext(); 1525 GraphicsContext* c = drawingContext();
1493 if (!c) 1526 if (!c)
1494 return; 1527 return;
1495 if (!state().m_invertibleCTM) 1528 if (!state().m_invertibleCTM)
1496 return; 1529 return;
1497 1530
1498 checkOrigin(video); 1531 checkOrigin(video);
1499 1532
1500 GraphicsContextStateSaver stateSaver(*c); 1533 GraphicsContextStateSaver stateSaver(*c);
1501 c->clip(dstRect); 1534 c->clip(normalizedDstRect);
1502 c->translate(dstRect.x(), dstRect.y()); 1535 c->translate(normalizedDstRect.x(), normalizedDstRect.y());
1503 c->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / src Rect.height())); 1536 c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), no rmalizedDstRect.height() / normalizedSrcRect.height()));
1504 c->translate(-srcRect.x(), -srcRect.y()); 1537 c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y());
1505 video->paintCurrentFrameInContext(c, IntRect(IntPoint(), size(video))); 1538 video->paintCurrentFrameInContext(c, IntRect(IntPoint(), size(video)));
1506 stateSaver.restore(); 1539 stateSaver.restore();
1507 didDraw(dstRect); 1540 didDraw(dstRect);
1508 } 1541 }
1509 1542
1510 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, 1543 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image,
1511 float sx, float sy, float sw, float sh, 1544 float sx, float sy, float sw, float sh,
1512 float dx, float dy, float dw, float dh, 1545 float dx, float dy, float dw, float dh,
1513 const String& compositeOperation) 1546 const String& compositeOperation)
1514 { 1547 {
(...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after
2301 } 2334 }
2302 2335
2303 PassRefPtr<Canvas2DContextAttributes> CanvasRenderingContext2D::getContextAttrib utes() const 2336 PassRefPtr<Canvas2DContextAttributes> CanvasRenderingContext2D::getContextAttrib utes() const
2304 { 2337 {
2305 RefPtr<Canvas2DContextAttributes> attributes = Canvas2DContextAttributes::cr eate(); 2338 RefPtr<Canvas2DContextAttributes> attributes = Canvas2DContextAttributes::cr eate();
2306 attributes->setAlpha(m_hasAlpha); 2339 attributes->setAlpha(m_hasAlpha);
2307 return attributes.release(); 2340 return attributes.release();
2308 } 2341 }
2309 2342
2310 } // namespace WebCore 2343 } // namespace WebCore
OLDNEW
« no previous file with comments | « LayoutTests/virtual/gpu/canvas/philip/tests/2d.drawImage.outsidesource-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698