Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Side by Side Diff: third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp

Issue 2797213002: Fix BaseRenderingContext2D create/put/get-ImageData() for color managed canvas (Closed)
Patch Set: Rebaseline Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698