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