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

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: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View 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 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 return; 283 return;
284 284
285 if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentColor(*style )) 285 if (state().m_strokeStyle && state().m_strokeStyle->isEquivalentColor(*style ))
286 return; 286 return;
287 287
288 if (style->isCurrentColor()) { 288 if (style->isCurrentColor()) {
289 if (style->hasOverrideAlpha()) 289 if (style->hasOverrideAlpha())
290 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha())); 290 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha()));
291 else 291 else
292 style = CanvasStyle::createFromRGBA(currentColor(canvas())); 292 style = CanvasStyle::createFromRGBA(currentColor(canvas()));
293 } else 293 } else if (canvas()->originClean() && style->canvasPattern() && !style->canv asPattern()->originClean()) {
294 checkOrigin(style->canvasPattern()); 294 canvas()->setOriginTainted();
295 }
295 296
296 realizeSaves(); 297 realizeSaves();
297 modifiableState().m_strokeStyle = style.release(); 298 modifiableState().m_strokeStyle = style.release();
298 GraphicsContext* c = drawingContext(); 299 GraphicsContext* c = drawingContext();
299 if (!c) 300 if (!c)
300 return; 301 return;
301 state().m_strokeStyle->applyStrokeColor(c); 302 state().m_strokeStyle->applyStrokeColor(c);
302 modifiableState().m_unparsedStrokeColor = String(); 303 modifiableState().m_unparsedStrokeColor = String();
303 } 304 }
304 305
(...skipping 10 matching lines...) Expand all
315 return; 316 return;
316 317
317 if (state().m_fillStyle && state().m_fillStyle->isEquivalentColor(*style)) 318 if (state().m_fillStyle && state().m_fillStyle->isEquivalentColor(*style))
318 return; 319 return;
319 320
320 if (style->isCurrentColor()) { 321 if (style->isCurrentColor()) {
321 if (style->hasOverrideAlpha()) 322 if (style->hasOverrideAlpha())
322 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha())); 323 style = CanvasStyle::createFromRGBA(colorWithOverrideAlpha(currentCo lor(canvas()), style->overrideAlpha()));
323 else 324 else
324 style = CanvasStyle::createFromRGBA(currentColor(canvas())); 325 style = CanvasStyle::createFromRGBA(currentColor(canvas()));
325 } else 326 } else if (canvas()->originClean() && style->canvasPattern() && !style->canv asPattern()->originClean()) {
326 checkOrigin(style->canvasPattern()); 327 canvas()->setOriginTainted();
328 }
327 329
328 realizeSaves(); 330 realizeSaves();
329 modifiableState().m_fillStyle = style.release(); 331 modifiableState().m_fillStyle = style.release();
330 GraphicsContext* c = drawingContext(); 332 GraphicsContext* c = drawingContext();
331 if (!c) 333 if (!c)
332 return; 334 return;
333 state().m_fillStyle->applyFillColor(c); 335 state().m_fillStyle->applyFillColor(c);
334 modifiableState().m_unparsedFillColor = String(); 336 modifiableState().m_unparsedFillColor = String();
335 } 337 }
336 338
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after
1239 bool CanvasRenderingContext2D::shouldDrawShadows() const 1241 bool CanvasRenderingContext2D::shouldDrawShadows() const
1240 { 1242 {
1241 return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !stat e().m_shadowOffset.isZero()); 1243 return alphaChannel(state().m_shadowColor) && (state().m_shadowBlur || !stat e().m_shadowOffset.isZero());
1242 } 1244 }
1243 1245
1244 enum ImageSizeType { 1246 enum ImageSizeType {
1245 ImageSizeAfterDevicePixelRatio, 1247 ImageSizeAfterDevicePixelRatio,
1246 ImageSizeBeforeDevicePixelRatio 1248 ImageSizeBeforeDevicePixelRatio
1247 }; 1249 };
1248 1250
1249 static LayoutSize sizeFor(HTMLImageElement* image, ImageSizeType sizeType)
1250 {
1251 LayoutSize size;
1252 ImageResource* cachedImage = image->cachedImage();
1253 if (cachedImage) {
1254 size = cachedImage->imageSizeForRenderer(image->renderer(), 1.0f); // FI XME: Not sure about this.
1255
1256 if (sizeType == ImageSizeAfterDevicePixelRatio && image->renderer() && i mage->renderer()->isRenderImage() && cachedImage->image() && !cachedImage->image ()->hasRelativeWidth())
1257 size.scale(toRenderImage(image->renderer())->imageDevicePixelRatio() );
1258 }
1259 return size;
1260 }
1261
1262 static IntSize sizeFor(HTMLVideoElement* video)
1263 {
1264 if (MediaPlayer* player = video->player())
1265 return player->naturalSize();
1266 return IntSize();
1267 }
1268
1269 static inline FloatRect normalizeRect(const FloatRect& rect) 1251 static inline FloatRect normalizeRect(const FloatRect& rect)
1270 { 1252 {
1271 return FloatRect(min(rect.x(), rect.maxX()), 1253 return FloatRect(min(rect.x(), rect.maxX()),
1272 min(rect.y(), rect.maxY()), 1254 min(rect.y(), rect.maxY()),
1273 max(rect.width(), -rect.width()), 1255 max(rect.width(), -rect.width()),
1274 max(rect.height(), -rect.height())); 1256 max(rect.height(), -rect.height()));
1275 } 1257 }
1276 1258
1277 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect) 1259 static inline void clipRectsToImageRect(const FloatRect& imageRect, FloatRect* s rcRect, FloatRect* dstRect)
1278 { 1260 {
1279 if (imageRect.contains(*srcRect)) 1261 if (imageRect.contains(*srcRect))
1280 return; 1262 return;
1281 1263
1282 // Compute the src to dst transform 1264 // Compute the src to dst transform
1283 FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect-> size().height() / srcRect->size().height()); 1265 FloatSize scale(dstRect->size().width() / srcRect->size().width(), dstRect-> size().height() / srcRect->size().height());
1284 FloatPoint scaledSrcLocation = srcRect->location(); 1266 FloatPoint scaledSrcLocation = srcRect->location();
1285 scaledSrcLocation.scale(scale.width(), scale.height()); 1267 scaledSrcLocation.scale(scale.width(), scale.height());
1286 FloatSize offset = dstRect->location() - scaledSrcLocation; 1268 FloatSize offset = dstRect->location() - scaledSrcLocation;
1287 1269
1288 srcRect->intersect(imageRect); 1270 srcRect->intersect(imageRect);
1289 1271
1290 // To clip the destination rectangle in the same proportion, transform the c lipped src rect 1272 // To clip the destination rectangle in the same proportion, transform the c lipped src rect
1291 *dstRect = *srcRect; 1273 *dstRect = *srcRect;
1292 dstRect->scale(scale.width(), scale.height()); 1274 dstRect->scale(scale.width(), scale.height());
1293 dstRect->move(offset); 1275 dstRect->move(offset);
1294 } 1276 }
1295 1277
1296 void CanvasRenderingContext2D::drawImageInternal(Image* image, const FloatRect& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink::Web BlendMode& blendMode) 1278 static bool checkImageSource(CanvasImageSource* imageSource, ExceptionState& exc eptionState)
1297 { 1279 {
1298 if (!image) 1280 if (!imageSource) {
1299 return; 1281 // FIXME: Message should mention ImageBitmap once that feature ships.
1300 1282 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, String("HTMLImageElement, HTMLCanvasElement or HTM LVideoElement")));
1301 GraphicsContext* c = drawingContext(); 1283 return false;
1302 if (!c)
1303 return;
1304 if (!state().m_invertibleCTM)
1305 return;
1306 FloatRect clipBounds;
1307 if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1308 return;
1309
1310 if (rectContainsTransformedRect(dstRect, clipBounds)) {
1311 c->drawImage(image, dstRect, srcRect, op, blendMode);
1312 didDraw(clipBounds);
1313 } else if (isFullCanvasCompositeMode(op)) {
1314 fullCanvasCompositedDrawImage(image, dstRect, srcRect, op);
1315 didDraw(clipBounds);
1316 } else if (op == CompositeCopy) {
1317 clearCanvas();
1318 c->drawImage(image, dstRect, srcRect, op, blendMode);
1319 didDraw(clipBounds);
1320 } else {
1321 FloatRect dirtyRect;
1322 if (computeDirtyRect(dstRect, &dirtyRect)) {
1323 c->drawImage(image, dstRect, srcRect, op, blendMode);
1324 didDraw(dirtyRect);
1325 }
1326 } 1284 }
1285 return true;
1327 } 1286 }
1328 1287
1329 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, float x, float y, ExceptionState& exceptionState) 1288 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, float x , float y, ExceptionState& exceptionState)
1330 { 1289 {
1331 if (!bitmap) { 1290 if (!checkImageSource(imageSource, exceptionState))
1332 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap"));
1333 return; 1291 return;
1334 } 1292 FloatSize destRectSize = imageSource->defaultDestinationSize();
1335 drawImage(bitmap, x, y, bitmap->width(), bitmap->height(), exceptionState); 1293 drawImage(imageSource, x, y, destRectSize.width(), destRectSize.height(), ex ceptionState);
1336 } 1294 }
1337 1295
1338 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, 1296 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
1339 float x, float y, float width, float height, ExceptionState& exceptionState) 1297 float x, float y, float width, float height, ExceptionState& exceptionState)
1340 { 1298 {
1341 if (!bitmap) { 1299 if (!checkImageSource(imageSource, exceptionState))
1342 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap"));
1343 return; 1300 return;
1344 } 1301 FloatSize sourceRectSize = imageSource->sourceSize();
1345 if (!bitmap->bitmapRect().width() || !bitmap->bitmapRect().height()) 1302 drawImage(imageSource, 0, 0, sourceRectSize.width(), sourceRectSize.height() , x, y, width, height, exceptionState);
1346 return;
1347
1348 drawImage(bitmap, 0, 0, bitmap->width(), bitmap->height(), x, y, width, heig ht, exceptionState);
1349 } 1303 }
1350 1304
1351 void CanvasRenderingContext2D::drawImage(ImageBitmap* bitmap, 1305 void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
1352 float sx, float sy, float sw, float sh, 1306 float sx, float sy, float sw, float sh,
1353 float dx, float dy, float dw, float dh, ExceptionState& exceptionState) 1307 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1354 { 1308 {
1355 if (!bitmap) { 1309 if (!checkImageSource(imageSource, exceptionState))
1356 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "ImageBitmap"));
1357 return;
1358 }
1359
1360 FloatRect srcRect(sx, sy, sw, sh);
1361 FloatRect dstRect(dx, dy, dw, dh);
1362 FloatRect bitmapRect = bitmap->bitmapRect();
1363
1364 if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfi nite(dstRect.width()) || !std::isfinite(dstRect.height())
1365 || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::i sfinite(srcRect.width()) || !std::isfinite(srcRect.height()))
1366 return; 1310 return;
1367 1311
1368 if (!dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.he ight())
1369 return;
1370
1371 ASSERT(bitmap->height() && bitmap->width());
1372 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1373 FloatRect normalizedDstRect = normalizeRect(dstRect);
1374
1375 // Clip the rects to where the user thinks that the image is situated.
1376 clipRectsToImageRect(IntRect(IntPoint(), bitmap->size()), &normalizedSrcRect , &normalizedDstRect);
1377
1378 FloatRect intersectRect = intersection(bitmapRect, normalizedSrcRect);
1379 FloatRect actualSrcRect(intersectRect);
1380
1381 IntPoint bitmapOffset = bitmap->bitmapOffset();
1382 actualSrcRect.move(bitmapOffset - bitmapRect.location());
1383 FloatRect imageRect = FloatRect(bitmapOffset, bitmapRect.size());
1384
1385 FloatRect actualDstRect(FloatPoint(intersectRect.location() - normalizedSrcR ect.location()), bitmapRect.size());
1386 actualDstRect.scale(normalizedDstRect.width() / normalizedSrcRect.width() * intersectRect.width() / bitmapRect.width(),
1387 normalizedDstRect.height() / normalizedSrcRect.height() * intersectRect. height() / bitmapRect.height());
1388 actualDstRect.moveBy(normalizedDstRect.location());
1389
1390 if (!imageRect.intersects(actualSrcRect))
1391 return;
1392
1393 RefPtr<Image> imageForRendering = bitmap->bitmapImage();
1394 if (!imageForRendering)
1395 return;
1396
1397 drawImageInternal(imageForRendering.get(), actualSrcRect, actualDstRect, sta te().m_globalComposite, state().m_globalBlend);
1398 }
1399
1400 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, float x, float y, ExceptionState& exceptionState)
1401 {
1402 if (!image) {
1403 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1404 return;
1405 }
1406 LayoutSize destRectSize = sizeFor(image, ImageSizeAfterDevicePixelRatio);
1407 drawImage(image, x, y, destRectSize.width(), destRectSize.height(), exceptio nState);
1408 }
1409
1410 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
1411 float x, float y, float width, float height, ExceptionState& exceptionState)
1412 {
1413 if (!image) {
1414 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1415 return;
1416 }
1417 LayoutSize sourceRectSize = sizeFor(image, ImageSizeBeforeDevicePixelRatio);
1418 drawImage(image, FloatRect(0, 0, sourceRectSize.width(), sourceRectSize.heig ht()), FloatRect(x, y, width, height), exceptionState);
1419 }
1420
1421 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image,
1422 float sx, float sy, float sw, float sh,
1423 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1424 {
1425 drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), excep tionState);
1426 }
1427
1428 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec t& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState)
1429 {
1430 drawImage(image, srcRect, dstRect, state().m_globalComposite, state().m_glob alBlend, exceptionState);
1431 }
1432
1433 void CanvasRenderingContext2D::drawImage(HTMLImageElement* image, const FloatRec t& srcRect, const FloatRect& dstRect, const CompositeOperator& op, const blink:: WebBlendMode& blendMode, ExceptionState& exceptionState)
1434 {
1435 if (!image) {
1436 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1437 return;
1438 }
1439
1440 if (!std::isfinite(dstRect.x()) || !std::isfinite(dstRect.y()) || !std::isfi nite(dstRect.width()) || !std::isfinite(dstRect.height())
1441 || !std::isfinite(srcRect.x()) || !std::isfinite(srcRect.y()) || !std::i sfinite(srcRect.width()) || !std::isfinite(srcRect.height()))
1442 return;
1443
1444 ImageResource* cachedImage = image->cachedImage();
1445 if (!cachedImage || !image->complete())
1446 return;
1447
1448 LayoutSize size = sizeFor(image, ImageSizeBeforeDevicePixelRatio);
1449 if (!size.width() || !size.height() || !dstRect.width() || !dstRect.height() || !srcRect.width() || !srcRect.height())
1450 return;
1451
1452 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1453 FloatRect normalizedDstRect = normalizeRect(dstRect);
1454
1455 FloatRect imageRect = FloatRect(FloatPoint(), size);
1456 if (!imageRect.intersects(normalizedSrcRect))
1457 return;
1458
1459 clipRectsToImageRect(imageRect, &normalizedSrcRect, &normalizedDstRect);
1460
1461 checkOrigin(image);
1462
1463 Image* imageForRendering = cachedImage->imageForRenderer(image->renderer());
1464
1465 // For images that depend on an unavailable container size, we need to fall back to the intrinsic
1466 // object size. http://www.w3.org/TR/2dcontext2/#dom-context-2d-drawimage
1467 // FIXME: Without a specified image size this should resolve against the can vas element's size, see: crbug.com/230163.
1468 if (!image->renderer() && imageForRendering->usesContainerSize())
1469 imageForRendering->setContainerSize(imageForRendering->size());
1470
1471 drawImageInternal(imageForRendering, normalizedSrcRect, normalizedDstRect, o p, blendMode);
1472 }
1473
1474 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, float x, float y, ExceptionState& exceptionState)
1475 {
1476 drawImage(sourceCanvas, 0, 0, sourceCanvas->width(), sourceCanvas->height(), x, y, sourceCanvas->width(), sourceCanvas->height(), exceptionState);
1477 }
1478
1479 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas,
1480 float x, float y, float width, float height, ExceptionState& exceptionState)
1481 {
1482 drawImage(sourceCanvas, FloatRect(0, 0, sourceCanvas->width(), sourceCanvas- >height()), FloatRect(x, y, width, height), exceptionState);
1483 }
1484
1485 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas,
1486 float sx, float sy, float sw, float sh,
1487 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1488 {
1489 drawImage(sourceCanvas, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh) , exceptionState);
1490 }
1491
1492 void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const FloatRect& srcRect,
1493 const FloatRect& dstRect, ExceptionState& exceptionState)
1494 {
1495 if (!sourceCanvas) {
1496 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLCanvasElement"));
1497 return;
1498 }
1499
1500 FloatRect srcCanvasRect = FloatRect(FloatPoint(), sourceCanvas->size());
1501
1502 if (!srcCanvasRect.width() || !srcCanvasRect.height() || !srcRect.width() || !srcRect.height())
1503 return;
1504
1505 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1506 FloatRect normalizedDstRect = normalizeRect(dstRect);
1507
1508 if (!srcCanvasRect.intersects(normalizedSrcRect) || !normalizedDstRect.width () || !normalizedDstRect.height())
1509 return;
1510
1511 clipRectsToImageRect(srcCanvasRect, &normalizedSrcRect, &normalizedDstRect);
1512
1513 GraphicsContext* c = drawingContext();
1514 if (!c)
1515 return;
1516 if (!state().m_invertibleCTM) 1312 if (!state().m_invertibleCTM)
1517 return; 1313 return;
1518 1314
1519 // FIXME: Do this through platform-independent GraphicsContext API. 1315 RefPtr<Image> image;
1520 ImageBuffer* buffer = sourceCanvas->buffer(); 1316 bool imageSourceIsVolatile = false;
1521 if (!buffer) 1317 if (!imageSource->isVideoElement()) {
1318 image = imageSource->getSourceImageForCanvas(canvas(), exceptionState, D rawCanvasImageSourceUsage, &imageSourceIsVolatile);
1319 if (!image || !image->width() || !image->height())
1320 return;
1321 }
1322
1323 if (!std::isfinite(dx) || !std::isfinite(dy) || !std::isfinite(dw) || !std:: isfinite(dh)
1324 || !std::isfinite(sx) || !std::isfinite(sy) || !std::isfinite(sw) || !st d::isfinite(sh)
1325 || !dw || !dh || !sw || !sh)
1522 return; 1326 return;
1523 1327
1524 FloatRect clipBounds; 1328 FloatRect clipBounds;
1525 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) 1329 if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1526 return; 1330 return;
1527 1331
1528 checkOrigin(sourceCanvas); 1332 FloatRect srcRect = normalizeRect(FloatRect(sx, sy, sw, sh));
1333 FloatRect dstRect = normalizeRect(FloatRect(dx, dy, dw, dh));
1529 1334
1530 // If we're drawing from one accelerated canvas 2d to another, avoid calling sourceCanvas->makeRenderingResultsAvailable() 1335 clipRectsToImageRect(FloatRect(FloatPoint(), imageSource->sourceSize()), &sr cRect, &dstRect);
1531 // as that will do a readback to software.
1532 CanvasRenderingContext* sourceContext = sourceCanvas->renderingContext();
1533 // FIXME: Implement an accelerated path for drawing from a WebGL canvas to a 2d canvas when possible.
1534 if (sourceContext && sourceContext->is3d())
1535 sourceContext->paintRenderingResultsToCanvas();
1536 1336
1537 if (rectContainsTransformedRect(normalizedDstRect, clipBounds)) { 1337 imageSource->adjustDrawRects(&srcRect, &dstRect);
1538 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend);
1539 didDraw(clipBounds);
1540 } else if (isFullCanvasCompositeMode(state().m_globalComposite)) {
1541 fullCanvasCompositedDrawImage(buffer, normalizedDstRect, normalizedSrcRe ct, state().m_globalComposite);
1542 didDraw(clipBounds);
1543 } else if (state().m_globalComposite == CompositeCopy) {
1544 clearCanvas();
1545 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, state() .m_globalComposite, state().m_globalBlend);
1546 didDraw(clipBounds);
1547 } else {
1548 FloatRect dirtyRect;
1549 if (computeDirtyRect(normalizedDstRect, clipBounds, &dirtyRect)) {
1550 c->drawImageBuffer(buffer, normalizedDstRect, normalizedSrcRect, sta te().m_globalComposite, state().m_globalBlend);
1551 didDraw(dirtyRect);
1552 }
1553 }
1554 1338
1555 // Flush canvas's ImageBuffer when drawImage from WebGL to HW accelerated 2d canvas 1339 if (srcRect.isEmpty())
1556 if (sourceContext && sourceContext->is3d() && is2d() && isAccelerated() && c anvas()->buffer())
1557 canvas()->buffer()->flush();
1558 }
1559
1560 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, float x, float y, ExceptionState& exceptionState)
1561 {
1562 if (!video) {
1563 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement"));
1564 return; 1340 return;
1565 }
1566 IntSize size = sizeFor(video);
1567 drawImage(video, x, y, size.width(), size.height(), exceptionState);
1568 }
1569
1570 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
1571 float x, float y, float width, float height, ExceptionState& exceptionState)
1572 {
1573 if (!video) {
1574 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement"));
1575 return;
1576 }
1577 IntSize size = sizeFor(video);
1578 drawImage(video, FloatRect(0, 0, size.width(), size.height()), FloatRect(x, y, width, height), exceptionState);
1579 }
1580
1581 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video,
1582 float sx, float sy, float sw, float sh,
1583 float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
1584 {
1585 drawImage(video, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), excep tionState);
1586 }
1587
1588 void CanvasRenderingContext2D::drawImage(HTMLVideoElement* video, const FloatRec t& srcRect, const FloatRect& dstRect, ExceptionState& exceptionState)
1589 {
1590 if (!video) {
1591 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLVideoElement"));
1592 return;
1593 }
1594
1595 if (video->readyState() == HTMLMediaElement::HAVE_NOTHING || video->readySta te() == HTMLMediaElement::HAVE_METADATA)
1596 return;
1597 if (!srcRect.width() || !srcRect.height())
1598 return;
1599
1600 FloatRect videoRect = FloatRect(FloatPoint(), sizeFor(video));
1601
1602 FloatRect normalizedSrcRect = normalizeRect(srcRect);
1603 FloatRect normalizedDstRect = normalizeRect(dstRect);
1604
1605 if (!videoRect.intersects(normalizedSrcRect) || !normalizedDstRect.width() | | !normalizedDstRect.height())
1606 return;
1607
1608 clipRectsToImageRect(videoRect, &normalizedSrcRect, &normalizedDstRect);
1609 1341
1610 GraphicsContext* c = drawingContext(); 1342 GraphicsContext* c = drawingContext();
1611 if (!c) 1343 if (!c)
1612 return; 1344 return;
1613 if (!state().m_invertibleCTM)
1614 return;
1615 1345
1616 checkOrigin(video); 1346 FloatRect dirtyRect = clipBounds;
1347 if (imageSource->isVideoElement()) {
1348 GraphicsContextStateSaver stateSaver(*c);
1349 c->clip(dstRect);
1350 c->translate(dstRect.x(), dstRect.y());
1351 c->scale(FloatSize(dstRect.width() / srcRect.width(), dstRect.height() / srcRect.height()));
1352 c->translate(-srcRect.x(), -srcRect.y());
1353 static_cast<HTMLVideoElement*>(imageSource)->paintCurrentFrameInContext( c, IntRect(IntPoint(), roundedIntSize(imageSource->sourceSize())));
1354 stateSaver.restore();
1355 computeDirtyRect(dstRect, clipBounds, &dirtyRect);
1356 } else {
1357 CompositeOperator op = c->compositeOperation();
1358 blink::WebBlendMode blendMode = c->blendModeOperation();
1359 if (rectContainsTransformedRect(dstRect, clipBounds)) {
1360 c->drawImage(image.get(), dstRect, srcRect, op, blendMode);
1361 } else if (isFullCanvasCompositeMode(op)) {
1362 fullCanvasCompositedDrawImage(image.get(), dstRect, srcRect, op);
1363 } else if (op == CompositeCopy) {
1364 clearCanvas();
1365 c->drawImage(image.get(), dstRect, srcRect, op, blendMode);
1366 } else {
1367 FloatRect dirtyRect;
1368 computeDirtyRect(dstRect, clipBounds, &dirtyRect);
1369 c->drawImage(image.get(), dstRect, srcRect, op, blendMode);
1370 }
1617 1371
1618 FloatRect dirtyRect; 1372 if (imageSourceIsVolatile && is2d() && isAccelerated() && canvas()->buff er())
1619 if (!computeDirtyRect(normalizedDstRect, &dirtyRect)) 1373 canvas()->buffer()->flush();
1620 return; 1374 }
1621 1375
1622 GraphicsContextStateSaver stateSaver(*c); 1376 if (canvas()->originClean() && imageSource->wouldTaintOrigin(this))
1623 c->clip(normalizedDstRect); 1377 canvas()->setOriginTainted();
1624 c->translate(normalizedDstRect.x(), normalizedDstRect.y());
1625 c->scale(FloatSize(normalizedDstRect.width() / normalizedSrcRect.width(), no rmalizedDstRect.height() / normalizedSrcRect.height()));
1626 c->translate(-normalizedSrcRect.x(), -normalizedSrcRect.y());
1627 video->paintCurrentFrameInContext(c, IntRect(IntPoint(), sizeFor(video)));
1628 stateSaver.restore();
1629 1378
1630 didDraw(dirtyRect); 1379 didDraw(dirtyRect);
1631 } 1380 }
1632 1381
1382
1633 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image, 1383 void CanvasRenderingContext2D::drawImageFromRect(HTMLImageElement* image,
1634 float sx, float sy, float sw, float sh, 1384 float sx, float sy, float sw, float sh,
1635 float dx, float dy, float dw, float dh, 1385 float dx, float dy, float dw, float dh,
1636 const String& compositeOperation) 1386 const String& compositeOperation)
1637 { 1387 {
1388 GraphicsContext* c = drawingContext();
1389 if (!c)
1390 return;
1638 CompositeOperator op; 1391 CompositeOperator op;
1639 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; 1392 blink::WebBlendMode blendOp = blink::WebBlendModeNormal;
1640 if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blen dOp != blink::WebBlendModeNormal) 1393 if (!parseCompositeAndBlendOperator(compositeOperation, op, blendOp) || blen dOp != blink::WebBlendModeNormal)
1641 op = CompositeSourceOver; 1394 op = CompositeSourceOver;
1642 1395
1643 drawImage(image, FloatRect(sx, sy, sw, sh), FloatRect(dx, dy, dw, dh), op, b link::WebBlendModeNormal, IGNORE_EXCEPTION); 1396 CompositeOperator savedOp = c->compositeOperation();
1397 blink::WebBlendMode savedBlendMode = c->blendModeOperation();
1398 c->setCompositeOperation(op, blink::WebBlendModeNormal);
1399 drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh, IGNORE_EXCEPTION);
1400 c->setCompositeOperation(savedOp, savedBlendMode);
1644 } 1401 }
1645 1402
1646 void CanvasRenderingContext2D::setAlpha(float alpha) 1403 void CanvasRenderingContext2D::setAlpha(float alpha)
1647 { 1404 {
1648 setGlobalAlpha(alpha); 1405 setGlobalAlpha(alpha);
1649 } 1406 }
1650 1407
1651 void CanvasRenderingContext2D::setCompositeOperation(const String& operation) 1408 void CanvasRenderingContext2D::setCompositeOperation(const String& operation)
1652 { 1409 {
1653 setGlobalCompositeOperation(operation); 1410 setGlobalCompositeOperation(operation);
(...skipping 17 matching lines...) Expand all
1671 FloatQuad quad(rect); 1428 FloatQuad quad(rect);
1672 FloatQuad transformedQuad(transformedRect); 1429 FloatQuad transformedQuad(transformedRect);
1673 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad); 1430 return state().m_transform.mapQuad(quad).containsQuad(transformedQuad);
1674 } 1431 }
1675 1432
1676 static void drawImageToContext(Image* image, GraphicsContext* context, const Flo atRect& dest, const FloatRect& src, CompositeOperator op) 1433 static void drawImageToContext(Image* image, GraphicsContext* context, const Flo atRect& dest, const FloatRect& src, CompositeOperator op)
1677 { 1434 {
1678 context->drawImage(image, dest, src, op); 1435 context->drawImage(image, dest, src, op);
1679 } 1436 }
1680 1437
1681 static void drawImageToContext(ImageBuffer* imageBuffer, GraphicsContext* contex t, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
1682 {
1683 context->drawImageBuffer(imageBuffer, dest, src, op);
1684 }
1685
1686 template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage( T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op) 1438 template<class T> void CanvasRenderingContext2D::fullCanvasCompositedDrawImage( T* image, const FloatRect& dest, const FloatRect& src, CompositeOperator op)
1687 { 1439 {
1688 ASSERT(isFullCanvasCompositeMode(op)); 1440 ASSERT(isFullCanvasCompositeMode(op));
1689 1441
1690 drawingContext()->beginLayer(1, op); 1442 drawingContext()->beginLayer(1, op);
1691 drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver); 1443 drawImageToContext(image, drawingContext(), dest, src, CompositeSourceOver);
1692 drawingContext()->endLayer(); 1444 drawingContext()->endLayer();
1693 } 1445 }
1694 1446
1695 static void fillPrimitive(const FloatRect& rect, GraphicsContext* context) 1447 static void fillPrimitive(const FloatRect& rect, GraphicsContext* context)
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1751 else if (r0 < 0 || r1 < 0) 1503 else if (r0 < 0 || r1 < 0)
1752 exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1")); 1504 exceptionState.throwDOMException(IndexSizeError, String::format("The %s provided is less than 0.", r0 < 0 ? "r0" : "r1"));
1753 1505
1754 if (exceptionState.hadException()) 1506 if (exceptionState.hadException())
1755 return nullptr; 1507 return nullptr;
1756 1508
1757 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1); 1509 RefPtr<CanvasGradient> gradient = CanvasGradient::create(FloatPoint(x0, y0), r0, FloatPoint(x1, y1), r1);
1758 return gradient.release(); 1510 return gradient.release();
1759 } 1511 }
1760 1512
1761 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLImageEleme nt* image, 1513 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(CanvasImageSou rce* imageSource,
1762 const String& repetitionType, ExceptionState& exceptionState) 1514 const String& repetitionType, ExceptionState& exceptionState)
1763 { 1515 {
1764 if (!image) { 1516 if (!checkImageSource(imageSource, exceptionState))
1765 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLImageElement"));
1766 return nullptr; 1517 return nullptr;
1767 }
1768 bool repeatX, repeatY; 1518 bool repeatX, repeatY;
1769 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState); 1519 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState);
1770 if (exceptionState.hadException()) 1520 if (exceptionState.hadException())
1771 return nullptr; 1521 return nullptr;
1772 1522
1773 if (!image->complete()) 1523 RefPtr<Image> imageForRendering = imageSource->getSourceImageForCanvas(canva s(), exceptionState, PatternCanvasImageSourceUsage);
1524 if (exceptionState.hadException() || !imageForRendering)
1774 return nullptr; 1525 return nullptr;
1775 1526
1776 ImageResource* cachedImage = image->cachedImage(); 1527 return CanvasPattern::create(imageForRendering.release(), repeatX, repeatY, !imageSource->wouldTaintOrigin(this));
1777 Image* imageForRendering = cachedImage ? cachedImage->imageForRenderer(image ->renderer()) : 0;
1778 if (!imageForRendering)
1779 return CanvasPattern::create(Image::nullImage(), repeatX, repeatY, true) ;
1780
1781 // We need to synthesize a container size if a renderer is not available to provide one.
1782 if (!image->renderer() && imageForRendering->usesContainerSize())
1783 imageForRendering->setContainerSize(imageForRendering->size());
1784
1785 bool originClean = cachedImage->isAccessAllowed(canvas()->securityOrigin());
1786 return CanvasPattern::create(imageForRendering, repeatX, repeatY, originClea n);
1787 }
1788
1789 PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElem ent* canvas,
1790 const String& repetitionType, ExceptionState& exceptionState)
1791 {
1792 if (!canvas)
1793 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::a rgumentNullOrIncorrectType(1, "HTMLCanvasElement"));
1794 else if (!canvas->width() || !canvas->height())
1795 exceptionState.throwDOMException(InvalidStateError, String::format("The canvas %s is 0.", canvas->width() ? "height" : "width"));
1796
1797 if (exceptionState.hadException())
1798 return nullptr;
1799
1800 bool repeatX, repeatY;
1801 CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, excepti onState);
1802 if (exceptionState.hadException())
1803 return nullptr;
1804 return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas ->originClean());
1805 } 1528 }
1806 1529
1807 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, Floa tRect* dirtyRect) 1530 bool CanvasRenderingContext2D::computeDirtyRect(const FloatRect& localRect, Floa tRect* dirtyRect)
1808 { 1531 {
1809 FloatRect clipBounds; 1532 FloatRect clipBounds;
1810 if (!drawingContext()->getTransformedClipBounds(&clipBounds)) 1533 if (!drawingContext()->getTransformedClipBounds(&clipBounds))
1811 return false; 1534 return false;
1812 return computeDirtyRect(localRect, clipBounds, dirtyRect); 1535 return computeDirtyRect(localRect, clipBounds, dirtyRect);
1813 } 1536 }
1814 1537
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
2444 const int focusRingWidth = 5; 2167 const int focusRingWidth = 5;
2445 const int focusRingOutline = 0; 2168 const int focusRingOutline = 0;
2446 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); 2169 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2447 2170
2448 c->restore(); 2171 c->restore();
2449 2172
2450 didDraw(dirtyRect); 2173 didDraw(dirtyRect);
2451 } 2174 }
2452 2175
2453 } // namespace WebCore 2176 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698