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 20 matching lines...) Expand all Loading... |
31 #include "platform/graphics/ImageBuffer.h" | 31 #include "platform/graphics/ImageBuffer.h" |
32 #include "platform/graphics/StrokeData.h" | 32 #include "platform/graphics/StrokeData.h" |
33 #include "platform/graphics/paint/PaintCanvas.h" | 33 #include "platform/graphics/paint/PaintCanvas.h" |
34 #include "platform/graphics/paint/PaintFlags.h" | 34 #include "platform/graphics/paint/PaintFlags.h" |
35 #include "platform/graphics/skia/SkiaUtils.h" | 35 #include "platform/graphics/skia/SkiaUtils.h" |
36 #include "platform/wtf/CheckedNumeric.h" | 36 #include "platform/wtf/CheckedNumeric.h" |
37 | 37 |
38 namespace blink { | 38 namespace blink { |
39 | 39 |
40 BaseRenderingContext2D::BaseRenderingContext2D() | 40 BaseRenderingContext2D::BaseRenderingContext2D() |
41 : clip_antialiasing_(kNotAntiAliased) { | 41 : clip_antialiasing_(kNotAntiAliased), color_management_enabled_(false) { |
42 state_stack_.push_back(CanvasRenderingContext2DState::Create()); | 42 state_stack_.push_back(CanvasRenderingContext2DState::Create()); |
| 43 color_management_enabled_ = |
| 44 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() && |
| 45 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
43 } | 46 } |
44 | 47 |
45 BaseRenderingContext2D::~BaseRenderingContext2D() {} | 48 BaseRenderingContext2D::~BaseRenderingContext2D() {} |
46 | 49 |
47 CanvasRenderingContext2DState& BaseRenderingContext2D::ModifiableState() { | 50 CanvasRenderingContext2DState& BaseRenderingContext2D::ModifiableState() { |
48 RealizeSaves(); | 51 RealizeSaves(); |
49 return *state_stack_.back(); | 52 return *state_stack_.back(); |
50 } | 53 } |
51 | 54 |
52 void BaseRenderingContext2D::RealizeSaves() { | 55 void BaseRenderingContext2D::RealizeSaves() { |
(...skipping 1448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1501 static_cast<SkRect>(canvas_rect).roundOut(&canvas_i_rect); | 1504 static_cast<SkRect>(canvas_rect).roundOut(&canvas_i_rect); |
1502 if (!canvas_i_rect.intersect(transformed_clip_bounds)) | 1505 if (!canvas_i_rect.intersect(transformed_clip_bounds)) |
1503 return false; | 1506 return false; |
1504 | 1507 |
1505 if (dirty_rect) | 1508 if (dirty_rect) |
1506 *dirty_rect = canvas_i_rect; | 1509 *dirty_rect = canvas_i_rect; |
1507 | 1510 |
1508 return true; | 1511 return true; |
1509 } | 1512 } |
1510 | 1513 |
| 1514 ImageDataColorSettings |
| 1515 BaseRenderingContext2D::GetColorSettingsAsImageDataColorSettings() const { |
| 1516 ImageDataColorSettings color_settings; |
| 1517 color_settings.setColorSpace(ColorSpaceAsString()); |
| 1518 if (PixelFormat() == kF16CanvasPixelFormat) |
| 1519 color_settings.setStorageFormat(kFloat32ArrayStorageFormatName); |
| 1520 return color_settings; |
| 1521 } |
| 1522 |
1511 ImageData* BaseRenderingContext2D::createImageData( | 1523 ImageData* BaseRenderingContext2D::createImageData( |
1512 ImageData* image_data, | 1524 ImageData* image_data, |
1513 ExceptionState& exception_state) const { | 1525 ExceptionState& exception_state) const { |
1514 ImageData* result = ImageData::Create(image_data->Size()); | 1526 ImageData* result = nullptr; |
| 1527 if (color_management_enabled_) { |
| 1528 ImageDataColorSettings color_settings = |
| 1529 GetColorSettingsAsImageDataColorSettings(); |
| 1530 result = ImageData::Create(image_data->Size(), &color_settings); |
| 1531 } else { |
| 1532 result = ImageData::Create(image_data->Size()); |
| 1533 } |
1515 if (!result) | 1534 if (!result) |
1516 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1535 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
1517 return result; | 1536 return result; |
1518 } | 1537 } |
1519 | 1538 |
1520 ImageData* BaseRenderingContext2D::createImageData( | 1539 ImageData* BaseRenderingContext2D::createImageData( |
1521 int sw, | 1540 int sw, |
1522 int sh, | 1541 int sh, |
1523 ExceptionState& exception_state) const { | 1542 ExceptionState& exception_state) const { |
1524 if (!sw || !sh) { | 1543 if (!sw || !sh) { |
1525 exception_state.ThrowDOMException( | 1544 exception_state.ThrowDOMException( |
1526 kIndexSizeError, | 1545 kIndexSizeError, |
1527 String::Format("The source %s is 0.", sw ? "height" : "width")); | 1546 String::Format("The source %s is 0.", sw ? "height" : "width")); |
1528 return nullptr; | 1547 return nullptr; |
1529 } | 1548 } |
1530 | 1549 |
1531 IntSize size(abs(sw), abs(sh)); | 1550 IntSize size(abs(sw), abs(sh)); |
| 1551 ImageData* result = nullptr; |
| 1552 if (color_management_enabled_) { |
| 1553 ImageDataColorSettings color_settings = |
| 1554 GetColorSettingsAsImageDataColorSettings(); |
| 1555 result = ImageData::Create(size, &color_settings); |
| 1556 } else { |
| 1557 result = ImageData::Create(size); |
| 1558 } |
1532 | 1559 |
1533 ImageData* result = ImageData::Create(size); | |
1534 if (!result) | 1560 if (!result) |
1535 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1561 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
1536 return result; | 1562 return result; |
1537 } | 1563 } |
1538 | 1564 |
| 1565 ImageData* BaseRenderingContext2D::createImageData( |
| 1566 unsigned width, |
| 1567 unsigned height, |
| 1568 ImageDataColorSettings& color_settings, |
| 1569 ExceptionState& exception_state) const { |
| 1570 return ImageData::CreateImageData(width, height, color_settings, |
| 1571 exception_state); |
| 1572 } |
| 1573 |
| 1574 ImageData* BaseRenderingContext2D::createImageData( |
| 1575 ImageDataArray& data_array, |
| 1576 unsigned width, |
| 1577 unsigned height, |
| 1578 ExceptionState& exception_state) const { |
| 1579 ImageDataColorSettings color_settings; |
| 1580 return ImageData::CreateImageData(data_array, width, height, color_settings, |
| 1581 exception_state); |
| 1582 } |
| 1583 |
| 1584 ImageData* BaseRenderingContext2D::createImageData( |
| 1585 ImageDataArray& data_array, |
| 1586 unsigned width, |
| 1587 unsigned height, |
| 1588 ImageDataColorSettings& color_settings, |
| 1589 ExceptionState& exception_state) const { |
| 1590 return ImageData::CreateImageData(data_array, width, height, color_settings, |
| 1591 exception_state); |
| 1592 } |
| 1593 |
1539 ImageData* BaseRenderingContext2D::getImageData( | 1594 ImageData* BaseRenderingContext2D::getImageData( |
1540 int sx, | 1595 int sx, |
1541 int sy, | 1596 int sy, |
1542 int sw, | 1597 int sw, |
1543 int sh, | 1598 int sh, |
1544 ExceptionState& exception_state) { | 1599 ExceptionState& exception_state) { |
1545 if (!WTF::CheckMul(sw, sh).IsValid<int>()) { | 1600 if (!WTF::CheckMul(sw, sh).IsValid<int>()) { |
1546 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1601 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
1547 return nullptr; | 1602 return nullptr; |
1548 } | 1603 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1591 } else { | 1646 } else { |
1592 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 1647 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
1593 CustomCountHistogram, scoped_us_counter_cpu, | 1648 CustomCountHistogram, scoped_us_counter_cpu, |
1594 new CustomCountHistogram("Blink.Canvas.GetImageData.CPU", 0, 10000000, | 1649 new CustomCountHistogram("Blink.Canvas.GetImageData.CPU", 0, 10000000, |
1595 50)); | 1650 50)); |
1596 timer.emplace(scoped_us_counter_cpu); | 1651 timer.emplace(scoped_us_counter_cpu); |
1597 } | 1652 } |
1598 | 1653 |
1599 IntRect image_data_rect(sx, sy, sw, sh); | 1654 IntRect image_data_rect(sx, sy, sw, sh); |
1600 ImageBuffer* buffer = GetImageBuffer(); | 1655 ImageBuffer* buffer = GetImageBuffer(); |
| 1656 ImageDataColorSettings color_settings = |
| 1657 GetColorSettingsAsImageDataColorSettings(); |
1601 if (!buffer || isContextLost()) { | 1658 if (!buffer || isContextLost()) { |
1602 ImageData* result = ImageData::Create(image_data_rect.Size()); | 1659 ImageData* result = nullptr; |
| 1660 if (color_management_enabled_) |
| 1661 result = ImageData::Create(image_data_rect.Size(), &color_settings); |
| 1662 else |
| 1663 result = ImageData::Create(image_data_rect.Size()); |
1603 if (!result) | 1664 if (!result) |
1604 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1665 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
1605 return result; | 1666 return result; |
1606 } | 1667 } |
1607 | 1668 |
1608 WTF::ArrayBufferContents contents; | 1669 WTF::ArrayBufferContents contents; |
1609 if (!buffer->GetImageData(kUnmultiplied, image_data_rect, contents)) { | 1670 if (!buffer->GetImageData(kUnmultiplied, image_data_rect, contents)) { |
1610 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1671 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
1611 return nullptr; | 1672 return nullptr; |
1612 } | 1673 } |
1613 | 1674 |
1614 NeedsFinalizeFrame(); | 1675 NeedsFinalizeFrame(); |
1615 | 1676 |
1616 DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); | 1677 if (!color_management_enabled_) { |
1617 return ImageData::Create( | 1678 DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); |
1618 image_data_rect.Size(), | 1679 return ImageData::Create( |
1619 NotShared<DOMUint8ClampedArray>(DOMUint8ClampedArray::Create( | 1680 image_data_rect.Size(), |
1620 array_buffer, 0, array_buffer->ByteLength()))); | 1681 NotShared<DOMUint8ClampedArray>(DOMUint8ClampedArray::Create( |
| 1682 array_buffer, 0, array_buffer->ByteLength()))); |
| 1683 } |
| 1684 |
| 1685 ImageDataStorageFormat storage_format = |
| 1686 ImageData::GetImageDataStorageFormat(color_settings.storageFormat()); |
| 1687 DOMArrayBufferView* array_buffer_view = |
| 1688 ImageData::ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat( |
| 1689 contents, PixelFormat(), storage_format); |
| 1690 return ImageData::Create(image_data_rect.Size(), |
| 1691 NotShared<DOMArrayBufferView>(array_buffer_view), |
| 1692 &color_settings); |
1621 } | 1693 } |
1622 | 1694 |
1623 void BaseRenderingContext2D::putImageData(ImageData* data, | 1695 void BaseRenderingContext2D::putImageData(ImageData* data, |
1624 int dx, | 1696 int dx, |
1625 int dy, | 1697 int dy, |
1626 ExceptionState& exception_state) { | 1698 ExceptionState& exception_state) { |
1627 putImageData(data, dx, dy, 0, 0, data->width(), data->height(), | 1699 putImageData(data, dx, dy, 0, 0, data->width(), data->height(), |
1628 exception_state); | 1700 exception_state); |
1629 } | 1701 } |
1630 | 1702 |
1631 void BaseRenderingContext2D::putImageData(ImageData* data, | 1703 void BaseRenderingContext2D::putImageData(ImageData* data, |
1632 int dx, | 1704 int dx, |
1633 int dy, | 1705 int dy, |
1634 int dirty_x, | 1706 int dirty_x, |
1635 int dirty_y, | 1707 int dirty_y, |
1636 int dirty_width, | 1708 int dirty_width, |
1637 int dirty_height, | 1709 int dirty_height, |
1638 ExceptionState& exception_state) { | 1710 ExceptionState& exception_state) { |
1639 if (!WTF::CheckMul(dirty_width, dirty_height).IsValid<int>()) { | 1711 if (!WTF::CheckMul(dirty_width, dirty_height).IsValid<int>()) { |
1640 return; | 1712 return; |
1641 } | 1713 } |
1642 | |
1643 usage_counters_.num_put_image_data_calls++; | 1714 usage_counters_.num_put_image_data_calls++; |
1644 usage_counters_.area_put_image_data_calls += dirty_width * dirty_height; | 1715 usage_counters_.area_put_image_data_calls += dirty_width * dirty_height; |
1645 if (data->data()->BufferBase()->IsNeutered()) { | 1716 |
| 1717 if (data->BufferBase()->IsNeutered()) { |
1646 exception_state.ThrowDOMException(kInvalidStateError, | 1718 exception_state.ThrowDOMException(kInvalidStateError, |
1647 "The source data has been neutered."); | 1719 "The source data has been neutered."); |
1648 return; | 1720 return; |
1649 } | 1721 } |
| 1722 |
1650 ImageBuffer* buffer = GetImageBuffer(); | 1723 ImageBuffer* buffer = GetImageBuffer(); |
1651 if (!buffer) | 1724 if (!buffer) |
1652 return; | 1725 return; |
1653 | 1726 |
1654 if (dirty_width < 0) { | 1727 if (dirty_width < 0) { |
1655 dirty_x += dirty_width; | 1728 dirty_x += dirty_width; |
1656 dirty_width = -dirty_width; | 1729 dirty_width = -dirty_width; |
1657 } | 1730 } |
1658 | 1731 |
1659 if (dirty_height < 0) { | 1732 if (dirty_height < 0) { |
(...skipping 29 matching lines...) Expand all Loading... |
1689 50)); | 1762 50)); |
1690 timer.emplace(scoped_us_counter_cpu); | 1763 timer.emplace(scoped_us_counter_cpu); |
1691 } | 1764 } |
1692 | 1765 |
1693 IntRect source_rect(dest_rect); | 1766 IntRect source_rect(dest_rect); |
1694 source_rect.Move(-dest_offset); | 1767 source_rect.Move(-dest_offset); |
1695 | 1768 |
1696 CheckOverdraw(dest_rect, 0, CanvasRenderingContext2DState::kNoImage, | 1769 CheckOverdraw(dest_rect, 0, CanvasRenderingContext2DState::kNoImage, |
1697 kUntransformedUnclippedFill); | 1770 kUntransformedUnclippedFill); |
1698 | 1771 |
1699 buffer->PutByteArray(kUnmultiplied, data->data()->Data(), | 1772 if (color_management_enabled_) { |
1700 IntSize(data->width(), data->height()), source_rect, | 1773 unsigned data_length = data->width() * data->height() * 4; |
1701 IntPoint(dest_offset)); | 1774 if (PixelFormat() == kF16CanvasPixelFormat) |
| 1775 data_length *= 2; |
| 1776 std::unique_ptr<uint8_t[]> converted_pixels(new uint8_t[data_length]); |
| 1777 data->ImageDataInCanvasColorSettings(ColorSpace(), PixelFormat(), |
| 1778 converted_pixels); |
1702 | 1779 |
| 1780 buffer->PutByteArray(kUnmultiplied, converted_pixels.get(), |
| 1781 IntSize(data->width(), data->height()), source_rect, |
| 1782 IntPoint(dest_offset)); |
| 1783 } else { |
| 1784 buffer->PutByteArray(kUnmultiplied, data->data()->Data(), |
| 1785 IntSize(data->width(), data->height()), source_rect, |
| 1786 IntPoint(dest_offset)); |
| 1787 } |
1703 DidDraw(dest_rect); | 1788 DidDraw(dest_rect); |
1704 } | 1789 } |
1705 | 1790 |
1706 void BaseRenderingContext2D::InflateStrokeRect(FloatRect& rect) const { | 1791 void BaseRenderingContext2D::InflateStrokeRect(FloatRect& rect) const { |
1707 // Fast approximation of the stroke's bounding rect. | 1792 // Fast approximation of the stroke's bounding rect. |
1708 // This yields a slightly oversized rect but is very fast | 1793 // This yields a slightly oversized rect but is very fast |
1709 // compared to Path::strokeBoundingRect(). | 1794 // compared to Path::strokeBoundingRect(). |
1710 static const double kRoot2 = sqrtf(2); | 1795 static const double kRoot2 = sqrtf(2); |
1711 double delta = GetState().LineWidth() / 2; | 1796 double delta = GetState().LineWidth() / 2; |
1712 if (GetState().GetLineJoin() == kMiterJoin) | 1797 if (GetState().GetLineJoin() == kMiterJoin) |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2053 ExpensiveCanvasHeuristicParameters::kShadowFixedCost[index] * | 2138 ExpensiveCanvasHeuristicParameters::kShadowFixedCost[index] * |
2054 usage_counters_.num_blurred_shadows + | 2139 usage_counters_.num_blurred_shadows + |
2055 ExpensiveCanvasHeuristicParameters:: | 2140 ExpensiveCanvasHeuristicParameters:: |
2056 kShadowVariableCostPerAreaTimesShadowBlurSquared[index] * | 2141 kShadowVariableCostPerAreaTimesShadowBlurSquared[index] * |
2057 usage_counters_.bounding_box_area_times_shadow_blur_squared; | 2142 usage_counters_.bounding_box_area_times_shadow_blur_squared; |
2058 | 2143 |
2059 return basic_cost_of_draw_calls + fill_type_adjustment + shadow_adjustment; | 2144 return basic_cost_of_draw_calls + fill_type_adjustment + shadow_adjustment; |
2060 } | 2145 } |
2061 | 2146 |
2062 } // namespace blink | 2147 } // namespace blink |
OLD | NEW |