| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "bindings/core/v8/ExceptionState.h" | 31 #include "bindings/core/v8/ExceptionState.h" |
| 32 #include "bindings/core/v8/V8Uint8ClampedArray.h" | 32 #include "bindings/core/v8/V8Uint8ClampedArray.h" |
| 33 #include "core/dom/ExceptionCode.h" | 33 #include "core/dom/ExceptionCode.h" |
| 34 #include "core/frame/ImageBitmap.h" | 34 #include "core/frame/ImageBitmap.h" |
| 35 #include "core/imagebitmap/ImageBitmapOptions.h" | 35 #include "core/imagebitmap/ImageBitmapOptions.h" |
| 36 #include "platform/RuntimeEnabledFeatures.h" | 36 #include "platform/RuntimeEnabledFeatures.h" |
| 37 #include "platform/graphics/ColorBehavior.h" | 37 #include "platform/graphics/ColorBehavior.h" |
| 38 | 38 |
| 39 namespace blink { | 39 namespace blink { |
| 40 | 40 |
| 41 bool RaiseDOMExceptionAndReturnFalse(ExceptionState* exceptionState, |
| 42 ExceptionCode exceptionCode, |
| 43 const char* message) { |
| 44 if (exceptionState) |
| 45 exceptionState->throwDOMException(exceptionCode, message); |
| 46 return false; |
| 47 } |
| 48 |
| 41 bool ImageData::validateConstructorArguments(const unsigned& paramFlags, | 49 bool ImageData::validateConstructorArguments(const unsigned& paramFlags, |
| 42 const IntSize* size, | 50 const IntSize* size, |
| 43 const unsigned& width, | 51 const unsigned& width, |
| 44 const unsigned& height, | 52 const unsigned& height, |
| 45 const DOMArrayBufferView* data, | 53 const DOMArrayBufferView* data, |
| 46 const String* colorSpace, | 54 ExceptionState* exceptionState) { |
| 47 ExceptionState* exceptionState, | 55 // We accept all the combinations of colorSpace and storageFormat in an |
| 48 ImageDataType imageDataType) { | 56 // ImageDataColorSettings to be stored in an ImageData. Therefore, we don't |
| 49 if (paramFlags & kParamData) { | 57 // check the color settings in this function. |
| 50 if (data->type() != DOMArrayBufferView::ViewType::TypeUint8Clamped && | 58 |
| 51 data->type() != DOMArrayBufferView::ViewType::TypeFloat32) | 59 if ((paramFlags & kParamWidth) && !width) { |
| 52 return false; | 60 return RaiseDOMExceptionAndReturnFalse( |
| 53 if (data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped && | 61 exceptionState, IndexSizeError, |
| 54 imageDataType != kUint8ClampedImageData) | 62 "The source width is zero or not a number."); |
| 55 imageDataType = kFloat32ImageData; | |
| 56 } | 63 } |
| 57 | 64 |
| 58 // ImageData::create parameters without ExceptionState | 65 if ((paramFlags & kParamHeight) && !height) { |
| 66 return RaiseDOMExceptionAndReturnFalse( |
| 67 exceptionState, IndexSizeError, |
| 68 "The source height is zero or not a number."); |
| 69 } |
| 70 |
| 71 if (paramFlags & (kParamWidth | kParamHeight)) { |
| 72 CheckedNumeric<unsigned> dataSize = 4; |
| 73 dataSize *= width; |
| 74 dataSize *= height; |
| 75 if (!dataSize.IsValid()) |
| 76 return RaiseDOMExceptionAndReturnFalse( |
| 77 exceptionState, IndexSizeError, |
| 78 "The requested image size exceeds the supported range."); |
| 79 } |
| 80 |
| 81 unsigned dataLength = 0; |
| 82 if (paramFlags & kParamData) { |
| 83 DCHECK(data); |
| 84 switch (data->type()) { |
| 85 case DOMArrayBufferView::ViewType::TypeUint8Clamped: |
| 86 dataLength = data->view()->byteLength(); |
| 87 break; |
| 88 case DOMArrayBufferView::ViewType::TypeUint16: |
| 89 dataLength = data->view()->byteLength() / 2; |
| 90 break; |
| 91 case DOMArrayBufferView::ViewType::TypeFloat32: |
| 92 dataLength = data->view()->byteLength() / 4; |
| 93 break; |
| 94 default: |
| 95 return RaiseDOMExceptionAndReturnFalse( |
| 96 exceptionState, NotSupportedError, |
| 97 "The input data type is not supported."); |
| 98 } |
| 99 |
| 100 if (!dataLength) { |
| 101 return RaiseDOMExceptionAndReturnFalse( |
| 102 exceptionState, IndexSizeError, "The input data has zero elements."); |
| 103 } |
| 104 |
| 105 if (dataLength % 4) { |
| 106 return RaiseDOMExceptionAndReturnFalse( |
| 107 exceptionState, IndexSizeError, |
| 108 "The input data length is not a multiple of 4."); |
| 109 } |
| 110 |
| 111 if ((paramFlags & kParamWidth) && (dataLength / 4) % width) { |
| 112 return RaiseDOMExceptionAndReturnFalse( |
| 113 exceptionState, IndexSizeError, |
| 114 "The input data length is not a multiple of (4 * width)."); |
| 115 } |
| 116 |
| 117 if ((paramFlags & kParamHeight & kParamWidth) && |
| 118 height != dataLength / (4 * width)) |
| 119 return RaiseDOMExceptionAndReturnFalse( |
| 120 exceptionState, IndexSizeError, |
| 121 "The input data length is not equal to (4 * width * height)."); |
| 122 } |
| 123 |
| 59 if (paramFlags & kParamSize) { | 124 if (paramFlags & kParamSize) { |
| 60 if (!size->width() || !size->height()) | 125 if (!size->width() || !size->height()) |
| 61 return false; | 126 return false; |
| 62 CheckedNumeric<unsigned> dataSize = 4; | 127 CheckedNumeric<unsigned> dataSize = 4; |
| 63 dataSize *= size->width(); | 128 dataSize *= size->width(); |
| 64 dataSize *= size->height(); | 129 dataSize *= size->height(); |
| 65 if (!dataSize.IsValid()) | 130 if (!dataSize.IsValid()) |
| 66 return false; | 131 return false; |
| 67 if (paramFlags & kParamData) { | 132 if (paramFlags & kParamData) { |
| 68 DCHECK(data); | 133 if (dataSize.ValueOrDie() > dataLength) |
| 69 unsigned length = | |
| 70 data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped | |
| 71 ? (const_cast<DOMUint8ClampedArray*>( | |
| 72 static_cast<const DOMUint8ClampedArray*>(data))) | |
| 73 ->length() | |
| 74 : (const_cast<DOMFloat32Array*>( | |
| 75 static_cast<const DOMFloat32Array*>(data))) | |
| 76 ->length(); | |
| 77 if (dataSize.ValueOrDie() > length) | |
| 78 return false; | 134 return false; |
| 79 } | 135 } |
| 80 return true; | |
| 81 } | 136 } |
| 82 | 137 |
| 83 // ImageData::create parameters with ExceptionState | |
| 84 if ((paramFlags & kParamWidth) && !width) { | |
| 85 exceptionState->throwDOMException( | |
| 86 IndexSizeError, "The source width is zero or not a number."); | |
| 87 return false; | |
| 88 } | |
| 89 if ((paramFlags & kParamHeight) && !height) { | |
| 90 exceptionState->throwDOMException( | |
| 91 IndexSizeError, "The source height is zero or not a number."); | |
| 92 return false; | |
| 93 } | |
| 94 if (paramFlags & (kParamWidth | kParamHeight)) { | |
| 95 CheckedNumeric<unsigned> dataSize = 4; | |
| 96 dataSize *= width; | |
| 97 dataSize *= height; | |
| 98 if (!dataSize.IsValid()) { | |
| 99 exceptionState->throwDOMException( | |
| 100 IndexSizeError, | |
| 101 "The requested image size exceeds the supported range."); | |
| 102 return false; | |
| 103 } | |
| 104 } | |
| 105 if (paramFlags & kParamData) { | |
| 106 DCHECK(data); | |
| 107 unsigned length = | |
| 108 data->type() == DOMArrayBufferView::ViewType::TypeUint8Clamped | |
| 109 ? (const_cast<DOMUint8ClampedArray*>( | |
| 110 static_cast<const DOMUint8ClampedArray*>(data))) | |
| 111 ->length() | |
| 112 : (const_cast<DOMFloat32Array*>( | |
| 113 static_cast<const DOMFloat32Array*>(data))) | |
| 114 ->length(); | |
| 115 if (!length) { | |
| 116 exceptionState->throwDOMException(IndexSizeError, | |
| 117 "The input data has zero elements."); | |
| 118 return false; | |
| 119 } | |
| 120 if (length % 4) { | |
| 121 exceptionState->throwDOMException( | |
| 122 IndexSizeError, "The input data length is not a multiple of 4."); | |
| 123 return false; | |
| 124 } | |
| 125 length /= 4; | |
| 126 if (length % width) { | |
| 127 exceptionState->throwDOMException( | |
| 128 IndexSizeError, | |
| 129 "The input data length is not a multiple of (4 * width)."); | |
| 130 return false; | |
| 131 } | |
| 132 if ((paramFlags & kParamHeight) && height != length / width) { | |
| 133 exceptionState->throwDOMException( | |
| 134 IndexSizeError, | |
| 135 "The input data length is not equal to (4 * width * height)."); | |
| 136 return false; | |
| 137 } | |
| 138 } | |
| 139 if (paramFlags & kParamColorSpace) { | |
| 140 if (!colorSpace || colorSpace->length() == 0) { | |
| 141 exceptionState->throwDOMException( | |
| 142 NotSupportedError, "The source color space is not defined."); | |
| 143 return false; | |
| 144 } | |
| 145 if (imageDataType == kUint8ClampedImageData && | |
| 146 *colorSpace != kLegacyImageDataColorSpaceName && | |
| 147 *colorSpace != kSRGBImageDataColorSpaceName) { | |
| 148 exceptionState->throwDOMException(NotSupportedError, | |
| 149 "The input color space is not " | |
| 150 "supported in " | |
| 151 "Uint8ClampedArray-backed ImageData."); | |
| 152 return false; | |
| 153 } | |
| 154 if (imageDataType == kFloat32ImageData && | |
| 155 *colorSpace != kLinearRGBImageDataColorSpaceName) { | |
| 156 exceptionState->throwDOMException(NotSupportedError, | |
| 157 "The input color space is not " | |
| 158 "supported in " | |
| 159 "Float32Array-backed ImageData."); | |
| 160 return false; | |
| 161 } | |
| 162 } | |
| 163 return true; | 138 return true; |
| 164 } | 139 } |
| 165 | 140 |
| 166 DOMUint8ClampedArray* ImageData::allocateAndValidateUint8ClampedArray( | 141 DOMArrayBufferView* ImageData::allocateAndValidateDataArray( |
| 167 const unsigned& length, | 142 const unsigned& length, |
| 143 ImageDataStorageFormat storageFormat, |
| 168 ExceptionState* exceptionState) { | 144 ExceptionState* exceptionState) { |
| 169 if (!length) | 145 if (!length) |
| 170 return nullptr; | 146 return nullptr; |
| 171 DOMUint8ClampedArray* dataArray = DOMUint8ClampedArray::createOrNull(length); | 147 |
| 172 if (!dataArray || length != dataArray->length()) { | 148 DOMArrayBufferView* dataArray = nullptr; |
| 173 if (exceptionState) { | 149 unsigned dataLength = 0; |
| 150 switch (storageFormat) { |
| 151 case kUint8ClampedArrayStorageFormat: |
| 152 dataArray = DOMUint8ClampedArray::createOrNull(length); |
| 153 dataLength = dataArray->view()->byteLength(); |
| 154 break; |
| 155 case kUint16ArrayStorageFormat: |
| 156 dataArray = DOMUint16Array::createOrNull(length); |
| 157 dataLength = dataArray->view()->byteLength() / 2; |
| 158 break; |
| 159 case kFloat32ArrayStorageFormat: |
| 160 dataArray = DOMFloat32Array::createOrNull(length); |
| 161 dataLength = dataArray->view()->byteLength() / 4; |
| 162 break; |
| 163 default: |
| 164 NOTREACHED(); |
| 165 } |
| 166 |
| 167 if (!dataArray || length != dataLength) { |
| 168 if (exceptionState) |
| 174 exceptionState->throwDOMException(V8RangeError, | 169 exceptionState->throwDOMException(V8RangeError, |
| 175 "Out of memory at ImageData creation"); | 170 "Out of memory at ImageData creation"); |
| 176 } | |
| 177 return nullptr; | 171 return nullptr; |
| 178 } | 172 } |
| 173 |
| 179 return dataArray; | 174 return dataArray; |
| 180 } | 175 } |
| 181 | 176 |
| 182 ImageData* ImageData::create(const IntSize& size) { | 177 ImageData* ImageData::create(const IntSize& size) { |
| 183 if (!ImageData::validateConstructorArguments(kParamSize, &size)) | 178 if (!ImageData::validateConstructorArguments(kParamSize, &size)) |
| 184 return nullptr; | 179 return nullptr; |
| 185 DOMUint8ClampedArray* byteArray = | 180 DOMArrayBufferView* byteArray = allocateAndValidateDataArray( |
| 186 ImageData::allocateAndValidateUint8ClampedArray(4 * size.width() * | 181 4 * size.width() * size.height(), kUint8ClampedArrayStorageFormat); |
| 187 size.height()); | |
| 188 if (!byteArray) | |
| 189 return nullptr; | |
| 190 return new ImageData(size, byteArray); | 182 return new ImageData(size, byteArray); |
| 191 } | 183 } |
| 192 | 184 |
| 193 // This function accepts size (0, 0). | 185 // This function accepts size (0, 0) and always returns the ImageData in |
| 186 // "srgb" color space and "uint8" storage format. |
| 194 ImageData* ImageData::createForTest(const IntSize& size) { | 187 ImageData* ImageData::createForTest(const IntSize& size) { |
| 195 CheckedNumeric<unsigned> dataSize = 4; | 188 CheckedNumeric<unsigned> dataSize = 4; |
| 196 dataSize *= size.width(); | 189 dataSize *= size.width(); |
| 197 dataSize *= size.height(); | 190 dataSize *= size.height(); |
| 198 if (!dataSize.IsValid()) | 191 if (!dataSize.IsValid()) |
| 199 return nullptr; | 192 return nullptr; |
| 200 | 193 |
| 201 DOMUint8ClampedArray* byteArray = | 194 DOMUint8ClampedArray* byteArray = |
| 202 DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie()); | 195 DOMUint8ClampedArray::createOrNull(dataSize.ValueOrDie()); |
| 203 if (!byteArray) | 196 if (!byteArray) |
| 204 return nullptr; | 197 return nullptr; |
| 205 | 198 |
| 206 return new ImageData(size, byteArray); | 199 return new ImageData(size, byteArray); |
| 207 } | 200 } |
| 208 | 201 |
| 209 ImageData* ImageData::create(const IntSize& size, | 202 ImageData* ImageData::create(const IntSize& size, |
| 210 DOMUint8ClampedArray* byteArray) { | 203 DOMUint8ClampedArray* byteArray) { |
| 211 if (!ImageData::validateConstructorArguments(kParamSize | kParamData, &size, | 204 if (!ImageData::validateConstructorArguments(kParamSize | kParamData, &size, |
| 212 0, 0, byteArray)) | 205 0, 0, byteArray)) |
| 213 return nullptr; | 206 return nullptr; |
| 207 |
| 214 return new ImageData(size, byteArray); | 208 return new ImageData(size, byteArray); |
| 215 } | 209 } |
| 216 | 210 |
| 217 ImageData* ImageData::create(const IntSize& size, | |
| 218 DOMUint8ClampedArray* byteArray, | |
| 219 const String& colorSpace) { | |
| 220 if (!ImageData::validateConstructorArguments( | |
| 221 kParamSize | kParamData | kParamColorSpace, &size, 0, 0, byteArray, | |
| 222 &colorSpace)) | |
| 223 return nullptr; | |
| 224 return new ImageData(size, byteArray, colorSpace); | |
| 225 } | |
| 226 | |
| 227 ImageData* ImageData::create(unsigned width, | 211 ImageData* ImageData::create(unsigned width, |
| 228 unsigned height, | 212 unsigned height, |
| 229 ExceptionState& exceptionState) { | 213 ExceptionState& exceptionState) { |
| 230 if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight, | 214 if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight, |
| 231 nullptr, width, height, nullptr, | 215 nullptr, width, height, nullptr, |
| 232 nullptr, &exceptionState)) | 216 &exceptionState)) |
| 233 return nullptr; | 217 return nullptr; |
| 234 DOMUint8ClampedArray* byteArray = | 218 |
| 235 ImageData::allocateAndValidateUint8ClampedArray(4 * width * height, | 219 DOMArrayBufferView* byteArray = allocateAndValidateDataArray( |
| 236 &exceptionState); | 220 4 * width * height, kUint8ClampedArrayStorageFormat, &exceptionState); |
| 237 return byteArray ? new ImageData(IntSize(width, height), byteArray) : nullptr; | 221 return byteArray ? new ImageData(IntSize(width, height), byteArray) : nullptr; |
| 238 } | 222 } |
| 239 | 223 |
| 240 ImageData* ImageData::create(DOMUint8ClampedArray* data, | 224 ImageData* ImageData::create(DOMUint8ClampedArray* data, |
| 241 unsigned width, | 225 unsigned width, |
| 242 ExceptionState& exceptionState) { | 226 ExceptionState& exceptionState) { |
| 243 if (!ImageData::validateConstructorArguments(kParamData | kParamWidth, | 227 if (!ImageData::validateConstructorArguments( |
| 244 nullptr, width, 0, data, nullptr, | 228 kParamData | kParamWidth, nullptr, width, 0, data, &exceptionState)) |
| 245 &exceptionState)) | |
| 246 return nullptr; | 229 return nullptr; |
| 230 |
| 247 unsigned height = data->length() / (width * 4); | 231 unsigned height = data->length() / (width * 4); |
| 248 return new ImageData(IntSize(width, height), data); | 232 return new ImageData(IntSize(width, height), data); |
| 249 } | 233 } |
| 250 | 234 |
| 251 ImageData* ImageData::create(DOMUint8ClampedArray* data, | 235 ImageData* ImageData::create(DOMUint8ClampedArray* data, |
| 252 unsigned width, | 236 unsigned width, |
| 253 unsigned height, | 237 unsigned height, |
| 254 ExceptionState& exceptionState) { | 238 ExceptionState& exceptionState) { |
| 255 if (!ImageData::validateConstructorArguments( | 239 if (!ImageData::validateConstructorArguments( |
| 256 kParamData | kParamWidth | kParamHeight, nullptr, width, height, data, | 240 kParamData | kParamWidth | kParamHeight, nullptr, width, height, data, |
| 257 nullptr, &exceptionState)) | 241 &exceptionState)) |
| 258 return nullptr; | 242 return nullptr; |
| 243 |
| 259 return new ImageData(IntSize(width, height), data); | 244 return new ImageData(IntSize(width, height), data); |
| 260 } | 245 } |
| 261 | 246 |
| 262 ImageData* ImageData::createImageData(unsigned width, | 247 ImageData* ImageData::createImageData( |
| 263 unsigned height, | 248 unsigned width, |
| 264 String colorSpace, | 249 unsigned height, |
| 265 ExceptionState& exceptionState) { | 250 const ImageDataColorSettings& colorSettings, |
| 266 if (!ImageData::validateConstructorArguments( | 251 ExceptionState& exceptionState) { |
| 267 kParamWidth | kParamHeight | kParamColorSpace, nullptr, width, height, | 252 if (!ImageData::validateConstructorArguments(kParamWidth | kParamHeight, |
| 268 nullptr, &colorSpace, &exceptionState)) | 253 nullptr, width, height, nullptr, |
| 254 &exceptionState)) |
| 269 return nullptr; | 255 return nullptr; |
| 270 | 256 |
| 271 DOMUint8ClampedArray* byteArray = | 257 ImageDataStorageFormat storageFormat = |
| 272 ImageData::allocateAndValidateUint8ClampedArray(4 * width * height, | 258 ImageData::getImageDataStorageFormat(colorSettings.storageFormat()); |
| 273 &exceptionState); | 259 DOMArrayBufferView* bufferView = allocateAndValidateDataArray( |
| 274 return byteArray | 260 4 * width * height, storageFormat, &exceptionState); |
| 275 ? new ImageData(IntSize(width, height), byteArray, colorSpace) | 261 |
| 276 : nullptr; | 262 if (!bufferView) |
| 263 return nullptr; |
| 264 |
| 265 return new ImageData(IntSize(width, height), bufferView, &colorSettings); |
| 277 } | 266 } |
| 278 | 267 |
| 279 ImageData* ImageData::createImageData(DOMUint8ClampedArray* data, | 268 ImageData* ImageData::createImageData( |
| 280 unsigned width, | 269 ImageDataArray& data, |
| 281 String colorSpace, | 270 unsigned width, |
| 282 ExceptionState& exceptionState) { | 271 unsigned height, |
| 272 const ImageDataColorSettings& colorSettings, |
| 273 ExceptionState& exceptionState) { |
| 274 DOMArrayBufferView* bufferView = nullptr; |
| 275 if (data.isUint8ClampedArray()) |
| 276 bufferView = data.getAsUint8ClampedArray(); |
| 277 else if (data.isUint16Array()) |
| 278 bufferView = data.getAsUint16Array(); |
| 279 else if (data.isFloat32Array()) |
| 280 bufferView = data.getAsFloat32Array(); |
| 281 else |
| 282 NOTREACHED(); |
| 283 |
| 283 if (!ImageData::validateConstructorArguments( | 284 if (!ImageData::validateConstructorArguments( |
| 284 kParamData | kParamWidth | kParamColorSpace, nullptr, width, 0, data, | 285 kParamData | kParamWidth | kParamHeight, nullptr, width, height, |
| 285 &colorSpace, &exceptionState)) | 286 bufferView, &exceptionState)) |
| 286 return nullptr; | 287 return nullptr; |
| 287 unsigned height = data->length() / (width * 4); | |
| 288 return new ImageData(IntSize(width, height), data, colorSpace); | |
| 289 } | |
| 290 | 288 |
| 291 ImageData* ImageData::createImageData(DOMUint8ClampedArray* data, | 289 return new ImageData(IntSize(width, height), bufferView, &colorSettings); |
| 292 unsigned width, | |
| 293 unsigned height, | |
| 294 String colorSpace, | |
| 295 ExceptionState& exceptionState) { | |
| 296 if (!ImageData::validateConstructorArguments( | |
| 297 kParamData | kParamWidth | kParamHeight | kParamColorSpace, nullptr, | |
| 298 width, height, data, &colorSpace, &exceptionState)) | |
| 299 return nullptr; | |
| 300 return new ImageData(IntSize(width, height), data, colorSpace); | |
| 301 } | 290 } |
| 302 | 291 |
| 303 ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState, | 292 ScriptPromise ImageData::createImageBitmap(ScriptState* scriptState, |
| 304 EventTarget& eventTarget, | 293 EventTarget& eventTarget, |
| 305 Optional<IntRect> cropRect, | 294 Optional<IntRect> cropRect, |
| 306 const ImageBitmapOptions& options, | 295 const ImageBitmapOptions& options, |
| 307 ExceptionState& exceptionState) { | 296 ExceptionState& exceptionState) { |
| 308 if ((cropRect && | 297 if ((cropRect && |
| 309 !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), | 298 !ImageBitmap::isSourceSizeValid(cropRect->width(), cropRect->height(), |
| 310 exceptionState)) || | 299 exceptionState)) || |
| (...skipping 12 matching lines...) Expand all Loading... |
| 323 scriptState, ImageBitmap::create(this, cropRect, options)); | 312 scriptState, ImageBitmap::create(this, cropRect, options)); |
| 324 } | 313 } |
| 325 | 314 |
| 326 v8::Local<v8::Object> ImageData::associateWithWrapper( | 315 v8::Local<v8::Object> ImageData::associateWithWrapper( |
| 327 v8::Isolate* isolate, | 316 v8::Isolate* isolate, |
| 328 const WrapperTypeInfo* wrapperType, | 317 const WrapperTypeInfo* wrapperType, |
| 329 v8::Local<v8::Object> wrapper) { | 318 v8::Local<v8::Object> wrapper) { |
| 330 wrapper = | 319 wrapper = |
| 331 ScriptWrappable::associateWithWrapper(isolate, wrapperType, wrapper); | 320 ScriptWrappable::associateWithWrapper(isolate, wrapperType, wrapper); |
| 332 | 321 |
| 333 if (!wrapper.IsEmpty() && m_data.get()) { | 322 if (!wrapper.IsEmpty() && m_data) { |
| 334 // Create a V8 Uint8ClampedArray object and set the "data" property | 323 // Create a V8 Uint8ClampedArray object and set the "data" property |
| 335 // of the ImageData object to the created v8 object, eliminating the | 324 // of the ImageData object to the created v8 object, eliminating the |
| 336 // C++ callback when accessing the "data" property. | 325 // C++ callback when accessing the "data" property. |
| 337 v8::Local<v8::Value> pixelArray = ToV8(m_data.get(), wrapper, isolate); | 326 v8::Local<v8::Value> pixelArray = ToV8(m_data.get(), wrapper, isolate); |
| 338 if (pixelArray.IsEmpty() || | 327 if (pixelArray.IsEmpty() || |
| 339 !v8CallBoolean(wrapper->DefineOwnProperty( | 328 !v8CallBoolean(wrapper->DefineOwnProperty( |
| 340 isolate->GetCurrentContext(), v8AtomicString(isolate, "data"), | 329 isolate->GetCurrentContext(), v8AtomicString(isolate, "data"), |
| 341 pixelArray, v8::ReadOnly))) | 330 pixelArray, v8::ReadOnly))) |
| 342 return v8::Local<v8::Object>(); | 331 return v8::Local<v8::Object>(); |
| 343 } | 332 } |
| 344 return wrapper; | 333 return wrapper; |
| 345 } | 334 } |
| 346 | 335 |
| 347 ImageDataColorSpace ImageData::getImageDataColorSpace(String colorSpaceName) { | 336 const DOMUint8ClampedArray* ImageData::data() const { |
| 348 if (colorSpaceName == kLegacyImageDataColorSpaceName) | 337 if (m_colorSettings.storageFormat() == kUint8ClampedArrayStorageFormatName) |
| 349 return kLegacyImageDataColorSpace; | 338 return m_data.get(); |
| 350 if (colorSpaceName == kSRGBImageDataColorSpaceName) | |
| 351 return kSRGBImageDataColorSpace; | |
| 352 if (colorSpaceName == kLinearRGBImageDataColorSpaceName) | |
| 353 return kLinearRGBImageDataColorSpace; | |
| 354 NOTREACHED(); | |
| 355 return kLegacyImageDataColorSpace; | |
| 356 } | |
| 357 | |
| 358 String ImageData::getImageDataColorSpaceName(ImageDataColorSpace colorSpace) { | |
| 359 switch (colorSpace) { | |
| 360 case kLegacyImageDataColorSpace: | |
| 361 return kLegacyImageDataColorSpaceName; | |
| 362 case kSRGBImageDataColorSpace: | |
| 363 return kSRGBImageDataColorSpaceName; | |
| 364 case kLinearRGBImageDataColorSpace: | |
| 365 return kLinearRGBImageDataColorSpaceName; | |
| 366 } | |
| 367 NOTREACHED(); | |
| 368 return String(); | |
| 369 } | |
| 370 | |
| 371 sk_sp<SkColorSpace> ImageData::imageDataColorSpaceToSkColorSpace( | |
| 372 ImageDataColorSpace colorSpace) { | |
| 373 switch (colorSpace) { | |
| 374 case kLegacyImageDataColorSpace: | |
| 375 return ColorBehavior::globalTargetColorSpace().ToSkColorSpace(); | |
| 376 case kSRGBImageDataColorSpace: | |
| 377 return SkColorSpace::MakeSRGB(); | |
| 378 case kLinearRGBImageDataColorSpace: | |
| 379 return SkColorSpace::MakeSRGBLinear(); | |
| 380 } | |
| 381 NOTREACHED(); | |
| 382 return nullptr; | 339 return nullptr; |
| 383 } | 340 } |
| 384 | 341 |
| 342 DOMUint8ClampedArray* ImageData::data() { |
| 343 if (m_colorSettings.storageFormat() == kUint8ClampedArrayStorageFormatName) |
| 344 return m_data.get(); |
| 345 return nullptr; |
| 346 } |
| 347 |
| 348 ImageDataStorageFormat ImageData::getImageDataStorageFormat( |
| 349 const String& storageFormatName) { |
| 350 if (storageFormatName == kUint8ClampedArrayStorageFormatName) |
| 351 return kUint8ClampedArrayStorageFormat; |
| 352 if (storageFormatName == kUint16ArrayStorageFormatName) |
| 353 return kUint16ArrayStorageFormat; |
| 354 if (storageFormatName == kFloat32ArrayStorageFormatName) |
| 355 return kFloat32ArrayStorageFormat; |
| 356 NOTREACHED(); |
| 357 return kUint8ClampedArrayStorageFormat; |
| 358 } |
| 359 |
| 360 // For ImageData, the color space is only specified by color settings. |
| 361 // It cannot have a SkColorSpace. This doesn't mean anything. Fix this. |
| 385 sk_sp<SkColorSpace> ImageData::getSkColorSpace() { | 362 sk_sp<SkColorSpace> ImageData::getSkColorSpace() { |
| 386 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || | 363 if (!RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled() || |
| 387 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 364 !RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
| 388 return nullptr; | 365 return nullptr; |
| 389 return ImageData::imageDataColorSpaceToSkColorSpace(m_colorSpace); | 366 |
| 367 return SkColorSpace::MakeSRGB(); |
| 368 } |
| 369 |
| 370 void ImageData::trace(Visitor* visitor) { |
| 371 visitor->trace(m_data); |
| 372 visitor->trace(m_dataU16); |
| 373 visitor->trace(m_dataF32); |
| 374 visitor->trace(m_dataUnion); |
| 390 } | 375 } |
| 391 | 376 |
| 392 ImageData::ImageData(const IntSize& size, | 377 ImageData::ImageData(const IntSize& size, |
| 393 DOMUint8ClampedArray* byteArray, | 378 DOMArrayBufferView* data, |
| 394 String colorSpaceName) | 379 const ImageDataColorSettings* colorSettings) |
| 395 : m_size(size), | 380 : m_size(size) { |
| 396 m_colorSpace(getImageDataColorSpace(colorSpaceName)), | |
| 397 m_data(byteArray) { | |
| 398 DCHECK_GE(size.width(), 0); | 381 DCHECK_GE(size.width(), 0); |
| 399 DCHECK_GE(size.height(), 0); | 382 DCHECK_GE(size.height(), 0); |
| 400 SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <= | 383 DCHECK(data); |
| 401 m_data->length()); | 384 |
| 385 m_data = nullptr; |
| 386 m_dataU16 = nullptr; |
| 387 m_dataF32 = nullptr; |
| 388 |
| 389 if (colorSettings) { |
| 390 m_colorSettings.setColorSpace(colorSettings->colorSpace()); |
| 391 m_colorSettings.setStorageFormat(colorSettings->storageFormat()); |
| 392 } |
| 393 |
| 394 ImageDataStorageFormat storageFormat = |
| 395 getImageDataStorageFormat(m_colorSettings.storageFormat()); |
| 396 |
| 397 switch (storageFormat) { |
| 398 case kUint8ClampedArrayStorageFormat: |
| 399 m_data = const_cast<DOMUint8ClampedArray*>( |
| 400 static_cast<const DOMUint8ClampedArray*>(data)); |
| 401 m_dataUnion.setUint8ClampedArray(m_data); |
| 402 SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <= |
| 403 m_data->length()); |
| 404 break; |
| 405 |
| 406 case kUint16ArrayStorageFormat: |
| 407 m_dataU16 = |
| 408 const_cast<DOMUint16Array*>(static_cast<const DOMUint16Array*>(data)); |
| 409 m_dataUnion.setUint16Array(m_dataU16); |
| 410 SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <= |
| 411 m_dataU16->length()); |
| 412 break; |
| 413 |
| 414 case kFloat32ArrayStorageFormat: |
| 415 m_dataF32 = const_cast<DOMFloat32Array*>( |
| 416 static_cast<const DOMFloat32Array*>(data)); |
| 417 m_dataUnion.setFloat32Array(m_dataF32); |
| 418 SECURITY_CHECK(static_cast<unsigned>(size.width() * size.height() * 4) <= |
| 419 m_dataF32->length()); |
| 420 break; |
| 421 |
| 422 default: |
| 423 NOTREACHED(); |
| 424 } |
| 402 } | 425 } |
| 403 | 426 |
| 404 } // namespace blink | 427 } // namespace blink |
| OLD | NEW |