Changeset 127440 in webkit


Ignore:
Timestamp:
Sep 3, 2012 11:37:37 PM (12 years ago)
Author:
Simon Hausmann
Message:

[Qt] Port the Qt pixmap JS bindings to use the JSC C API
https://bugs.webkit.org/show_bug.cgi?id=94702

Reviewed by Kenneth Rohde Christiansen.

Based on patch by Noam Rosenthal.

The conversion uses a simple JSClassRef based binding and only a few
uses of private JSC API for the HTML element DOM bindings remain.

This is essentially used for wrapping QPixmap and QImage types in
JavaScript and the other way around, for retrieving the image data
out of a HTML image element when converting from JS/DOM to Qt.

  • bridge/qt/qt_pixmapruntime.cpp:

(JSC::Bindings::copyPixels):
(JSC::Bindings::toPixmap):
(JSC::Bindings::toImage):
(JSC::Bindings::imageSizeForVariant):
(JSC::Bindings::getPixmapWidth):
(JSC::Bindings::getPixmapHeight):
(JSC::Bindings::assignToHTMLImageElement):
(JSC::Bindings::pixmapToImageData):
(JSC::Bindings::pixmapToDataUrl):
(JSC::Bindings::pixmapToString):
(JSC::Bindings::QtPixmapRuntime::toJS):
(JSC::Bindings::QtPixmapRuntime::toQt):
(JSC::Bindings::QtPixmapRuntime::canHandle):
(JSC::Bindings::QtPixmapRuntime::getClassRef):

  • bridge/qt/qt_pixmapruntime.h:

(QtPixmapRuntime):

  • bridge/qt/qt_runtime.cpp:

(JSC::Bindings::convertValueToQVariant):
(JSC::Bindings::convertQVariantToValue):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r127438 r127440  
     12012-08-31  Simon Hausmann  <simon.hausmann@nokia.com>
     2
     3        [Qt] Port the Qt pixmap JS bindings to use the JSC C API
     4        https://bugs.webkit.org/show_bug.cgi?id=94702
     5
     6        Reviewed by Kenneth Rohde Christiansen.
     7
     8        Based on patch by Noam Rosenthal.
     9
     10        The conversion uses a simple JSClassRef based binding and only a few
     11        uses of private JSC API for the HTML element DOM bindings remain.
     12
     13        This is essentially used for wrapping QPixmap and QImage types in
     14        JavaScript and the other way around, for retrieving the image data
     15        out of a HTML image element when converting from JS/DOM to Qt.
     16
     17        * bridge/qt/qt_pixmapruntime.cpp:
     18        (JSC::Bindings::copyPixels):
     19        (JSC::Bindings::toPixmap):
     20        (JSC::Bindings::toImage):
     21        (JSC::Bindings::imageSizeForVariant):
     22        (JSC::Bindings::getPixmapWidth):
     23        (JSC::Bindings::getPixmapHeight):
     24        (JSC::Bindings::assignToHTMLImageElement):
     25        (JSC::Bindings::pixmapToImageData):
     26        (JSC::Bindings::pixmapToDataUrl):
     27        (JSC::Bindings::pixmapToString):
     28        (JSC::Bindings::QtPixmapRuntime::toJS):
     29        (JSC::Bindings::QtPixmapRuntime::toQt):
     30        (JSC::Bindings::QtPixmapRuntime::canHandle):
     31        (JSC::Bindings::QtPixmapRuntime::getClassRef):
     32        * bridge/qt/qt_pixmapruntime.h:
     33        (QtPixmapRuntime):
     34        * bridge/qt/qt_runtime.cpp:
     35        (JSC::Bindings::convertValueToQVariant):
     36        (JSC::Bindings::convertQVariantToValue):
     37
    1382012-09-03  Andreas Kling  <kling@webkit.org>
    239
  • trunk/Source/WebCore/bridge/qt/qt_pixmapruntime.cpp

    r127191 r127440  
    2020#include "qt_pixmapruntime.h"
    2121
     22#include "APICast.h"
    2223#include "CachedImage.h"
    2324#include "HTMLImageElement.h"
     
    2829#include "JSHTMLImageElement.h"
    2930#include "JSImageData.h"
    30 #include "JSLock.h"
    31 #include "ObjectPrototype.h"
     31#include "JSRetainPtr.h"
     32#include "JavaScript.h"
    3233#include "StillImageQt.h"
    3334#include <QtEndian>
     
    3839#include <QPixmap>
    3940#include <QVariant>
    40 #include <runtime_method.h>
    41 #include <runtime_object.h>
    42 #include <runtime_root.h>
    43 #include "runtime/FunctionPrototype.h"
    4441
    4542using namespace WebCore;
     
    4845namespace Bindings {
    4946
    50 class QtPixmapClass : public Class {
    51 public:
    52     QtPixmapClass();
    53     virtual MethodList methodsNamed(PropertyName, Instance*) const;
    54     virtual Field* fieldNamed(PropertyName, Instance*) const;
    55 };
    56 
    57 
    58 class QtPixmapWidthField : public Field {
    59 public:
    60     static const char* name() { return "width"; }
    61     virtual JSValue valueFromInstance(ExecState*, const Instance* instance) const
    62     {
    63         return jsNumber(static_cast<const QtPixmapInstance*>(instance)->width());
     47static void copyPixelsInto(const QImage& sourceImage, int width, int height, unsigned char* destPixels)
     48{
     49    QImage image(sourceImage);
     50    switch (image.format()) {
     51    case QImage::Format_RGB888:
     52        for (int y = 0; y < height; y++) {
     53            const uchar* scanLine = image.scanLine(y);
     54            for (int x = 0; x < width; x++) {
     55                *(destPixels++) = *(scanLine++);
     56                *(destPixels++) = *(scanLine++);
     57                *(destPixels++) = *(scanLine++);
     58                *(destPixels++) = 0xFF;
     59            }
     60        }
     61        break;
     62    default:
     63        image = image.convertToFormat(QImage::Format_ARGB32);
     64        // Fall through
     65    case QImage::Format_RGB32:
     66    case QImage::Format_ARGB32:
     67        for (int y = 0; y < height; y++) {
     68            const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(image.scanLine(y));
     69            for (int x = 0; x < width; x++) {
     70                QRgb pixel = scanLine[x];
     71                qToBigEndian<quint32>((pixel << 8) | qAlpha(pixel), destPixels);
     72                destPixels += 4;
     73            }
     74        }
     75        break;
    6476    }
    65     virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {}
    66 };
    67 
    68 class QtPixmapHeightField : public Field {
    69 public:
    70     static const char* name() { return "height"; }
    71     virtual JSValue valueFromInstance(ExecState*, const Instance* instance) const
    72     {
    73         return jsNumber(static_cast<const QtPixmapInstance*>(instance)->height());
    74     }
    75     virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {}
    76 };
    77 
    78 class QtPixmapRuntimeMethod : public Method {
    79 public:
    80     virtual int numParameters() const
    81     {
    82         return 0;
    83     }
    84     virtual JSValue invoke(ExecState* exec, QtPixmapInstance*) = 0;
    85 
    86 };
    87 
    88 class QtPixmapToImageDataMethod : public QtPixmapRuntimeMethod {
    89 public:
    90     static const char* name() { return "toImageData"; }
    91     JSValue invoke(ExecState* exec, QtPixmapInstance* instance)
    92     {
    93         int width = instance->width();
    94         int height = instance->height();
    95         RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
    96         copyPixels(instance->toImage(), width, height, imageData->data()->data());
    97         return toJS(exec, static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), imageData.get());
    98     }
    99 private:
    100     void copyPixels(const QImage& sourceImage, int width, int height, unsigned char* destPixels)
    101     {
    102         QImage image(sourceImage);
    103         switch (image.format()) {
    104         case QImage::Format_RGB888:
    105             for (int y = 0; y < height; y++) {
    106                 const uchar* scanLine = image.scanLine(y);
    107                 for (int x = 0; x < width; x++) {
    108                     *(destPixels++) = *(scanLine++);
    109                     *(destPixels++) = *(scanLine++);
    110                     *(destPixels++) = *(scanLine++);
    111                     *(destPixels++) = 0xFF;
    112                 }
    113             }
    114             break;
    115         default:
    116             image = image.convertToFormat(QImage::Format_ARGB32);
    117             // Fall through
    118         case QImage::Format_RGB32:
    119         case QImage::Format_ARGB32:
    120             for (int y = 0; y < height; y++) {
    121                 const quint32* scanLine = reinterpret_cast_ptr<const quint32*>(image.scanLine(y));
    122                 for (int x = 0; x < width; x++) {
    123                     QRgb pixel = scanLine[x];
    124                     qToBigEndian<quint32>((pixel << 8) | qAlpha(pixel), destPixels);
    125                     destPixels += 4;
    126                 }
    127             }
    128             break;
    129         }
    130     }
    131 };
    132 
    133 // this function receives an HTML image element as a parameter, makes it display the pixmap/image from Qt
    134 class QtPixmapAssignToElementMethod : public QtPixmapRuntimeMethod {
    135 public:
    136     static const char* name() { return "assignToHTMLImageElement"; }
    137     JSValue invoke(ExecState* exec, QtPixmapInstance* instance)
    138     {
    139         if (!exec->argumentCount())
    140             return jsUndefined();
    141 
    142         JSObject* objectArg = exec->argument(0).toObject(exec);
    143         if (!objectArg)
    144             return jsUndefined();
    145 
    146         if (!objectArg->inherits(&JSHTMLImageElement::s_info))
    147             return jsUndefined();
    148 
    149         // we now know that we have a valid <img> element as the argument, we can attach the image to it.
    150         RefPtr<StillImage> stillImage = WebCore::StillImage::create(instance->toImage());
    151         HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(objectArg)->impl());
    152         imageElement->setCachedImage(new CachedImage(stillImage.get()));
    153         JSDOMGlobalObject* global = static_cast<JSDOMGlobalObject*>(instance->rootObject()->globalObject());
    154         toJS(exec, global, imageElement->document());
    155         return jsUndefined();
    156     }
    157 
    158     virtual int numParameters() const
    159     {
    160         return 1;
    161     }
    162 };
    163 
    164 // this function encodes the image to a dataUrl, to be used in background etc. Note: very slow.
    165 class QtPixmapToDataUrlMethod : public QtPixmapRuntimeMethod {
    166 public:
    167     static const char* name() { return "toDataUrl"; }
    168     JSValue invoke(ExecState* exec, QtPixmapInstance* instance)
    169     {
    170         QByteArray byteArray;
    171         QBuffer buffer(&byteArray);
    172         instance->toImage().save(&buffer, "PNG");
    173         const QString encodedString = QLatin1String("data:image/png;base64,") + QLatin1String(byteArray.toBase64());
    174         const String ustring((UChar*)encodedString.utf16(), encodedString.length());
    175         return JSC::jsString(exec, ustring);
    176     }
    177 };
    178 
    179 class QtPixmapToStringMethod : public QtPixmapRuntimeMethod {
    180     public:
    181     static const char* name() { return "toString"; }
    182     JSValue invoke(ExecState* exec, QtPixmapInstance* instance)
    183     {
    184         return instance->valueOf(exec);
    185     }
    186 };
    187 
    188 struct QtPixmapMetaData {
    189     QtPixmapToDataUrlMethod toDataUrlMethod;
    190     QtPixmapToImageDataMethod toImageDataMethod;
    191     QtPixmapAssignToElementMethod assignToElementMethod;
    192     QtPixmapToStringMethod toStringMethod;
    193     QtPixmapHeightField heightField;
    194     QtPixmapWidthField widthField;
    195     QtPixmapClass cls;
    196 } qt_pixmap_metaData;
    197 
    198 // Derived RuntimeObject
    199 class QtPixmapRuntimeObject : public RuntimeObject {
    200 public:
    201     typedef RuntimeObject Base;
    202 
    203     static QtPixmapRuntimeObject* create(ExecState* exec, JSGlobalObject* globalObject, PassRefPtr<Instance> instance)
    204     {
    205         Structure* domStructure = WebCore::deprecatedGetDOMStructure<QtPixmapRuntimeObject>(exec);
    206         QtPixmapRuntimeObject* object = new (allocateCell<QtPixmapRuntimeObject>(*exec->heap())) QtPixmapRuntimeObject(exec, globalObject, domStructure, instance);
    207         object->finishCreation(globalObject);
    208         return object;
    209     }
    210 
    211     static const ClassInfo s_info;
    212 
    213     static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype)
    214     {
    215         return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType,  StructureFlags), &s_info);
    216     }
    217 
    218 protected:
    219     static const unsigned StructureFlags = RuntimeObject::StructureFlags | OverridesVisitChildren;
    220 
    221 private:
    222     QtPixmapRuntimeObject(ExecState*, JSGlobalObject*, Structure*, PassRefPtr<Instance>);
    223 };
    224 
    225 QtPixmapRuntimeObject::QtPixmapRuntimeObject(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, PassRefPtr<Instance> instance)
    226     : RuntimeObject(exec, globalObject, structure, instance)
    227 {
    228 }
    229 
    230 const ClassInfo QtPixmapRuntimeObject::s_info = { "QtPixmapRuntimeObject", &RuntimeObject::s_info, 0, 0, CREATE_METHOD_TABLE(QtPixmapRuntimeObject) };
    231 
    232 QtPixmapClass::QtPixmapClass()
    233 {
    234 }
    235 
    236 
    237 Class* QtPixmapInstance::getClass() const
    238 {
    239     return &qt_pixmap_metaData.cls;
    240 }
    241 
    242 JSValue QtPixmapInstance::getMethod(ExecState* exec, PropertyName propertyName)
    243 {
    244     MethodList methodList = getClass()->methodsNamed(propertyName, this);
    245     return RuntimeMethod::create(exec, exec->lexicalGlobalObject(), WebCore::deprecatedGetDOMStructure<RuntimeMethod>(exec), propertyName.publicName(), methodList);
    246 }
    247 
    248 JSValue QtPixmapInstance::invokeMethod(ExecState* exec, RuntimeMethod* runtimeMethod)
    249 {
    250     const MethodList& methods = *runtimeMethod->methods();
    251 
    252     if (methods.size() == 1) {
    253         QtPixmapRuntimeMethod* method = static_cast<QtPixmapRuntimeMethod*>(methods[0]);
    254         return method->invoke(exec, this);
    255     }
    256     return jsUndefined();
    257 }
    258 
    259 MethodList QtPixmapClass::methodsNamed(PropertyName identifier, Instance*) const
    260 {
    261     MethodList methods;
    262     String ustring(identifier.publicName());
    263     if (ustring == QtPixmapToDataUrlMethod::name())
    264         methods.append(&qt_pixmap_metaData.toDataUrlMethod);
    265     else if (ustring == QtPixmapToImageDataMethod::name())
    266         methods.append(&qt_pixmap_metaData.toImageDataMethod);
    267     else if (ustring == QtPixmapAssignToElementMethod::name())
    268         methods.append(&qt_pixmap_metaData.assignToElementMethod);
    269     else if (ustring == QtPixmapToStringMethod::name())
    270         methods.append(&qt_pixmap_metaData.toStringMethod);
    271     return methods;
    272 }
    273 
    274 Field* QtPixmapClass::fieldNamed(PropertyName identifier, Instance*) const
    275 {
    276     String ustring(identifier.publicName());
    277     if (ustring == QtPixmapWidthField::name())
    278         return &qt_pixmap_metaData.widthField;
    279     if (ustring == QtPixmapHeightField::name())
    280         return &qt_pixmap_metaData.heightField;
    281     return 0;
    282 }
    283 
    284 void QtPixmapInstance::getPropertyNames(ExecState*exec, PropertyNameArray& arr)
    285 {
    286     arr.add(Identifier(exec, String(QtPixmapToDataUrlMethod::name())));
    287     arr.add(Identifier(exec, String(QtPixmapToImageDataMethod::name())));
    288     arr.add(Identifier(exec, String(QtPixmapAssignToElementMethod::name())));
    289     arr.add(Identifier(exec, String(QtPixmapToStringMethod::name())));
    290     arr.add(Identifier(exec, String(QtPixmapWidthField::name())));
    291     arr.add(Identifier(exec, String(QtPixmapHeightField::name())));
    292 }
    293 
    294 JSValue QtPixmapInstance::defaultValue(ExecState* exec, PreferredPrimitiveType ptype) const
    295 {
    296     if (ptype == PreferNumber) {
    297         return jsBoolean(
    298                 (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()) && !(data.value<QImage>()).isNull())
    299                 || (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()) && !data.value<QPixmap>().isNull()));
    300     }
    301 
    302     if (ptype == PreferString)
    303         return valueOf(exec);
    304 
    305     return jsUndefined();
    306 }
    307 
    308 JSValue QtPixmapInstance::valueOf(ExecState* exec) const
    309 {
    310     const QString stringValue = QString::fromLatin1("[Qt Native Pixmap %1,%2]").arg(width()).arg(height());
    311     String ustring((UChar*)stringValue.utf16(), stringValue.length());
    312     return JSC::jsString(exec, ustring);
    313 }
    314 
    315 QtPixmapInstance::QtPixmapInstance(PassRefPtr<RootObject> rootObj, const QVariant& d)
    316         :Instance(rootObj), data(d)
    317 {
    318 }
    319 
    320 int QtPixmapInstance::width() const
    321 {
    322     if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
    323         return data.value<QPixmap>().width();
    324     if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
    325         return data.value<QImage>().width();
    326     return 0;
    327 }
    328 
    329 int QtPixmapInstance::height() const
    330 {
    331     if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
    332         return data.value<QPixmap>().height();
    333     if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
    334         return data.value<QImage>().height();
    335     return 0;
    336 }
    337 
    338 QPixmap QtPixmapInstance::toPixmap()
     77}
     78
     79static QPixmap toPixmap(const QVariant& data)
    33980{
    34081    if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
    34182        return data.value<QPixmap>();
    34283
    343     if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) {
    344         const QPixmap pixmap = QPixmap::fromImage(data.value<QImage>());
    345         data = QVariant::fromValue<QPixmap>(pixmap);
    346         return pixmap;
    347     }
     84    if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
     85        return QPixmap::fromImage(data.value<QImage>());
    34886
    34987    return QPixmap();
    35088}
    35189
    352 QImage QtPixmapInstance::toImage()
     90static QImage toImage(const QVariant& data)
    35391{
    35492    if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
    35593        return data.value<QImage>();
    35694
    357     if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) {
    358         const QImage image = data.value<QPixmap>().toImage();
    359         data = QVariant::fromValue<QImage>(image);
    360         return image;
     95    if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
     96        return data.value<QPixmap>().toImage();
     97
     98    return QImage();
     99}
     100
     101static QSize imageSizeForVariant(const QVariant& data)
     102{
     103    if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()))
     104        return data.value<QPixmap>().size();
     105    if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()))
     106        return data.value<QImage>().size();
     107    return QSize(0, 0);
     108}
     109
     110static JSValueRef getPixmapWidth(JSContextRef context, JSObjectRef object, JSStringRef, JSValueRef*)
     111{
     112    QVariant& data = *static_cast<QVariant*>(JSObjectGetPrivate(object));
     113    return JSValueMakeNumber(context, imageSizeForVariant(data).width());
     114}
     115
     116static JSValueRef getPixmapHeight(JSContextRef context, JSObjectRef object, JSStringRef, JSValueRef*)
     117{
     118    QVariant& data = *static_cast<QVariant*>(JSObjectGetPrivate(object));
     119    return JSValueMakeNumber(context, imageSizeForVariant(data).height());
     120}
     121
     122static JSValueRef assignToHTMLImageElement(JSContextRef context, JSObjectRef function, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
     123{
     124    if (!argumentCount)
     125        return JSValueMakeUndefined(context);
     126
     127    JSObjectRef objectArg = JSValueToObject(context, arguments[0], exception);
     128    if (!objectArg)
     129        return JSValueMakeUndefined(context);
     130
     131    JSObject* jsObject = ::toJS(objectArg);
     132
     133    if (!jsObject->inherits(&JSHTMLImageElement::s_info))
     134        return JSValueMakeUndefined(context);
     135
     136    QVariant& data = *static_cast<QVariant*>(JSObjectGetPrivate(object));
     137
     138    // We now know that we have a valid <img> element as the argument, we can attach the image to it.
     139    RefPtr<StillImage> stillImage = WebCore::StillImage::create(toImage(data));
     140    HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(jsObject)->impl());
     141    imageElement->setCachedImage(new CachedImage(stillImage.get()));
     142    return JSValueMakeUndefined(context);
     143}
     144
     145static JSValueRef pixmapToImageData(JSContextRef context, JSObjectRef function, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
     146{
     147    QVariant& data = *static_cast<QVariant*>(JSObjectGetPrivate(object));
     148    QImage image = toImage(data);
     149    int width = image.width();
     150    int height = image.height();
     151
     152    RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
     153    copyPixelsInto(image, width, height, imageData->data()->data());
     154    JSDOMGlobalObject* globalObject = static_cast<JSDOMGlobalObject*>(::toJS(JSContextGetGlobalObject(context)));
     155    JSC::ExecState* exec = ::toJS(context);
     156    return ::toRef(exec, toJS(exec, globalObject, imageData.get()));
     157}
     158
     159static JSValueRef pixmapToDataUrl(JSContextRef context, JSObjectRef function, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
     160{
     161    QVariant& data = *static_cast<QVariant*>(JSObjectGetPrivate(object));
     162    QByteArray byteArray;
     163    QBuffer buffer(&byteArray);
     164    toImage(data).save(&buffer, "PNG");
     165    QByteArray encoded = QByteArray("data:image/png;base64,") + byteArray.toBase64();
     166    JSRetainPtr<JSStringRef> str(Adopt, JSStringCreateWithUTF8CString(encoded.constData()));
     167    JSValueRef value = JSValueMakeString(context, str.get());
     168
     169    return value;
     170}
     171
     172static JSValueRef pixmapToString(JSContextRef context, JSObjectRef function, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
     173{
     174    QVariant& data = *static_cast<QVariant*>(JSObjectGetPrivate(object));
     175    QSize size = imageSizeForVariant(data);
     176    QString stringValue = QString::fromLatin1("[Qt Native Pixmap %1,%2]").arg(size.width()).arg(size.height());
     177    JSRetainPtr<JSStringRef> str(Adopt, JSStringCreateWithUTF8CString(stringValue.toUtf8().constData()));
     178    JSValueRef value = JSValueMakeString(context, str.get());
     179
     180    return value;
     181}
     182
     183static void finalizePixmap(JSObjectRef object)
     184{
     185    delete static_cast<QVariant*>(JSObjectGetPrivate(object));
     186}
     187
     188JSObjectRef QtPixmapRuntime::toJS(JSContextRef context, const QVariant& value, JSValueRef* exception)
     189{
     190    return JSObjectMake(context, getClassRef(), new QVariant(value));
     191}
     192
     193static QVariant emptyVariantForHint(QMetaType::Type hint)
     194{
     195    if (hint == qMetaTypeId<QPixmap>())
     196        return QVariant::fromValue(QPixmap());
     197    if (hint == qMetaTypeId<QImage>())
     198        return QVariant::fromValue(QImage());
     199    return QVariant();
     200}
     201
     202QVariant QtPixmapRuntime::toQt(JSContextRef context, JSObjectRef obj, QMetaType::Type hint, JSValueRef* exception)
     203{
     204    if (!obj)
     205        return emptyVariantForHint(hint);
     206
     207    if (JSValueIsObjectOfClass(context, obj, QtPixmapRuntime::getClassRef())) {
     208        QVariant* originalVariant = static_cast<QVariant*>(JSObjectGetPrivate(obj));
     209        if (hint == qMetaTypeId<QPixmap>())
     210            return QVariant::fromValue<QPixmap>(toPixmap(*originalVariant));
     211
     212        if (hint == qMetaTypeId<QImage>())
     213            return QVariant::fromValue<QImage>(toImage(*originalVariant));
    361214    }
    362215
    363     return QImage();
    364 }
    365 
    366 QVariant QtPixmapInstance::variantFromObject(JSObject* object, QMetaType::Type hint)
    367 {
    368     if (!object)
    369         goto returnEmptyVariant;
    370 
    371     if (object->inherits(&JSHTMLImageElement::s_info)) {
    372         JSHTMLImageElement* elementJSWrapper = static_cast<JSHTMLImageElement*>(object);
    373         HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(elementJSWrapper->impl());
    374 
    375         if (!imageElement)
    376             goto returnEmptyVariant;
    377 
    378         CachedImage* cachedImage = imageElement->cachedImage();
    379         if (!cachedImage)
    380             goto returnEmptyVariant;
    381 
    382         Image* image = cachedImage->imageForRenderer(imageElement->renderer());
    383         if (!image)
    384             goto returnEmptyVariant;
    385 
    386         QImage* nativeImage = image->nativeImageForCurrentFrame();
    387         if (!nativeImage)
    388             goto returnEmptyVariant;
    389 
    390         return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>()))
    391                   ? QVariant::fromValue<QPixmap>(QPixmap::fromImage(*nativeImage))
    392                   : QVariant::fromValue<QImage>(*nativeImage);
    393     }
    394 
    395     if (object->inherits(&QtPixmapRuntimeObject::s_info)) {
    396         QtPixmapRuntimeObject* runtimeObject = static_cast<QtPixmapRuntimeObject*>(object);
    397         QtPixmapInstance* instance = static_cast<QtPixmapInstance*>(runtimeObject->getInternalInstance());
    398         if (!instance)
    399             goto returnEmptyVariant;
    400 
    401         if (hint == qMetaTypeId<QPixmap>())
    402             return QVariant::fromValue<QPixmap>(instance->toPixmap());
    403 
    404         if (hint == qMetaTypeId<QImage>())
    405             return QVariant::fromValue<QImage>(instance->toImage());
    406     }
    407 
    408 returnEmptyVariant:
    409     if (hint == qMetaTypeId<QPixmap>())
    410         return QVariant::fromValue<QPixmap>(QPixmap());
    411     if (hint == qMetaTypeId<QImage>())
    412         return QVariant::fromValue<QImage>(QImage());
    413     return QVariant();
    414 }
    415 
    416 RuntimeObject* QtPixmapInstance::newRuntimeObject(ExecState* exec)
    417 {
    418     return QtPixmapRuntimeObject::create(exec, exec->lexicalGlobalObject(), this);
    419 }
    420 
    421 JSObject* QtPixmapInstance::createPixmapRuntimeObject(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& data)
    422 {
    423     JSLockHolder lock(exec);
    424     RefPtr<QtPixmapInstance> instance = adoptRef(new QtPixmapInstance(root, data));
    425     return instance->createRuntimeObject(exec);
    426 }
    427 
    428 bool QtPixmapInstance::canHandle(QMetaType::Type hint)
     216    JSObject* jsObject = ::toJS(obj);
     217    if (!jsObject->inherits(&JSHTMLImageElement::s_info))
     218        return emptyVariantForHint(hint);
     219
     220    JSHTMLImageElement* elementJSWrapper = static_cast<JSHTMLImageElement*>(jsObject);
     221    HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(elementJSWrapper->impl());
     222
     223    if (!imageElement)
     224        return emptyVariantForHint(hint);
     225
     226    CachedImage* cachedImage = imageElement->cachedImage();
     227    if (!cachedImage)
     228        return emptyVariantForHint(hint);
     229
     230    Image* image = cachedImage->imageForRenderer(imageElement->renderer());
     231    if (!image)
     232        return emptyVariantForHint(hint);
     233
     234    QImage* nativeImage = image->nativeImageForCurrentFrame();
     235    if (!nativeImage)
     236        return emptyVariantForHint(hint);
     237
     238    return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>()))
     239              ? QVariant::fromValue<QPixmap>(QPixmap::fromImage(*nativeImage))
     240              : QVariant::fromValue<QImage>(*nativeImage);
     241}
     242
     243bool QtPixmapRuntime::canHandle(QMetaType::Type hint)
    429244{
    430245    return hint == qMetaTypeId<QImage>() || hint == qMetaTypeId<QPixmap>();
    431246}
    432247
    433 }
    434 
    435 }
     248JSClassRef QtPixmapRuntime::getClassRef()
     249{
     250    static const JSStaticValue staticValues[] = {
     251        { "width", getPixmapWidth, 0, 0 },
     252        { "height", getPixmapHeight, 0, 0 }
     253    };
     254
     255    static const JSStaticFunction staticFunctions[] = {
     256        { "assignTo", assignToHTMLImageElement, 0 },
     257        { "toDataUrl", pixmapToDataUrl, 0 },
     258        { "toImageData", pixmapToImageData, 0 },
     259        { "toString", pixmapToString, 0 }
     260    };
     261
     262    static const JSClassDefinition classDefinition = {
     263        0, 0, "QtPixmapRuntimeObject", 0, staticValues, staticFunctions,
     264        0, finalizePixmap, 0, 0, 0, 0, 0, 0, 0, 0, 0
     265    };
     266
     267    static JSClassRef classRef = JSClassCreate(&classDefinition);
     268    return classRef;
     269}
     270
     271
     272}
     273
     274}
  • trunk/Source/WebCore/bridge/qt/qt_pixmapruntime.h

    r116828 r127440  
    2222
    2323#include "BridgeJSC.h"
     24#include "JavaScript.h"
    2425#include <QVariant>
    2526
     
    2829namespace Bindings {
    2930
    30 class QtPixmapInstance : public Instance {
    31     QVariant data;
     31class QtPixmapRuntime {
    3232public:
    33     QtPixmapInstance(PassRefPtr<RootObject> rootObj, const QVariant& newData);
    34     virtual Class* getClass() const;
    35     virtual JSValue getMethod(ExecState*, PropertyName);
    36     virtual JSValue invokeMethod(ExecState*, RuntimeMethod*);
    37     virtual void getPropertyNames(ExecState*, PropertyNameArray&);
     33    static JSObjectRef toJS(JSContextRef, const QVariant&, JSValueRef* exception);
     34    static QVariant toQt(JSContextRef, JSObjectRef, QMetaType::Type hint, JSValueRef* exception);
     35    static bool canHandle(QMetaType::Type hint);
    3836
    39     virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const;
    40     virtual JSValue valueOf(ExecState*) const;
    41     int width() const;
    42     int height() const;
    43     QPixmap toPixmap();
    44     QImage toImage();
    45     RuntimeObject* newRuntimeObject(ExecState*);
    46     static JSObject* createPixmapRuntimeObject(ExecState*, PassRefPtr<RootObject>, const QVariant&);
    47     static QVariant variantFromObject(JSObject*, QMetaType::Type hint);
    48     static bool canHandle(QMetaType::Type hint);
     37    static JSClassRef getClassRef();
    4938};
    5039
  • trunk/Source/WebCore/bridge/qt/qt_runtime.cpp

    r127238 r127440  
    624624                break;
    625625            }
    626             if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(hint))) {
    627                 ret = QtPixmapInstance::variantFromObject(toJS(object), static_cast<QMetaType::Type>(hint));
     626            if (QtPixmapRuntime::canHandle(static_cast<QMetaType::Type>(hint))) {
     627                ret = QtPixmapRuntime::toQt(context, object, static_cast<QMetaType::Type>(hint), exception);
    628628            } else if (customRuntimeConversions()->contains(hint)) {
    629629                ret = customRuntimeConversions()->value(hint).toVariantFunc(toJS(object), &dist, visitedObjects);
     
    741741    }
    742742
    743     if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type()))) {
    744         ExecState* exec = toJS(context);
    745         return toRef(exec, QtPixmapInstance::createPixmapRuntimeObject(exec, root, variant));
    746     }
     743    if (QtPixmapRuntime::canHandle(static_cast<QMetaType::Type>(variant.type())))
     744        return QtPixmapRuntime::toJS(context, variant, exception);
    747745
    748746    if (customRuntimeConversions()->contains(type)) {
Note: See TracChangeset for help on using the changeset viewer.