1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "config.h" 30 #include "core/html/ImageData.h" 31 32 #include "bindings/core/v8/ExceptionState.h" 33 #include "bindings/core/v8/custom/V8Uint8ClampedArrayCustom.h" 34 #include "core/dom/ExceptionCode.h" 35 #include "platform/RuntimeEnabledFeatures.h" 36 37 namespace blink { 38 39 PassRefPtrWillBeRawPtr<ImageData> ImageData::create(const IntSize& size) 40 { 41 Checked<int, RecordOverflow> dataSize = 4; 42 dataSize *= size.width(); 43 dataSize *= size.height(); 44 if (dataSize.hasOverflowed()) 45 return nullptr; 46 47 return adoptRefWillBeNoop(new ImageData(size)); 48 } 49 50 PassRefPtrWillBeRawPtr<ImageData> ImageData::create(const IntSize& size, PassRefPtr<Uint8ClampedArray> byteArray) 51 { 52 Checked<int, RecordOverflow> dataSize = 4; 53 dataSize *= size.width(); 54 dataSize *= size.height(); 55 if (dataSize.hasOverflowed()) 56 return nullptr; 57 58 if (dataSize.unsafeGet() < 0 59 || static_cast<unsigned>(dataSize.unsafeGet()) > byteArray->length()) 60 return nullptr; 61 62 return adoptRefWillBeNoop(new ImageData(size, byteArray)); 63 } 64 65 PassRefPtrWillBeRawPtr<ImageData> ImageData::create(unsigned width, unsigned height, ExceptionState& exceptionState) 66 { 67 if (!RuntimeEnabledFeatures::imageDataConstructorEnabled()) { 68 exceptionState.throwTypeError("Illegal constructor"); 69 return nullptr; 70 } 71 if (!width || !height) { 72 exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is zero or not a number.", width ? "height" : "width")); 73 return nullptr; 74 } 75 76 Checked<unsigned, RecordOverflow> dataSize = 4; 77 dataSize *= width; 78 dataSize *= height; 79 if (dataSize.hasOverflowed()) { 80 exceptionState.throwDOMException(IndexSizeError, "The requested image size exceeds the supported range."); 81 return nullptr; 82 } 83 84 RefPtrWillBeRawPtr<ImageData> imageData = adoptRefWillBeNoop(new ImageData(IntSize(width, height))); 85 imageData->data()->zeroFill(); 86 return imageData.release(); 87 } 88 89 PassRefPtrWillBeRawPtr<ImageData> ImageData::create(Uint8ClampedArray* data, unsigned width, unsigned height, ExceptionState& exceptionState) 90 { 91 if (!RuntimeEnabledFeatures::imageDataConstructorEnabled()) { 92 exceptionState.throwTypeError("Illegal constructor"); 93 return nullptr; 94 } 95 if (!data) { 96 exceptionState.throwTypeError("Expected a Uint8ClampedArray as first argument."); 97 return nullptr; 98 } 99 if (!width) { 100 exceptionState.throwDOMException(IndexSizeError, "The source width is zero or not a number."); 101 return nullptr; 102 } 103 104 unsigned length = data->length(); 105 if (!length) { 106 exceptionState.throwDOMException(IndexSizeError, "The input data has a zero byte length."); 107 return nullptr; 108 } 109 if (length % 4) { 110 exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not a multiple of 4."); 111 return nullptr; 112 } 113 length /= 4; 114 if (length % width) { 115 exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not a multiple of (4 * width)."); 116 return nullptr; 117 } 118 if (!height) { 119 height = length / width; 120 } else if (height != length / width) { 121 exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not equal to (4 * width * height)."); 122 return nullptr; 123 } 124 125 return adoptRefWillBeNoop(new ImageData(IntSize(width, height), data)); 126 } 127 128 v8::Handle<v8::Object> ImageData::associateWithWrapper(const WrapperTypeInfo* wrapperType, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate) 129 { 130 ScriptWrappable::associateWithWrapper(wrapperType, wrapper, isolate); 131 132 if (!wrapper.IsEmpty()) { 133 // Create a V8 Uint8ClampedArray object. 134 v8::Handle<v8::Value> pixelArray = toV8(data(), wrapper, isolate); 135 // Set the "data" property of the ImageData object to 136 // the created v8 object, eliminating the C++ callback 137 // when accessing the "data" property. 138 if (!pixelArray.IsEmpty()) 139 wrapper->ForceSet(v8AtomicString(isolate, "data"), pixelArray, v8::ReadOnly); 140 } 141 return wrapper; 142 } 143 144 ImageData::ImageData(const IntSize& size) 145 : m_size(size) 146 , m_data(Uint8ClampedArray::create(size.width() * size.height() * 4)) 147 { 148 } 149 150 ImageData::ImageData(const IntSize& size, PassRefPtr<Uint8ClampedArray> byteArray) 151 : m_size(size) 152 , m_data(byteArray) 153 { 154 ASSERT_WITH_SECURITY_IMPLICATION(static_cast<unsigned>(size.width() * size.height() * 4) <= m_data->length()); 155 } 156 157 } // namespace blink 158