OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/canvas2d/BaseRenderingContext2D.h" | 5 #include "modules/canvas2d/BaseRenderingContext2D.h" |
6 | 6 |
7 #include "bindings/core/v8/ExceptionMessages.h" | 7 #include "bindings/core/v8/ExceptionMessages.h" |
8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
9 #include "bindings/core/v8/ScriptState.h" | 9 #include "bindings/core/v8/ScriptState.h" |
10 #include "core/css/cssom/CSSURLImageValue.h" | 10 #include "core/css/cssom/CSSURLImageValue.h" |
(...skipping 1478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1489 static_cast<SkRect>(canvasRect).roundOut(&canvasIRect); | 1489 static_cast<SkRect>(canvasRect).roundOut(&canvasIRect); |
1490 if (!canvasIRect.intersect(transformedClipBounds)) | 1490 if (!canvasIRect.intersect(transformedClipBounds)) |
1491 return false; | 1491 return false; |
1492 | 1492 |
1493 if (dirtyRect) | 1493 if (dirtyRect) |
1494 *dirtyRect = canvasIRect; | 1494 *dirtyRect = canvasIRect; |
1495 | 1495 |
1496 return true; | 1496 return true; |
1497 } | 1497 } |
1498 | 1498 |
1499 bool BaseRenderingContext2D::colorSettingsAsImageDataColorSettings( | |
1500 ImageDataColorSettings& colorSettings) const { | |
1501 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || | |
1502 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | |
1503 return false; | |
1504 colorSettings.setColorSpace(renderingContext()->colorSpaceAsString()); | |
1505 switch (renderingContext()->pixelFormat()) { | |
1506 case kRGBA8CanvasPixelFormat: | |
1507 colorSettings.setStorageFormat(kUint8ClampedArrayStorageFormatName); | |
1508 break; | |
1509 case kF16CanvasPixelFormat: | |
1510 colorSettings.setStorageFormat(kFloat32ArrayStorageFormatName); | |
1511 break; | |
1512 case kRGB10A2CanvasPixelFormat: | |
1513 case kRGBA12CanvasPixelFormat: | |
1514 default: | |
1515 NOTREACHED(); | |
1516 return false; | |
1517 } | |
1518 return true; | |
1519 } | |
1520 | |
1499 ImageData* BaseRenderingContext2D::createImageData( | 1521 ImageData* BaseRenderingContext2D::createImageData( |
1500 ImageData* imageData, | 1522 ImageData* imageData, |
1501 ExceptionState& exceptionState) const { | 1523 ExceptionState& exceptionState) const { |
1502 ImageData* result = ImageData::create(imageData->size()); | 1524 ImageData* result = nullptr; |
1525 if (RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && | |
1526 RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) { | |
1527 ImageDataColorSettings colorSettings; | |
1528 if (colorSettingsAsImageDataColorSettings(colorSettings)) | |
1529 result = ImageData::create(imageData->size(), &colorSettings); | |
1530 } else { | |
1531 result = ImageData::create(imageData->size()); | |
1532 } | |
1503 if (!result) | 1533 if (!result) |
1504 exceptionState.throwRangeError("Out of memory at ImageData creation"); | 1534 exceptionState.throwRangeError("Out of memory at ImageData creation"); |
1505 return result; | 1535 return result; |
1506 } | 1536 } |
1507 | 1537 |
1508 ImageData* BaseRenderingContext2D::createImageData( | 1538 ImageData* BaseRenderingContext2D::createImageData( |
1509 int sw, | 1539 int sw, |
1510 int sh, | 1540 int sh, |
1511 ExceptionState& exceptionState) const { | 1541 ExceptionState& exceptionState) const { |
1512 if (!sw || !sh) { | 1542 if (!sw || !sh) { |
1513 exceptionState.throwDOMException( | 1543 exceptionState.throwDOMException( |
1514 IndexSizeError, | 1544 IndexSizeError, |
1515 String::format("The source %s is 0.", sw ? "height" : "width")); | 1545 String::format("The source %s is 0.", sw ? "height" : "width")); |
1516 return nullptr; | 1546 return nullptr; |
1517 } | 1547 } |
1518 | 1548 |
1519 IntSize size(abs(sw), abs(sh)); | 1549 IntSize size(abs(sw), abs(sh)); |
1520 | 1550 ImageData* result = nullptr; |
1521 ImageData* result = ImageData::create(size); | 1551 if (RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
1552 RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) { | |
1553 ImageDataColorSettings colorSettings; | |
1554 if (colorSettingsAsImageDataColorSettings(colorSettings)) | |
1555 result = ImageData::create(size, &colorSettings); | |
1556 } else { | |
1557 result = ImageData::create(size); | |
1558 } | |
1522 if (!result) | 1559 if (!result) |
1523 exceptionState.throwRangeError("Out of memory at ImageData creation"); | 1560 exceptionState.throwRangeError("Out of memory at ImageData creation"); |
1524 return result; | 1561 return result; |
1525 } | 1562 } |
1526 | 1563 |
1527 ImageData* BaseRenderingContext2D::getImageData( | 1564 ImageData* BaseRenderingContext2D::getImageData( |
1528 int sx, | 1565 int sx, |
1529 int sy, | 1566 int sy, |
1530 int sw, | 1567 int sw, |
1531 int sh, | 1568 int sh, |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1566 10000000, 50)); | 1603 10000000, 50)); |
1567 timer.emplace(scopedUsCounterDisplayList); | 1604 timer.emplace(scopedUsCounterDisplayList); |
1568 } else { | 1605 } else { |
1569 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 1606 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
1570 CustomCountHistogram, scopedUsCounterCPU, | 1607 CustomCountHistogram, scopedUsCounterCPU, |
1571 new CustomCountHistogram("Blink.Canvas.GetImageData.CPU", 0, 10000000, | 1608 new CustomCountHistogram("Blink.Canvas.GetImageData.CPU", 0, 10000000, |
1572 50)); | 1609 50)); |
1573 timer.emplace(scopedUsCounterCPU); | 1610 timer.emplace(scopedUsCounterCPU); |
1574 } | 1611 } |
1575 | 1612 |
1613 ImageDataColorSettings colorSettings; | |
1614 bool canvasIsColorManaged = | |
1615 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && | |
1616 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); | |
1617 if (canvasIsColorManaged) | |
1618 canvasIsColorManaged = colorSettingsAsImageDataColorSettings(colorSettings); | |
1576 IntRect imageDataRect(sx, sy, sw, sh); | 1619 IntRect imageDataRect(sx, sy, sw, sh); |
1577 DVLOG(1) << sx << ", " << sy << ", " << sw << ", " << sh; | 1620 DVLOG(1) << sx << ", " << sy << ", " << sw << ", " << sh; |
1578 ImageBuffer* buffer = imageBuffer(); | 1621 ImageBuffer* buffer = imageBuffer(); |
1579 if (!buffer || isContextLost()) { | 1622 if (!buffer || isContextLost()) { |
1580 ImageData* result = ImageData::create(imageDataRect.size()); | 1623 ImageData* result = nullptr; |
1624 if (canvasIsColorManaged) | |
1625 result = ImageData::create(imageDataRect.size(), &colorSettings); | |
1626 else | |
1627 result = ImageData::create(imageDataRect.size()); | |
1581 if (!result) | 1628 if (!result) |
1582 exceptionState.throwRangeError("Out of memory at ImageData creation"); | 1629 exceptionState.throwRangeError("Out of memory at ImageData creation"); |
1583 return result; | 1630 return result; |
1584 } | 1631 } |
1585 | 1632 |
1586 WTF::ArrayBufferContents contents; | 1633 WTF::ArrayBufferContents contents; |
1587 if (!buffer->getImageData(Unmultiplied, imageDataRect, contents)) { | 1634 if (!buffer->getImageData(Unmultiplied, imageDataRect, contents)) { |
1588 exceptionState.throwRangeError("Out of memory at ImageData creation"); | 1635 exceptionState.throwRangeError("Out of memory at ImageData creation"); |
1589 return nullptr; | 1636 return nullptr; |
1590 } | 1637 } |
1591 | 1638 |
1592 DOMArrayBuffer* arrayBuffer = DOMArrayBuffer::create(contents); | 1639 DOMArrayBuffer* arrayBuffer = nullptr; |
1640 DOMArrayBufferView* arrayBufferView = nullptr; | |
1641 DOMFloat32Array* dataArray = nullptr; | |
1642 | |
1643 if (canvasIsColorManaged) { | |
1644 ImageDataStorageFormat storageFormat = | |
1645 ImageData::imageDataStorageFormat(colorSettings.storageFormat()); | |
1646 switch (storageFormat) { | |
1647 case kUint8ClampedArrayStorageFormat: | |
1648 arrayBuffer = DOMArrayBuffer::create(contents); | |
1649 return ImageData::create( | |
1650 imageDataRect.size(), | |
1651 DOMUint8ClampedArray::create(arrayBuffer, 0, | |
1652 arrayBuffer->byteLength())); | |
1653 break; | |
1654 case kUint16ArrayStorageFormat: | |
1655 NOTREACHED(); | |
1656 break; | |
1657 case kFloat32ArrayStorageFormat: | |
1658 arrayBufferView = ImageData:: | |
1659 convertPixelsFromCanvasPixelFormatToImageDataStorageFormat( | |
1660 contents, renderingContext()->pixelFormat(), storageFormat); | |
1661 dataArray = const_cast<DOMFloat32Array*>( | |
1662 static_cast<const DOMFloat32Array*>(arrayBufferView)); | |
1663 return ImageData::create(imageDataRect.size(), arrayBufferView, | |
1664 &colorSettings); | |
1665 default: | |
1666 NOTREACHED(); | |
1667 } | |
1668 return nullptr; | |
1669 } | |
1670 | |
1671 arrayBuffer = DOMArrayBuffer::create(contents); | |
1593 return ImageData::create( | 1672 return ImageData::create( |
1594 imageDataRect.size(), | 1673 imageDataRect.size(), |
1595 DOMUint8ClampedArray::create(arrayBuffer, 0, arrayBuffer->byteLength())); | 1674 DOMUint8ClampedArray::create(arrayBuffer, 0, arrayBuffer->byteLength())); |
1596 } | 1675 } |
1597 | 1676 |
1598 void BaseRenderingContext2D::putImageData(ImageData* data, | 1677 void BaseRenderingContext2D::putImageData(ImageData* data, |
1599 int dx, | 1678 int dx, |
1600 int dy, | 1679 int dy, |
1601 ExceptionState& exceptionState) { | 1680 ExceptionState& exceptionState) { |
1602 putImageData(data, dx, dy, 0, 0, data->width(), data->height(), | 1681 putImageData(data, dx, dy, 0, 0, data->width(), data->height(), |
1603 exceptionState); | 1682 exceptionState); |
1604 } | 1683 } |
1605 | 1684 |
1606 void BaseRenderingContext2D::putImageData(ImageData* data, | 1685 void BaseRenderingContext2D::putImageData(ImageData* data, |
1607 int dx, | 1686 int dx, |
1608 int dy, | 1687 int dy, |
1609 int dirtyX, | 1688 int dirtyX, |
1610 int dirtyY, | 1689 int dirtyY, |
1611 int dirtyWidth, | 1690 int dirtyWidth, |
1612 int dirtyHeight, | 1691 int dirtyHeight, |
1613 ExceptionState& exceptionState) { | 1692 ExceptionState& exceptionState) { |
1614 m_usageCounters.numPutImageDataCalls++; | 1693 m_usageCounters.numPutImageDataCalls++; |
1615 m_usageCounters.areaPutImageDataCalls += dirtyWidth * dirtyHeight; | 1694 m_usageCounters.areaPutImageDataCalls += dirtyWidth * dirtyHeight; |
1616 if (data->data()->bufferBase()->isNeutered()) { | 1695 |
1696 bool canvasIsColorManaged = | |
1697 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && | |
1698 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); | |
Justin Novosad
2017/04/06 19:01:04
This check is copied in many placed, perhaps we co
zakerinasab
2017/04/11 19:52:59
Done.
| |
1699 | |
1700 bool dataIsNeutered = false; | |
1701 if (canvasIsColorManaged) { | |
1702 dataIsNeutered = | |
1703 (data->dataUnion().isUint8ClampedArray() && | |
1704 data->dataUnion() | |
1705 .getAsUint8ClampedArray() | |
1706 ->bufferBase() | |
1707 ->isNeutered()) || | |
1708 (data->dataUnion().isUint16Array() && | |
1709 data->dataUnion().getAsUint16Array()->bufferBase()->isNeutered()) || | |
1710 (data->dataUnion().isFloat32Array() && | |
1711 data->dataUnion().getAsFloat32Array()->bufferBase()->isNeutered()); | |
1712 } else { | |
1713 dataIsNeutered = data->data()->bufferBase()->isNeutered(); | |
1714 } | |
1715 if (dataIsNeutered) { | |
1617 exceptionState.throwDOMException(InvalidStateError, | 1716 exceptionState.throwDOMException(InvalidStateError, |
1618 "The source data has been neutered."); | 1717 "The source data has been neutered."); |
1619 return; | 1718 return; |
1620 } | 1719 } |
1720 | |
1621 ImageBuffer* buffer = imageBuffer(); | 1721 ImageBuffer* buffer = imageBuffer(); |
1622 if (!buffer) | 1722 if (!buffer) |
1623 return; | 1723 return; |
1624 | 1724 |
1625 if (dirtyWidth < 0) { | 1725 if (dirtyWidth < 0) { |
1626 dirtyX += dirtyWidth; | 1726 dirtyX += dirtyWidth; |
1627 dirtyWidth = -dirtyWidth; | 1727 dirtyWidth = -dirtyWidth; |
1628 } | 1728 } |
1629 | 1729 |
1630 if (dirtyHeight < 0) { | 1730 if (dirtyHeight < 0) { |
(...skipping 29 matching lines...) Expand all Loading... | |
1660 50)); | 1760 50)); |
1661 timer.emplace(scopedUsCounterCPU); | 1761 timer.emplace(scopedUsCounterCPU); |
1662 } | 1762 } |
1663 | 1763 |
1664 IntRect sourceRect(destRect); | 1764 IntRect sourceRect(destRect); |
1665 sourceRect.move(-destOffset); | 1765 sourceRect.move(-destOffset); |
1666 | 1766 |
1667 checkOverdraw(destRect, 0, CanvasRenderingContext2DState::NoImage, | 1767 checkOverdraw(destRect, 0, CanvasRenderingContext2DState::NoImage, |
1668 UntransformedUnclippedFill); | 1768 UntransformedUnclippedFill); |
1669 | 1769 |
1670 buffer->putByteArray(Unmultiplied, data->data()->data(), | 1770 if (RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
1671 IntSize(data->width(), data->height()), sourceRect, | 1771 RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) { |
1672 IntPoint(destOffset)); | 1772 unsigned dataLength = data->width() * data->height(); |
1673 | 1773 if (renderingContext()->pixelFormat() == kF16CanvasPixelFormat) |
1774 dataLength *= 2; | |
1775 std::unique_ptr<uint8_t[]> convertedPixels(new uint8_t[4 * dataLength]); | |
1776 data->imageDataInCanvasColorSettings(renderingContext()->colorSpace(), | |
1777 renderingContext()->pixelFormat(), | |
1778 convertedPixels); | |
1779 buffer->putByteArray(Unmultiplied, convertedPixels.get(), | |
1780 IntSize(data->width(), data->height()), sourceRect, | |
1781 IntPoint(destOffset)); | |
1782 } else { | |
1783 buffer->putByteArray(Unmultiplied, data->data()->data(), | |
1784 IntSize(data->width(), data->height()), sourceRect, | |
1785 IntPoint(destOffset)); | |
1786 } | |
1674 didDraw(destRect); | 1787 didDraw(destRect); |
1675 } | 1788 } |
1676 | 1789 |
1677 void BaseRenderingContext2D::inflateStrokeRect(FloatRect& rect) const { | 1790 void BaseRenderingContext2D::inflateStrokeRect(FloatRect& rect) const { |
1678 // Fast approximation of the stroke's bounding rect. | 1791 // Fast approximation of the stroke's bounding rect. |
1679 // This yields a slightly oversized rect but is very fast | 1792 // This yields a slightly oversized rect but is very fast |
1680 // compared to Path::strokeBoundingRect(). | 1793 // compared to Path::strokeBoundingRect(). |
1681 static const double root2 = sqrtf(2); | 1794 static const double root2 = sqrtf(2); |
1682 double delta = state().lineWidth() / 2; | 1795 double delta = state().lineWidth() / 2; |
1683 if (state().getLineJoin() == MiterJoin) | 1796 if (state().getLineJoin() == MiterJoin) |
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2014 ExpensiveCanvasHeuristicParameters::ShadowFixedCost[index] * | 2127 ExpensiveCanvasHeuristicParameters::ShadowFixedCost[index] * |
2015 m_usageCounters.numBlurredShadows + | 2128 m_usageCounters.numBlurredShadows + |
2016 ExpensiveCanvasHeuristicParameters:: | 2129 ExpensiveCanvasHeuristicParameters:: |
2017 ShadowVariableCostPerAreaTimesShadowBlurSquared[index] * | 2130 ShadowVariableCostPerAreaTimesShadowBlurSquared[index] * |
2018 m_usageCounters.boundingBoxAreaTimesShadowBlurSquared; | 2131 m_usageCounters.boundingBoxAreaTimesShadowBlurSquared; |
2019 | 2132 |
2020 return basicCostOfDrawCalls + fillTypeAdjustment + shadowAdjustment; | 2133 return basicCostOfDrawCalls + fillTypeAdjustment + shadowAdjustment; |
2021 } | 2134 } |
2022 | 2135 |
2023 } // namespace blink | 2136 } // namespace blink |
OLD | NEW |