WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2007, 2008, 2009 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  * 1. Redistributions of source code must retain the above copyright
       
     8  *    notice, this list of conditions and the following disclaimer.
       
     9  * 2. Redistributions in binary form must reproduce the above copyright
       
    10  *    notice, this list of conditions and the following disclaimer in the
       
    11  *    documentation and/or other materials provided with the distribution.
       
    12  *
       
    13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
       
    14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       
    15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       
    16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
       
    17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
       
    18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
       
    19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
       
    20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
       
    21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "JSCSSStyleDeclarationCustom.h"
       
    28 
       
    29 #include "AtomicString.h"
       
    30 #include "CSSMutableStyleDeclaration.h"
       
    31 #include "CSSPrimitiveValue.h"
       
    32 #include "CSSValue.h"
       
    33 #include "PlatformString.h"
       
    34 #include <runtime/StringObjectThatMasqueradesAsUndefined.h>
       
    35 #include <runtime/StringPrototype.h>
       
    36 #include <wtf/ASCIICType.h>
       
    37 
       
    38 using namespace JSC;
       
    39 using namespace WTF;
       
    40 
       
    41 namespace WebCore {
       
    42 
       
    43 void JSCSSStyleDeclaration::markChildren(MarkStack& markStack)
       
    44 {
       
    45     Base::markChildren(markStack);
       
    46 
       
    47     CSSStyleDeclaration* declaration = impl();
       
    48     JSGlobalData& globalData = *Heap::heap(this)->globalData();
       
    49 
       
    50     if (declaration->isMutableStyleDeclaration()) {
       
    51         CSSMutableStyleDeclaration* mutableDeclaration = static_cast<CSSMutableStyleDeclaration*>(declaration);
       
    52         CSSMutableStyleDeclaration::const_iterator end = mutableDeclaration->end();
       
    53         for (CSSMutableStyleDeclaration::const_iterator it = mutableDeclaration->begin(); it != end; ++it)
       
    54             markDOMObjectWrapper(markStack, globalData, it->value());
       
    55     }
       
    56 }
       
    57 
       
    58 // Check for a CSS prefix.
       
    59 // Passed prefix is all lowercase.
       
    60 // First character of the prefix within the property name may be upper or lowercase.
       
    61 // Other characters in the prefix within the property name must be lowercase.
       
    62 // The prefix within the property name must be followed by a capital letter.
       
    63 static bool hasCSSPropertyNamePrefix(const Identifier& propertyName, const char* prefix)
       
    64 {
       
    65 #ifndef NDEBUG
       
    66     ASSERT(*prefix);
       
    67     for (const char* p = prefix; *p; ++p)
       
    68         ASSERT(isASCIILower(*p));
       
    69     ASSERT(propertyName.size());
       
    70 #endif
       
    71 
       
    72     if (toASCIILower(propertyName.data()[0]) != prefix[0])
       
    73         return false;
       
    74 
       
    75     unsigned length = propertyName.size();
       
    76     for (unsigned i = 1; i < length; ++i) {
       
    77         if (!prefix[i])
       
    78             return isASCIIUpper(propertyName.data()[i]);
       
    79         if (propertyName.data()[i] != prefix[i])
       
    80             return false;
       
    81     }
       
    82     return false;
       
    83 }
       
    84 
       
    85 static String cssPropertyName(const Identifier& propertyName, bool* hadPixelOrPosPrefix = 0)
       
    86 {
       
    87     if (hadPixelOrPosPrefix)
       
    88         *hadPixelOrPosPrefix = false;
       
    89 
       
    90     unsigned length = propertyName.size();
       
    91     if (!length)
       
    92         return String();
       
    93 
       
    94     Vector<UChar> name;
       
    95     name.reserveInitialCapacity(length);
       
    96 
       
    97     unsigned i = 0;
       
    98 
       
    99     if (hasCSSPropertyNamePrefix(propertyName, "css"))
       
   100         i += 3;
       
   101     else if (hasCSSPropertyNamePrefix(propertyName, "pixel")) {
       
   102         i += 5;
       
   103         if (hadPixelOrPosPrefix)
       
   104             *hadPixelOrPosPrefix = true;
       
   105     } else if (hasCSSPropertyNamePrefix(propertyName, "pos")) {
       
   106         i += 3;
       
   107         if (hadPixelOrPosPrefix)
       
   108             *hadPixelOrPosPrefix = true;
       
   109     } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")
       
   110             || hasCSSPropertyNamePrefix(propertyName, "khtml")
       
   111             || hasCSSPropertyNamePrefix(propertyName, "apple"))
       
   112         name.append('-');
       
   113     else {
       
   114         if (isASCIIUpper(propertyName.data()[0]))
       
   115             return String();
       
   116     }
       
   117 
       
   118     name.append(toASCIILower(propertyName.data()[i++]));
       
   119 
       
   120     for (; i < length; ++i) {
       
   121         UChar c = propertyName.data()[i];
       
   122         if (!isASCIIUpper(c))
       
   123             name.append(c);
       
   124         else {
       
   125             name.append('-');
       
   126             name.append(toASCIILower(c));
       
   127         }
       
   128     }
       
   129 
       
   130     return String::adopt(name);
       
   131 }
       
   132 
       
   133 static bool isCSSPropertyName(const Identifier& propertyName)
       
   134 {
       
   135     return CSSStyleDeclaration::isPropertyName(cssPropertyName(propertyName));
       
   136 }
       
   137 
       
   138 bool JSCSSStyleDeclaration::canGetItemsForName(ExecState*, CSSStyleDeclaration*, const Identifier& propertyName)
       
   139 {
       
   140     return isCSSPropertyName(propertyName);
       
   141 }
       
   142 
       
   143 // FIXME: You can get these properties, and set them (see putDelegate below),
       
   144 // but you should also be able to enumerate them.
       
   145 JSValue JSCSSStyleDeclaration::nameGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName)
       
   146 {
       
   147     JSCSSStyleDeclaration* thisObj = static_cast<JSCSSStyleDeclaration*>(asObject(slotBase));
       
   148 
       
   149     // Set up pixelOrPos boolean to handle the fact that
       
   150     // pixelTop returns "CSS Top" as number value in unit pixels
       
   151     // posTop returns "CSS top" as number value in unit pixels _if_ its a
       
   152     // positioned element. if it is not a positioned element, return 0
       
   153     // from MSIE documentation FIXME: IMPLEMENT THAT (Dirk)
       
   154     bool pixelOrPos;
       
   155     String prop = cssPropertyName(propertyName, &pixelOrPos);
       
   156     RefPtr<CSSValue> v = thisObj->impl()->getPropertyCSSValue(prop);
       
   157     if (v) {
       
   158         if (pixelOrPos && v->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE)
       
   159             return jsNumber(exec, static_pointer_cast<CSSPrimitiveValue>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX));
       
   160         return jsStringOrNull(exec, v->cssText());
       
   161     }
       
   162 
       
   163     // If the property is a shorthand property (such as "padding"), 
       
   164     // it can only be accessed using getPropertyValue.
       
   165 
       
   166     // Make the SVG 'filter' attribute undetectable, to avoid confusion with the IE 'filter' attribute.
       
   167     if (propertyName == "filter")
       
   168         return StringObjectThatMasqueradesAsUndefined::create(exec, stringToUString(thisObj->impl()->getPropertyValue(prop)));
       
   169 
       
   170     return jsString(exec, thisObj->impl()->getPropertyValue(prop));
       
   171 }
       
   172 
       
   173 
       
   174 bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot&)
       
   175 {
       
   176     if (!isCSSPropertyName(propertyName))
       
   177         return false;
       
   178 
       
   179     bool pixelOrPos;
       
   180     String prop = cssPropertyName(propertyName, &pixelOrPos);
       
   181     String propValue = valueToStringWithNullCheck(exec, value);
       
   182     if (pixelOrPos)
       
   183         propValue += "px";
       
   184     ExceptionCode ec = 0;
       
   185     impl()->setProperty(prop, propValue, ec);
       
   186     setDOMException(exec, ec);
       
   187     return true;
       
   188 }
       
   189 
       
   190 } // namespace WebCore