Chromium Code Reviews| 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), is_color_managed_(false) { |
| 40 state_stack_.push_back(CanvasRenderingContext2DState::Create()); | 40 state_stack_.push_back(CanvasRenderingContext2DState::Create()); |
| 41 is_color_managed_ = | |
|
fserb
2017/04/11 03:21:44
a RenderingContext is color managed even if it has
zakerinasab
2017/04/11 19:52:59
Done.
| |
| 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 bool BaseRenderingContext2D::ColorSettingsAsImageDataColorSettings( | |
| 1513 ImageDataColorSettings& color_settings) const { | |
|
fserb
2017/04/11 03:21:44
maybe ImageDataColorSettings* ?
zakerinasab
2017/04/11 19:52:59
Rewritten.
| |
| 1514 if (!is_color_managed_) | |
| 1515 return false; | |
| 1516 color_settings.setColorSpace(ColorSpaceAsString()); | |
| 1517 switch (PixelFormat()) { | |
| 1518 case kRGBA8CanvasPixelFormat: | |
| 1519 color_settings.setStorageFormat(kUint8ClampedArrayStorageFormatName); | |
| 1520 break; | |
| 1521 case kF16CanvasPixelFormat: | |
| 1522 color_settings.setStorageFormat(kFloat32ArrayStorageFormatName); | |
| 1523 break; | |
| 1524 case kRGB10A2CanvasPixelFormat: | |
| 1525 case kRGBA12CanvasPixelFormat: | |
| 1526 default: | |
| 1527 NOTREACHED(); | |
| 1528 return false; | |
| 1529 } | |
| 1530 return true; | |
| 1531 } | |
| 1532 | |
| 1509 ImageData* BaseRenderingContext2D::createImageData( | 1533 ImageData* BaseRenderingContext2D::createImageData( |
| 1510 ImageData* image_data, | 1534 ImageData* image_data, |
| 1511 ExceptionState& exception_state) const { | 1535 ExceptionState& exception_state) const { |
| 1512 ImageData* result = ImageData::Create(image_data->size()); | 1536 ImageData* result = nullptr; |
| 1537 if (is_color_managed_) { | |
| 1538 ImageDataColorSettings color_settings; | |
| 1539 if (ColorSettingsAsImageDataColorSettings(color_settings)) | |
| 1540 result = ImageData::Create(image_data->size(), &color_settings); | |
| 1541 } else { | |
| 1542 result = ImageData::Create(image_data->size()); | |
| 1543 } | |
| 1513 if (!result) | 1544 if (!result) |
| 1514 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1545 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
| 1515 return result; | 1546 return result; |
| 1516 } | 1547 } |
| 1517 | 1548 |
| 1518 ImageData* BaseRenderingContext2D::createImageData( | 1549 ImageData* BaseRenderingContext2D::createImageData( |
| 1519 int sw, | 1550 int sw, |
| 1520 int sh, | 1551 int sh, |
| 1521 ExceptionState& exception_state) const { | 1552 ExceptionState& exception_state) const { |
| 1522 if (!sw || !sh) { | 1553 if (!sw || !sh) { |
| 1523 exception_state.ThrowDOMException( | 1554 exception_state.ThrowDOMException( |
| 1524 kIndexSizeError, | 1555 kIndexSizeError, |
| 1525 String::Format("The source %s is 0.", sw ? "height" : "width")); | 1556 String::Format("The source %s is 0.", sw ? "height" : "width")); |
| 1526 return nullptr; | 1557 return nullptr; |
| 1527 } | 1558 } |
| 1528 | 1559 |
| 1529 IntSize size(abs(sw), abs(sh)); | 1560 IntSize size(abs(sw), abs(sh)); |
| 1561 ImageData* result = nullptr; | |
| 1562 if (is_color_managed_) { | |
| 1563 ImageDataColorSettings color_settings; | |
| 1564 if (ColorSettingsAsImageDataColorSettings(color_settings)) | |
| 1565 result = ImageData::Create(size, &color_settings); | |
| 1566 } else { | |
| 1567 result = ImageData::Create(size); | |
| 1568 } | |
| 1530 | 1569 |
| 1531 ImageData* result = ImageData::Create(size); | |
| 1532 if (!result) | 1570 if (!result) |
| 1533 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1571 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
| 1534 return result; | 1572 return result; |
| 1535 } | 1573 } |
| 1536 | 1574 |
| 1537 ImageData* BaseRenderingContext2D::getImageData( | 1575 ImageData* BaseRenderingContext2D::getImageData( |
| 1538 int sx, | 1576 int sx, |
| 1539 int sy, | 1577 int sy, |
| 1540 int sw, | 1578 int sw, |
| 1541 int sh, | 1579 int sh, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1587 10000000, 50)); | 1625 10000000, 50)); |
| 1588 timer.emplace(scoped_us_counter_display_list); | 1626 timer.emplace(scoped_us_counter_display_list); |
| 1589 } else { | 1627 } else { |
| 1590 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 1628 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
| 1591 CustomCountHistogram, scoped_us_counter_cpu, | 1629 CustomCountHistogram, scoped_us_counter_cpu, |
| 1592 new CustomCountHistogram("Blink.Canvas.GetImageData.CPU", 0, 10000000, | 1630 new CustomCountHistogram("Blink.Canvas.GetImageData.CPU", 0, 10000000, |
| 1593 50)); | 1631 50)); |
| 1594 timer.emplace(scoped_us_counter_cpu); | 1632 timer.emplace(scoped_us_counter_cpu); |
| 1595 } | 1633 } |
| 1596 | 1634 |
| 1635 ImageDataColorSettings color_settings; | |
| 1636 bool valid_color_settings = false; | |
| 1637 if (is_color_managed_) { | |
| 1638 valid_color_settings = | |
|
fserb
2017/04/11 03:21:44
just use is_color_managed_?
zakerinasab
2017/04/11 19:52:59
Done.
| |
| 1639 ColorSettingsAsImageDataColorSettings(color_settings); | |
| 1640 } | |
| 1597 IntRect image_data_rect(sx, sy, sw, sh); | 1641 IntRect image_data_rect(sx, sy, sw, sh); |
| 1642 DVLOG(1) << sx << ", " << sy << ", " << sw << ", " << sh; | |
|
fserb
2017/04/11 03:21:44
^^^^
zakerinasab
2017/04/11 19:52:59
Removed, but it's funny that I don't remember putt
| |
| 1598 ImageBuffer* buffer = GetImageBuffer(); | 1643 ImageBuffer* buffer = GetImageBuffer(); |
| 1599 if (!buffer || isContextLost()) { | 1644 if (!buffer || isContextLost()) { |
| 1600 ImageData* result = ImageData::Create(image_data_rect.size()); | 1645 ImageData* result = nullptr; |
| 1646 if (valid_color_settings) | |
| 1647 result = ImageData::Create(image_data_rect.size(), &color_settings); | |
| 1648 else | |
| 1649 result = ImageData::Create(image_data_rect.size()); | |
| 1601 if (!result) | 1650 if (!result) |
| 1602 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1651 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
| 1603 return result; | 1652 return result; |
| 1604 } | 1653 } |
| 1605 | 1654 |
| 1606 WTF::ArrayBufferContents contents; | 1655 WTF::ArrayBufferContents contents; |
| 1607 if (!buffer->GetImageData(kUnmultiplied, image_data_rect, contents)) { | 1656 if (!buffer->GetImageData(kUnmultiplied, image_data_rect, contents)) { |
| 1608 exception_state.ThrowRangeError("Out of memory at ImageData creation"); | 1657 exception_state.ThrowRangeError("Out of memory at ImageData creation"); |
| 1609 return nullptr; | 1658 return nullptr; |
| 1610 } | 1659 } |
| 1611 | 1660 |
| 1612 NeedsFinalizeFrame(); | 1661 NeedsFinalizeFrame(); |
| 1613 | 1662 |
| 1614 DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(contents); | 1663 DOMArrayBuffer* array_buffer = nullptr; |
| 1664 DOMArrayBufferView* array_buffer_view = nullptr; | |
| 1665 DOMFloat32Array* data_array = nullptr; | |
| 1666 | |
| 1667 if (is_color_managed_) { | |
| 1668 ImageDataStorageFormat storage_format = | |
| 1669 ImageData::GetImageDataStorageFormat(color_settings.storageFormat()); | |
| 1670 switch (storage_format) { | |
|
fserb
2017/04/11 03:21:44
this code is looking weird.
I'm Assuming is_color_
zakerinasab
2017/04/11 19:52:59
Simplified.
| |
| 1671 case kUint8ClampedArrayStorageFormat: | |
| 1672 array_buffer = DOMArrayBuffer::Create(contents); | |
| 1673 return ImageData::Create( | |
| 1674 image_data_rect.size(), | |
| 1675 DOMUint8ClampedArray::Create(array_buffer, 0, | |
| 1676 array_buffer->ByteLength())); | |
| 1677 break; | |
| 1678 case kUint16ArrayStorageFormat: | |
| 1679 NOTREACHED(); | |
| 1680 break; | |
| 1681 case kFloat32ArrayStorageFormat: | |
| 1682 array_buffer_view = ImageData:: | |
| 1683 ConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat( | |
| 1684 contents, PixelFormat(), storage_format); | |
| 1685 data_array = const_cast<DOMFloat32Array*>( | |
| 1686 static_cast<const DOMFloat32Array*>(array_buffer_view)); | |
| 1687 return ImageData::Create(image_data_rect.size(), array_buffer_view, | |
| 1688 &color_settings); | |
| 1689 default: | |
| 1690 NOTREACHED(); | |
| 1691 } | |
| 1692 return nullptr; | |
| 1693 } | |
| 1694 | |
| 1695 array_buffer = DOMArrayBuffer::Create(contents); | |
| 1615 return ImageData::Create(image_data_rect.size(), | 1696 return ImageData::Create(image_data_rect.size(), |
| 1616 DOMUint8ClampedArray::Create( | 1697 DOMUint8ClampedArray::Create( |
| 1617 array_buffer, 0, array_buffer->ByteLength())); | 1698 array_buffer, 0, array_buffer->ByteLength())); |
| 1618 } | 1699 } |
| 1619 | 1700 |
| 1620 void BaseRenderingContext2D::putImageData(ImageData* data, | 1701 void BaseRenderingContext2D::putImageData(ImageData* data, |
| 1621 int dx, | 1702 int dx, |
| 1622 int dy, | 1703 int dy, |
| 1623 ExceptionState& exception_state) { | 1704 ExceptionState& exception_state) { |
| 1624 putImageData(data, dx, dy, 0, 0, data->width(), data->height(), | 1705 putImageData(data, dx, dy, 0, 0, data->width(), data->height(), |
| 1625 exception_state); | 1706 exception_state); |
| 1626 } | 1707 } |
| 1627 | 1708 |
| 1628 void BaseRenderingContext2D::putImageData(ImageData* data, | 1709 void BaseRenderingContext2D::putImageData(ImageData* data, |
| 1629 int dx, | 1710 int dx, |
| 1630 int dy, | 1711 int dy, |
| 1631 int dirty_x, | 1712 int dirty_x, |
| 1632 int dirty_y, | 1713 int dirty_y, |
| 1633 int dirty_width, | 1714 int dirty_width, |
| 1634 int dirty_height, | 1715 int dirty_height, |
| 1635 ExceptionState& exception_state) { | 1716 ExceptionState& exception_state) { |
| 1636 if (!WTF::CheckMul(dirty_width, dirty_height).IsValid<int>()) { | 1717 if (!WTF::CheckMul(dirty_width, dirty_height).IsValid<int>()) { |
| 1637 return; | 1718 return; |
| 1638 } | 1719 } |
| 1639 | |
| 1640 usage_counters_.num_put_image_data_calls++; | 1720 usage_counters_.num_put_image_data_calls++; |
| 1641 usage_counters_.area_put_image_data_calls += dirty_width * dirty_height; | 1721 usage_counters_.area_put_image_data_calls += dirty_width * dirty_height; |
| 1642 if (data->data()->BufferBase()->IsNeutered()) { | 1722 |
| 1723 bool data_is_neutered = false; | |
| 1724 if (is_color_managed_) { | |
|
fserb
2017/04/11 03:21:44
again, if this is an experimental flag thingy, I'd
zakerinasab
2017/04/11 19:52:59
You mean if(original_check) {something} else {chec
| |
| 1725 data_is_neutered = | |
| 1726 (data->dataUnion().isUint8ClampedArray() && | |
| 1727 data->dataUnion() | |
| 1728 .getAsUint8ClampedArray() | |
| 1729 ->BufferBase() | |
| 1730 ->IsNeutered()) || | |
| 1731 (data->dataUnion().isUint16Array() && | |
| 1732 data->dataUnion().getAsUint16Array()->BufferBase()->IsNeutered()) || | |
| 1733 (data->dataUnion().isFloat32Array() && | |
| 1734 data->dataUnion().getAsFloat32Array()->BufferBase()->IsNeutered()); | |
| 1735 } else { | |
| 1736 data_is_neutered = data->data()->BufferBase()->IsNeutered(); | |
| 1737 } | |
| 1738 if (data_is_neutered) { | |
| 1643 exception_state.ThrowDOMException(kInvalidStateError, | 1739 exception_state.ThrowDOMException(kInvalidStateError, |
| 1644 "The source data has been neutered."); | 1740 "The source data has been neutered."); |
| 1645 return; | 1741 return; |
| 1646 } | 1742 } |
| 1743 | |
| 1647 ImageBuffer* buffer = GetImageBuffer(); | 1744 ImageBuffer* buffer = GetImageBuffer(); |
| 1648 if (!buffer) | 1745 if (!buffer) |
| 1649 return; | 1746 return; |
| 1650 | 1747 |
| 1651 if (dirty_width < 0) { | 1748 if (dirty_width < 0) { |
| 1652 dirty_x += dirty_width; | 1749 dirty_x += dirty_width; |
| 1653 dirty_width = -dirty_width; | 1750 dirty_width = -dirty_width; |
| 1654 } | 1751 } |
| 1655 | 1752 |
| 1656 if (dirty_height < 0) { | 1753 if (dirty_height < 0) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1686 50)); | 1783 50)); |
| 1687 timer.emplace(scoped_us_counter_cpu); | 1784 timer.emplace(scoped_us_counter_cpu); |
| 1688 } | 1785 } |
| 1689 | 1786 |
| 1690 IntRect source_rect(dest_rect); | 1787 IntRect source_rect(dest_rect); |
| 1691 source_rect.Move(-dest_offset); | 1788 source_rect.Move(-dest_offset); |
| 1692 | 1789 |
| 1693 CheckOverdraw(dest_rect, 0, CanvasRenderingContext2DState::kNoImage, | 1790 CheckOverdraw(dest_rect, 0, CanvasRenderingContext2DState::kNoImage, |
| 1694 kUntransformedUnclippedFill); | 1791 kUntransformedUnclippedFill); |
| 1695 | 1792 |
| 1696 buffer->PutByteArray(kUnmultiplied, data->data()->Data(), | 1793 if (is_color_managed_) { |
| 1697 IntSize(data->width(), data->height()), source_rect, | 1794 unsigned data_length = data->width() * data->height(); |
|
fserb
2017/04/11 03:21:44
name the type?
zakerinasab
2017/04/11 19:52:59
?
| |
| 1698 IntPoint(dest_offset)); | 1795 if (PixelFormat() == kF16CanvasPixelFormat) |
| 1699 | 1796 data_length *= 2; |
| 1797 std::unique_ptr<uint8_t[]> converted_pixels(new uint8_t[4 * data_length]); | |
| 1798 data->ImageDataInCanvasColorSettings(ColorSpace(), PixelFormat(), | |
| 1799 converted_pixels); | |
| 1800 buffer->PutByteArray(kUnmultiplied, converted_pixels.get(), | |
| 1801 IntSize(data->width(), data->height()), source_rect, | |
| 1802 IntPoint(dest_offset)); | |
| 1803 } else { | |
| 1804 buffer->PutByteArray(kUnmultiplied, data->data()->Data(), | |
| 1805 IntSize(data->width(), data->height()), source_rect, | |
| 1806 IntPoint(dest_offset)); | |
| 1807 } | |
| 1700 DidDraw(dest_rect); | 1808 DidDraw(dest_rect); |
| 1701 } | 1809 } |
| 1702 | 1810 |
| 1703 void BaseRenderingContext2D::InflateStrokeRect(FloatRect& rect) const { | 1811 void BaseRenderingContext2D::InflateStrokeRect(FloatRect& rect) const { |
| 1704 // Fast approximation of the stroke's bounding rect. | 1812 // Fast approximation of the stroke's bounding rect. |
| 1705 // This yields a slightly oversized rect but is very fast | 1813 // This yields a slightly oversized rect but is very fast |
| 1706 // compared to Path::strokeBoundingRect(). | 1814 // compared to Path::strokeBoundingRect(). |
| 1707 static const double kRoot2 = sqrtf(2); | 1815 static const double kRoot2 = sqrtf(2); |
| 1708 double delta = GetState().LineWidth() / 2; | 1816 double delta = GetState().LineWidth() / 2; |
| 1709 if (GetState().GetLineJoin() == kMiterJoin) | 1817 if (GetState().GetLineJoin() == kMiterJoin) |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2050 ExpensiveCanvasHeuristicParameters::kShadowFixedCost[index] * | 2158 ExpensiveCanvasHeuristicParameters::kShadowFixedCost[index] * |
| 2051 usage_counters_.num_blurred_shadows + | 2159 usage_counters_.num_blurred_shadows + |
| 2052 ExpensiveCanvasHeuristicParameters:: | 2160 ExpensiveCanvasHeuristicParameters:: |
| 2053 kShadowVariableCostPerAreaTimesShadowBlurSquared[index] * | 2161 kShadowVariableCostPerAreaTimesShadowBlurSquared[index] * |
| 2054 usage_counters_.bounding_box_area_times_shadow_blur_squared; | 2162 usage_counters_.bounding_box_area_times_shadow_blur_squared; |
| 2055 | 2163 |
| 2056 return basic_cost_of_draw_calls + fill_type_adjustment + shadow_adjustment; | 2164 return basic_cost_of_draw_calls + fill_type_adjustment + shadow_adjustment; |
| 2057 } | 2165 } |
| 2058 | 2166 |
| 2059 } // namespace blink | 2167 } // namespace blink |
| OLD | NEW |