Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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(); |
|
Stephen White
2014/03/10 15:27:03
Do we have tests for pattern tainting (or tainting
| |
| 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 Loading... | |
| 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 961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1298 bool CanvasRenderingContext2D::shouldDrawShadows() const | 1299 bool CanvasRenderingContext2D::shouldDrawShadows() const |
| 1299 { | 1300 { |
| 1300 return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !stat e().m_shadowOffset.isZero()); | 1301 return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !stat e().m_shadowOffset.isZero()); |
| 1301 } | 1302 } |
| 1302 | 1303 |
| 1303 enum ImageSizeType { | 1304 enum ImageSizeType { |
| 1304 ImageSizeAfterDevicePixelRatio, | 1305 ImageSizeAfterDevicePixelRatio, |
| 1305 ImageSizeBeforeDevicePixelRatio | 1306 ImageSizeBeforeDevicePixelRatio |
| 1306 }; | 1307 }; |
| 1307 | 1308 |
| 1308 static LayoutSize sizeFor(HTMLImageElement* image, ImageSizeType sizeType) | |
| 1309 { | |
| 1310 LayoutSize size; | |
| 1311 ImageResource* cachedImage = image->cachedImage(); | |
| 1312 if (cachedImage) { | |
| 1313 size = cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FI XME: Not sure about this. | |
| 1314 | |
| 1315 if (sizeType == ImageSizeAfterDevicePixelRatio && image->renderer() && i mage->renderer()->isRenderImage() && cachedImage->image() && !cachedImage->image ()->hasRelativeWidth()) | |
| 1316 size.scale(toRenderImage(image->renderer())->imageDevicePixelRatio() ); | |
| 1317 } | |
| 1318 return size; | |
| 1319 } | |
| 1320 | |
| 1321 static IntSize sizeFor(HTMLVideoElement* video) | |
| 1322 { | |
| 1323 if (MediaPlayer* player = video->player()) | |
| 1324 return player->naturalSize(); | |
| 1325 return IntSize(); | |
| 1326 } | |
| 1327 | |
| 1328 static inline FloatRect normalizeRect(const FloatRect& rect) | 1309 static inline FloatRect normalizeRect(const FloatRect& rect) |
| 1329 { | 1310 { |
| 1330 return FloatRect(min(rect.x(), rect.maxX()), | 1311 return FloatRect(min(rect.x(), rect.maxX()), |
| 1331 min(rect.y(), rect.maxY()), | 1312 min(rect.y(), rect.maxY()), |
| 1332 max(rect.width(), -rect.width()), | 1313 max(rect.width(), -rect.width()), |
| 1333 max(rect.height(), -rect.height())); | 1314 max(rect.height(), -rect.height())); |
| 1334 } | 1315 } |
| 1335 | 1316 |
| 1336 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect) | 1317 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect) |
| 1337 { | 1318 { |
| 1338 if (imageRect.contains(*srcRect)) | 1319 if (imageRect.contains(*srcRect)) |
| 1339 return; | 1320 return; |
| 1340 | 1321 |
| 1341 // Compute the src to dst transform | 1322 // Compute the src to dst transform |
| 1342 FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect-> size().height() / srcRect->size().height()); | 1323 FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect-> size().height() / srcRect->size().height()); |
| 1343 FloatPoint scaledSrcLocation = srcRect->location(); | 1324 FloatPoint scaledSrcLocation = srcRect->location(); |
| 1344 scaledSrcLocation.scale(scale.width(), scale.height()); | 1325 scaledSrcLocation.scale(scale.width(), scale.height()); |
| 1345 FloatSize offset = dstRect->location() - scaledSrcLocation; | 1326 FloatSize offset = dstRect->location() - scaledSrcLocation; |
| 1346 | 1327 |
| 1347 srcRect->intersect(imageRect); | 1328 srcRect->intersect(imageRect); |
| 1348 | 1329 |
| 1349 // To clip the destination rectangle in the same proportion, transform the c lipped src rect | 1330 // To clip the destination rectangle in the same proportion, transform the c lipped src rect |
| 1350 *dstRect = *srcRect; | 1331 *dstRect = *srcRect; |
| 1351 dstRect->scale(scale.width(), scale.height()); | 1332 dstRect->scale(scale.width(), scale.height()); |
| 1352 dstRect->move(offset); | 1333 dstRect->move(offset); |
| 1353 } | 1334 } |
| 1354 | 1335 |
| 1355 void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::Web BlendMode& blendMode) | 1336 static bool checkImageSource(CanvasImageSource* imageSource, ExceptionState& exc eptionState) |
| 1356 { | 1337 { |
| 1357 if (!image) | 1338 if (!imageSource) { |
| 1358 return; | 1339 // FIXME: Message should mention ImageBitmap once that feature ships. |
| 1359 | 1340 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, String("HTMLImageElement, HTMLCanvasElement or HTM LVideoElement"))); |
| 1360 GraphicsContext* c = drawingContext(); | 1341 return false; |
| 1361 if (!c) | |
| 1362 return; | |
| 1363 if (!state().m_invertibleCTM) | |
| 1364 return; | |
| 1365 FloatRect clipBounds; | |
| 1366 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) | |
| 1367 return; | |
| 1368 | |
| 1369 if (rectContainsTransformedRect(dstRect, clipBounds)) { | |
| 1370 c->drawImage(image, dstRect, srcRect, op, blendMode); | |
| 1371 didDraw(clipBounds); | |
| 1372 } else if (isFullCanvasCompositeMode(op)) { | |
| 1373 fullCanvasCompositedDrawImage(image, dstRect, srcRect, op); | |
| 1374 didDraw(clipBounds); | |
| 1375 } else if (op == CompositeCopy) { | |
| 1376 clearCanvas(); | |
| 1377 c->drawImage(image, dstRect, srcRect, op, blendMode); | |
| 1378 didDraw(clipBounds); | |
| 1379 } else { | |
| 1380 FloatRect dirtyRect; | |
| 1381 if (computeDirtyRect(dstRect, &dirtyRect)) { | |
| 1382 c->drawImage(image, dstRect, srcRect, op, blendMode); | |
| 1383 didDraw(dirtyRect); | |
| 1384 } | |
| 1385 } | 1342 } |
| 1343 return true; | |
| 1386 } | 1344 } |
| 1387 | 1345 |
| 1388 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, float x, float y, ExceptionState& exceptionState) | 1346 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float x , float y, ExceptionState& exceptionState) |
| 1389 { | 1347 { |
| 1390 if (!bitmap) { | 1348 if (!checkImageSource(imageSource, exceptionState)) |
| 1391 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap")); | |
| 1392 return; | 1349 return; |
| 1393 } | 1350 FloatSize destRectSize = imageSource->defaultDestinationSize(); |
| 1394 drawImage(bitmap, x, y, bitmap->width(), bitmap->height(), exceptionState); | 1351 drawImage(imageSource, x, y, destRectSize.width(), destRectSize.height(), ex ceptionState); |
| 1395 } | 1352 } |
| 1396 | 1353 |
| 1397 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, | 1354 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
| 1398 float x, float y, float width, float height, ExceptionState& exceptionState) | 1355 float x, float y, float width, float height, ExceptionState& exceptionState) |
| 1399 { | 1356 { |
| 1400 if (!bitmap) { | 1357 if (!checkImageSource(imageSource, exceptionState)) |
| 1401 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap")); | |
| 1402 return; | 1358 return; |
| 1403 } | 1359 FloatSize sourceRectSize = imageSource->sourceSize(); |
| 1404 if (!bitmap->bitmapRect().width() || !bitmap->bitmapRect().height()) | 1360 drawImage(imageSource, 0, 0, sourceRectSize.width(), sourceRectSize.height() , x, y, width, height, exceptionState); |
| 1405 return; | |
| 1406 | |
| 1407 drawImage(bitmap, 0, 0, bitmap->width(), bitmap->height(), x, y, width, heig ht, exceptionState); | |
| 1408 } | 1361 } |
| 1409 | 1362 |
| 1410 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, | 1363 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
| 1411 float sx, float sy, float sw, float sh, | 1364 float sx, float sy, float sw, float sh, |
| 1412 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) | 1365 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) |
| 1413 { | 1366 { |
| 1414 if (!bitmap) { | 1367 GraphicsContext* c = drawingContext(); // Do not exit yet if !c because we m ay need to throw exceptions first |
| 1415 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap")); | 1368 CompositeOperator op = c ? c->compositeOperation() : CompositeSourceOver; |
| 1369 blink::WebBlendMode blendMode = c ? c->blendModeOperation() : blink::WebBlen dModeNormal; | |
| 1370 drawImageInternal(imageSource, sx, sy, sw, sh, dx, dy, dw, dh, exceptionStat e, op, blendMode); | |
| 1371 } | |
| 1372 | |
| 1373 void CanvasRenderingContext2D::drawImageInternal(CanvasImageSource* imageSource, | |
| 1374 float sx, float sy, float sw, float sh, | |
| 1375 float dx, float dy, float dw, float dh, ExceptionState& exceptionState, | |
| 1376 CompositeOperator op, blink::WebBlendMode blendMode) | |
| 1377 { | |
| 1378 if (!checkImageSource(imageSource, exceptionState)) | |
| 1416 return; | 1379 return; |
| 1380 | |
| 1381 RefPtr<Image> image; | |
| 1382 SourceImageStatus sourceImageStatus; | |
| 1383 if (!imageSource->isVideoElement()) { | |
| 1384 SourceImageMode mode = canvas()->asCanvasImageSource() == imageSource ? CopySourceImageIfVolatile : DontCopySourceImage; | |
|
Stephen White
2014/03/10 15:27:03
As discussed, this could just be canvas() == image
| |
| 1385 image = imageSource->getSourceImageForCanvas(mode, &sourceImageStatus); | |
| 1386 if (sourceImageStatus == UndecodableSourceImageStatus) | |
| 1387 exceptionState.throwDOMException(InvalidStateError, "The HTMLImageEl ement provided is in the 'broken' state."); | |
| 1388 if (!image || !image->width() || !image->height()) | |
| 1389 return; | |
| 1417 } | 1390 } |
| 1418 | 1391 |
| 1419 FloatRect srcRect(sx, sy, sw, sh); | |
| 1420 FloatRect dstRect(dx, dy, dw, dh); | |
| 1421 FloatRect bitmapRect = bitmap->bitmapRect(); | |
| 1422 | |
| 1423 if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfi nite(dstRect.width()) || !std::isfinite(dstRect.height()) | |
| 1424 || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::i sfinite(srcRect.width()) || !std::isfinite(srcRect.height())) | |
| 1425 return; | |
| 1426 | |
| 1427 if (!dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.he ight()) | |
| 1428 return; | |
| 1429 | |
| 1430 ASSERT(bitmap->height() && bitmap->width()); | |
| 1431 FloatRect normalizedSrcRect = normalizeRect(srcRect); | |
| 1432 FloatRect normalizedDstRect = normalizeRect(dstRect); | |
| 1433 | |
| 1434 // Clip the rects to where the user thinks that the image is situated. | |
| 1435 clipRectsToImageRect(IntRect(IntPoint(), bitmap->size()), &normalizedSrcRect , &normalizedDstRect); | |
| 1436 | |
| 1437 FloatRect intersectRect = intersection(bitmapRect, normalizedSrcRect); | |
| 1438 FloatRect actualSrcRect(intersectRect); | |
| 1439 | |
| 1440 IntPoint bitmapOffset = bitmap->bitmapOffset(); | |
| 1441 actualSrcRect.move(bitmapOffset - bitmapRect.location()); | |
| 1442 FloatRect imageRect = FloatRect(bitmapOffset, bitmapRect.size()); | |
| 1443 | |
| 1444 FloatRect actualDstRect(FloatPoint(intersectRect.location() - normalizedSrcR ect.location()), bitmapRect.size()); | |
| 1445 actualDstRect.scale(normalizedDstRect.width() / normalizedSrcRect.width() * intersectRect.width() / bitmapRect.width(), | |
| 1446 normalizedDstRect.height() / normalizedSrcRect.height() * intersectRect. height() / bitmapRect.height()); | |
| 1447 actualDstRect.moveBy(normalizedDstRect.location()); | |
| 1448 | |
| 1449 if (!imageRect.intersects(actualSrcRect)) | |
| 1450 return; | |
| 1451 | |
| 1452 RefPtr<Image> imageForRendering = bitmap->bitmapImage(); | |
| 1453 if (!imageForRendering) | |
| 1454 return; | |
| 1455 | |
| 1456 drawImageInternal(imageForRendering.get(), actualSrcRect, actualDstRect, sta te().m_globalComposite, state().m_globalBlend); | |
| 1457 } | |
| 1458 | |
| 1459 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionState& exceptionState) | |
| 1460 { | |
| 1461 if (!image) { | |
| 1462 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement")); | |
| 1463 return; | |
| 1464 } | |
| 1465 LayoutSize destRectSize = sizeFor(image, ImageSizeAfterDevicePixelRatio); | |
| 1466 drawImage(image, x, y, destRectSize.width(), destRectSize.height(), exceptio nState); | |
| 1467 } | |
| 1468 | |
| 1469 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, | |
| 1470 float x, float y, float width, float height, ExceptionState& exceptionState) | |
| 1471 { | |
| 1472 if (!image) { | |
| 1473 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement")); | |
| 1474 return; | |
| 1475 } | |
| 1476 LayoutSize sourceRectSize = sizeFor(image, ImageSizeBeforeDevicePixelRatio); | |
| 1477 drawImage(image, FloatRect(0, 0, sourceRectSize.width(), sourceRectSize.heig ht()), FloatRect(x, y, width, height), exceptionState); | |
| 1478 } | |
| 1479 | |
| 1480 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, | |
| 1481 float sx, float sy, float sw, float sh, | |
| 1482 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) | |
| 1483 { | |
| 1484 drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), excep tionState); | |
| 1485 } | |
| 1486 | |
| 1487 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec t& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState) | |
| 1488 { | |
| 1489 drawImage(image, srcRect, dstRect, state().m_globalComposite, state().m_glob alBlend, exceptionState); | |
| 1490 } | |
| 1491 | |
| 1492 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec t& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink:: WebBlendMode& blendMode, ExceptionState& exceptionState) | |
| 1493 { | |
| 1494 if (!image) { | |
| 1495 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement")); | |
| 1496 return; | |
| 1497 } | |
| 1498 | |
| 1499 if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfi nite(dstRect.width()) || !std::isfinite(dstRect.height()) | |
| 1500 || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::i sfinite(srcRect.width()) || !std::isfinite(srcRect.height())) | |
| 1501 return; | |
| 1502 | |
| 1503 ImageResource* cachedImage = image->cachedImage(); | |
| 1504 if (!cachedImage || !image->complete()) | |
| 1505 return; | |
| 1506 | |
| 1507 LayoutSize size = sizeFor(image, ImageSizeBeforeDevicePixelRatio); | |
| 1508 if (!size.width() || !size.height() || !dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.height()) | |
| 1509 return; | |
| 1510 | |
| 1511 FloatRect normalizedSrcRect = normalizeRect(srcRect); | |
| 1512 FloatRect normalizedDstRect = normalizeRect(dstRect); | |
| 1513 | |
| 1514 FloatRect imageRect = FloatRect(FloatPoint(), size); | |
| 1515 if (!imageRect.intersects(normalizedSrcRect)) | |
| 1516 return; | |
| 1517 | |
| 1518 clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect); | |
| 1519 | |
| 1520 checkOrigin(image); | |
| 1521 | |
| 1522 Image* imageForRendering = cachedImage->imageForRenderer(image->renderer()); | |
| 1523 | |
| 1524 // For images that depend on an unavailable container size, we need to fall back to the intrinsic | |
| 1525 // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage | |
| 1526 // FIXME: Without a specified image size this should resolve against the can vas element's size, see: crbug.com/230163. | |
| 1527 if (!image->renderer() && imageForRendering->usesContainerSize()) | |
| 1528 imageForRendering->setContainerSize(imageForRendering->size()); | |
| 1529 | |
| 1530 drawImageInternal(imageForRendering, normalizedSrcRect, normalizedDstRect, o p, blendMode); | |
| 1531 } | |
| 1532 | |
| 1533 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, float x, float y, ExceptionState& exceptionState) | |
| 1534 { | |
| 1535 drawImage(sourceCanvas, 0, 0, sourceCanvas->width(), sourceCanvas->height(), x, y, sourceCanvas->width(), sourceCanvas->height(), exceptionState); | |
| 1536 } | |
| 1537 | |
| 1538 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, | |
| 1539 float x, float y, float width, float height, ExceptionState& exceptionState) | |
| 1540 { | |
| 1541 drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas->width(), sourceCanvas- >height()), FloatRect(x, y, width, height), exceptionState); | |
| 1542 } | |
| 1543 | |
| 1544 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, | |
| 1545 float sx, float sy, float sw, float sh, | |
| 1546 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) | |
| 1547 { | |
| 1548 drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh) , exceptionState); | |
| 1549 } | |
| 1550 | |
| 1551 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect, | |
| 1552 const FloatRect& dstRect, ExceptionState& exceptionState) | |
| 1553 { | |
| 1554 if (!sourceCanvas) { | |
| 1555 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLCanvasElement")); | |
| 1556 return; | |
| 1557 } | |
| 1558 | |
| 1559 FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size()); | |
| 1560 | |
| 1561 if (!srcCanvasRect.width() || !srcCanvasRect.height() || !srcRect.width() || !srcRect.height()) | |
| 1562 return; | |
| 1563 | |
| 1564 FloatRect normalizedSrcRect = normalizeRect(srcRect); | |
| 1565 FloatRect normalizedDstRect = normalizeRect(dstRect); | |
| 1566 | |
| 1567 if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width () || !normalizedDstRect.height()) | |
| 1568 return; | |
| 1569 | |
| 1570 clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect); | |
| 1571 | |
| 1572 GraphicsContext* c = drawingContext(); | |
| 1573 if (!c) | |
| 1574 return; | |
| 1575 if (!state().m_invertibleCTM) | 1392 if (!state().m_invertibleCTM) |
| 1576 return; | 1393 return; |
| 1577 | 1394 |
| 1578 // FIXME: Do this through platform-independent GraphicsContext API. | 1395 if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dw) || !std:: isfinite(dh) |
| 1579 ImageBuffer* buffer = sourceCanvas->buffer(); | 1396 || !std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !st d::isfinite(sh) |
| 1580 if (!buffer) | 1397 || !dw || !dh || !sw || !sh) |
| 1581 return; | 1398 return; |
| 1582 | 1399 |
| 1583 FloatRect clipBounds; | 1400 FloatRect clipBounds; |
| 1584 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) | 1401 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) |
| 1585 return; | 1402 return; |
| 1586 | 1403 |
| 1587 checkOrigin(sourceCanvas); | 1404 FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh)); |
| 1405 FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh)); | |
| 1588 | 1406 |
| 1589 // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable() | 1407 clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->sourceSize()), &sr cRect, &dstRect); |
| 1590 // as that will do a readback to software. | |
| 1591 CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext(); | |
| 1592 // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible. | |
| 1593 if (sourceContext && sourceContext->is3d()) | |
| 1594 sourceContext->paintRenderingResultsToCanvas(); | |
| 1595 | 1408 |
| 1596 if (rectContainsTransformedRect(normalizedDstRect, clipBounds)) { | 1409 imageSource->adjustDrawRects(&srcRect, &dstRect); |
| 1597 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend); | |
| 1598 didDraw(clipBounds); | |
| 1599 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) { | |
| 1600 fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRe ct, state().m_globalComposite); | |
| 1601 didDraw(clipBounds); | |
| 1602 } else if (state().m_globalComposite == CompositeCopy) { | |
| 1603 clearCanvas(); | |
| 1604 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend); | |
| 1605 didDraw(clipBounds); | |
| 1606 } else { | |
| 1607 FloatRect dirtyRect; | |
| 1608 if (computeDirtyRect(normalizedDstRect, clipBounds, &dirtyRect)) { | |
| 1609 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, sta te().m_globalComposite, state().m_globalBlend); | |
| 1610 didDraw(dirtyRect); | |
| 1611 } | |
| 1612 } | |
| 1613 | 1410 |
| 1614 // Flush canvas's ImageBuffer when drawImage from WebGL to HW accelerated 2d canvas | 1411 if (srcRect.isEmpty()) |
| 1615 if (sourceContext && sourceContext->is3d() && is2d() && isAccelerated() && c anvas()->buffer()) | |
| 1616 canvas()->buffer()->flush(); | |
| 1617 } | |
| 1618 | |
| 1619 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionState& exceptionState) | |
| 1620 { | |
| 1621 if (!video) { | |
| 1622 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement")); | |
| 1623 return; | 1412 return; |
| 1624 } | |
| 1625 IntSize size = sizeFor(video); | |
| 1626 drawImage(video, x, y, size.width(), size.height(), exceptionState); | |
| 1627 } | |
| 1628 | |
| 1629 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, | |
| 1630 float x, float y, float width, float height, ExceptionState& exceptionState) | |
| 1631 { | |
| 1632 if (!video) { | |
| 1633 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement")); | |
| 1634 return; | |
| 1635 } | |
| 1636 IntSize size = sizeFor(video); | |
| 1637 drawImage(video, FloatRect(0, 0, size.width(), size.height()), FloatRect(x, y, width, height), exceptionState); | |
| 1638 } | |
| 1639 | |
| 1640 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, | |
| 1641 float sx, float sy, float sw, float sh, | |
| 1642 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) | |
| 1643 { | |
| 1644 drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), excep tionState); | |
| 1645 } | |
| 1646 | |
| 1647 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec t& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState) | |
| 1648 { | |
| 1649 if (!video) { | |
| 1650 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement")); | |
| 1651 return; | |
| 1652 } | |
| 1653 | |
| 1654 if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readySta te() == HTMLMediaElement::HAVE_METADATA) | |
| 1655 return; | |
| 1656 if (!srcRect.width() || !srcRect.height()) | |
| 1657 return; | |
| 1658 | |
| 1659 FloatRect videoRect = FloatRect(FloatPoint(), sizeFor(video)); | |
| 1660 | |
| 1661 FloatRect normalizedSrcRect = normalizeRect(srcRect); | |
| 1662 FloatRect normalizedDstRect = normalizeRect(dstRect); | |
| 1663 | |
| 1664 if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() | | !normalizedDstRect.height()) | |
| 1665 return; | |
| 1666 | |
| 1667 clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect); | |
| 1668 | 1413 |
| 1669 GraphicsContext* c = drawingContext(); | 1414 GraphicsContext* c = drawingContext(); |
| 1670 if (!c) | 1415 if (!c) |
| 1671 return; | 1416 return; |
| 1672 if (!state().m_invertibleCTM) | |
| 1673 return; | |
| 1674 | 1417 |
| 1675 checkOrigin(video); | 1418 FloatRect dirtyRect = clipBounds; |
| 1419 if (imageSource->isVideoElement()) { | |
| 1420 drawVideo(static_cast<HTMLVideoElement*>(imageSource), srcRect, dstRect) ; | |
| 1421 computeDirtyRect(dstRect, clipBounds, &dirtyRect); | |
| 1422 } else { | |
| 1423 if (rectContainsTransformedRect(dstRect, clipBounds)) { | |
| 1424 c->drawImage(image.get(), dstRect, srcRect, op, blendMode); | |
| 1425 } else if (isFullCanvasCompositeMode(op)) { | |
| 1426 fullCanvasCompositedDrawImage(image.get(), dstRect, srcRect, op); | |
| 1427 } else if (op == CompositeCopy) { | |
| 1428 clearCanvas(); | |
| 1429 c->drawImage(image.get(), dstRect, srcRect, op, blendMode); | |
| 1430 } else { | |
| 1431 FloatRect dirtyRect; | |
| 1432 computeDirtyRect(dstRect, clipBounds, &dirtyRect); | |
| 1433 c->drawImage(image.get(), dstRect, srcRect, op, blendMode); | |
| 1434 } | |
| 1676 | 1435 |
| 1677 FloatRect dirtyRect; | 1436 if (sourceImageStatus == ExternalSourceImageStatus && is2d() && isAccele rated() && canvas()->buffer()) |
|
Stephen White
2014/03/10 15:27:03
<philosoraptor>I wonder if we'd ever get in here i
| |
| 1678 if (!computeDirtyRect(normalizedDstRect, &dirtyRect)) | 1437 canvas()->buffer()->flush(); |
| 1679 return; | 1438 } |
| 1680 | 1439 |
| 1681 GraphicsContextStateSaver stateSaver(*c); | 1440 if (canvas()->originClean() && imageSource->wouldTaintOrigin(canvas()->secur ityOrigin())) |
| 1682 c->clip(normalizedDstRect); | 1441 canvas()->setOriginTainted(); |
| 1683 c->translate(normalizedDstRect.x(), normalizedDstRect.y()); | |
| 1684 c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), no rmalizedDstRect.height() / normalizedSrcRect.height())); | |
| 1685 c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y()); | |
| 1686 video->paintCurrentFrameInContext(c, IntRect(IntPoint(), sizeFor(video))); | |
| 1687 stateSaver.restore(); | |
| 1688 | 1442 |
| 1689 didDraw(dirtyRect); | 1443 didDraw(dirtyRect); |
| 1690 } | 1444 } |
| 1691 | 1445 |
| 1446 void CanvasRenderingContext2D::drawVideo(HTMLVideoElement* video, FloatRect srcR ect, FloatRect dstRect) | |
| 1447 { | |
| 1448 GraphicsContext* c = drawingContext(); | |
| 1449 GraphicsContextStateSaver stateSaver(*c); | |
| 1450 c->clip(dstRect); | |
| 1451 c->translate(dstRect.x(), dstRect.y()); | |
| 1452 c->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / src Rect.height())); | |
| 1453 c->translate(-srcRect.x(), -srcRect.y()); | |
| 1454 video->paintCurrentFrameInContext(c, IntRect(IntPoint(), IntSize(video->vide oWidth(), video->videoHeight()))); | |
| 1455 stateSaver.restore(); | |
| 1456 } | |
| 1457 | |
| 1692 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, | 1458 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, |
| 1693 float sx, float sy, float sw, float sh, | 1459 float sx, float sy, float sw, float sh, |
| 1694 float dx, float dy, float dw, float dh, | 1460 float dx, float dy, float dw, float dh, |
| 1695 const String& compositeOperation) | 1461 const String& compositeOperation) |
| 1696 { | 1462 { |
| 1697 CompositeOperator op; | 1463 CompositeOperator op; |
| 1698 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; | 1464 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; |
| 1699 if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blen dOp != blink::WebBlendModeNormal) | 1465 if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blen dOp != blink::WebBlendModeNormal) |
| 1700 op = CompositeSourceOver; | 1466 op = CompositeSourceOver; |
| 1701 | 1467 |
| 1702 drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, b link::WebBlendModeNormal, IGNORE_EXCEPTION); | 1468 drawImageInternal(image, sx, sy, sw, sh, dx, dy, dw, dh, IGNORE_EXCEPTION, o p, blendOp); |
| 1703 } | 1469 } |
| 1704 | 1470 |
| 1705 void CanvasRenderingContext2D::setAlpha(float alpha) | 1471 void CanvasRenderingContext2D::setAlpha(float alpha) |
| 1706 { | 1472 { |
| 1707 setGlobalAlpha(alpha); | 1473 setGlobalAlpha(alpha); |
| 1708 } | 1474 } |
| 1709 | 1475 |
| 1710 void CanvasRenderingContext2D::setCompositeOperation(const String& operation) | 1476 void CanvasRenderingContext2D::setCompositeOperation(const String& operation) |
| 1711 { | 1477 { |
| 1712 setGlobalCompositeOperation(operation); | 1478 setGlobalCompositeOperation(operation); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1730 FloatQuad quad(rect); | 1496 FloatQuad quad(rect); |
| 1731 FloatQuad transformedQuad(transformedRect); | 1497 FloatQuad transformedQuad(transformedRect); |
| 1732 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); | 1498 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); |
| 1733 } | 1499 } |
| 1734 | 1500 |
| 1735 static void drawImageToContext(Image* image, GraphicsContext* context, const Flo atRect& dest, const FloatRect& src, CompositeOperator op) | 1501 static void drawImageToContext(Image* image, GraphicsContext* context, const Flo atRect& dest, const FloatRect& src, CompositeOperator op) |
| 1736 { | 1502 { |
| 1737 context->drawImage(image, dest, src, op); | 1503 context->drawImage(image, dest, src, op); |
| 1738 } | 1504 } |
| 1739 | 1505 |
| 1740 static void drawImageToContext(ImageBuffer* imageBuffer, GraphicsContext* contex t, const FloatRect& dest, const FloatRect& src, CompositeOperator op) | |
| 1741 { | |
| 1742 context->drawImageBuffer(imageBuffer, dest, src, op); | |
| 1743 } | |
| 1744 | |
| 1745 template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage( T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op) | 1506 template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage( T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op) |
| 1746 { | 1507 { |
| 1747 ASSERT(isFullCanvasCompositeMode(op)); | 1508 ASSERT(isFullCanvasCompositeMode(op)); |
| 1748 | 1509 |
| 1749 drawingContext()->beginLayer(1, op); | 1510 drawingContext()->beginLayer(1, op); |
| 1750 drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver); | 1511 drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver); |
| 1751 drawingContext()->endLayer(); | 1512 drawingContext()->endLayer(); |
| 1752 } | 1513 } |
| 1753 | 1514 |
| 1754 static void fillPrimitive(const FloatRect& rect, GraphicsContext* context) | 1515 static void fillPrimitive(const FloatRect& rect, GraphicsContext* context) |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1810 else if (r0 < 0 || r1 < 0) | 1571 else if (r0 < 0 || r1 < 0) |
| 1811 exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); | 1572 exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); |
| 1812 | 1573 |
| 1813 if (exceptionState.hadException()) | 1574 if (exceptionState.hadException()) |
| 1814 return nullptr; | 1575 return nullptr; |
| 1815 | 1576 |
| 1816 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); | 1577 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); |
| 1817 return gradient.release(); | 1578 return gradient.release(); |
| 1818 } | 1579 } |
| 1819 | 1580 |
| 1820 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme nt* image, | 1581 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(CanvasImageSou rce* imageSource, |
| 1821 const String& repetitionType, ExceptionState& exceptionState) | 1582 const String& repetitionType, ExceptionState& exceptionState) |
| 1822 { | 1583 { |
| 1823 if (!image) { | 1584 if (!checkImageSource(imageSource, exceptionState)) |
| 1824 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement")); | |
| 1825 return nullptr; | 1585 return nullptr; |
| 1826 } | |
| 1827 bool repeatX, repeatY; | 1586 bool repeatX, repeatY; |
| 1828 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState); | 1587 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState); |
| 1829 if (exceptionState.hadException()) | 1588 if (exceptionState.hadException()) |
| 1830 return nullptr; | 1589 return nullptr; |
| 1831 | 1590 |
| 1832 if (!image->complete()) | 1591 SourceImageStatus status; |
| 1592 RefPtr<Image> imageForRendering = imageSource->getSourceImageForCanvas(CopyS ourceImageIfVolatile, &status); | |
| 1593 | |
| 1594 switch (status) { | |
| 1595 case NormalSourceImageStatus: | |
| 1596 break; | |
| 1597 case ZeroSizeCanvasSourceImageStatus: | |
| 1598 exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", imageSource->sourceSize().width() ? "height" : "width")); | |
| 1833 return nullptr; | 1599 return nullptr; |
| 1600 case UndecodableSourceImageStatus: | |
| 1601 exceptionState.throwDOMException(InvalidStateError, "Source image is in the 'broken' state."); | |
| 1602 return nullptr; | |
| 1603 case InvalidSourceImageStatus: | |
| 1604 imageForRendering = Image::nullImage(); | |
| 1605 break; | |
| 1606 case IncompleteSourceImageStatus: | |
| 1607 return nullptr; | |
| 1608 default: | |
| 1609 case ExternalSourceImageStatus: // should not happen when mode is CopySource ImageIfVolatile | |
| 1610 ASSERT_NOT_REACHED(); | |
| 1611 return nullptr; | |
| 1612 } | |
| 1613 ASSERT(imageForRendering); | |
| 1834 | 1614 |
| 1835 ImageResource* cachedImage = image->cachedImage(); | 1615 return CanvasPattern::create(imageForRendering.release(), repeatX, repeatY, !imageSource->wouldTaintOrigin(canvas()->securityOrigin())); |
| 1836 Image* imageForRendering = cachedImage ? cachedImage->imageForRenderer(image ->renderer()) : 0; | |
| 1837 if (!imageForRendering) | |
| 1838 return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true) ; | |
| 1839 | |
| 1840 // We need to synthesize a container size if a renderer is not available to provide one. | |
| 1841 if (!image->renderer() && imageForRendering->usesContainerSize()) | |
| 1842 imageForRendering->setContainerSize(imageForRendering->size()); | |
| 1843 | |
| 1844 bool originClean = cachedImage->isAccessAllowed(canvas()->securityOrigin()); | |
| 1845 return CanvasPattern::create(imageForRendering, repeatX, repeatY, originClea n); | |
| 1846 } | |
| 1847 | |
| 1848 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElem ent* canvas, | |
| 1849 const String& repetitionType, ExceptionState& exceptionState) | |
| 1850 { | |
| 1851 if (!canvas) | |
| 1852 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLCanvasElement")); | |
| 1853 else if (!canvas->width() || !canvas->height()) | |
| 1854 exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", canvas->width() ? "height" : "width")); | |
| 1855 | |
| 1856 if (exceptionState.hadException()) | |
| 1857 return nullptr; | |
| 1858 | |
| 1859 bool repeatX, repeatY; | |
| 1860 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState); | |
| 1861 if (exceptionState.hadException()) | |
| 1862 return nullptr; | |
| 1863 return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas ->originClean()); | |
| 1864 } | 1616 } |
| 1865 | 1617 |
| 1866 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, Floa tRect* dirtyRect) | 1618 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, Floa tRect* dirtyRect) |
| 1867 { | 1619 { |
| 1868 FloatRect clipBounds; | 1620 FloatRect clipBounds; |
| 1869 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) | 1621 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) |
| 1870 return false; | 1622 return false; |
| 1871 return computeDirtyRect(localRect, clipBounds, dirtyRect); | 1623 return computeDirtyRect(localRect, clipBounds, dirtyRect); |
| 1872 } | 1624 } |
| 1873 | 1625 |
| (...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2548 const int focusRingWidth = 5; | 2300 const int focusRingWidth = 5; |
| 2549 const int focusRingOutline = 0; | 2301 const int focusRingOutline = 0; |
| 2550 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); | 2302 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); |
| 2551 | 2303 |
| 2552 c->restore(); | 2304 c->restore(); |
| 2553 | 2305 |
| 2554 didDraw(dirtyRect); | 2306 didDraw(dirtyRect); |
| 2555 } | 2307 } |
| 2556 | 2308 |
| 2557 } // namespace WebCore | 2309 } // namespace WebCore |
| OLD | NEW |