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