Index: third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
diff --git a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
index 032bbacabde8818d45eee516a4696bbc9fb92a76..86600c029a2e977cc5a5404e250adb764c7fb184 100644 |
--- a/third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
+++ b/third_party/WebKit/Source/core/frame/ImageBitmap.cpp |
@@ -11,6 +11,7 @@ |
#include "platform/image-decoders/ImageDecoder.h" |
#include "third_party/skia/include/core/SkCanvas.h" |
#include "third_party/skia/include/core/SkSurface.h" |
+#include "wtf/CheckedNumeric.h" |
#include "wtf/PtrUtil.h" |
#include "wtf/RefPtr.h" |
#include <memory> |
@@ -30,6 +31,9 @@ struct ParsedOptions { |
unsigned resizeHeight = 0; |
IntRect cropRect; |
SkFilterQuality resizeQuality = kLow_SkFilterQuality; |
+ // This value should be changed in the future when we support createImageBitmap with higher |
+ // bit depth, in the parseOptions() function. For now, it is always 4. |
+ int bytesPerPixel = 4; |
}; |
// The following two functions are helpers used in cropImage |
@@ -100,32 +104,58 @@ ParsedOptions parseOptions(const ImageBitmapOptions& options, Optional<IntRect> |
return parsedOptions; |
} |
+bool dstBufferSizeHasOverflow(ParsedOptions options) |
+{ |
+ CheckedNumeric<size_t> totalBytes = options.cropRect.width(); |
+ totalBytes *= options.cropRect.height(); |
+ totalBytes *= options.bytesPerPixel; |
+ if (!totalBytes.IsValid()) |
+ return true; |
+ |
+ if (!options.shouldScaleInput) |
+ return false; |
+ totalBytes = options.resizeWidth; |
+ totalBytes *= options.resizeHeight; |
+ totalBytes *= options.bytesPerPixel; |
+ if (!totalBytes.IsValid()) |
+ return true; |
+ |
+ return false; |
+} |
+ |
} // namespace |
-static std::unique_ptr<uint8_t[]> copySkImageData(SkImage* input, const SkImageInfo& info) |
+static PassRefPtr<Uint8Array> copySkImageData(SkImage* input, const SkImageInfo& info) |
{ |
- std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[input->width() * input->height() * info.bytesPerPixel()]); |
- input->readPixels(info, dstPixels.get(), input->width() * info.bytesPerPixel(), 0, 0); |
+ // The function dstBufferSizeHasOverflow() is being called at the beginning of each |
+ // ImageBitmap() constructor, which makes sure that doing width * height * bytesPerPixel |
+ // will never overflow size_t. |
+ size_t width = static_cast<size_t>(input->width()); |
+ RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(width * input->height(), info.bytesPerPixel()); |
+ if (!dstBuffer) |
+ return nullptr; |
+ RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffer->byteLength()); |
+ input->readPixels(info, dstPixels->data(), width * info.bytesPerPixel(), 0, 0); |
return dstPixels; |
} |
-static PassRefPtr<SkImage> newSkImageFromRaster(const SkImageInfo& info, std::unique_ptr<uint8_t[]> imagePixels, int imageRowBytes) |
+static PassRefPtr<SkImage> newSkImageFromRaster(const SkImageInfo& info, PassRefPtr<Uint8Array> imagePixels, size_t imageRowBytes) |
{ |
- return fromSkSp(SkImage::MakeFromRaster(SkPixmap(info, imagePixels.release(), imageRowBytes), |
- [](const void* pixels, void*) |
+ SkPixmap pixmap(info, imagePixels->data(), imageRowBytes); |
+ return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels) |
{ |
- delete[] static_cast<const uint8_t*>(pixels); |
- }, nullptr)); |
+ static_cast<Uint8Array*>(pixels)->deref(); |
+ }, imagePixels.leakRef())); |
} |
-static void swizzleImageData(unsigned char* srcAddr, int height, int bytesPerRow, bool flipY) |
+static void swizzleImageData(unsigned char* srcAddr, size_t height, size_t bytesPerRow, bool flipY) |
{ |
if (flipY) { |
- for (int i = 0; i < height / 2; i++) { |
- int topRowStartPosition = i * bytesPerRow; |
- int bottomRowStartPosition = (height - 1 - i) * bytesPerRow; |
+ for (size_t i = 0; i < height / 2; i++) { |
+ size_t topRowStartPosition = i * bytesPerRow; |
+ size_t bottomRowStartPosition = (height - 1 - i) * bytesPerRow; |
if (kN32_SkColorType == kBGRA_8888_SkColorType) { // needs to swizzle |
- for (int j = 0; j < bytesPerRow; j += 4) { |
+ for (size_t j = 0; j < bytesPerRow; j += 4) { |
std::swap(srcAddr[topRowStartPosition + j], srcAddr[bottomRowStartPosition + j + 2]); |
std::swap(srcAddr[topRowStartPosition + j + 1], srcAddr[bottomRowStartPosition + j + 1]); |
std::swap(srcAddr[topRowStartPosition + j + 2], srcAddr[bottomRowStartPosition + j]); |
@@ -137,23 +167,25 @@ static void swizzleImageData(unsigned char* srcAddr, int height, int bytesPerRow |
} |
} else { |
if (kN32_SkColorType == kBGRA_8888_SkColorType) // needs to swizzle |
- for (int i = 0; i < height * bytesPerRow; i += 4) |
+ for (size_t i = 0; i < height * bytesPerRow; i += 4) |
std::swap(srcAddr[i], srcAddr[i + 2]); |
} |
} |
static PassRefPtr<SkImage> flipSkImageVertically(SkImage* input, AlphaDisposition alphaOp) |
{ |
- int width = input->width(); |
- int height = input->height(); |
- SkImageInfo info = SkImageInfo::MakeN32(width, height, (alphaOp == PremultiplyAlpha) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
- int imageRowBytes = width * info.bytesPerPixel(); |
- std::unique_ptr<uint8_t[]> imagePixels = copySkImageData(input, info); |
- for (int i = 0; i < height / 2; i++) { |
- int topFirstElement = i * imageRowBytes; |
- int topLastElement = (i + 1) * imageRowBytes; |
- int bottomFirstElement = (height - 1 - i) * imageRowBytes; |
- std::swap_ranges(imagePixels.get() + topFirstElement, imagePixels.get() + topLastElement, imagePixels.get() + bottomFirstElement); |
+ size_t width = static_cast<size_t>(input->width()); |
+ size_t height = static_cast<size_t>(input->height()); |
+ SkImageInfo info = SkImageInfo::MakeN32(input->width(), input->height(), (alphaOp == PremultiplyAlpha) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
+ size_t imageRowBytes = width * info.bytesPerPixel(); |
+ RefPtr<Uint8Array> imagePixels = copySkImageData(input, info); |
+ if (!imagePixels) |
+ return nullptr; |
+ for (size_t i = 0; i < height / 2; i++) { |
+ size_t topFirstElement = i * imageRowBytes; |
+ size_t topLastElement = (i + 1) * imageRowBytes; |
+ size_t bottomFirstElement = (height - 1 - i) * imageRowBytes; |
+ std::swap_ranges(imagePixels->data() + topFirstElement, imagePixels->data() + topLastElement, imagePixels->data() + bottomFirstElement); |
} |
return newSkImageFromRaster(info, std::move(imagePixels), imageRowBytes); |
} |
@@ -161,15 +193,19 @@ static PassRefPtr<SkImage> flipSkImageVertically(SkImage* input, AlphaDispositio |
static PassRefPtr<SkImage> premulSkImageToUnPremul(SkImage* input) |
{ |
SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_SkColorType, kUnpremul_SkAlphaType); |
- std::unique_ptr<uint8_t[]> dstPixels = copySkImageData(input, info); |
- return newSkImageFromRaster(info, std::move(dstPixels), input->width() * info.bytesPerPixel()); |
+ RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
+ if (!dstPixels) |
+ return nullptr; |
+ return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(input->width()) * info.bytesPerPixel()); |
} |
static PassRefPtr<SkImage> unPremulSkImageToPremul(SkImage* input) |
{ |
SkImageInfo info = SkImageInfo::Make(input->width(), input->height(), kN32_SkColorType, kPremul_SkAlphaType); |
- std::unique_ptr<uint8_t[]> dstPixels = copySkImageData(input, info); |
- return newSkImageFromRaster(info, std::move(dstPixels), input->width() * info.bytesPerPixel()); |
+ RefPtr<Uint8Array> dstPixels = copySkImageData(input, info); |
+ if (!dstPixels) |
+ return nullptr; |
+ return newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(input->width()) * info.bytesPerPixel()); |
} |
PassRefPtr<SkImage> ImageBitmap::getSkImageFromDecoder(std::unique_ptr<ImageDecoder> decoder) |
@@ -210,7 +246,6 @@ bool ImageBitmap::isSourceSizeValid(int sourceWidth, int sourceHeight, Exception |
static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions& parsedOptions, AlphaDisposition imageFormat = PremultiplyAlpha, ImageDecoder::GammaAndColorProfileOption colorSpaceOp = ImageDecoder::GammaAndColorProfileApplied) |
{ |
ASSERT(image); |
- |
IntRect imgRect(IntPoint(), IntSize(image->width(), image->height())); |
const IntRect srcRect = intersection(imgRect, parsedOptions.cropRect); |
@@ -218,8 +253,11 @@ static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions |
// We immediately return a transparent black image with cropRect.size() |
if (srcRect.isEmpty() && !parsedOptions.premultiplyAlpha) { |
SkImageInfo info = SkImageInfo::Make(parsedOptions.resizeWidth, parsedOptions.resizeHeight, kN32_SkColorType, kUnpremul_SkAlphaType); |
- std::unique_ptr<uint8_t[]> dstPixels = wrapArrayUnique(new uint8_t[info.width() * info.height() * info.bytesPerPixel()]()); |
- return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(dstPixels), info.width() * info.bytesPerPixel())); |
+ RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cast<size_t>(info.width()) * info.height(), info.bytesPerPixel()); |
+ if (!dstBuffer) |
+ return nullptr; |
+ RefPtr<Uint8Array> dstPixels = Uint8Array::create(dstBuffer, 0, dstBuffer->byteLength()); |
+ return StaticBitmapImage::create(newSkImageFromRaster(info, std::move(dstPixels), static_cast<size_t>(info.width()) * info.bytesPerPixel())); |
} |
RefPtr<SkImage> skiaImage = image->imageForCurrentFrame(); |
@@ -276,7 +314,7 @@ static PassRefPtr<StaticBitmapImage> cropImage(Image* image, const ParsedOptions |
skiaImage = fromSkSp(surface->makeImageSnapshot()); |
if (parsedOptions.premultiplyAlpha) { |
- if (imageFormat == PremultiplyAlpha) |
+ if (imageFormat == DontPremultiplyAlpha) |
return StaticBitmapImage::create(unPremulSkImageToPremul(skiaImage.get())); |
return StaticBitmapImage::create(skiaImage.release()); |
} |
@@ -287,6 +325,8 @@ ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do |
{ |
RefPtr<Image> input = image->cachedImage()->getImage(); |
ParsedOptions parsedOptions = parseOptions(options, cropRect, image->bitmapSourceSize()); |
+ if (dstBufferSizeHasOverflow(parsedOptions)) |
+ return; |
if (options.colorSpaceConversion() == "none") |
m_image = cropImage(input.get(), parsedOptions, PremultiplyAlpha, ImageDecoder::GammaAndColorProfileIgnored); |
@@ -303,6 +343,8 @@ ImageBitmap::ImageBitmap(HTMLImageElement* image, Optional<IntRect> cropRect, Do |
surface->getCanvas()->drawImage(skImage.get(), 0, 0); |
m_image = StaticBitmapImage::create(fromSkSp(surface->makeImageSnapshot())); |
} |
+ if (!m_image) |
+ return; |
m_image->setOriginClean(!image->wouldTaintOrigin(document->getSecurityOrigin())); |
m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
} |
@@ -313,6 +355,8 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do |
if (video->webMediaPlayer()) |
playerSize = video->webMediaPlayer()->naturalSize(); |
ParsedOptions parsedOptions = parseOptions(options, cropRect, video->bitmapSourceSize()); |
+ if (dstBufferSizeHasOverflow(parsedOptions)) |
+ return; |
IntRect videoRect = IntRect(IntPoint(), playerSize); |
IntRect srcRect = intersection(parsedOptions.cropRect, videoRect); |
@@ -339,6 +383,8 @@ ImageBitmap::ImageBitmap(HTMLVideoElement* video, Optional<IntRect> cropRect, Do |
RefPtr<SkImage> skiaImage = buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown); |
if (!parsedOptions.premultiplyAlpha) |
skiaImage = premulSkImageToUnPremul(skiaImage.get()); |
+ if (!skiaImage) |
+ return; |
m_image = StaticBitmapImage::create(skiaImage.release()); |
m_image->setOriginClean(!video->wouldTaintOrigin(document->getSecurityOrigin())); |
m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
@@ -349,6 +395,8 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect, |
ASSERT(canvas->isPaintable()); |
RefPtr<Image> input = canvas->copiedImage(BackBuffer, PreferAcceleration); |
ParsedOptions parsedOptions = parseOptions(options, cropRect, canvas->bitmapSourceSize()); |
+ if (dstBufferSizeHasOverflow(parsedOptions)) |
+ return; |
bool isPremultiplyAlphaReverted = false; |
if (!parsedOptions.premultiplyAlpha) { |
@@ -362,6 +410,8 @@ ImageBitmap::ImageBitmap(HTMLCanvasElement* canvas, Optional<IntRect> cropRect, |
parsedOptions.premultiplyAlpha = false; |
m_image = StaticBitmapImage::create(premulSkImageToUnPremul(m_image->imageForCurrentFrame().get())); |
} |
+ if (!m_image) |
+ return; |
m_image->setOriginClean(canvas->originClean()); |
m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
} |
@@ -370,6 +420,8 @@ ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 |
{ |
SkImageInfo info = SkImageInfo::MakeN32(width, height, isImageBitmapPremultiplied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
m_image = StaticBitmapImage::create(fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, data.get(), info.bytesPerPixel() * width)))); |
+ if (!m_image) |
+ return; |
m_image->setPremultiplied(isImageBitmapPremultiplied); |
m_image->setOriginClean(isImageBitmapOriginClean); |
} |
@@ -377,13 +429,16 @@ ImageBitmap::ImageBitmap(std::unique_ptr<uint8_t[]> data, uint32_t width, uint32 |
static PassRefPtr<SkImage> scaleSkImage(PassRefPtr<SkImage> skImage, unsigned resizeWidth, unsigned resizeHeight, SkFilterQuality resizeQuality) |
{ |
SkImageInfo resizedInfo = SkImageInfo::Make(resizeWidth, resizeHeight, kN32_SkColorType, kUnpremul_SkAlphaType); |
- std::unique_ptr<uint8_t[]> resizedPixels = wrapArrayUnique(new uint8_t[resizeWidth * resizeHeight * resizedInfo.bytesPerPixel()]); |
- SkPixmap pixmap(resizedInfo, resizedPixels.release(), resizeWidth * resizedInfo.bytesPerPixel()); |
+ RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(resizeWidth * resizeHeight, resizedInfo.bytesPerPixel()); |
+ if (!dstBuffer) |
+ return nullptr; |
+ RefPtr<Uint8Array> resizedPixels = Uint8Array::create(dstBuffer, 0, dstBuffer->byteLength()); |
+ SkPixmap pixmap(resizedInfo, resizedPixels->data(), static_cast<size_t>(resizeWidth) * resizedInfo.bytesPerPixel()); |
skImage->scalePixels(pixmap, resizeQuality); |
- return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void* pixels, void*) |
+ return fromSkSp(SkImage::MakeFromRaster(pixmap, [](const void*, void* pixels) |
{ |
- delete[] static_cast<const uint8_t*>(pixels); |
- }, nullptr)); |
+ static_cast<Uint8Array*>(pixels)->deref(); |
+ }, resizedPixels.release().leakRef())); |
} |
ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const ImageBitmapOptions& options) |
@@ -391,64 +446,72 @@ ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag |
// TODO(xidachen): implement the resize option |
IntRect dataSrcRect = IntRect(IntPoint(), data->size()); |
ParsedOptions parsedOptions = parseOptions(options, cropRect, data->bitmapSourceSize()); |
+ if (dstBufferSizeHasOverflow(parsedOptions)) |
+ return; |
IntRect srcRect = cropRect ? intersection(parsedOptions.cropRect, dataSrcRect) : dataSrcRect; |
// treat non-premultiplyAlpha as a special case |
if (!parsedOptions.premultiplyAlpha) { |
unsigned char* srcAddr = data->data()->data(); |
- int srcHeight = data->size().height(); |
- int dstHeight = parsedOptions.cropRect.height(); |
// Using kN32 type, swizzle input if necessary. |
- SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), dstHeight, kN32_SkColorType, kUnpremul_SkAlphaType); |
- int srcPixelBytesPerRow = info.bytesPerPixel() * data->size().width(); |
- int dstPixelBytesPerRow = info.bytesPerPixel() * parsedOptions.cropRect.width(); |
+ SkImageInfo info = SkImageInfo::Make(parsedOptions.cropRect.width(), parsedOptions.cropRect.height(), kN32_SkColorType, kUnpremul_SkAlphaType); |
+ size_t bytesPerPixel = static_cast<size_t>(info.bytesPerPixel()); |
+ size_t srcPixelBytesPerRow = bytesPerPixel * data->size().width(); |
+ size_t dstPixelBytesPerRow = bytesPerPixel * parsedOptions.cropRect.width(); |
RefPtr<SkImage> skImage; |
if (parsedOptions.cropRect == IntRect(IntPoint(), data->size())) { |
- swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOptions.flipY); |
+ swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow, parsedOptions.flipY); |
skImage = fromSkSp(SkImage::MakeRasterCopy(SkPixmap(info, srcAddr, dstPixelBytesPerRow))); |
// restore the original ImageData |
- swizzleImageData(srcAddr, srcHeight, srcPixelBytesPerRow, parsedOptions.flipY); |
+ swizzleImageData(srcAddr, data->size().height(), srcPixelBytesPerRow, parsedOptions.flipY); |
} else { |
- std::unique_ptr<uint8_t[]> copiedDataBuffer = wrapArrayUnique(new uint8_t[dstHeight * dstPixelBytesPerRow]()); |
+ RefPtr<ArrayBuffer> dstBuffer = ArrayBuffer::createOrNull(static_cast<size_t>(parsedOptions.cropRect.height()) * parsedOptions.cropRect.width(), bytesPerPixel); |
+ if (!dstBuffer) |
+ return; |
+ RefPtr<Uint8Array> copiedDataBuffer = Uint8Array::create(dstBuffer, 0, dstBuffer->byteLength()); |
if (!srcRect.isEmpty()) { |
IntPoint srcPoint = IntPoint((parsedOptions.cropRect.x() > 0) ? parsedOptions.cropRect.x() : 0, (parsedOptions.cropRect.y() > 0) ? parsedOptions.cropRect.y() : 0); |
IntPoint dstPoint = IntPoint((parsedOptions.cropRect.x() >= 0) ? 0 : -parsedOptions.cropRect.x(), (parsedOptions.cropRect.y() >= 0) ? 0 : -parsedOptions.cropRect.y()); |
- int copyHeight = srcHeight - srcPoint.y(); |
+ int copyHeight = data->size().height() - srcPoint.y(); |
if (parsedOptions.cropRect.height() < copyHeight) |
copyHeight = parsedOptions.cropRect.height(); |
int copyWidth = data->size().width() - srcPoint.x(); |
if (parsedOptions.cropRect.width() < copyWidth) |
copyWidth = parsedOptions.cropRect.width(); |
for (int i = 0; i < copyHeight; i++) { |
- int srcStartCopyPosition = (i + srcPoint.y()) * srcPixelBytesPerRow + srcPoint.x() * info.bytesPerPixel(); |
- int srcEndCopyPosition = srcStartCopyPosition + copyWidth * info.bytesPerPixel(); |
- int dstStartCopyPosition; |
+ size_t srcStartCopyPosition = (i + srcPoint.y()) * srcPixelBytesPerRow + srcPoint.x() * bytesPerPixel; |
+ size_t srcEndCopyPosition = srcStartCopyPosition + copyWidth * bytesPerPixel; |
+ size_t dstStartCopyPosition; |
if (parsedOptions.flipY) |
- dstStartCopyPosition = (dstHeight -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); |
+ dstStartCopyPosition = (parsedOptions.cropRect.height() -1 - dstPoint.y() - i) * dstPixelBytesPerRow + dstPoint.x() * bytesPerPixel; |
else |
- dstStartCopyPosition = (dstPoint.y() + i) * dstPixelBytesPerRow + dstPoint.x() * info.bytesPerPixel(); |
- for (int j = 0; j < srcEndCopyPosition - srcStartCopyPosition; j++) { |
+ dstStartCopyPosition = (dstPoint.y() + i) * dstPixelBytesPerRow + dstPoint.x() * bytesPerPixel; |
+ for (size_t j = 0; j < srcEndCopyPosition - srcStartCopyPosition; j++) { |
// swizzle when necessary |
if (kN32_SkColorType == kBGRA_8888_SkColorType) { |
if (j % 4 == 0) |
- copiedDataBuffer[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j + 2]; |
+ copiedDataBuffer->data()[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j + 2]; |
else if (j % 4 == 2) |
- copiedDataBuffer[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j - 2]; |
+ copiedDataBuffer->data()[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j - 2]; |
else |
- copiedDataBuffer[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j]; |
+ copiedDataBuffer->data()[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j]; |
} else { |
- copiedDataBuffer[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j]; |
+ copiedDataBuffer->data()[dstStartCopyPosition + j] = srcAddr[srcStartCopyPosition + j]; |
} |
} |
} |
} |
skImage = newSkImageFromRaster(info, std::move(copiedDataBuffer), dstPixelBytesPerRow); |
} |
+ if (!skImage) |
+ return; |
if (parsedOptions.shouldScaleInput) |
m_image = StaticBitmapImage::create(scaleSkImage(skImage, parsedOptions.resizeWidth, parsedOptions.resizeHeight, parsedOptions.resizeQuality)); |
else |
m_image = StaticBitmapImage::create(skImage); |
+ if (!m_image) |
+ return; |
m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
return; |
} |
@@ -471,6 +534,8 @@ ImageBitmap::ImageBitmap(ImageData* data, Optional<IntRect> cropRect, const Imag |
RefPtr<SkImage> skImage = buffer->newSkImageSnapshot(PreferNoAcceleration, SnapshotReasonUnknown); |
if (parsedOptions.flipY) |
skImage = flipSkImageVertically(skImage.get(), PremultiplyAlpha); |
+ if (!skImage) |
+ return; |
if (parsedOptions.shouldScaleInput) { |
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(parsedOptions.resizeWidth, parsedOptions.resizeHeight); |
if (!surface) |
@@ -490,6 +555,8 @@ ImageBitmap::ImageBitmap(ImageBitmap* bitmap, Optional<IntRect> cropRect, const |
if (!input) |
return; |
ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); |
+ if (dstBufferSizeHasOverflow(parsedOptions)) |
+ return; |
m_image = cropImage(input.get(), parsedOptions, bitmap->isPremultiplied() ? PremultiplyAlpha : DontPremultiplyAlpha); |
if (!m_image) |
@@ -503,10 +570,13 @@ ImageBitmap::ImageBitmap(PassRefPtr<StaticBitmapImage> image, Optional<IntRect> |
bool originClean = image->originClean(); |
RefPtr<Image> input = image; |
ParsedOptions parsedOptions = parseOptions(options, cropRect, input->size()); |
+ if (dstBufferSizeHasOverflow(parsedOptions)) |
+ return; |
- m_image = cropImage(input.get(), parsedOptions, DontPremultiplyAlpha); |
+ m_image = cropImage(input.get(), parsedOptions); |
if (!m_image) |
return; |
+ |
m_image->setOriginClean(originClean); |
m_image->setPremultiplied(parsedOptions.premultiplyAlpha); |
} |
@@ -581,11 +651,11 @@ ImageBitmap* ImageBitmap::take(ScriptPromiseResolver*, sk_sp<SkImage> image) |
return ImageBitmap::create(StaticBitmapImage::create(fromSkSp(image))); |
} |
-std::unique_ptr<uint8_t[]> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp, DataColorFormat format) |
+PassRefPtr<Uint8Array> ImageBitmap::copyBitmapData(AlphaDisposition alphaOp, DataColorFormat format) |
{ |
SkImageInfo info = SkImageInfo::Make(width(), height(), (format == RGBAColorType) ? kRGBA_8888_SkColorType : kN32_SkColorType, (alphaOp == PremultiplyAlpha) ? kPremul_SkAlphaType : kUnpremul_SkAlphaType); |
- std::unique_ptr<uint8_t[]> dstPixels = copySkImageData(m_image->imageForCurrentFrame().get(), info); |
- return dstPixels; |
+ RefPtr<Uint8Array> dstPixels = copySkImageData(m_image->imageForCurrentFrame().get(), info); |
+ return dstPixels.release(); |
} |
unsigned long ImageBitmap::width() const |