| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/CanvasRenderingContext2D.h" | 5 #include "modules/canvas2d/CanvasRenderingContext2D.h" |
| 6 | 6 |
| 7 #include "core/dom/Document.h" | 7 #include "core/dom/Document.h" |
| 8 #include "core/fetch/MemoryCache.h" | 8 #include "core/fetch/MemoryCache.h" |
| 9 #include "core/frame/FrameView.h" | 9 #include "core/frame/FrameView.h" |
| 10 #include "core/frame/ImageBitmap.h" | 10 #include "core/frame/ImageBitmap.h" |
| 11 #include "core/html/HTMLCanvasElement.h" | 11 #include "core/html/HTMLCanvasElement.h" |
| 12 #include "core/html/ImageData.h" | 12 #include "core/html/ImageData.h" |
| 13 #include "core/imagebitmap/ImageBitmapOptions.h" | 13 #include "core/imagebitmap/ImageBitmapOptions.h" |
| 14 #include "core/loader/EmptyClients.h" | 14 #include "core/loader/EmptyClients.h" |
| 15 #include "core/testing/DummyPageHolder.h" | 15 #include "core/testing/DummyPageHolder.h" |
| 16 #include "modules/canvas2d/CanvasGradient.h" | 16 #include "modules/canvas2d/CanvasGradient.h" |
| 17 #include "modules/canvas2d/CanvasPattern.h" | 17 #include "modules/canvas2d/CanvasPattern.h" |
| 18 #include "modules/webgl/WebGLRenderingContext.h" | 18 #include "modules/webgl/WebGLRenderingContext.h" |
| 19 #include "platform/graphics/Canvas2DImageBufferSurface.h" | 19 #include "platform/graphics/Canvas2DImageBufferSurface.h" |
| 20 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" | 20 #include "platform/graphics/ExpensiveCanvasHeuristicParameters.h" |
| 21 #include "platform/graphics/RecordingImageBufferSurface.h" | 21 #include "platform/graphics/RecordingImageBufferSurface.h" |
| 22 #include "platform/graphics/StaticBitmapImage.h" | 22 #include "platform/graphics/StaticBitmapImage.h" |
| 23 #include "platform/graphics/UnacceleratedImageBufferSurface.h" | 23 #include "platform/graphics/UnacceleratedImageBufferSurface.h" |
| 24 #include "platform/graphics/test/FakeGLES2Interface.h" | 24 #include "platform/graphics/test/FakeGLES2Interface.h" |
| 25 #include "platform/graphics/test/FakeWebGraphicsContext3DProvider.h" | 25 #include "platform/graphics/test/FakeWebGraphicsContext3DProvider.h" |
| 26 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
| 27 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 28 #include "third_party/skia/include/core/SkColorSpaceXform.h" |
| 29 #include "third_party/skia/include/core/SkImage.h" |
| 28 #include "third_party/skia/include/core/SkSurface.h" | 30 #include "third_party/skia/include/core/SkSurface.h" |
| 29 #include "wtf/PtrUtil.h" | 31 #include "wtf/PtrUtil.h" |
| 30 #include <memory> | 32 #include <memory> |
| 31 | 33 |
| 32 using ::testing::Mock; | 34 using ::testing::Mock; |
| 33 | 35 |
| 34 namespace blink { | 36 namespace blink { |
| 35 | 37 |
| 36 enum BitmapOpacity { OpaqueBitmap, TransparentBitmap }; | 38 enum BitmapOpacity { OpaqueBitmap, TransparentBitmap }; |
| 37 | 39 |
| (...skipping 1226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named); | 1266 SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named); |
| 1265 EXPECT_TRUE(behavior.isTransformToTargetColorSpace()); | 1267 EXPECT_TRUE(behavior.isTransformToTargetColorSpace()); |
| 1266 EXPECT_TRUE(SkColorSpace::Equals(linearSrgbColorSpace.get(), | 1268 EXPECT_TRUE(SkColorSpace::Equals(linearSrgbColorSpace.get(), |
| 1267 behavior.targetColorSpace().get())); | 1269 behavior.targetColorSpace().get())); |
| 1268 | 1270 |
| 1269 // Restore global state to avoid interfering with other tests | 1271 // Restore global state to avoid interfering with other tests |
| 1270 ColorBehavior::setGlobalTargetColorSpaceForTesting( | 1272 ColorBehavior::setGlobalTargetColorSpaceForTesting( |
| 1271 savedGlobalTargetColorSpace); | 1273 savedGlobalTargetColorSpace); |
| 1272 } | 1274 } |
| 1273 | 1275 |
| 1276 enum class ColorSpaceConversion : uint8_t { |
| 1277 NONE = 0, |
| 1278 DEFAULT_NOT_COLOR_CORRECTED = 1, |
| 1279 DEFAULT_COLOR_CORRECTED = 2, |
| 1280 SRGB = 3, |
| 1281 LINEAR_RGB = 4, |
| 1282 |
| 1283 LAST = LINEAR_RGB |
| 1284 }; |
| 1285 |
| 1286 static ImageBitmapOptions prepareBitmapOptionsAndSetRuntimeFlags( |
| 1287 const ColorSpaceConversion& colorSpaceConversion) { |
| 1288 // Set the color space conversion in ImageBitmapOptions |
| 1289 ImageBitmapOptions options; |
| 1290 static const Vector<String> conversions = {"none", "default", "default", |
| 1291 "srgb", "linear-rgb"}; |
| 1292 options.setColorSpaceConversion( |
| 1293 conversions[static_cast<uint8_t>(colorSpaceConversion)]); |
| 1294 |
| 1295 // Set the runtime flags |
| 1296 bool flag = (colorSpaceConversion != |
| 1297 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); |
| 1298 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled(true); |
| 1299 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled(flag); |
| 1300 RuntimeEnabledFeatures::setColorCorrectRenderingDefaultModeEnabled(!flag); |
| 1301 |
| 1302 return options; |
| 1303 } |
| 1304 |
| 1305 TEST_F(CanvasRenderingContext2DTest, ImageBitmapColorSpaceConversion) { |
| 1306 bool experimentalCanvasFeaturesRuntimeFlag = |
| 1307 RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); |
| 1308 bool colorCorrectRenderingRuntimeFlag = |
| 1309 RuntimeEnabledFeatures::colorCorrectRenderingEnabled(); |
| 1310 bool colorCorrectRenderingDefaultModeRuntimeFlag = |
| 1311 RuntimeEnabledFeatures::colorCorrectRenderingDefaultModeEnabled(); |
| 1312 |
| 1313 Persistent<HTMLCanvasElement> canvas = |
| 1314 Persistent<HTMLCanvasElement>(canvasElement()); |
| 1315 CanvasContextCreationAttributes attributes; |
| 1316 attributes.setAlpha(true); |
| 1317 attributes.setColorSpace("srgb"); |
| 1318 CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>( |
| 1319 canvas->getCanvasRenderingContext("2d", attributes)); |
| 1320 StringOrCanvasGradientOrCanvasPattern fillStyle; |
| 1321 fillStyle.setString("#FF0000"); |
| 1322 context->setFillStyle(fillStyle); |
| 1323 context->fillRect(0, 0, 10, 10); |
| 1324 NonThrowableExceptionState exceptionState; |
| 1325 uint8_t* srcPixel = |
| 1326 context->getImageData(5, 5, 1, 1, exceptionState)->data()->data(); |
| 1327 // Swizzle if needed |
| 1328 if (kN32_SkColorType == kBGRA_8888_SkColorType) |
| 1329 std::swap(srcPixel[0], srcPixel[2]); |
| 1330 |
| 1331 // Create and test the ImageBitmap objects. |
| 1332 Optional<IntRect> cropRect = IntRect(0, 0, 10, 10); |
| 1333 sk_sp<SkColorSpace> colorSpace = nullptr; |
| 1334 SkColorType colorType = SkColorType::kN32_SkColorType; |
| 1335 SkColorSpaceXform::ColorFormat colorFormat32 = |
| 1336 (colorType == kBGRA_8888_SkColorType) |
| 1337 ? SkColorSpaceXform::ColorFormat::kBGRA_8888_ColorFormat |
| 1338 : SkColorSpaceXform::ColorFormat::kRGBA_8888_ColorFormat; |
| 1339 SkColorSpaceXform::ColorFormat colorFormat = colorFormat32; |
| 1340 sk_sp<SkColorSpace> srcRGBColorSpace = |
| 1341 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
| 1342 |
| 1343 for (uint8_t i = static_cast<uint8_t>( |
| 1344 ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED); |
| 1345 i <= static_cast<uint8_t>(ColorSpaceConversion::LAST); i++) { |
| 1346 ColorSpaceConversion colorSpaceConversion = |
| 1347 static_cast<ColorSpaceConversion>(i); |
| 1348 ImageBitmapOptions options = |
| 1349 prepareBitmapOptionsAndSetRuntimeFlags(colorSpaceConversion); |
| 1350 ImageBitmap* imageBitmap = ImageBitmap::create(canvas, cropRect, options); |
| 1351 // ColorBehavior::ignore() is used instead of |
| 1352 // ColorBehavior::transformToTargetForTesting() to avoid color conversion to |
| 1353 // display color profile, as we want to solely rely on the color correction |
| 1354 // that happens in ImageBitmap create method. |
| 1355 SkImage* convertedImage = |
| 1356 imageBitmap->bitmapImage() |
| 1357 ->imageForCurrentFrame(ColorBehavior::ignore()) |
| 1358 .get(); |
| 1359 |
| 1360 switch (colorSpaceConversion) { |
| 1361 case ColorSpaceConversion::NONE: |
| 1362 NOTREACHED(); |
| 1363 break; |
| 1364 case ColorSpaceConversion::DEFAULT_NOT_COLOR_CORRECTED: |
| 1365 // TODO(zakerinasab): Replace sRGB with a call to |
| 1366 // ImageDecoder::globalTargetColorSpace() when the crash problem on Mac |
| 1367 // is fixed. crbug.com/668546. |
| 1368 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
| 1369 colorFormat = colorFormat32; |
| 1370 break; |
| 1371 case ColorSpaceConversion::DEFAULT_COLOR_CORRECTED: |
| 1372 case ColorSpaceConversion::SRGB: |
| 1373 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); |
| 1374 colorFormat = colorFormat32; |
| 1375 break; |
| 1376 case ColorSpaceConversion::LINEAR_RGB: |
| 1377 colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named); |
| 1378 colorType = SkColorType::kRGBA_F16_SkColorType; |
| 1379 colorFormat = SkColorSpaceXform::ColorFormat::kRGBA_F16_ColorFormat; |
| 1380 break; |
| 1381 default: |
| 1382 NOTREACHED(); |
| 1383 } |
| 1384 |
| 1385 SkImageInfo imageInfo = SkImageInfo::Make( |
| 1386 1, 1, colorType, SkAlphaType::kPremul_SkAlphaType, colorSpace); |
| 1387 std::unique_ptr<uint8_t[]> convertedPixel( |
| 1388 new uint8_t[imageInfo.bytesPerPixel()]()); |
| 1389 convertedImage->readPixels( |
| 1390 imageInfo, convertedPixel.get(), |
| 1391 convertedImage->width() * imageInfo.bytesPerPixel(), 5, 5); |
| 1392 |
| 1393 // Transform the source pixel and check if the image bitmap color conversion |
| 1394 // is done correctly. |
| 1395 std::unique_ptr<SkColorSpaceXform> colorSpaceXform = |
| 1396 SkColorSpaceXform::New(srcRGBColorSpace.get(), colorSpace.get()); |
| 1397 std::unique_ptr<uint8_t[]> transformedPixel( |
| 1398 new uint8_t[imageInfo.bytesPerPixel()]()); |
| 1399 colorSpaceXform->apply(colorFormat, transformedPixel.get(), colorFormat32, |
| 1400 srcPixel, 1, SkAlphaType::kPremul_SkAlphaType); |
| 1401 |
| 1402 int compare = std::memcmp(convertedPixel.get(), transformedPixel.get(), |
| 1403 imageInfo.bytesPerPixel()); |
| 1404 ASSERT_EQ(compare, 0); |
| 1405 } |
| 1406 |
| 1407 RuntimeEnabledFeatures::setExperimentalCanvasFeaturesEnabled( |
| 1408 experimentalCanvasFeaturesRuntimeFlag); |
| 1409 RuntimeEnabledFeatures::setColorCorrectRenderingEnabled( |
| 1410 colorCorrectRenderingRuntimeFlag); |
| 1411 RuntimeEnabledFeatures::setColorCorrectRenderingDefaultModeEnabled( |
| 1412 colorCorrectRenderingDefaultModeRuntimeFlag); |
| 1413 } |
| 1414 |
| 1274 } // namespace blink | 1415 } // namespace blink |
| OLD | NEW |