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

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

Issue 181693006: Refactoring source image usage in CanvasRenderingContext2D (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: response to comments Created 6 years, 9 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 | Annotate | Revision Log
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, 2013 Intel Corporation. All rights reserved. 8 * Copyright (C) 2012, 2013 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 #include "core/html/canvas/DOMPath.h" 56 #include "core/html/canvas/DOMPath.h"
57 #include "core/frame/ImageBitmap.h" 57 #include "core/frame/ImageBitmap.h"
58 #include "core/rendering/RenderImage.h" 58 #include "core/rendering/RenderImage.h"
59 #include "core/rendering/RenderLayer.h" 59 #include "core/rendering/RenderLayer.h"
60 #include "core/rendering/RenderTheme.h" 60 #include "core/rendering/RenderTheme.h"
61 #include "platform/fonts/FontCache.h" 61 #include "platform/fonts/FontCache.h"
62 #include "platform/geometry/FloatQuad.h" 62 #include "platform/geometry/FloatQuad.h"
63 #include "platform/graphics/GraphicsContextStateSaver.h" 63 #include "platform/graphics/GraphicsContextStateSaver.h"
64 #include "platform/graphics/DrawLooper.h" 64 #include "platform/graphics/DrawLooper.h"
65 #include "platform/text/TextRun.h" 65 #include "platform/text/TextRun.h"
66 #include "platform/weborigin/SecurityOrigin.h"
67 #include "wtf/CheckedArithmetic.h" 66 #include "wtf/CheckedArithmetic.h"
68 #include "wtf/MathExtras.h" 67 #include "wtf/MathExtras.h"
69 #include "wtf/OwnPtr.h" 68 #include "wtf/OwnPtr.h"
70 #include "wtf/Uint8ClampedArray.h" 69 #include "wtf/Uint8ClampedArray.h"
71 #include "wtf/text/StringBuilder.h" 70 #include "wtf/text/StringBuilder.h"
72 71
73 using namespace std; 72 using namespace std;
74 73
75 namespace WebCore { 74 namespace WebCore {
76 75
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 return; 282 return;
284 283
285 if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentColor(*style )) 284 if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentColor(*style ))
286 return; 285 return;
287 286
288 if (style->isCurrentColor()) { 287 if (style->isCurrentColor()) {
289 if (style->hasOverrideAlpha()) 288 if (style->hasOverrideAlpha())
290 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha())); 289 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha()));
291 else 290 else
292 style = CanvasStyle::createFromRGBA(currentColor(canvas())); 291 style = CanvasStyle::createFromRGBA(currentColor(canvas()));
293 } else 292 } else if (canvas()->originClean() && style->canvasPattern() && !style->canv asPattern()->originClean()) {
294 checkOrigin(style->canvasPattern()); 293 canvas()->setOriginTainted();
294 }
295 295
296 realizeSaves(); 296 realizeSaves();
297 modifiableState().m_strokeStyle = style.release(); 297 modifiableState().m_strokeStyle = style.release();
298 GraphicsContext* c = drawingContext(); 298 GraphicsContext* c = drawingContext();
299 if (!c) 299 if (!c)
300 return; 300 return;
301 state().m_strokeStyle->applyStrokeColor(c); 301 state().m_strokeStyle->applyStrokeColor(c);
302 modifiableState().m_unparsedStrokeColor = String(); 302 modifiableState().m_unparsedStrokeColor = String();
303 } 303 }
304 304
(...skipping 10 matching lines...) Expand all
315 return; 315 return;
316 316
317 if (state().m_fillStyle && state().m_fillStyle->isEquivalentColor(*style)) 317 if (state().m_fillStyle && state().m_fillStyle->isEquivalentColor(*style))
318 return; 318 return;
319 319
320 if (style->isCurrentColor()) { 320 if (style->isCurrentColor()) {
321 if (style->hasOverrideAlpha()) 321 if (style->hasOverrideAlpha())
322 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha())); 322 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha()));
323 else 323 else
324 style = CanvasStyle::createFromRGBA(currentColor(canvas())); 324 style = CanvasStyle::createFromRGBA(currentColor(canvas()));
325 } else 325 } else if (canvas()->originClean() && style->canvasPattern() && !style->canv asPattern()->originClean()) {
326 checkOrigin(style->canvasPattern()); 326 canvas()->setOriginTainted();
327 }
327 328
328 realizeSaves(); 329 realizeSaves();
329 modifiableState().m_fillStyle = style.release(); 330 modifiableState().m_fillStyle = style.release();
330 GraphicsContext* c = drawingContext(); 331 GraphicsContext* c = drawingContext();
331 if (!c) 332 if (!c)
332 return; 333 return;
333 state().m_fillStyle->applyFillColor(c); 334 state().m_fillStyle->applyFillColor(c);
334 modifiableState().m_unparsedFillColor = String(); 335 modifiableState().m_unparsedFillColor = String();
335 } 336 }
336 337
(...skipping 927 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 bool CanvasRenderingContext2D::shouldDrawShadows() const 1265 bool CanvasRenderingContext2D::shouldDrawShadows() const
1265 { 1266 {
1266 return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !stat e().m_shadowOffset.isZero()); 1267 return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !stat e().m_shadowOffset.isZero());
1267 } 1268 }
1268 1269
1269 enum ImageSizeType { 1270 enum ImageSizeType {
1270 ImageSizeAfterDevicePixelRatio, 1271 ImageSizeAfterDevicePixelRatio,
1271 ImageSizeBeforeDevicePixelRatio 1272 ImageSizeBeforeDevicePixelRatio
1272 }; 1273 };
1273 1274
1274 static LayoutSize sizeFor(HTMLImageElement* image, ImageSizeType sizeType)
1275 {
1276 LayoutSize size;
1277 ImageResource* cachedImage = image->cachedImage();
1278 if (cachedImage) {
1279 size = cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FI XME: Not sure about this.
1280
1281 if (sizeType == ImageSizeAfterDevicePixelRatio && image->renderer() && i mage->renderer()->isRenderImage() && cachedImage->image() && !cachedImage->image ()->hasRelativeWidth())
1282 size.scale(toRenderImage(image->renderer())->imageDevicePixelRatio() );
1283 }
1284 return size;
1285 }
1286
1287 static IntSize sizeFor(HTMLVideoElement* video)
1288 {
1289 if (MediaPlayer* player = video->player())
1290 return player->naturalSize();
1291 return IntSize();
1292 }
1293
1294 static inline FloatRect normalizeRect(const FloatRect& rect) 1275 static inline FloatRect normalizeRect(const FloatRect& rect)
1295 { 1276 {
1296 return FloatRect(min(rect.x(), rect.maxX()), 1277 return FloatRect(min(rect.x(), rect.maxX()),
1297 min(rect.y(), rect.maxY()), 1278 min(rect.y(), rect.maxY()),
1298 max(rect.width(), -rect.width()), 1279 max(rect.width(), -rect.width()),
1299 max(rect.height(), -rect.height())); 1280 max(rect.height(), -rect.height()));
1300 } 1281 }
1301 1282
1302 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect) 1283 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect)
1303 { 1284 {
1304 if (imageRect.contains(*srcRect)) 1285 if (imageRect.contains(*srcRect))
1305 return; 1286 return;
1306 1287
1307 // Compute the src to dst transform 1288 // Compute the src to dst transform
1308 FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect-> size().height() / srcRect->size().height()); 1289 FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect-> size().height() / srcRect->size().height());
1309 FloatPoint scaledSrcLocation = srcRect->location(); 1290 FloatPoint scaledSrcLocation = srcRect->location();
1310 scaledSrcLocation.scale(scale.width(), scale.height()); 1291 scaledSrcLocation.scale(scale.width(), scale.height());
1311 FloatSize offset = dstRect->location() - scaledSrcLocation; 1292 FloatSize offset = dstRect->location() - scaledSrcLocation;
1312 1293
1313 srcRect->intersect(imageRect); 1294 srcRect->intersect(imageRect);
1314 1295
1315 // To clip the destination rectangle in the same proportion, transform the c lipped src rect 1296 // To clip the destination rectangle in the same proportion, transform the c lipped src rect
1316 *dstRect = *srcRect; 1297 *dstRect = *srcRect;
1317 dstRect->scale(scale.width(), scale.height()); 1298 dstRect->scale(scale.width(), scale.height());
1318 dstRect->move(offset); 1299 dstRect->move(offset);
1319 } 1300 }
1320 1301
1321 void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::Web BlendMode& blendMode) 1302 static bool checkImageSource(CanvasImageSource* imageSource, ExceptionState& exc eptionState)
1322 { 1303 {
1323 if (!image) 1304 if (!imageSource) {
1324 return; 1305 // FIXME: Message should mention ImageBitmap once that feature ships.
1325 1306 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, String("HTMLImageElement, HTMLCanvasElement or HTM LVideoElement")));
1326 GraphicsContext* c = drawingContext(); 1307 return false;
1327 if (!c)
1328 return;
1329 if (!state().m_invertibleCTM)
1330 return;
1331 FloatRect clipBounds;
1332 if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1333 return;
1334
1335 if (rectContainsTransformedRect(dstRect, clipBounds)) {
1336 c->drawImage(image, dstRect, srcRect, op, blendMode);
1337 didDraw(clipBounds);
1338 } else if (isFullCanvasCompositeMode(op)) {
1339 fullCanvasCompositedDrawImage(image, dstRect, srcRect, op);
1340 didDraw(clipBounds);
1341 } else if (op == CompositeCopy) {
1342 clearCanvas();
1343 c->drawImage(image, dstRect, srcRect, op, blendMode);
1344 didDraw(clipBounds);
1345 } else {
1346 FloatRect dirtyRect;
1347 if (computeDirtyRect(dstRect, &dirtyRect)) {
1348 c->drawImage(image, dstRect, srcRect, op, blendMode);
1349 didDraw(dirtyRect);
1350 }
1351 } 1308 }
1309 return true;
1352 } 1310 }
1353 1311
1354 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, float x, float y, ExceptionState& exceptionState) 1312 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float x , float y, ExceptionState& exceptionState)
1355 { 1313 {
1356 if (!bitmap) { 1314 if (!checkImageSource(imageSource, exceptionState))
1357 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap"));
1358 return; 1315 return;
1359 } 1316 FloatSize destRectSize = imageSource->defaultDestinationSize();
1360 drawImage(bitmap, x, y, bitmap->width(), bitmap->height(), exceptionState); 1317 drawImage(imageSource, x, y, destRectSize.width(), destRectSize.height(), ex ceptionState);
1361 } 1318 }
1362 1319
1363 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, 1320 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
1364 float x, float y, float width, float height, ExceptionState& exceptionState) 1321 float x, float y, float width, float height, ExceptionState& exceptionState)
1365 { 1322 {
1366 if (!bitmap) { 1323 if (!checkImageSource(imageSource, exceptionState))
1367 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap"));
1368 return; 1324 return;
1369 } 1325 FloatSize sourceRectSize = imageSource->sourceSize();
1370 if (!bitmap->bitmapRect().width() || !bitmap->bitmapRect().height()) 1326 drawImage(imageSource, 0, 0, sourceRectSize.width(), sourceRectSize.height() , x, y, width, height, exceptionState);
1371 return;
1372
1373 drawImage(bitmap, 0, 0, bitmap->width(), bitmap->height(), x, y, width, heig ht, exceptionState);
1374 } 1327 }
1375 1328
1376 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, 1329 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
1377 float sx, float sy, float sw, float sh, 1330 float sx, float sy, float sw, float sh,
1378 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1331 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1379 { 1332 {
1380 if (!bitmap) { 1333 if (!checkImageSource(imageSource, exceptionState))
1381 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap"));
1382 return;
1383 }
1384
1385 FloatRect srcRect(sx, sy, sw, sh);
1386 FloatRect dstRect(dx, dy, dw, dh);
1387 FloatRect bitmapRect = bitmap->bitmapRect();
1388
1389 if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfi nite(dstRect.width()) || !std::isfinite(dstRect.height())
1390 || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::i sfinite(srcRect.width()) || !std::isfinite(srcRect.height()))
1391 return; 1334 return;
1392 1335
1393 if (!dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.he ight())
1394 return;
1395
1396 ASSERT(bitmap->height() && bitmap->width());
1397 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1398 FloatRect normalizedDstRect = normalizeRect(dstRect);
1399
1400 // Clip the rects to where the user thinks that the image is situated.
1401 clipRectsToImageRect(IntRect(IntPoint(), bitmap->size()), &normalizedSrcRect , &normalizedDstRect);
1402
1403 FloatRect intersectRect = intersection(bitmapRect, normalizedSrcRect);
1404 FloatRect actualSrcRect(intersectRect);
1405
1406 IntPoint bitmapOffset = bitmap->bitmapOffset();
1407 actualSrcRect.move(bitmapOffset - bitmapRect.location());
1408 FloatRect imageRect = FloatRect(bitmapOffset, bitmapRect.size());
1409
1410 FloatRect actualDstRect(FloatPoint(intersectRect.location() - normalizedSrcR ect.location()), bitmapRect.size());
1411 actualDstRect.scale(normalizedDstRect.width() / normalizedSrcRect.width() * intersectRect.width() / bitmapRect.width(),
1412 normalizedDstRect.height() / normalizedSrcRect.height() * intersectRect. height() / bitmapRect.height());
1413 actualDstRect.moveBy(normalizedDstRect.location());
1414
1415 if (!imageRect.intersects(actualSrcRect))
1416 return;
1417
1418 RefPtr<Image> imageForRendering = bitmap->bitmapImage();
1419 if (!imageForRendering)
1420 return;
1421
1422 drawImageInternal(imageForRendering.get(), actualSrcRect, actualDstRect, sta te().m_globalComposite, state().m_globalBlend);
1423 }
1424
1425 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionState& exceptionState)
1426 {
1427 if (!image) {
1428 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1429 return;
1430 }
1431 LayoutSize destRectSize = sizeFor(image, ImageSizeAfterDevicePixelRatio);
1432 drawImage(image, x, y, destRectSize.width(), destRectSize.height(), exceptio nState);
1433 }
1434
1435 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
1436 float x, float y, float width, float height, ExceptionState& exceptionState)
1437 {
1438 if (!image) {
1439 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1440 return;
1441 }
1442 LayoutSize sourceRectSize = sizeFor(image, ImageSizeBeforeDevicePixelRatio);
1443 drawImage(image, FloatRect(0, 0, sourceRectSize.width(), sourceRectSize.heig ht()), FloatRect(x, y, width, height), exceptionState);
1444 }
1445
1446 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
1447 float sx, float sy, float sw, float sh,
1448 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1449 {
1450 drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), excep tionState);
1451 }
1452
1453 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec t& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState)
1454 {
1455 drawImage(image, srcRect, dstRect, state().m_globalComposite, state().m_glob alBlend, exceptionState);
1456 }
1457
1458 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec t& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink:: WebBlendMode& blendMode, ExceptionState& exceptionState)
1459 {
1460 if (!image) {
1461 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1462 return;
1463 }
1464
1465 if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfi nite(dstRect.width()) || !std::isfinite(dstRect.height())
1466 || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::i sfinite(srcRect.width()) || !std::isfinite(srcRect.height()))
1467 return;
1468
1469 ImageResource* cachedImage = image->cachedImage();
1470 if (!cachedImage || !image->complete())
1471 return;
1472
1473 LayoutSize size = sizeFor(image, ImageSizeBeforeDevicePixelRatio);
1474 if (!size.width() || !size.height() || !dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.height())
1475 return;
1476
1477 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1478 FloatRect normalizedDstRect = normalizeRect(dstRect);
1479
1480 FloatRect imageRect = FloatRect(FloatPoint(), size);
1481 if (!imageRect.intersects(normalizedSrcRect))
1482 return;
1483
1484 clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect);
1485
1486 checkOrigin(image);
1487
1488 Image* imageForRendering = cachedImage->imageForRenderer(image->renderer());
1489
1490 // For images that depend on an unavailable container size, we need to fall back to the intrinsic
1491 // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage
1492 // FIXME: Without a specified image size this should resolve against the can vas element's size, see: crbug.com/230163.
1493 if (!image->renderer() && imageForRendering->usesContainerSize())
1494 imageForRendering->setContainerSize(imageForRendering->size());
1495
1496 drawImageInternal(imageForRendering, normalizedSrcRect, normalizedDstRect, o p, blendMode);
1497 }
1498
1499 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, float x, float y, ExceptionState& exceptionState)
1500 {
1501 drawImage(sourceCanvas, 0, 0, sourceCanvas->width(), sourceCanvas->height(), x, y, sourceCanvas->width(), sourceCanvas->height(), exceptionState);
1502 }
1503
1504 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas,
1505 float x, float y, float width, float height, ExceptionState& exceptionState)
1506 {
1507 drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas->width(), sourceCanvas- >height()), FloatRect(x, y, width, height), exceptionState);
1508 }
1509
1510 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas,
1511 float sx, float sy, float sw, float sh,
1512 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1513 {
1514 drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh) , exceptionState);
1515 }
1516
1517 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect,
1518 const FloatRect& dstRect, ExceptionState& exceptionState)
1519 {
1520 if (!sourceCanvas) {
1521 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLCanvasElement"));
1522 return;
1523 }
1524
1525 FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size());
1526
1527 if (!srcCanvasRect.width() || !srcCanvasRect.height() || !srcRect.width() || !srcRect.height())
1528 return;
1529
1530 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1531 FloatRect normalizedDstRect = normalizeRect(dstRect);
1532
1533 if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width () || !normalizedDstRect.height())
1534 return;
1535
1536 clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect);
1537
1538 GraphicsContext* c = drawingContext();
1539 if (!c)
1540 return;
1541 if (!state().m_invertibleCTM) 1336 if (!state().m_invertibleCTM)
1542 return; 1337 return;
1543 1338
1544 // FIXME: Do this through platform-independent GraphicsContext API. 1339 RefPtr<Image> image;
1545 ImageBuffer* buffer = sourceCanvas->buffer(); 1340 bool imageSourceIsVolatile = false;
1546 if (!buffer) 1341 if (!imageSource->isVideoElement()) {
1342 CanvasImageSourceUsage usage = canvas()->asCanvasImageSource() == imageS ource ? DrawToSelfCanvasImageSourceUsage : DrawCanvasImageSourceUsage;
1343 image = imageSource->getSourceImageForCanvas(exceptionState, usage, &ima geSourceIsVolatile);
1344 if (!image || !image->width() || !image->height())
1345 return;
1346 }
1347
1348 if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dw) || !std:: isfinite(dh)
1349 || !std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !st d::isfinite(sh)
1350 || !dw || !dh || !sw || !sh)
1547 return; 1351 return;
1548 1352
1549 FloatRect clipBounds; 1353 FloatRect clipBounds;
1550 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) 1354 if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1551 return; 1355 return;
1552 1356
1553 checkOrigin(sourceCanvas); 1357 FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh));
1358 FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh));
1554 1359
1555 // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable() 1360 clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->sourceSize()), &sr cRect, &dstRect);
1556 // as that will do a readback to software.
1557 CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext();
1558 // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible.
1559 if (sourceContext && sourceContext->is3d())
1560 sourceContext->paintRenderingResultsToCanvas();
1561 1361
1562 if (rectContainsTransformedRect(normalizedDstRect, clipBounds)) { 1362 imageSource->adjustDrawRects(&srcRect, &dstRect);
1563 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend);
1564 didDraw(clipBounds);
1565 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
1566 fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRe ct, state().m_globalComposite);
1567 didDraw(clipBounds);
1568 } else if (state().m_globalComposite == CompositeCopy) {
1569 clearCanvas();
1570 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend);
1571 didDraw(clipBounds);
1572 } else {
1573 FloatRect dirtyRect;
1574 if (computeDirtyRect(normalizedDstRect, clipBounds, &dirtyRect)) {
1575 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, sta te().m_globalComposite, state().m_globalBlend);
1576 didDraw(dirtyRect);
1577 }
1578 }
1579 1363
1580 // Flush canvas's ImageBuffer when drawImage from WebGL to HW accelerated 2d canvas 1364 if (srcRect.isEmpty())
1581 if (sourceContext && sourceContext->is3d() && is2d() && isAccelerated() && c anvas()->buffer())
1582 canvas()->buffer()->flush();
1583 }
1584
1585 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionState& exceptionState)
1586 {
1587 if (!video) {
1588 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement"));
1589 return; 1365 return;
1590 }
1591 IntSize size = sizeFor(video);
1592 drawImage(video, x, y, size.width(), size.height(), exceptionState);
1593 }
1594
1595 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
1596 float x, float y, float width, float height, ExceptionState& exceptionState)
1597 {
1598 if (!video) {
1599 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement"));
1600 return;
1601 }
1602 IntSize size = sizeFor(video);
1603 drawImage(video, FloatRect(0, 0, size.width(), size.height()), FloatRect(x, y, width, height), exceptionState);
1604 }
1605
1606 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
1607 float sx, float sy, float sw, float sh,
1608 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1609 {
1610 drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), excep tionState);
1611 }
1612
1613 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec t& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState)
1614 {
1615 if (!video) {
1616 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement"));
1617 return;
1618 }
1619
1620 if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readySta te() == HTMLMediaElement::HAVE_METADATA)
1621 return;
1622 if (!srcRect.width() || !srcRect.height())
1623 return;
1624
1625 FloatRect videoRect = FloatRect(FloatPoint(), sizeFor(video));
1626
1627 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1628 FloatRect normalizedDstRect = normalizeRect(dstRect);
1629
1630 if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() | | !normalizedDstRect.height())
1631 return;
1632
1633 clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect);
1634 1366
1635 GraphicsContext* c = drawingContext(); 1367 GraphicsContext* c = drawingContext();
1636 if (!c) 1368 if (!c)
1637 return; 1369 return;
1638 if (!state().m_invertibleCTM)
1639 return;
1640 1370
1641 checkOrigin(video); 1371 FloatRect dirtyRect = clipBounds;
1372 if (imageSource->isVideoElement()) {
1373 GraphicsContextStateSaver stateSaver(*c);
1374 c->clip(dstRect);
1375 c->translate(dstRect.x(), dstRect.y());
1376 c->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()));
1377 c->translate(-srcRect.x(), -srcRect.y());
1378 static_cast<HTMLVideoElement*>(imageSource)->paintCurrentFrameInContext( c, IntRect(IntPoint(), roundedIntSize(imageSource->sourceSize())));
1379 stateSaver.restore();
1380 computeDirtyRect(dstRect, clipBounds, &dirtyRect);
1381 } else {
1382 CompositeOperator op = c->compositeOperation();
1383 blink::WebBlendMode blendMode = c->blendModeOperation();
1384 if (rectContainsTransformedRect(dstRect, clipBounds)) {
1385 c->drawImage(image.get(), dstRect, srcRect, op, blendMode);
1386 } else if (isFullCanvasCompositeMode(op)) {
1387 fullCanvasCompositedDrawImage(image.get(), dstRect, srcRect, op);
1388 } else if (op == CompositeCopy) {
1389 clearCanvas();
1390 c->drawImage(image.get(), dstRect, srcRect, op, blendMode);
1391 } else {
1392 FloatRect dirtyRect;
1393 computeDirtyRect(dstRect, clipBounds, &dirtyRect);
1394 c->drawImage(image.get(), dstRect, srcRect, op, blendMode);
1395 }
1642 1396
1643 FloatRect dirtyRect; 1397 if (imageSourceIsVolatile && is2d() && isAccelerated() && canvas()->buff er())
1644 if (!computeDirtyRect(normalizedDstRect, &dirtyRect)) 1398 canvas()->buffer()->flush();
1645 return; 1399 }
1646 1400
1647 GraphicsContextStateSaver stateSaver(*c); 1401 if (canvas()->originClean() && imageSource->wouldTaintOrigin(canvas()->secur ityOrigin()))
1648 c->clip(normalizedDstRect); 1402 canvas()->setOriginTainted();
1649 c->translate(normalizedDstRect.x(), normalizedDstRect.y());
1650 c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), no rmalizedDstRect.height() / normalizedSrcRect.height()));
1651 c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y());
1652 video->paintCurrentFrameInContext(c, IntRect(IntPoint(), sizeFor(video)));
1653 stateSaver.restore();
1654 1403
1655 didDraw(dirtyRect); 1404 didDraw(dirtyRect);
1656 } 1405 }
1657 1406
1407
1658 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, 1408 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image,
1659 float sx, float sy, float sw, float sh, 1409 float sx, float sy, float sw, float sh,
1660 float dx, float dy, float dw, float dh, 1410 float dx, float dy, float dw, float dh,
1661 const String& compositeOperation) 1411 const String& compositeOperation)
1662 { 1412 {
1413 GraphicsContext* c = drawingContext();
1414 if (!c)
1415 return;
1663 CompositeOperator op; 1416 CompositeOperator op;
1664 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; 1417 blink::WebBlendMode blendOp = blink::WebBlendModeNormal;
1665 if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blen dOp != blink::WebBlendModeNormal) 1418 if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blen dOp != blink::WebBlendModeNormal)
1666 op = CompositeSourceOver; 1419 op = CompositeSourceOver;
1667 1420
1668 drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, b link::WebBlendModeNormal, IGNORE_EXCEPTION); 1421 CompositeOperator savedOp = c->compositeOperation();
1422 blink::WebBlendMode savedBlendMode = c->blendModeOperation();
1423 c->setCompositeOperation(op, blink::WebBlendModeNormal);
1424 drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, IGNORE_EXCEPTION);
1425 c->setCompositeOperation(savedOp, savedBlendMode);
1669 } 1426 }
1670 1427
1671 void CanvasRenderingContext2D::setAlpha(float alpha) 1428 void CanvasRenderingContext2D::setAlpha(float alpha)
1672 { 1429 {
1673 setGlobalAlpha(alpha); 1430 setGlobalAlpha(alpha);
1674 } 1431 }
1675 1432
1676 void CanvasRenderingContext2D::setCompositeOperation(const String& operation) 1433 void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
1677 { 1434 {
1678 setGlobalCompositeOperation(operation); 1435 setGlobalCompositeOperation(operation);
(...skipping 17 matching lines...) Expand all
1696 FloatQuad quad(rect); 1453 FloatQuad quad(rect);
1697 FloatQuad transformedQuad(transformedRect); 1454 FloatQuad transformedQuad(transformedRect);
1698 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); 1455 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad);
1699 } 1456 }
1700 1457
1701 static void drawImageToContext(Image* image, GraphicsContext* context, const Flo atRect& dest, const FloatRect& src, CompositeOperator op) 1458 static void drawImageToContext(Image* image, GraphicsContext* context, const Flo atRect& dest, const FloatRect& src, CompositeOperator op)
1702 { 1459 {
1703 context->drawImage(image, dest, src, op); 1460 context->drawImage(image, dest, src, op);
1704 } 1461 }
1705 1462
1706 static void drawImageToContext(ImageBuffer* imageBuffer, GraphicsContext* contex t, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
1707 {
1708 context->drawImageBuffer(imageBuffer, dest, src, op);
1709 }
1710
1711 template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage( T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op) 1463 template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage( T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
1712 { 1464 {
1713 ASSERT(isFullCanvasCompositeMode(op)); 1465 ASSERT(isFullCanvasCompositeMode(op));
1714 1466
1715 drawingContext()->beginLayer(1, op); 1467 drawingContext()->beginLayer(1, op);
1716 drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver); 1468 drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver);
1717 drawingContext()->endLayer(); 1469 drawingContext()->endLayer();
1718 } 1470 }
1719 1471
1720 static void fillPrimitive(const FloatRect& rect, GraphicsContext* context) 1472 static void fillPrimitive(const FloatRect& rect, GraphicsContext* context)
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 else if (r0 < 0 || r1 < 0) 1528 else if (r0 < 0 || r1 < 0)
1777 exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); 1529 exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1"));
1778 1530
1779 if (exceptionState.hadException()) 1531 if (exceptionState.hadException())
1780 return nullptr; 1532 return nullptr;
1781 1533
1782 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); 1534 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
1783 return gradient.release(); 1535 return gradient.release();
1784 } 1536 }
1785 1537
1786 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme nt* image, 1538 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(CanvasImageSou rce* imageSource,
1787 const String& repetitionType, ExceptionState& exceptionState) 1539 const String& repetitionType, ExceptionState& exceptionState)
1788 { 1540 {
1789 if (!image) { 1541 if (!checkImageSource(imageSource, exceptionState))
1790 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1791 return nullptr; 1542 return nullptr;
1792 }
1793 bool repeatX, repeatY; 1543 bool repeatX, repeatY;
1794 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState); 1544 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState);
1795 if (exceptionState.hadException()) 1545 if (exceptionState.hadException())
1796 return nullptr; 1546 return nullptr;
1797 1547
1798 if (!image->complete()) 1548 RefPtr<Image> imageForRendering = imageSource->getSourceImageForCanvas(excep tionState, PatternCanvasImageSourceUsage);
1549 if (exceptionState.hadException() || !imageForRendering)
1799 return nullptr; 1550 return nullptr;
1800 1551
1801 ImageResource* cachedImage = image->cachedImage(); 1552 return CanvasPattern::create(imageForRendering.release(), repeatX, repeatY, !imageSource->wouldTaintOrigin(canvas()->securityOrigin()));
1802 Image* imageForRendering = cachedImage ? cachedImage->imageForRenderer(image ->renderer()) : 0;
1803 if (!imageForRendering)
1804 return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true) ;
1805
1806 // We need to synthesize a container size if a renderer is not available to provide one.
1807 if (!image->renderer() && imageForRendering->usesContainerSize())
1808 imageForRendering->setContainerSize(imageForRendering->size());
1809
1810 bool originClean = cachedImage->isAccessAllowed(canvas()->securityOrigin());
1811 return CanvasPattern::create(imageForRendering, repeatX, repeatY, originClea n);
1812 }
1813
1814 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElem ent* canvas,
1815 const String& repetitionType, ExceptionState& exceptionState)
1816 {
1817 if (!canvas)
1818 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLCanvasElement"));
1819 else if (!canvas->width() || !canvas->height())
1820 exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", canvas->width() ? "height" : "width"));
1821
1822 if (exceptionState.hadException())
1823 return nullptr;
1824
1825 bool repeatX, repeatY;
1826 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState);
1827 if (exceptionState.hadException())
1828 return nullptr;
1829 return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas ->originClean());
1830 } 1553 }
1831 1554
1832 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, Floa tRect* dirtyRect) 1555 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, Floa tRect* dirtyRect)
1833 { 1556 {
1834 FloatRect clipBounds; 1557 FloatRect clipBounds;
1835 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) 1558 if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1836 return false; 1559 return false;
1837 return computeDirtyRect(localRect, clipBounds, dirtyRect); 1560 return computeDirtyRect(localRect, clipBounds, dirtyRect);
1838 } 1561 }
1839 1562
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
2469 const int focusRingWidth = 5; 2192 const int focusRingWidth = 5;
2470 const int focusRingOutline = 0; 2193 const int focusRingOutline = 0;
2471 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); 2194 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2472 2195
2473 c->restore(); 2196 c->restore();
2474 2197
2475 didDraw(dirtyRect); 2198 didDraw(dirtyRect);
2476 } 2199 }
2477 2200
2478 } // namespace WebCore 2201 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698