Index: third_party/WebKit/Source/core/html/ImageDataTest.cpp |
diff --git a/third_party/WebKit/Source/core/html/ImageDataTest.cpp b/third_party/WebKit/Source/core/html/ImageDataTest.cpp |
index daa0d9af1063391c41fb3d93ed69c4188ff8f252..716b0a67ceebdd083dac2e34c0ed651174f6189b 100644 |
--- a/third_party/WebKit/Source/core/html/ImageDataTest.cpp |
+++ b/third_party/WebKit/Source/core/html/ImageDataTest.cpp |
@@ -7,14 +7,31 @@ |
#include "core/dom/ExceptionCode.h" |
#include "platform/geometry/IntSize.h" |
#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/skia/include/core/SkColorSpaceXform.h" |
namespace blink { |
namespace { |
class ImageDataTest : public ::testing::Test { |
protected: |
- ImageDataTest(){}; |
- void TearDown(){}; |
+ virtual void SetUp() { |
+ // Save the state of experimental canvas features and color correct |
+ // rendering flags to restore them on teardown. |
+ experimentalCanvasFeatures = |
+ RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); |
+ colorCorrectRendering = |
+ RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
+ } |
+ |
+ virtual void TearDown() { |
+ RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled( |
+ experimentalCanvasFeatures); |
+ RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( |
+ colorCorrectRendering); |
+ } |
+ |
+ bool experimentalCanvasFeatures; |
+ bool colorCorrectRendering; |
}; |
TEST_F(ImageDataTest, NegativeAndZeroIntSizeTest) { |
@@ -50,5 +67,117 @@ TEST_F(ImageDataTest, CreateImageDataTooBig) { |
} |
} |
+// Skia conversion does not guarantee to be exact, se we need to do |
+// approximate comparisons. |
+static inline bool IsNearlyTheSame(float f, float g) { |
+ static const float epsilonScale = 0.01f; |
+ return std::abs(f - g) < epsilonScale * |
+ std::max(std::max(std::abs(f), std::abs(g)), epsilonScale); |
+} |
+ |
+// This test verifies the correct behavior of ImageData member function used |
+// to convert pixels data from canvas pixel format image data storage format. |
+// This function is used in BaseRenderingContext2D::getImageData. |
+TEST_F(ImageDataTest, TestConvertPixelsFromCanvasPixelFormatToImageDataStorageFormat) { |
+ // Source pixels in RGBA32 |
+ unsigned char rgba32Pixels[] = {255, 0, 0, 255, // Red |
+ 0, 0, 0, 0, // Transparent |
+ 255, 192, 128, 64, // Decreasing values |
+ 93, 117, 205, 11}; // Random values |
+ const unsigned numColorComponents = 16; |
+ // Source pixels in F16 |
+ unsigned char* f16Pixels = new unsigned char [numColorComponents * 2]; |
+ |
+ // Filling F16 source pixels |
+ std::unique_ptr<SkColorSpaceXform> xform = |
+ SkColorSpaceXform::New(SkColorSpace::MakeSRGBLinear().get(), |
+ SkColorSpace::MakeSRGBLinear().get()); |
+ xform->apply(SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat, f16Pixels, |
+ SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat, rgba32Pixels, |
+ 4, SkAlphaType::kUnpremul_SkAlphaType); |
+ |
+ // Creating ArrayBufferContents objects. We need two buffers for RGBA32 data |
+ // because kRGBA8CanvasPixelFormat->kUint8ClampedArrayStorageFormat consumes |
+ // the input data parameter. |
+ WTF::ArrayBufferContents contentsRGBA32(numColorComponents, 1, WTF::ArrayBufferContents::NotShared, |
+ WTF::ArrayBufferContents::DontInitialize); |
+ std::memcpy(contentsRGBA32.data(), rgba32Pixels, numColorComponents); |
+ |
+ WTF::ArrayBufferContents contents2RGBA32(numColorComponents, 1, WTF::ArrayBufferContents::NotShared, |
+ WTF::ArrayBufferContents::DontInitialize); |
+ std::memcpy(contents2RGBA32.data(), rgba32Pixels, numColorComponents); |
+ |
+ WTF::ArrayBufferContents contentsF16(numColorComponents * 2, 1, WTF::ArrayBufferContents::NotShared, |
+ WTF::ArrayBufferContents::DontInitialize); |
+ std::memcpy(contentsF16.data(), f16Pixels, numColorComponents * 2); |
+ |
+ // Uint16 is not supported as the storage format for ImageData created from a |
+ // canvas, so this conversion is neither implemented nor tested here. |
+ bool testPassed = true; |
+ DOMArrayBufferView* data = nullptr; |
+ DOMUint8ClampedArray* dataU8 = nullptr; |
+ DOMFloat32Array* dataF32 = nullptr; |
+ |
+ // Testing kRGBA8CanvasPixelFormat -> kUint8ClampedArrayStorageFormat |
+ data = ImageData::convertPixelsFromCanvasPixelFormatToImageDataStorageFormat( |
+ contentsRGBA32, kRGBA8CanvasPixelFormat, kUint8ClampedArrayStorageFormat); |
+ DCHECK(data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped); |
+ dataU8 = const_cast<DOMUint8ClampedArray*>( |
+ static_cast<const DOMUint8ClampedArray*>(data)); |
+ DCHECK(dataU8); |
+ for (unsigned i = 0; i < numColorComponents; i++) { |
+ if (dataU8->data()[i] != rgba32Pixels[i]){ |
+ testPassed = false; |
+ break; |
+ } |
+ } |
+ EXPECT_TRUE(testPassed); |
+ |
+ // Testing kRGBA8CanvasPixelFormat -> kFloat32ArrayStorageFormat |
+ data = ImageData::convertPixelsFromCanvasPixelFormatToImageDataStorageFormat( |
+ contents2RGBA32, kRGBA8CanvasPixelFormat, kFloat32ArrayStorageFormat); |
+ DCHECK(data->type() == DOMArrayBufferView::ViewType::TypeFloat32); |
+ dataF32 = const_cast<DOMFloat32Array*>( |
+ static_cast<const DOMFloat32Array*>(data)); |
+ DCHECK(dataF32); |
+ for (unsigned i = 0; i < numColorComponents; i++) { |
+ if (!IsNearlyTheSame(dataF32->data()[i], rgba32Pixels[i] / 255.0)){ |
+ testPassed = false; |
+ break; |
+ } |
+ } |
+ EXPECT_TRUE(testPassed); |
+ |
+ // Testing kF16CanvasPixelFormat -> kUint8ClampedArrayStorageFormat |
+ data = ImageData::convertPixelsFromCanvasPixelFormatToImageDataStorageFormat( |
+ contentsF16, kF16CanvasPixelFormat, kUint8ClampedArrayStorageFormat); |
+ DCHECK(data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped); |
+ dataU8 = const_cast<DOMUint8ClampedArray*>( |
+ static_cast<const DOMUint8ClampedArray*>(data)); |
+ DCHECK(dataU8); |
+ for (unsigned i = 0; i < numColorComponents; i++) { |
+ if (!IsNearlyTheSame(dataU8->data()[i], rgba32Pixels[i])){ |
+ testPassed = false; |
+ break; |
+ } |
+ } |
+ EXPECT_TRUE(testPassed); |
+ |
+ // Testing kF16CanvasPixelFormat -> kFloat32ArrayStorageFormat |
+ data = ImageData::convertPixelsFromCanvasPixelFormatToImageDataStorageFormat( |
+ contentsF16, kF16CanvasPixelFormat, kFloat32ArrayStorageFormat); |
+ DCHECK(data->type() == DOMArrayBufferView::ViewType::TypeFloat32); |
+ dataF32 = const_cast<DOMFloat32Array*>( |
+ static_cast<const DOMFloat32Array*>(data)); |
+ DCHECK(dataF32); |
+ for (unsigned i = 0; i < numColorComponents; i++) { |
+ if (!IsNearlyTheSame(dataF32->data()[i], rgba32Pixels[i] / 255.0)){ |
+ testPassed = false; |
+ break; |
+ } |
+ } |
+ EXPECT_TRUE(testPassed); |
+} |
+ |
} // namspace |
} // namespace blink |