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

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, 7 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 20 matching lines...) Expand all
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698