Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "core/frame/ImageBitmap.h" | 5 #include "core/frame/ImageBitmap.h" |
| 6 | 6 |
| 7 #include "core/html/HTMLCanvasElement.h" | 7 #include "core/html/HTMLCanvasElement.h" |
| 8 #include "core/html/HTMLVideoElement.h" | 8 #include "core/html/HTMLVideoElement.h" |
| 9 #include "core/html/ImageData.h" | 9 #include "core/html/ImageData.h" |
| 10 #include "platform/graphics/skia/SkiaUtils.h" | 10 #include "platform/graphics/skia/SkiaUtils.h" |
| 11 #include "platform/image-decoders/ImageDecoder.h" | 11 #include "platform/image-decoders/ImageDecoder.h" |
| 12 #include "third_party/skia/include/core/SkCanvas.h" | 12 #include "third_party/skia/include/core/SkCanvas.h" |
| 13 #include "third_party/skia/include/core/SkImageInfo.h" | |
| 13 #include "third_party/skia/include/core/SkSurface.h" | 14 #include "third_party/skia/include/core/SkSurface.h" |
| 14 #include "wtf/CheckedNumeric.h" | 15 #include "wtf/CheckedNumeric.h" |
| 15 #include "wtf/PtrUtil.h" | 16 #include "wtf/PtrUtil.h" |
| 16 #include "wtf/RefPtr.h" | 17 #include "wtf/RefPtr.h" |
| 17 #include <memory> | 18 #include <memory> |
| 18 | 19 |
| 19 namespace blink { | 20 namespace blink { |
| 20 | 21 |
| 21 static const char* imageOrientationFlipY = "flipY"; | 22 static const char* imageOrientationFlipY = "flipY"; |
| 22 static const char* imageBitmapOptionNone = "none"; | 23 static const char* imageBitmapOptionNone = "none"; |
| 23 | 24 |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 struct ParsedOptions { | 27 struct ParsedOptions { |
| 27 bool flipY = false; | 28 bool flipY = false; |
| 28 bool premultiplyAlpha = true; | 29 bool premultiplyAlpha = true; |
| 29 bool shouldScaleInput = false; | 30 bool shouldScaleInput = false; |
| 30 unsigned resizeWidth = 0; | 31 unsigned resizeWidth = 0; |
| 31 unsigned resizeHeight = 0; | 32 unsigned resizeHeight = 0; |
| 32 IntRect cropRect; | 33 IntRect cropRect; |
| 33 SkFilterQuality resizeQuality = kLow_SkFilterQuality; | 34 SkFilterQuality resizeQuality = kLow_SkFilterQuality; |
| 34 // This value should be changed in the future when we support | 35 sk_sp<SkColorSpace> dstColorSpace = nullptr; |
| 35 // createImageBitmap with higher bit depth, in the parseOptions() function. | 36 sk_sp<SkColorSpace> latestColorSpace = nullptr; |
| 36 // For now, it is always 4. | 37 SkColorType dstColorType = kN32_SkColorType; |
| 37 int bytesPerPixel = 4; | 38 SkColorType latestColorType = kN32_SkColorType; |
| 38 }; | 39 }; |
| 39 | 40 |
| 41 ParsedOptions defaultOptions() { | |
| 42 return ParsedOptions(); | |
| 43 } | |
| 44 | |
| 40 // The following two functions are helpers used in cropImage | 45 // The following two functions are helpers used in cropImage |
| 41 static inline IntRect normalizeRect(const IntRect& rect) { | 46 static inline IntRect normalizeRect(const IntRect& rect) { |
| 42 return IntRect(std::min(rect.x(), rect.maxX()), | 47 return IntRect(std::min(rect.x(), rect.maxX()), |
| 43 std::min(rect.y(), rect.maxY()), | 48 std::min(rect.y(), rect.maxY()), |
| 44 std::max(rect.width(), -rect.width()), | 49 std::max(rect.width(), -rect.width()), |
| 45 std::max(rect.height(), -rect.height())); | 50 std::max(rect.height(), -rect.height())); |
| 46 } | 51 } |
| 47 | 52 |
| 48 ParsedOptions parseOptions(const ImageBitmapOptions& options, | 53 ParsedOptions parseOptions(const ImageBitmapOptions& options, |
| 49 Optional<IntRect> cropRect, | 54 Optional<IntRect> cropRect, |
| 50 IntSize sourceSize) { | 55 IntSize sourceSize) { |
| 51 ParsedOptions parsedOptions; | 56 ParsedOptions parsedOptions; |
| 52 if (options.imageOrientation() == imageOrientationFlipY) { | 57 if (options.imageOrientation() == imageOrientationFlipY) { |
| 53 parsedOptions.flipY = true; | 58 parsedOptions.flipY = true; |
| 54 } else { | 59 } else { |
| 55 parsedOptions.flipY = false; | 60 parsedOptions.flipY = false; |
| 56 DCHECK(options.imageOrientation() == imageBitmapOptionNone); | 61 DCHECK(options.imageOrientation() == imageBitmapOptionNone); |
| 57 } | 62 } |
| 58 if (options.premultiplyAlpha() == imageBitmapOptionNone) { | 63 if (options.premultiplyAlpha() == imageBitmapOptionNone) { |
| 59 parsedOptions.premultiplyAlpha = false; | 64 parsedOptions.premultiplyAlpha = false; |
| 60 } else { | 65 } else { |
| 61 parsedOptions.premultiplyAlpha = true; | 66 parsedOptions.premultiplyAlpha = true; |
| 62 DCHECK(options.premultiplyAlpha() == "default" || | 67 DCHECK(options.premultiplyAlpha() == "default" || |
| 63 options.premultiplyAlpha() == "premultiply"); | 68 options.premultiplyAlpha() == "premultiply"); |
| 64 } | 69 } |
| 65 | 70 |
| 71 if (options.colorSpaceConversion() != "none") { | |
| 72 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || | |
| 73 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) { | |
| 74 DCHECK_EQ(options.colorSpaceConversion(), "default"); | |
| 75 // TODO(zakerinasab): Replace sRGB with a call to | |
| 76 // ImageDecoder::globalTargetColorSpace() when the crash problem on Mac | |
| 77 // is fixed. crbug.com/668546. | |
| 78 if (RuntimeEnabledFeatures::colorCorrectRenderingDefaultModeEnabled()) { | |
| 79 parsedOptions.dstColorSpace = | |
| 80 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | |
| 81 parsedOptions.dstColorType = SkColorType::kN32_SkColorType; | |
| 82 } | |
| 83 } else { | |
| 84 if (options.colorSpaceConversion() == "default" || | |
| 85 options.colorSpaceConversion() == "srgb") { | |
| 86 parsedOptions.dstColorSpace = | |
| 87 SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named); | |
| 88 parsedOptions.dstColorType = SkColorType::kN32_SkColorType; | |
| 89 } else if (options.colorSpaceConversion() == "linear-rgb") { | |
| 90 parsedOptions.dstColorSpace = | |
| 91 SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named); | |
| 92 parsedOptions.dstColorType = SkColorType::kRGBA_F16_SkColorType; | |
| 93 } else { | |
| 94 NOTREACHED() | |
| 95 << "Invalid ImageBitmap creation attribute colorSpaceConversion: " | |
| 96 << options.colorSpaceConversion(); | |
| 97 } | |
| 98 } | |
| 99 } | |
| 100 | |
| 66 int sourceWidth = sourceSize.width(); | 101 int sourceWidth = sourceSize.width(); |
| 67 int sourceHeight = sourceSize.height(); | 102 int sourceHeight = sourceSize.height(); |
| 68 if (!cropRect) { | 103 if (!cropRect) { |
| 69 parsedOptions.cropRect = IntRect(0, 0, sourceWidth, sourceHeight); | 104 parsedOptions.cropRect = IntRect(0, 0, sourceWidth, sourceHeight); |
| 70 } else { | 105 } else { |
| 71 parsedOptions.cropRect = normalizeRect(*cropRect); | 106 parsedOptions.cropRect = normalizeRect(*cropRect); |
| 72 } | 107 } |
| 73 if (!options.hasResizeWidth() && !options.hasResizeHeight()) { | 108 if (!options.hasResizeWidth() && !options.hasResizeHeight()) { |
| 74 parsedOptions.resizeWidth = parsedOptions.cropRect.width(); | 109 parsedOptions.resizeWidth = parsedOptions.cropRect.width(); |
| 75 parsedOptions.resizeHeight = parsedOptions.cropRect.height(); | 110 parsedOptions.resizeHeight = parsedOptions.cropRect.height(); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 100 parsedOptions.resizeQuality = kHigh_SkFilterQuality; | 135 parsedOptions.resizeQuality = kHigh_SkFilterQuality; |
| 101 else if (options.resizeQuality() == "medium") | 136 else if (options.resizeQuality() == "medium") |
| 102 parsedOptions.resizeQuality = kMedium_SkFilterQuality; | 137 parsedOptions.resizeQuality = kMedium_SkFilterQuality; |
| 103 else if (options.resizeQuality() == "pixelated") | 138 else if (options.resizeQuality() == "pixelated") |
| 104 parsedOptions.resizeQuality = kNone_SkFilterQuality; | 139 parsedOptions.resizeQuality = kNone_SkFilterQuality; |
| 105 else | 140 else |
| 106 parsedOptions.resizeQuality = kLow_SkFilterQuality; | 141 parsedOptions.resizeQuality = kLow_SkFilterQuality; |
| 107 return parsedOptions; | 142 return parsedOptions; |
| 108 } | 143 } |
| 109 | 144 |
| 110 bool dstBufferSizeHasOverflow(ParsedOptions options) { | 145 bool dstBufferSizeHasOverflow(ParsedOptions options) { |
|
dcheng
2016/12/11 20:11:58
Nit: not introduced by this CL, but this should be
zakerinasab1
2016/12/12 18:35:21
Done.
| |
| 111 CheckedNumeric<unsigned> totalBytes = options.cropRect.width(); | 146 CheckedNumeric<unsigned> totalBytes = options.cropRect.width(); |
| 112 totalBytes *= options.cropRect.height(); | 147 totalBytes *= options.cropRect.height(); |
| 113 totalBytes *= options.bytesPerPixel; | 148 totalBytes *= SkColorTypeBytesPerPixel(options.latestColorType); |
| 114 if (!totalBytes.IsValid()) | 149 if (!totalBytes.IsValid()) |
| 115 return true; | 150 return true; |
| 116 | 151 |
| 117 if (!options.shouldScaleInput) | 152 if (!options.shouldScaleInput) |
| 118 return false; | 153 return false; |
| 119 totalBytes = options.resizeWidth; | 154 totalBytes = options.resizeWidth; |
| 120 totalBytes *= options.resizeHeight; | 155 totalBytes *= options.resizeHeight; |
| 121 totalBytes *= options.bytesPerPixel; | 156 totalBytes *= SkColorTypeBytesPerPixel(options.latestColorType); |
| 122 if (!totalBytes.IsValid()) | 157 if (!totalBytes.IsValid()) |
| 123 return true; | 158 return true; |
| 124 | 159 |
| 125 return false; | 160 return false; |
| 126 } | 161 } |
| 127 | 162 |
| 128 } // namespace | 163 } // namespace |
| 129 | 164 |
| 130 static PassRefPtr<Uint8Array> copySkImageData(SkImage* input, | 165 static PassRefPtr<Uint8Array> copySkImageData(SkImage* input, |
| 131 const SkImageInfo& info) { | 166 const SkImageInfo& info) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 srcAddr + bottomRowStartPosition); | 215 srcAddr + bottomRowStartPosition); |
| 181 } | 216 } |
| 182 } | 217 } |
| 183 } else { | 218 } else { |
| 184 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle | 219 if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle |
| 185 for (unsigned i = 0; i < height * bytesPerRow; i += 4) | 220 for (unsigned i = 0; i < height * bytesPerRow; i += 4) |
| 186 std::swap(srcAddr[i], srcAddr[i + 2]); | 221 std::swap(srcAddr[i], srcAddr[i + 2]); |
| 187 } | 222 } |
| 188 } | 223 } |
| 189 | 224 |
| 190 static sk_sp<SkImage> flipSkImageVertically(SkImage* input, | 225 static sk_sp<SkImage> flipSkImageVertically( |
| 191 AlphaDisposition alphaOp) { | 226 SkImage* input, |
| 227 bool enforceAlphaPremultiply = false, | |
|
dcheng
2016/12/11 20:11:58
Ditto about preferring enums over bools here as we
zakerinasab1
2016/12/12 18:35:21
Done.
| |
| 228 const ParsedOptions& options = defaultOptions()) { | |
| 192 unsigned width = static_cast<unsigned>(input->width()); | 229 unsigned width = static_cast<unsigned>(input->width()); |
| 193 unsigned height = static_cast<unsigned>(input->height()); | 230 unsigned height = static_cast<unsigned>(input->height()); |
| 194 SkImageInfo info = SkImageInfo::MakeN32(input->width(), input->height(), | 231 SkAlphaType alphaType = (enforceAlphaPremultiply || options.premultiplyAlpha) |
| 195 (alphaOp == PremultiplyAlpha) | 232 ? kPremul_SkAlphaType |
| 196 ? kPremul_SkAlphaType | 233 : kUnpremul_SkAlphaType; |
| 197 : kUnpremul_SkAlphaType); | 234 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), |
| 235 options.latestColorType, alphaType, | |
| 236 options.latestColorSpace); | |
| 237 | |
| 198 unsigned imageRowBytes = width * info.bytesPerPixel(); | 238 unsigned imageRowBytes = width * info.bytesPerPixel(); |
| 199 RefPtr<Uint8Array> imagePixels = copySkImageData(input, info); | 239 RefPtr<Uint8Array> imagePixels = copySkImageData(input, info); |
| 200 if (!imagePixels) | 240 if (!imagePixels) |
| 201 return nullptr; | 241 return nullptr; |
| 202 for (unsigned i = 0; i < height / 2; i++) { | 242 for (unsigned i = 0; i < height / 2; i++) { |
| 203 unsigned topFirstElement = i * imageRowBytes; | 243 unsigned topFirstElement = i * imageRowBytes; |
| 204 unsigned topLastElement = (i + 1) * imageRowBytes; | 244 unsigned topLastElement = (i + 1) * imageRowBytes; |
| 205 unsigned bottomFirstElement = (height - 1 - i) * imageRowBytes; | 245 unsigned bottomFirstElement = (height - 1 - i) * imageRowBytes; |
| 206 std::swap_ranges(imagePixels->data() + topFirstElement, | 246 std::swap_ranges(imagePixels->data() + topFirstElement, |
| 207 imagePixels->data() + topLastElement, | 247 imagePixels->data() + topLastElement, |
| 208 imagePixels->data() + bottomFirstElement); | 248 imagePixels->data() + bottomFirstElement); |
| 209 } | 249 } |
| 210 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); | 250 return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); |
| 211 } | 251 } |
| 212 | 252 |
| 213 static sk_sp<SkImage> premulSkImageToUnPremul(SkImage* input) { | 253 static sk_sp<SkImage> premulSkImageToUnPremul( |
| 214 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), | 254 SkImage* input, |
| 215 kN32_SkColorType, kUnpremul_SkAlphaType); | 255 const ParsedOptions& options = defaultOptions()) { |
| 256 SkImageInfo info = SkImageInfo::Make( | |
| 257 input->width(), input->height(), options.latestColorType, | |
| 258 kUnpremul_SkAlphaType, options.latestColorSpace); | |
| 259 | |
| 216 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); | 260 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
| 217 if (!dstPixels) | 261 if (!dstPixels) |
| 218 return nullptr; | 262 return nullptr; |
| 219 return newSkImageFromRaster( | 263 return newSkImageFromRaster( |
| 220 info, std::move(dstPixels), | 264 info, std::move(dstPixels), |
| 221 static_cast<unsigned>(input->width()) * info.bytesPerPixel()); | 265 static_cast<unsigned>(input->width()) * info.bytesPerPixel()); |
| 222 } | 266 } |
| 223 | 267 |
| 224 static sk_sp<SkImage> unPremulSkImageToPremul(SkImage* input) { | 268 static sk_sp<SkImage> unPremulSkImageToPremul( |
| 225 SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), | 269 SkImage* input, |
| 226 kN32_SkColorType, kPremul_SkAlphaType); | 270 const ParsedOptions& options = defaultOptions()) { |
| 271 SkImageInfo info = SkImageInfo::Make( | |
| 272 input->width(), input->height(), options.latestColorType, | |
| 273 kPremul_SkAlphaType, options.latestColorSpace); | |
| 274 | |
| 227 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); | 275 RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
| 228 if (!dstPixels) | 276 if (!dstPixels) |
| 229 return nullptr; | 277 return nullptr; |
| 230 return newSkImageFromRaster( | 278 return newSkImageFromRaster( |
| 231 info, std::move(dstPixels), | 279 info, std::move(dstPixels), |
| 232 static_cast<unsigned>(input->width()) * info.bytesPerPixel()); | 280 static_cast<unsigned>(input->width()) * info.bytesPerPixel()); |
| 233 } | 281 } |
| 234 | 282 |
| 283 // This code is borrowed from third_party/skia/src/codec/SkCodecPriv.h | |
| 284 // If you need to change this, please check SkColorSpaceXform::ColorFormat | |
| 285 // and SkColorType for proper coverage. | |
| 286 static inline SkColorSpaceXform::ColorFormat getXformFormat( | |
| 287 SkColorType colorType) { | |
| 288 switch (colorType) { | |
| 289 case kRGBA_8888_SkColorType: | |
| 290 return SkColorSpaceXform::kRGBA_8888_ColorFormat; | |
| 291 case kBGRA_8888_SkColorType: | |
| 292 return SkColorSpaceXform::kBGRA_8888_ColorFormat; | |
| 293 case kRGBA_F16_SkColorType: | |
| 294 return SkColorSpaceXform::kRGBA_F16_ColorFormat; | |
| 295 default: | |
| 296 SkASSERT(false); | |
|
dcheng
2016/12/11 20:11:58
I think we should be writing NOTREACHED in Blink c
zakerinasab1
2016/12/12 18:35:21
Done.
| |
| 297 return SkColorSpaceXform::kRGBA_8888_ColorFormat; | |
| 298 } | |
| 299 } | |
| 300 | |
| 301 static inline void updateLatestColorInformation(ParsedOptions& options) { | |
| 302 options.latestColorType = options.dstColorType; | |
| 303 options.latestColorSpace = options.dstColorSpace; | |
| 304 } | |
| 305 | |
| 306 // TODO (zakrinasab). Rewrite this when SkImage::readPixels() respectes the | |
| 307 // color space of the passed SkImageInfo (crbug.com/skia/6021) and SkImage | |
| 308 // exposes SkColorSpace and SkColorType (crbug.com/skia/6022). | |
| 309 | |
| 310 static sk_sp<SkImage> applyColorSpaceConversion(const sk_sp<SkImage> image, | |
|
dcheng
2016/12/11 20:11:58
This refs the SkImage unnecessarily, as this metho
zakerinasab1
2016/12/12 18:35:21
I changed the function signature. PTAL.
Passing Sk
dcheng
2016/12/12 21:13:57
Ah... another option is to pass by value (instead
| |
| 311 ParsedOptions& options) { | |
| 312 if (!options.dstColorSpace) | |
| 313 return image; | |
| 314 if (SkColorSpace::Equals(options.latestColorSpace.get(), | |
| 315 options.dstColorSpace.get())) | |
| 316 return image; | |
| 317 | |
| 318 // If we have the color space information of the source image, we can use | |
| 319 // SkColorSpaceXform. Otherwise, we need to draw the image on a canvas and | |
| 320 // take a snapshot. | |
| 321 if (options.latestColorSpace) { | |
| 322 SkImageInfo info = SkImageInfo::Make( | |
| 323 image->width(), image->height(), options.latestColorType, | |
| 324 image->alphaType(), options.latestColorSpace); | |
| 325 size_t size = image->width() * image->height() * info.bytesPerPixel(); | |
| 326 auto srcPixels = WTF::makeUnique<uint8_t>(size); | |
| 327 if (!image->readPixels(info, &srcPixels, | |
| 328 image->width() * info.bytesPerPixel(), 0, 0)) { | |
| 329 return image; | |
| 330 } | |
| 331 | |
| 332 // For in-place color correction, bytes per pixel must be equal for source | |
| 333 // and destination color spaces. | |
| 334 std::unique_ptr<uint8_t> dstPixels = nullptr; | |
| 335 if (SkColorTypeBytesPerPixel(options.dstColorType) != | |
| 336 SkColorTypeBytesPerPixel(options.latestColorType)) { | |
| 337 size = image->width() * image->height() * | |
| 338 SkColorTypeBytesPerPixel(options.latestColorType); | |
| 339 dstPixels = WTF::makeUnique<uint8_t>(size); | |
| 340 } | |
| 341 | |
| 342 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New( | |
| 343 options.latestColorSpace.get(), options.dstColorSpace.get()); | |
| 344 xform->apply(getXformFormat(options.dstColorType), | |
| 345 dstPixels ? &dstPixels : &srcPixels, | |
| 346 getXformFormat(options.latestColorType), &srcPixels, | |
| 347 image->width() * image->height(), kUnpremul_SkAlphaType); | |
| 348 | |
| 349 SkImageInfo dstInfo = | |
| 350 SkImageInfo::Make(image->width(), image->height(), options.dstColorType, | |
| 351 image->alphaType(), options.dstColorSpace); | |
| 352 sk_sp<SkData> data(SkData::MakeWithoutCopy(&dstPixels, size)); | |
| 353 sk_sp<SkImage> coloredImage = SkImage::MakeRasterData( | |
| 354 dstInfo, data, image->width() * dstInfo.bytesPerPixel()); | |
| 355 if (coloredImage) { | |
| 356 updateLatestColorInformation(options); | |
| 357 return coloredImage; | |
| 358 } | |
| 359 return image; | |
| 360 } | |
| 361 | |
| 362 // Skia does not support drawing to unpremul surfaces/canvases. | |
| 363 sk_sp<SkImage> unPremulImage = nullptr; | |
| 364 if (image->alphaType() == kUnpremul_SkAlphaType) | |
| 365 unPremulImage = unPremulSkImageToPremul(image.get(), options); | |
| 366 | |
| 367 // If the color space of the source SkImage is null, the following code | |
| 368 // does not do any color conversion even thought the new SkImage will be | |
| 369 // tagged by the new color space. If this is the case, the following code | |
| 370 // will tag a wrong color space to the SkImage. However, this cannot be | |
| 371 // addressed here and the code that creates the SkImage must tag the | |
| 372 // SkImage with proper color space. | |
| 373 SkImageInfo imageInfo = SkImageInfo::Make( | |
| 374 image->width(), image->height(), options.dstColorType, | |
| 375 unPremulImage ? unPremulImage->alphaType() : image->alphaType(), | |
| 376 options.dstColorSpace); | |
| 377 sk_sp<SkSurface> surface = SkSurface::MakeRaster(imageInfo); | |
| 378 surface->getCanvas()->drawImage(unPremulImage ? unPremulImage : image, 0, 0); | |
| 379 sk_sp<SkImage> coloredImage = surface->makeImageSnapshot(); | |
| 380 updateLatestColorInformation(options); | |
| 381 return coloredImage; | |
| 382 } | |
| 383 | |
| 235 sk_sp<SkImage> ImageBitmap::getSkImageFromDecoder( | 384 sk_sp<SkImage> ImageBitmap::getSkImageFromDecoder( |
| 236 std::unique_ptr<ImageDecoder> decoder) { | 385 std::unique_ptr<ImageDecoder> decoder, |
| 386 SkColorType* decodedColorType, | |
| 387 sk_sp<SkColorSpace> decodedColorSpace, | |
| 388 bool returnColorSpaceInformation) { | |
| 237 if (!decoder->frameCount()) | 389 if (!decoder->frameCount()) |
| 238 return nullptr; | 390 return nullptr; |
| 239 ImageFrame* frame = decoder->frameBufferAtIndex(0); | 391 ImageFrame* frame = decoder->frameBufferAtIndex(0); |
| 240 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) | 392 if (!frame || frame->getStatus() != ImageFrame::FrameComplete) |
| 241 return nullptr; | 393 return nullptr; |
| 242 DCHECK(!frame->bitmap().isNull() && !frame->bitmap().empty()); | 394 DCHECK(!frame->bitmap().isNull() && !frame->bitmap().empty()); |
| 243 return frame->finalizePixelsAndGetImage(); | 395 sk_sp<SkImage> image = frame->finalizePixelsAndGetImage(); |
| 396 if (returnColorSpaceInformation) { | |
| 397 *decodedColorType = frame->bitmap().colorType(); | |
| 398 decodedColorSpace = sk_sp<SkColorSpace>(frame->bitmap().colorSpace()); | |
|
dcheng
2016/12/11 20:11:58
This parameter is passed by value, so the caller w
zakerinasab1
2016/12/12 18:35:21
The parameter is fixed. The flag is needed as the
| |
| 399 } | |
| 400 return image; | |
| 244 } | 401 } |
| 245 | 402 |
| 246 bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options, | 403 bool ImageBitmap::isResizeOptionValid(const ImageBitmapOptions& options, |
| 247 ExceptionState& exceptionState) { | 404 ExceptionState& exceptionState) { |
| 248 if ((options.hasResizeWidth() && options.resizeWidth() == 0) || | 405 if ((options.hasResizeWidth() && options.resizeWidth() == 0) || |
| 249 (options.hasResizeHeight() && options.resizeHeight() == 0)) { | 406 (options.hasResizeHeight() && options.resizeHeight() == 0)) { |
| 250 exceptionState.throwDOMException( | 407 exceptionState.throwDOMException( |
| 251 InvalidStateError, | 408 InvalidStateError, |
| 252 "The resizeWidth or/and resizeHeight is equal to 0."); | 409 "The resizeWidth or/and resizeHeight is equal to 0."); |
| 253 return false; | 410 return false; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 265 return false; | 422 return false; |
| 266 } | 423 } |
| 267 return true; | 424 return true; |
| 268 } | 425 } |
| 269 | 426 |
| 270 // The parameter imageFormat indicates whether the first parameter "image" is | 427 // The parameter imageFormat indicates whether the first parameter "image" is |
| 271 // unpremultiplied or not. imageFormat = PremultiplyAlpha means the image is in | 428 // unpremultiplied or not. imageFormat = PremultiplyAlpha means the image is in |
| 272 // premuliplied format For example, if the image is already in unpremultiplied | 429 // premuliplied format For example, if the image is already in unpremultiplied |
| 273 // format and we want the created ImageBitmap in the same format, then we don't | 430 // format and we want the created ImageBitmap in the same format, then we don't |
| 274 // need to use the ImageDecoder to decode the image. | 431 // need to use the ImageDecoder to decode the image. |
| 275 static PassRefPtr<StaticBitmapImage> cropImage( | 432 static PassRefPtr<StaticBitmapImage> cropImageAndApplyColorSpaceConversion( |
| 276 Image* image, | 433 Image* image, |
| 277 const ParsedOptions& parsedOptions, | 434 ParsedOptions& parsedOptions, |
| 278 AlphaDisposition imageFormat, | 435 AlphaDisposition imageFormat, |
| 279 ColorBehavior colorBehavior) { | 436 ColorBehavior colorBehavior) { |
| 280 ASSERT(image); | 437 ASSERT(image); |
| 281 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); | 438 IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
| 282 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); | 439 const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); |
| 283 | 440 |
| 284 // In the case when cropRect doesn't intersect the source image and it | 441 // In the case when cropRect doesn't intersect the source image and it |
| 285 // requires a umpremul image We immediately return a transparent black image | 442 // requires a umpremul image We immediately return a transparent black image |
| 286 // with cropRect.size() | 443 // with cropRect.size() |
| 287 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { | 444 if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 307 !skiaImage) && | 464 !skiaImage) && |
| 308 image->data() && imageFormat == PremultiplyAlpha) || | 465 image->data() && imageFormat == PremultiplyAlpha) || |
| 309 colorBehavior.isIgnore()) { | 466 colorBehavior.isIgnore()) { |
| 310 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( | 467 std::unique_ptr<ImageDecoder> decoder(ImageDecoder::create( |
| 311 image->data(), true, | 468 image->data(), true, |
| 312 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied | 469 parsedOptions.premultiplyAlpha ? ImageDecoder::AlphaPremultiplied |
| 313 : ImageDecoder::AlphaNotPremultiplied, | 470 : ImageDecoder::AlphaNotPremultiplied, |
| 314 colorBehavior)); | 471 colorBehavior)); |
| 315 if (!decoder) | 472 if (!decoder) |
| 316 return nullptr; | 473 return nullptr; |
| 317 skiaImage = ImageBitmap::getSkImageFromDecoder(std::move(decoder)); | 474 skiaImage = ImageBitmap::getSkImageFromDecoder( |
| 475 std::move(decoder), &parsedOptions.latestColorType, | |
| 476 parsedOptions.latestColorSpace, true); | |
| 318 if (!skiaImage) | 477 if (!skiaImage) |
| 319 return nullptr; | 478 return nullptr; |
| 320 } | 479 } |
| 321 | 480 |
| 322 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) { | 481 if (parsedOptions.cropRect == srcRect && !parsedOptions.shouldScaleInput) { |
| 323 sk_sp<SkImage> croppedSkImage = skiaImage->makeSubset(srcRect); | 482 sk_sp<SkImage> croppedSkImage = skiaImage->makeSubset(srcRect); |
| 324 if (parsedOptions.flipY) | 483 if (parsedOptions.dstColorSpace) { |
| 325 return StaticBitmapImage::create(flipSkImageVertically( | 484 croppedSkImage = applyColorSpaceConversion(croppedSkImage, parsedOptions); |
| 326 croppedSkImage.get(), parsedOptions.premultiplyAlpha | 485 } |
| 327 ? PremultiplyAlpha | 486 if (parsedOptions.flipY) { |
| 328 : DontPremultiplyAlpha)); | 487 return StaticBitmapImage::create( |
| 488 flipSkImageVertically(croppedSkImage.get(), false, parsedOptions)); | |
| 489 } | |
| 329 // Special case: The first parameter image is unpremul but we need to turn | 490 // Special case: The first parameter image is unpremul but we need to turn |
| 330 // it into premul. | 491 // it into premul. |
| 331 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlpha) | 492 if (parsedOptions.premultiplyAlpha && imageFormat == DontPremultiplyAlpha) |
| 332 return StaticBitmapImage::create( | 493 return StaticBitmapImage::create( |
| 333 unPremulSkImageToPremul(croppedSkImage.get())); | 494 unPremulSkImageToPremul(croppedSkImage.get())); |
| 334 // Call preroll to trigger image decoding. | 495 // Call preroll to trigger image decoding. |
| 335 croppedSkImage->preroll(); | 496 croppedSkImage->preroll(); |
| 336 return StaticBitmapImage::create(std::move(croppedSkImage)); | 497 return StaticBitmapImage::create(std::move(croppedSkImage)); |
| 337 } | 498 } |
| 338 | 499 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 360 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, | 521 SkRect drawDstRect = SkRect::MakeXYWH(0, 0, parsedOptions.resizeWidth, |
| 361 parsedOptions.resizeHeight); | 522 parsedOptions.resizeHeight); |
| 362 SkPaint paint; | 523 SkPaint paint; |
| 363 paint.setFilterQuality(parsedOptions.resizeQuality); | 524 paint.setFilterQuality(parsedOptions.resizeQuality); |
| 364 surface->getCanvas()->drawImageRect(skiaImage, drawSrcRect, drawDstRect, | 525 surface->getCanvas()->drawImageRect(skiaImage, drawSrcRect, drawDstRect, |
| 365 &paint); | 526 &paint); |
| 366 } else { | 527 } else { |
| 367 surface->getCanvas()->drawImage(skiaImage, dstLeft, dstTop); | 528 surface->getCanvas()->drawImage(skiaImage, dstLeft, dstTop); |
| 368 } | 529 } |
| 369 skiaImage = surface->makeImageSnapshot(); | 530 skiaImage = surface->makeImageSnapshot(); |
| 531 if (parsedOptions.dstColorSpace) | |
| 532 skiaImage = applyColorSpaceConversion(skiaImage, parsedOptions); | |
| 370 | 533 |
| 371 if (parsedOptions.premultiplyAlpha) { | 534 if (parsedOptions.premultiplyAlpha) { |
| 372 if (imageFormat == DontPremultiplyAlpha) | 535 if (imageFormat == DontPremultiplyAlpha) |
| 373 return StaticBitmapImage::create( | 536 return StaticBitmapImage::create( |
| 374 unPremulSkImageToPremul(skiaImage.get())); | 537 unPremulSkImageToPremul(skiaImage.get())); |
| 375 return StaticBitmapImage::create(std::move(skiaImage)); | 538 return StaticBitmapImage::create(std::move(skiaImage)); |
| 376 } | 539 } |
| 377 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); | 540 return StaticBitmapImage::create(premulSkImageToUnPremul(skiaImage.get())); |
| 378 } | 541 } |
| 379 | 542 |
| 380 ImageBitmap::ImageBitmap(HTMLImageElement* image, | 543 ImageBitmap::ImageBitmap(HTMLImageElement* image, |
| 381 Optional<IntRect> cropRect, | 544 Optional<IntRect> cropRect, |
| 382 Document* document, | 545 Document* document, |
| 383 const ImageBitmapOptions& options) { | 546 const ImageBitmapOptions& options) { |
| 384 RefPtr<Image> input = image->cachedImage()->getImage(); | 547 RefPtr<Image> input = image->cachedImage()->getImage(); |
| 385 ParsedOptions parsedOptions = | 548 ParsedOptions parsedOptions = |
| 386 parseOptions(options, cropRect, image->bitmapSourceSize()); | 549 parseOptions(options, cropRect, image->bitmapSourceSize()); |
| 387 if (dstBufferSizeHasOverflow(parsedOptions)) | 550 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 388 return; | 551 return; |
| 389 | 552 |
| 390 if (options.colorSpaceConversion() == "none") { | 553 if (options.colorSpaceConversion() == "none") { |
| 391 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, | 554 m_image = cropImageAndApplyColorSpaceConversion( |
| 392 ColorBehavior::ignore()); | 555 input.get(), parsedOptions, PremultiplyAlpha, ColorBehavior::ignore()); |
| 393 } else { | 556 } else { |
| 394 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, | 557 m_image = cropImageAndApplyColorSpaceConversion( |
| 395 ColorBehavior::transformToGlobalTarget()); | 558 input.get(), parsedOptions, PremultiplyAlpha, |
| 559 ColorBehavior::transformToGlobalTarget()); | |
| 396 } | 560 } |
| 561 | |
| 397 if (!m_image) | 562 if (!m_image) |
| 398 return; | 563 return; |
| 399 // In the case where the source image is lazy-decoded, m_image may not be in | 564 // In the case where the source image is lazy-decoded, m_image may not be in |
| 400 // a decoded state, we trigger it here. | 565 // a decoded state, we trigger it here. |
| 401 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame(); | 566 sk_sp<SkImage> skImage = m_image->imageForCurrentFrame(); |
| 402 SkPixmap pixmap; | 567 SkPixmap pixmap; |
| 403 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { | 568 if (!skImage->isTextureBacked() && !skImage->peekPixels(&pixmap)) { |
| 404 sk_sp<SkSurface> surface = | 569 SkImageInfo imageInfo = SkImageInfo::Make( |
| 405 SkSurface::MakeRasterN32Premul(skImage->width(), skImage->height()); | 570 skImage->width(), skImage->height(), parsedOptions.dstColorType, |
| 571 kPremul_SkAlphaType, parsedOptions.dstColorSpace); | |
| 572 sk_sp<SkSurface> surface = SkSurface::MakeRaster(imageInfo); | |
| 406 surface->getCanvas()->drawImage(skImage, 0, 0); | 573 surface->getCanvas()->drawImage(skImage, 0, 0); |
| 407 m_image = StaticBitmapImage::create(surface->makeImageSnapshot()); | 574 m_image = StaticBitmapImage::create(surface->makeImageSnapshot()); |
| 408 } | 575 } |
| 409 if (!m_image) | 576 if (!m_image) |
| 410 return; | 577 return; |
| 411 m_image->setOriginClean( | 578 m_image->setOriginClean( |
| 412 !image->wouldTaintOrigin(document->getSecurityOrigin())); | 579 !image->wouldTaintOrigin(document->getSecurityOrigin())); |
| 413 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 580 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 414 } | 581 } |
| 415 | 582 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 ParsedOptions parsedOptions = | 643 ParsedOptions parsedOptions = |
| 477 parseOptions(options, cropRect, IntSize(input->width(), input->height())); | 644 parseOptions(options, cropRect, IntSize(input->width(), input->height())); |
| 478 if (dstBufferSizeHasOverflow(parsedOptions)) | 645 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 479 return; | 646 return; |
| 480 | 647 |
| 481 bool isPremultiplyAlphaReverted = false; | 648 bool isPremultiplyAlphaReverted = false; |
| 482 if (!parsedOptions.premultiplyAlpha) { | 649 if (!parsedOptions.premultiplyAlpha) { |
| 483 parsedOptions.premultiplyAlpha = true; | 650 parsedOptions.premultiplyAlpha = true; |
| 484 isPremultiplyAlphaReverted = true; | 651 isPremultiplyAlphaReverted = true; |
| 485 } | 652 } |
| 486 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, | 653 m_image = cropImageAndApplyColorSpaceConversion( |
| 487 ColorBehavior::transformToGlobalTarget()); | 654 input.get(), parsedOptions, PremultiplyAlpha, |
| 655 ColorBehavior::transformToGlobalTarget()); | |
| 488 if (!m_image) | 656 if (!m_image) |
| 489 return; | 657 return; |
| 490 if (isPremultiplyAlphaReverted) { | 658 if (isPremultiplyAlphaReverted) { |
| 491 parsedOptions.premultiplyAlpha = false; | 659 parsedOptions.premultiplyAlpha = false; |
| 492 m_image = StaticBitmapImage::create( | 660 m_image = StaticBitmapImage::create( |
| 493 premulSkImageToUnPremul(m_image->imageForCurrentFrame().get())); | 661 premulSkImageToUnPremul(m_image->imageForCurrentFrame().get())); |
| 494 } | 662 } |
| 495 if (!m_image) | 663 if (!m_image) |
| 496 return; | 664 return; |
| 497 m_image->setOriginClean(canvas->originClean()); | 665 m_image->setOriginClean(canvas->originClean()); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 660 std::min(0, -parsedOptions.cropRect.y())); | 828 std::min(0, -parsedOptions.cropRect.y())); |
| 661 if (parsedOptions.cropRect.x() < 0) | 829 if (parsedOptions.cropRect.x() < 0) |
| 662 dstPoint.setX(-parsedOptions.cropRect.x()); | 830 dstPoint.setX(-parsedOptions.cropRect.x()); |
| 663 if (parsedOptions.cropRect.y() < 0) | 831 if (parsedOptions.cropRect.y() < 0) |
| 664 dstPoint.setY(-parsedOptions.cropRect.y()); | 832 dstPoint.setY(-parsedOptions.cropRect.y()); |
| 665 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), | 833 buffer->putByteArray(Unmultiplied, data->data()->data(), data->size(), |
| 666 srcRect, dstPoint); | 834 srcRect, dstPoint); |
| 667 sk_sp<SkImage> skImage = | 835 sk_sp<SkImage> skImage = |
| 668 buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown); | 836 buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown); |
| 669 if (parsedOptions.flipY) | 837 if (parsedOptions.flipY) |
| 670 skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); | 838 skImage = flipSkImageVertically(skImage.get(), true); |
| 671 if (!skImage) | 839 if (!skImage) |
| 672 return; | 840 return; |
| 673 if (parsedOptions.shouldScaleInput) { | 841 if (parsedOptions.shouldScaleInput) { |
| 674 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( | 842 sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul( |
| 675 parsedOptions.resizeWidth, parsedOptions.resizeHeight); | 843 parsedOptions.resizeWidth, parsedOptions.resizeHeight); |
| 676 if (!surface) | 844 if (!surface) |
| 677 return; | 845 return; |
| 678 SkPaint paint; | 846 SkPaint paint; |
| 679 paint.setFilterQuality(parsedOptions.resizeQuality); | 847 paint.setFilterQuality(parsedOptions.resizeQuality); |
| 680 SkRect dstDrawRect = | 848 SkRect dstDrawRect = |
| 681 SkRect::MakeWH(parsedOptions.resizeWidth, parsedOptions.resizeHeight); | 849 SkRect::MakeWH(parsedOptions.resizeWidth, parsedOptions.resizeHeight); |
| 682 surface->getCanvas()->drawImageRect(skImage, dstDrawRect, &paint); | 850 surface->getCanvas()->drawImageRect(skImage, dstDrawRect, &paint); |
| 683 skImage = surface->makeImageSnapshot(); | 851 skImage = surface->makeImageSnapshot(); |
| 684 } | 852 } |
| 685 m_image = StaticBitmapImage::create(std::move(skImage)); | 853 m_image = StaticBitmapImage::create(std::move(skImage)); |
| 686 } | 854 } |
| 687 | 855 |
| 688 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, | 856 ImageBitmap::ImageBitmap(ImageBitmap* bitmap, |
| 689 Optional<IntRect> cropRect, | 857 Optional<IntRect> cropRect, |
| 690 const ImageBitmapOptions& options) { | 858 const ImageBitmapOptions& options) { |
| 691 RefPtr<Image> input = bitmap->bitmapImage(); | 859 RefPtr<Image> input = bitmap->bitmapImage(); |
| 692 if (!input) | 860 if (!input) |
| 693 return; | 861 return; |
| 694 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); | 862 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); |
| 695 if (dstBufferSizeHasOverflow(parsedOptions)) | 863 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 696 return; | 864 return; |
| 697 | 865 |
| 698 m_image = cropImage( | 866 m_image = cropImageAndApplyColorSpaceConversion( |
| 699 input.get(), parsedOptions, | 867 input.get(), parsedOptions, |
| 700 bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha, | 868 bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha, |
| 701 ColorBehavior::transformToGlobalTarget()); | 869 ColorBehavior::transformToGlobalTarget()); |
| 702 if (!m_image) | 870 if (!m_image) |
| 703 return; | 871 return; |
| 704 m_image->setOriginClean(bitmap->originClean()); | 872 m_image->setOriginClean(bitmap->originClean()); |
| 705 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 873 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 706 } | 874 } |
| 707 | 875 |
| 708 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, | 876 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, |
| 709 Optional<IntRect> cropRect, | 877 Optional<IntRect> cropRect, |
| 710 const ImageBitmapOptions& options) { | 878 const ImageBitmapOptions& options) { |
| 711 bool originClean = image->originClean(); | 879 bool originClean = image->originClean(); |
| 712 RefPtr<Image> input = image; | 880 RefPtr<Image> input = image; |
| 713 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); | 881 ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); |
| 714 if (dstBufferSizeHasOverflow(parsedOptions)) | 882 if (dstBufferSizeHasOverflow(parsedOptions)) |
| 715 return; | 883 return; |
| 716 | 884 |
| 717 m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, | 885 m_image = cropImageAndApplyColorSpaceConversion( |
| 718 ColorBehavior::transformToGlobalTarget()); | 886 input.get(), parsedOptions, PremultiplyAlpha, |
| 887 ColorBehavior::transformToGlobalTarget()); | |
| 719 if (!m_image) | 888 if (!m_image) |
| 720 return; | 889 return; |
| 721 | 890 |
| 722 m_image->setOriginClean(originClean); | 891 m_image->setOriginClean(originClean); |
| 723 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); | 892 m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
| 724 } | 893 } |
| 725 | 894 |
| 726 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) { | 895 ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image) { |
| 727 m_image = image; | 896 m_image = image; |
| 728 } | 897 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 864 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, | 1033 void ImageBitmap::adjustDrawRects(FloatRect* srcRect, |
| 865 FloatRect* dstRect) const {} | 1034 FloatRect* dstRect) const {} |
| 866 | 1035 |
| 867 FloatSize ImageBitmap::elementSize(const FloatSize&) const { | 1036 FloatSize ImageBitmap::elementSize(const FloatSize&) const { |
| 868 return FloatSize(width(), height()); | 1037 return FloatSize(width(), height()); |
| 869 } | 1038 } |
| 870 | 1039 |
| 871 DEFINE_TRACE(ImageBitmap) {} | 1040 DEFINE_TRACE(ImageBitmap) {} |
| 872 | 1041 |
| 873 } // namespace blink | 1042 } // namespace blink |
| OLD | NEW |