Home | History | Annotate | Download | only in html
      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