Home | History | Annotate | Download | only in custom
      1 /*
      2  * Copyright (C) 2009 Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 
     33 #if ENABLE(3D_CANVAS)
     34 
     35 #include "WebGLArrayBuffer.h"
     36 
     37 #include "V8Binding.h"
     38 #include "V8WebGLArrayBuffer.h"
     39 #include "V8Proxy.h"
     40 
     41 namespace WebCore {
     42 
     43 // Template function used by the WebGLArray*Constructor callbacks.
     44 template<class ArrayClass>
     45 v8::Handle<v8::Value> constructWebGLArray(const v8::Arguments& args,
     46                                           int classIndex)
     47 {
     48     if (!args.IsConstructCall())
     49         return throwError("DOM object constructor cannot be called as a function.");
     50 
     51     int argLen = args.Length();
     52     if (argLen == 0) {
     53         // This happens when we return a previously constructed
     54         // WebGLArray, e.g. from the call to WebGL<T>Array.slice().
     55         // The V8DOMWrapper will set the internal pointer in the
     56         // created object. Unfortunately it doesn't look like it's
     57         // possible to distinguish between this case and that where
     58         // the user calls "new WebGL<T>Array()" from JavaScript.
     59         return args.Holder();
     60     }
     61 
     62     // Supported constructors:
     63     // WebGL<T>Array(n) where n is an integer:
     64     //   -- create an empty array of n elements
     65     // WebGL<T>Array(arr) where arr is an array:
     66     //   -- create a WebGL<T>Array containing the contents of "arr"
     67     // WebGL<T>Array(buf, offset, length)
     68     //   -- create a WebGL<T>Array pointing to the WebGLArrayBuffer
     69     //      "buf", starting at the specified offset, for the given
     70     //      length
     71 
     72     // See whether the first argument is a WebGLArrayBuffer.
     73     if (V8WebGLArrayBuffer::HasInstance(args[0])) {
     74         if (argLen > 3)
     75             return throwError("Wrong number of arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)");
     76 
     77         WebGLArrayBuffer* buf = V8WebGLArrayBuffer::toNative(args[0]->ToObject());
     78         if (buf == NULL)
     79             return throwError("Could not convert argument 0 to a WebGLArrayBuffer");
     80         bool ok;
     81         int offset = 0;
     82         if (argLen > 1) {
     83             offset = toInt32(args[1], ok);
     84             if (!ok)
     85                 return throwError("Could not convert argument 1 to an integer");
     86         }
     87         int length = buf->byteLength() - offset;
     88         if (argLen > 2) {
     89             length = toInt32(args[2], ok);
     90             if (!ok)
     91                 return throwError("Could not convert argument 2 to an integer");
     92         }
     93         if (length < 0)
     94             return throwError("Length / offset out of range");
     95 
     96         RefPtr<ArrayClass> array = ArrayClass::create(buf, offset, length);
     97         if (array == NULL)
     98             return throwError("Invalid arguments to new WebGL<T>Array(WebGLArrayBuffer, int, int)");
     99         // Transform the holder into a wrapper object for the array.
    100         V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get());
    101         V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(),
    102                                                           classIndex,
    103                                                           array.get()->baseAddress(),
    104                                                           array.get()->length());
    105         return toV8(array.release(), args.Holder());
    106     }
    107 
    108     int len = 0;
    109     v8::Handle<v8::Object> srcArray;
    110     if (argLen != 1)
    111         return throwError("Wrong number of arguments to new WebGL<T>Array(int / array)");
    112 
    113     if (args[0]->IsInt32()) {
    114         len = toInt32(args[0]);
    115     } else if (args[0]->IsObject()) {
    116         srcArray = args[0]->ToObject();
    117         if (srcArray.IsEmpty())
    118             return throwError("Could not convert argument 0 to an object");
    119         len = toInt32(srcArray->Get(v8::String::New("length")));
    120     } else
    121         return throwError("Could not convert argument 0 to either an int32 or an object");
    122 
    123     RefPtr<ArrayClass> array = ArrayClass::create(len);
    124     if (!srcArray.IsEmpty()) {
    125         // Need to copy the incoming array into the newly created WebGLArray.
    126         for (int i = 0; i < len; i++) {
    127             v8::Local<v8::Value> val = srcArray->Get(v8::Integer::New(i));
    128             array->set(i, val->NumberValue());
    129         }
    130     }
    131 
    132     // Transform the holder into a wrapper object for the array.
    133     V8DOMWrapper::setDOMWrapper(args.Holder(), classIndex, array.get());
    134     V8DOMWrapper::setIndexedPropertiesToExternalArray(args.Holder(),
    135                                                       classIndex,
    136                                                       array.get()->baseAddress(),
    137                                                       array.get()->length());
    138     return toV8(array.release(), args.Holder());
    139 }
    140 
    141 template <class T, typename ElementType>
    142 v8::Handle<v8::Value> getWebGLArrayElement(const v8::Arguments& args,
    143                                            V8ClassIndex::V8WrapperType wrapperType)
    144 {
    145     if (args.Length() != 1) {
    146         V8Proxy::setDOMException(SYNTAX_ERR);
    147         return notHandledByInterceptor();
    148     }
    149     bool ok;
    150     uint32_t index = toInt32(args[0], ok);
    151     if (!ok) {
    152         V8Proxy::setDOMException(SYNTAX_ERR);
    153         return notHandledByInterceptor();
    154     }
    155     T* array = reinterpret_cast<T*>(args.Holder()->GetPointerFromInternalField(v8DOMWrapperObjectIndex));
    156     if (index >= array->length())
    157         return v8::Undefined();
    158     ElementType result;
    159     if (!array->get(index, result))
    160         return v8::Undefined();
    161     return v8::Number::New(result);
    162 }
    163 
    164 template <class T>
    165 v8::Handle<v8::Value> setWebGLArrayFromArray(T* webGLArray, const v8::Arguments& args)
    166 {
    167     if (args[0]->IsObject()) {
    168         // void set(in sequence<long> array, [Optional] in unsigned long offset);
    169         v8::Local<v8::Object> array = args[0]->ToObject();
    170         uint32_t offset = 0;
    171         if (args.Length() == 2)
    172             offset = toInt32(args[1]);
    173         uint32_t length = toInt32(array->Get(v8::String::New("length")));
    174         if (offset + length > webGLArray->length())
    175             V8Proxy::setDOMException(INDEX_SIZE_ERR);
    176         else
    177             for (uint32_t i = 0; i < length; i++)
    178                 webGLArray->set(offset + i, array->Get(v8::Integer::New(i))->NumberValue());
    179     }
    180 
    181     return v8::Undefined();
    182 }
    183 
    184 template <class CPlusPlusArrayType, class JavaScriptWrapperArrayType>
    185 v8::Handle<v8::Value> setWebGLArray(const v8::Arguments& args,
    186                                     V8ClassIndex::V8WrapperType wrapperType)
    187 {
    188     if (args.Length() < 1 || args.Length() > 2) {
    189         V8Proxy::setDOMException(SYNTAX_ERR);
    190         return notHandledByInterceptor();
    191     }
    192 
    193     CPlusPlusArrayType* array = JavaScriptWrapperArrayType::toNative(args.Holder());
    194 
    195     if (args.Length() == 2 && args[0]->IsInt32()) {
    196         // void set(in unsigned long index, in {long|float} value);
    197         uint32_t index = toInt32(args[0]);
    198         array->set(index, args[1]->NumberValue());
    199         return v8::Undefined();
    200     }
    201 
    202     if (JavaScriptWrapperArrayType::HasInstance(args[0])) {
    203         // void set(in WebGL<T>Array array, [Optional] in unsigned long offset);
    204         CPlusPlusArrayType* src = JavaScriptWrapperArrayType::toNative(args[0]->ToObject());
    205         uint32_t offset = 0;
    206         if (args.Length() == 2)
    207             offset = toInt32(args[1]);
    208         ExceptionCode ec = 0;
    209         array->set(src, offset, ec);
    210         V8Proxy::setDOMException(ec);
    211         return v8::Undefined();
    212     }
    213 
    214     return setWebGLArrayFromArray(array, args);
    215 }
    216 
    217 }
    218 
    219 #endif // ENABLE(3D_CANVAS)
    220