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

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: Fixing more interface listings fails 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), 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698