Reviewed by eseidel.
authorrwlbuis <rwlbuis@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Sep 2006 19:43:13 +0000 (19:43 +0000)
committerrwlbuis <rwlbuis@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 24 Sep 2006 19:43:13 +0000 (19:43 +0000)
        Fix for http://bugzilla.opendarwin.org/show_bug.cgi?id=6001
        WebKit does not handle fallback custom cursors
        Fix for http://bugzilla.opendarwin.org/show_bug.cgi?id=6002
        WebKit does not properly handle SVG <cursor> element

        Add support for svg cursor images. Also make sure hotspot
        settings are handled correctly. Add tests for handling of css3
        cursor syntax with hotspots in strict and quirks mode. Finally
        implement fallback.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@16549 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/css/CSSComputedStyleDeclaration.cpp
WebCore/css/CSSCursorImageValue.cpp [new file with mode: 0644]
WebCore/css/CSSCursorImageValue.h [new file with mode: 0644]
WebCore/css/cssparser.cpp
WebCore/css/cssstyleselector.cpp
WebCore/ksvg2/svg/SVGCursorElement.cpp
WebCore/manual-tests/css3-cursor-fallback-quirks.html [new file with mode: 0644]
WebCore/manual-tests/css3-cursor-fallback-strict.html [new file with mode: 0644]
WebCore/manual-tests/cursorfallback.xml [new file with mode: 0644]
WebCore/page/FrameView.cpp
WebCore/platform/Cursor.h
WebCore/platform/mac/CursorMac.mm
WebCore/platform/qt/CursorQt.cpp
WebCore/rendering/RenderStyle.cpp
WebCore/rendering/RenderStyle.h

index 3cacf3894e578653c266f552e0920fac0556cbb2..de9285c53f9c4ec3ffe631c2f8d37ed6d6f4e445 100644 (file)
@@ -1,3 +1,56 @@
+2006-09-24  Rob Buis  <buis@kde.org>
+
+        Reviewed by eseidel.
+
+        Fix for http://bugzilla.opendarwin.org/show_bug.cgi?id=6001
+        WebKit does not handle fallback custom cursors
+        Fix for http://bugzilla.opendarwin.org/show_bug.cgi?id=6002
+        WebKit does not properly handle SVG <cursor> element
+
+        Add support for svg cursor images. Also make sure hotspot
+        settings are handled correctly. Add tests for handling of css3
+        cursor syntax with hotspots in strict and quirks mode. Finally
+        implement fallback.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue):
+        * css/CSSCursorImageValue.cpp: Added.
+        (WebCore::CSSCursorImageValue::CSSCursorImageValue):
+        (WebCore::CSSCursorImageValue::~CSSCursorImageValue):
+        * css/CSSCursorImageValue.h: Added.
+        (WebCore::CSSCursorImageValue::hotspot):
+        * css/cssparser.cpp:
+        (WebCore::CSSParser::parseValue):
+        * css/cssstyleselector.cpp:
+        (WebCore::CSSStyleSelector::applyProperty):
+        * ksvg2/svg/SVGCursorElement.cpp:
+        * manual-tests/css3-cursor-fallback-quirks.html: Added.
+        * manual-tests/css3-cursor-fallback-strict.html: Added.
+        * manual-tests/cursorfallback.xml: Added.
+        * page/FrameView.cpp:
+        (WebCore::selectCursor):
+        * platform/Cursor.h:
+        * platform/mac/CursorMac.mm:
+        (WebCore::createCustomCursor):
+        (WebCore::Cursor::Cursor):
+        * platform/qt/CursorQt.cpp:
+        (WebCore::Cursor::Cursor):
+        * rendering/RenderStyle.cpp:
+        (WebCore::StyleInheritedData::StyleInheritedData):
+        (WebCore::StyleInheritedData::operator==):
+        (WebCore::RenderStyle::diff):
+        (WebCore::RenderStyle::addCursor):
+        (WebCore::RenderStyle::addSVGCursor):
+        (WebCore::RenderStyle::setCursorList):
+        (WebCore::RenderStyle::clearCursorList):
+        * rendering/RenderStyle.h:
+        (WebCore::CursorData::CursorData):
+        (WebCore::CursorList::operator[]):
+        (WebCore::CursorList::size):
+        (WebCore::CursorList::append):
+        (WebCore::RenderStyle::cursors):
+
 2006-09-24  Sam Weinig  <sam.weinig@gmail.com>
 
         Reviewed by Tim H.
index 1c0100de01f33a48b2f1be5c6983ef31f556a6e4..a972a5b4e694e2a35e56df47280fe1260ceaa493 100644 (file)
                A8FEFB0B0979F472005839FD /* RenderForeignObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8FEFB090979F472005839FD /* RenderForeignObject.cpp */; };
                A8FEFB310979F4F6005839FD /* SVGForeignObjectElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8FEFB2F0979F4F6005839FD /* SVGForeignObjectElement.cpp */; };
                A8FEFB320979F4F6005839FD /* SVGForeignObjectElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A8FEFB300979F4F6005839FD /* SVGForeignObjectElement.h */; };
+               AA21ECCA0ABF0FBA002B834C /* CSSCursorImageValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA0978ED0ABAA6E100874480 /* CSSCursorImageValue.cpp */; };
+               AA21ECCD0ABF0FC6002B834C /* CSSCursorImageValue.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0978EE0ABAA6E100874480 /* CSSCursorImageValue.h */; };
                AA98B87D0AAA02F8001A44C2 /* Path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AA98B87C0AAA02F8001A44C2 /* Path.cpp */; };
                AAC8DAB10AA1002000DC0907 /* SVGMetadataElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AAC8DAAF0AA1002000DC0907 /* SVGMetadataElement.cpp */; };
                AAC8DAB20AA1002000DC0907 /* SVGMetadataElement.h in Headers */ = {isa = PBXBuildFile; fileRef = AAC8DAB00AA1002000DC0907 /* SVGMetadataElement.h */; };
                A8FEFB090979F472005839FD /* RenderForeignObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderForeignObject.cpp; sourceTree = "<group>"; };
                A8FEFB2F0979F4F6005839FD /* SVGForeignObjectElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGForeignObjectElement.cpp; sourceTree = "<group>"; };
                A8FEFB300979F4F6005839FD /* SVGForeignObjectElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGForeignObjectElement.h; sourceTree = "<group>"; };
+               AA0978ED0ABAA6E100874480 /* CSSCursorImageValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CSSCursorImageValue.cpp; sourceTree = "<group>"; };
+               AA0978EE0ABAA6E100874480 /* CSSCursorImageValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CSSCursorImageValue.h; sourceTree = "<group>"; };
                AA98B87C0AAA02F8001A44C2 /* Path.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Path.cpp; sourceTree = "<group>"; };
                AAC8DAAF0AA1002000DC0907 /* SVGMetadataElement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SVGMetadataElement.cpp; sourceTree = "<group>"; };
                AAC8DAB00AA1002000DC0907 /* SVGMetadataElement.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SVGMetadataElement.h; sourceTree = "<group>"; };
                F523D18402DE42E8018635CA /* css */ = {
                        isa = PBXGroup;
                        children = (
+                               AA0978ED0ABAA6E100874480 /* CSSCursorImageValue.cpp */,
+                               AA0978EE0ABAA6E100874480 /* CSSCursorImageValue.h */,
                                A80E6CDA0A1989CA007FB8C5 /* Counter.h */,
                                930705C709E0C95F00B17FE4 /* Counter.idl */,
                                A80E6CBB0A1989CA007FB8C5 /* CSSBorderImageValue.cpp */,
                                853BF4DB0ABB6B55008647BB /* DOMNode.h in Headers */,
                                853BF4EB0ABB6E97008647BB /* DOMNodePrivate.h in Headers */,
                                85BCBC130ABBA87D00381160 /* DOMHTMLDocument.h in Headers */,
+                               AA21ECCD0ABF0FC6002B834C /* CSSCursorImageValue.h in Headers */,
                                851EE80C0ABCA28F00A6AA33 /* DOMAbstractView.h in Headers */,
                                851EE8110ABCA39600A6AA33 /* DOMEventException.h in Headers */,
                                851EE8210ABCA58100A6AA33 /* DOMRangeException.h in Headers */,
                                B20111070AB7740500DB0E68 /* JSSVGAElement.cpp in Sources */,
                                853BF4DC0ABB6B55008647BB /* DOMNode.mm in Sources */,
                                85BCBC140ABBA87D00381160 /* DOMHTMLDocument.mm in Sources */,
+                               AA21ECCA0ABF0FBA002B834C /* CSSCursorImageValue.cpp in Sources */,
                                851EE80D0ABCA28F00A6AA33 /* DOMAbstractView.mm in Sources */,
                                A8415F9B0AC10C5D00F7D0DF /* KCanvasClipper.cpp in Sources */,
                                A8415F9D0AC10C5D00F7D0DF /* KCanvasResource.cpp in Sources */,
index dab7985d32570cd0cd4b62f298774d41e0b88118..8fee8805084d9bd92f7dd90eae4199079f623346 100644 (file)
@@ -607,57 +607,89 @@ PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
     case CSS_PROP_COUNTER_RESET:
         // FIXME: unimplemented
         break;
-    case CSS_PROP_CURSOR:
-        if (style->cursorImage())
-            return new CSSPrimitiveValue(style->cursorImage()->url(), CSSPrimitiveValue::CSS_URI);
+    case CSS_PROP_CURSOR: {
+        CSSValueList* list = 0;
+        CSSValue* value = 0;
+        CursorList* cursors = style->cursors();
+        if (cursors && cursors->size() > 0) {
+            list = new CSSValueList;
+            for (unsigned i = 0; i < cursors->size(); ++i)
+                list->append(new CSSPrimitiveValue((*cursors)[i].cursorImage->url(), CSSPrimitiveValue::CSS_URI));
+        }
         switch (style->cursor()) {
             case CURSOR_AUTO:
-                return new CSSPrimitiveValue(CSS_VAL_AUTO);
+                value = new CSSPrimitiveValue(CSS_VAL_AUTO);
+                break;
             case CURSOR_CROSS:
-                return new CSSPrimitiveValue(CSS_VAL_CROSSHAIR);
+                value = new CSSPrimitiveValue(CSS_VAL_CROSSHAIR);
+                break;
             case CURSOR_DEFAULT:
-                return new CSSPrimitiveValue(CSS_VAL_DEFAULT);
+                value = new CSSPrimitiveValue(CSS_VAL_DEFAULT);
+                break;
             case CURSOR_POINTER:
-                return new CSSPrimitiveValue(CSS_VAL_POINTER);
+                value = new CSSPrimitiveValue(CSS_VAL_POINTER);
+                break;
             case CURSOR_MOVE:
-                return new CSSPrimitiveValue(CSS_VAL_MOVE);
+                value = new CSSPrimitiveValue(CSS_VAL_MOVE);
+                break;
             case CURSOR_E_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_E_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_E_RESIZE);
+                break;
             case CURSOR_NE_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_NE_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_NE_RESIZE);
+                break;
             case CURSOR_NW_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_NW_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_NW_RESIZE);
+                break;
             case CURSOR_N_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_N_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_N_RESIZE);
+                break;
             case CURSOR_SE_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_SE_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_SE_RESIZE);
+                break;
             case CURSOR_SW_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_SW_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_SW_RESIZE);
+                break;
             case CURSOR_S_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_S_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_S_RESIZE);
+                break;
             case CURSOR_W_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_W_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_W_RESIZE);
+                break;
             case CURSOR_EW_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_EW_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_EW_RESIZE);
+                break;
             case CURSOR_NS_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_NS_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_NS_RESIZE);
+                break;
             case CURSOR_NESW_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_NESW_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_NESW_RESIZE);
+                break;
             case CURSOR_NWSE_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_NWSE_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_NWSE_RESIZE);
+                break;
             case CURSOR_COL_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_COL_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_COL_RESIZE);
+                break;
             case CURSOR_ROW_RESIZE:
-                return new CSSPrimitiveValue(CSS_VAL_ROW_RESIZE);
+                value = new CSSPrimitiveValue(CSS_VAL_ROW_RESIZE);
+                break;
             case CURSOR_TEXT:
-                return new CSSPrimitiveValue(CSS_VAL_TEXT);
+                value = new CSSPrimitiveValue(CSS_VAL_TEXT);
+                break;
             case CURSOR_WAIT:
-                return new CSSPrimitiveValue(CSS_VAL_WAIT);
+                value = new CSSPrimitiveValue(CSS_VAL_WAIT);
+                break;
             case CURSOR_HELP:
-                return new CSSPrimitiveValue(CSS_VAL_HELP);
+                value = new CSSPrimitiveValue(CSS_VAL_HELP);
         }
-        ASSERT_NOT_REACHED();
-        return 0;
+        ASSERT(value);
+        if (list) {
+            list->append(value);
+            return list;
+        }
+        return value;
+    }
     case CSS_PROP_DIRECTION:
         switch (style->direction()) {
             case LTR:
diff --git a/WebCore/css/CSSCursorImageValue.cpp b/WebCore/css/CSSCursorImageValue.cpp
new file mode 100644 (file)
index 0000000..371b689
--- /dev/null
@@ -0,0 +1,35 @@
+/**
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2006, Rob Buis <buis@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include "config.h"
+#include "CSSCursorImageValue.h"
+
+namespace WebCore {
+
+CSSCursorImageValue::CSSCursorImageValue(const String& url, const IntPoint& p, StyleBase* style)
+    : CSSImageValue(url, style)
+    , m_hotspot(p)
+{
+}
+
+CSSCursorImageValue::~CSSCursorImageValue()
+{
+}
+}
diff --git a/WebCore/css/CSSCursorImageValue.h b/WebCore/css/CSSCursorImageValue.h
new file mode 100644 (file)
index 0000000..0f93eb6
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the DOM implementation for KDE.
+ *
+ * Copyright (C) 2006, Rob Buis <buis@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef CSSCursorImageValue_H
+#define CSSCursorImageValue_H
+
+#include "IntPoint.h"
+#include "CSSImageValue.h"
+
+namespace WebCore {
+
+class CSSCursorImageValue : public CSSImageValue
+{
+public:
+    CSSCursorImageValue(const String& url, const IntPoint&, StyleBase*);
+    virtual ~CSSCursorImageValue();
+
+    IntPoint hotspot() const { return m_hotspot; }
+
+protected:
+    IntPoint m_hotspot;
+};
+} // namespace
+
+#endif
index ed26e233556caaf553d338f98bf8f3cde177fcf0..fd3e29a87cd83d2f4fab0623846c527451f08b24 100644 (file)
@@ -25,6 +25,7 @@
 #include "cssparser.h"
 
 #include "CSSBorderImageValue.h"
+#include "CSSCursorImageValue.h"
 #include "CSSImageValue.h"
 #include "CSSCharsetRule.h"
 #include "CSSImportRule.h"
@@ -694,26 +695,68 @@ bool CSSParser::parseValue(int propId, bool important)
         }
         break;
 
-    case CSS_PROP_CURSOR:
+    case CSS_PROP_CURSOR: {
         // [<uri>,]*  [ auto | crosshair | default | pointer | progress | move | e-resize | ne-resize |
         // nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | ew-resize | 
         // ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | text | wait | help ] ] | inherit
-        if (!strict && id == CSS_VAL_HAND) { // MSIE 5 compatibility :/
-            id = CSS_VAL_POINTER;
-            valid_primitive = true;
-        } else if (id >= CSS_VAL_AUTO && id <= CSS_VAL_HELP)
-            valid_primitive = true;
-        else if (value->unit == CSSPrimitiveValue::CSS_URI) {
+        CSSValueList* list = 0;
+        while (value && value->unit == CSSPrimitiveValue::CSS_URI) {
             String uri = parseURL(domString(value->string));
+            Vector<int> coords;
+            value = valueList->next();
+            while (value && value->unit == CSSPrimitiveValue::CSS_NUMBER) {
+                coords.append(value->fValue);
+                value = valueList->next();
+            }
+            IntPoint hotspot;
+            int nrcoords = coords.size();
+            if (nrcoords > 0 && nrcoords != 2) {
+                if (strict) { // only support hotspot pairs in strict mode
+                    delete list;
+                    return false;
+                }
+            } else if(strict && nrcoords == 2)
+                hotspot = IntPoint(coords[0], coords[1]);
+            if (strict || coords.size() == 0) {
+#if SVG_SUPPORT
+            if (uri.startsWith("#")) {
+                if (!list)
+                    list = new CSSValueList; 
+                list->append(new CSSPrimitiveValue(uri, CSSPrimitiveValue::CSS_URI));
+            } else
+#endif
             if (!uri.isEmpty()) {
-                parsedValue = new CSSImageValue(String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()), styleElement);
-                // FIXME: we don't support fallback cursors yet, but ignoring the remaining values
-                // will at least let compliant declarations parse.
-                addProperty(propId, parsedValue, important);
-                return true;
+                if (!list)
+                    list = new CSSValueList; 
+                list->append(new CSSCursorImageValue(
+                             String(KURL(styleElement->baseURL().deprecatedString(), uri.deprecatedString()).url()),
+                             hotspot, styleElement));
+            }
             }
+            if ((strict && !value) || (value && !(value->unit == Value::Operator && value->iValue == ',')))
+                return false;
+            value = valueList->next(); // comma
+        }
+        if (list) {
+            if (!value) { // no value after url list (MSIE 5 compatibility)
+                if (list->length() > 1)
+                    return false;
+            } else if (!strict && value->id == CSS_VAL_HAND) // MSIE 5 compatibility :/
+                list->append(new CSSPrimitiveValue(CSS_VAL_POINTER));
+            else if (value && value->id >= CSS_VAL_AUTO && value->id <= CSS_VAL_HELP)
+                list->append(new CSSPrimitiveValue(value->id));
+            valueList->next();
+            parsedValue = list;
+            break;
         }
+        id = value->id;
+        if (!strict && value->id == CSS_VAL_HAND) { // MSIE 5 compatibility :/
+            id = CSS_VAL_POINTER;
+            valid_primitive = true;
+        } else if (value->id >= CSS_VAL_AUTO && value->id <= CSS_VAL_HELP)
+            valid_primitive = true;
         break;
+    }
 
     case CSS_PROP_BACKGROUND_ATTACHMENT:
     case CSS_PROP__WEBKIT_BACKGROUND_CLIP:
@@ -1295,8 +1338,8 @@ bool CSSParser::parseValue(int propId, bool important)
     }
 
     if (valid_primitive) {
-        if (id != 0)
-            parsedValue = new CSSPrimitiveValue(id);
+        if (id != 0) {
+            parsedValue = new CSSPrimitiveValue(id); }
         else if (value->unit == CSSPrimitiveValue::CSS_STRING)
             parsedValue = new CSSPrimitiveValue(domString(value->string), (CSSPrimitiveValue::UnitTypes) value->unit);
         else if (value->unit >= CSSPrimitiveValue::CSS_NUMBER && value->unit <= CSSPrimitiveValue::CSS_KHZ)
index 248573bde18efbdf8946d197bacaf6d9d0a7f214..21ea1703b4a95c358d7f8070e53d41ae94c521c8 100644 (file)
@@ -26,6 +26,7 @@
 #include "cssstyleselector.h"
 
 #include "CSSBorderImageValue.h"
+#include "CSSCursorImageValue.h"
 #include "CSSImageValue.h"
 #include "CSSImportRule.h"
 #include "CSSMediaRule.h"
@@ -2410,24 +2411,41 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value)
     case CSS_PROP_CURSOR:
         if (isInherit) {
             style->setCursor(parentStyle->cursor());
-            style->setCursorImage(parentStyle->cursorImage());
+            style->setCursorList(parentStyle->cursors());
             return;
         }
+        style->clearCursorList();
         if (isInitial) {
             style->setCursor(RenderStyle::initialCursor());
-            style->setCursorImage(0);
             return;
         }
-        if (primitiveValue) {
+        if (value->isValueList()) {
+            CSSValueList* list = static_cast<CSSValueList*>(value);
+            int len = list->length();
+            style->setCursor(CURSOR_AUTO);
+            for (int i = 0; i < len; i++) {
+                CSSValue* item = list->item(i);
+                if (!item->isPrimitiveValue())
+                    continue;
+                primitiveValue = static_cast<CSSPrimitiveValue*>(item);
+                int type = primitiveValue->primitiveType();
+                if (type == CSSPrimitiveValue::CSS_URI) {
+#if SVG_SUPPORT
+                    if (primitiveValue->getStringValue().find("#") == 0)
+                        style->addSVGCursor(primitiveValue->getStringValue().substring(1));
+                    else
+#endif
+                    {
+                        CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
+                        style->addCursor(image->image(element->document()->docLoader()), image->hotspot());
+                    }
+                } else if (type == CSSPrimitiveValue::CSS_IDENT)
+                    style->setCursor((ECursor)(primitiveValue->getIdent() - CSS_VAL_AUTO));
+            }
+        } else if (primitiveValue) {
             int type = primitiveValue->primitiveType();
-            if (type == CSSPrimitiveValue::CSS_IDENT) {
+            if (type == CSSPrimitiveValue::CSS_IDENT)
                 style->setCursor((ECursor)(primitiveValue->getIdent() - CSS_VAL_AUTO));
-                style->setCursorImage(0);
-            } else if (type == CSSPrimitiveValue::CSS_URI) {
-                CSSImageValue* image = static_cast<CSSImageValue*>(primitiveValue);
-                style->setCursor(CURSOR_AUTO);
-                style->setCursorImage(image->image(element->document()->docLoader()));
-            }
         }
         break;
 // colors || inherit
index 3bf845d7b960d5a5859decfe167faa4aba78acfd..a4b027e4530514c5538f058b31667ea61270e994 100644 (file)
@@ -32,7 +32,7 @@
 #include "SVGHelper.h"
 #include "SVGLength.h"
 
-using namespace WebCore;
+namespace WebCore {
 
 SVGCursorElement::SVGCursorElement(const QualifiedName& tagName, Document *doc)
     : SVGElement(tagName, doc)
@@ -80,6 +80,8 @@ void SVGCursorElement::parseMappedAttribute(MappedAttribute *attr)
     }
 }
 
+}
+
 // vim:ts=4:noet
 #endif // SVG_SUPPORT
 
diff --git a/WebCore/manual-tests/css3-cursor-fallback-quirks.html b/WebCore/manual-tests/css3-cursor-fallback-quirks.html
new file mode 100644 (file)
index 0000000..bd833db
--- /dev/null
@@ -0,0 +1,58 @@
+<html>
+<head><title>Quirks custom cursor tests</title></head>
+<body>
+<p><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=8991">Bug .991</a>: REGRESSION: missing or broken CSS custom cursors are displayed as a missing image icon.</p>
+<p>Move the cursor over the blue box - it should not turn into a missing image icon, and should turn into an I-beam over text.</p>
+
+<div style="width:100px;height:50px;background-color:lightblue; cursor:url(nonexistent.png), auto;"><span style="cursor:url(nonexistent.png), auto;">some text</span></div>
+<div style="width:100px;height:50px;background-color:lightblue; cursor:url(nonexistent.png);"></div>
+
+<hr>
+<p><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=6001">Bug 6001</a>: WebKit does not handle fallback custom cursors</p>
+<p><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=9013">Bug 9013</a>: Let correct CSS custom cursor declarations parse</p>
+<p>In each of the blue boxes below, the cursor should become a help cursor (question mark).</p>
+<table><tr>
+ <td><div style="width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;"></div></td> <!-- Valid, no fallback needed -->
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff);'></div></td> <!-- Invalid, but allowed by WinIE -->
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(nonexistent.png), help;'></div></td>
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(nonexistent.png), url(custom-cursors.html), url(unknown-scheme:custom-cursors.html), url(resources/helpCursor.tiff), text;'></div></td>
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(nonexistent.png), url("resources/helpCursor.tiff"), text;'></div></td>
+</tr>
+</table>
+<p>In each of the blue boxes below, the cursor should remain the default cursor, since all cursor definitions are invalid in quirks mode.</p>
+<table><tr>
+<td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1 1 text;'></div></td> <!-- CSS3 hot spot - invalid, should have comma after hotspot coords -->
+</tr>
+</table>
+<p>In each of the blue boxes below, the cursor should show the text cursor, since all hotspot definitions are ignored in quirks mode.</p>
+<table><tr>
+<td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1, text;'></div></td> <!-- CSS3 hot spot - ignored in IE -->
+<td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1 2, text;'></div></td> <!-- CSS3 hot spot - ignored in IE -->
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1 2 3, text;'></div></td> <!-- CSS3 hot spot - ignored in IE -->
+</tr>
+</table>
+
+<p></p>
+<p><span style='background-color:gray; cursor:url(nonexistent.png), url("resources/helpCursor.tiff");'>Should show an I-beam cursor.</span></p> <!-- An invalid declaration, even by WinIE standards -->
+<p>The following testcases test inheritance of the cursor property. The first one should have the help cursor for both divs (normal inheritance). The second one should have help cursor for big div, text cursor for small div (inner div has cursor property, should not inherit). The next has invalid css syntax in the inner div, so it should inherit from the parent. The last two testcases have correct syntax and there is no inheritance in this case.</p>
+<table>
+<tr><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:text"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:foobar"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:url(resources/helpCursor.tiff) 1 2 3, text"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:url(nonexistant.png), text"></div></div>
+</td></tr>
+</table>
+<p>In each of the blue boxes below, the hotspot is out-of-range. In quirks mode we do not support hotspots at all, so we show the fallback cursor(text).</p>
+<table><tr>
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) -1 -1, text;'></div></td> <!-- CSS3 hot spot out-of-range -->
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 100 100, text;'></div></td> <!-- CSS3 hot spot out-of-range -->
+</tr>
+</table>
+</body>
+</html>
diff --git a/WebCore/manual-tests/css3-cursor-fallback-strict.html b/WebCore/manual-tests/css3-cursor-fallback-strict.html
new file mode 100644 (file)
index 0000000..f4d2a43
--- /dev/null
@@ -0,0 +1,56 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
+   "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head><title>Strict custom cursor tests</title></head>
+<body>
+<p><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=8991">Bug .991</a>: REGRESSION: missing or broken CSS custom cursors are displayed as a missing image icon.</p>
+<p>Move the cursor over the blue box - it should not turn into a missing image icon, and should turn into an I-beam over text.</p>
+
+<div style="width:100px;height:50px;background-color:lightblue; cursor:url(nonexistent.png), auto;"><span style="cursor:url(nonexistent.png), auto;">some text</span></div>
+<div style="width:100px;height:50px;background-color:lightblue; cursor:url(nonexistent.png);"></div>
+
+<hr>
+<p><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=6001">Bug 6001</a>: WebKit does not handle fallback custom cursors</p>
+<p><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=9013">Bug 9013</a>: Let correct CSS custom cursor declarations parse</p>
+<p>In each of the blue boxes below, the cursor should become a help cursor (question mark).</p>
+<table><tr>
+ <td><div style="width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;"></div></td> <!-- Valid, no fallback needed -->
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(nonexistent.png), help;'></div></td>
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(nonexistent.png), url(custom-cursors.html), url(unknown-scheme:custom-cursors.html), url(resources/helpCursor.tiff), text;'></div></td>
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(nonexistent.png), url("resources/helpCursor.tiff"), text;'></div></td>
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1 1, text;'></div></td> <!-- CSS3 hot spot - valid, no fallback needed -->
+</tr>
+</table>
+<p>In each of the blue boxes below, the cursor should remain the default cursor, since all cursor definitions are invalid in strict mode.</p>
+<table><tr>
+<td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1 1 text;'></div></td> <!-- CSS3 hot spot - invalid, should have comma after hotspot coords -->
+<td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1, text;'></div></td> <!-- CSS3 hot spot - invalid, should have two hotspot coords -->
+<td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 1 2 3, text;'></div></td> <!-- CSS3 hot spot - invalid, should have two hotspot coords -->
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff);'></div></td> <!-- Invalid -->
+</tr>
+</table>
+
+<p></p>
+<p><span style='background-color:gray; cursor:url(nonexistent.png), url("resources/helpCursor.tiff");'>Should show an I-beam cursor.</span></p> <!-- An invalid declaration, even by WinIE standards -->
+<p>The following testcases test inheritance of the cursor property. The first one should have the help cursor for both divs (normal inheritance). The second one should have help cursor for big div, text cursor for small div (inner div has cursor property, should not inherit). The next two have invalid css syntax in the inner div, so they should inherit from parent. The rightmost testcase has a nonexistant url, but the syntax is correct, and there is no inheritance in this case.</p>
+<table>
+<tr><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:text"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:foobar"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:url(resources/helpCursor.tiff) 1 2 3, text"></div></div>
+</td><td>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff), text;'><div style="width:50px;height:50px;background-color:gray;cursor:url(nonexistant.png), text"></div></div>
+</td></tr>
+</table>
+<p>In each of the blue boxes below, the hotspot is out-of-range. For now this means a failure to show the custom cursor(lower level problem?).</p>
+<table><tr>
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) -1 -1, help;'></div></td> <!-- CSS3 hot spot out-of-range -->
+ <td><div style='width:100px;height:100px;background-color:lightblue; cursor:url(resources/helpCursor.tiff) 100 100, help;'></div></td> <!-- CSS3 hot spot out-of-range -->
+</tr>
+</table>
+</body>
+</html>
diff --git a/WebCore/manual-tests/cursorfallback.xml b/WebCore/manual-tests/cursorfallback.xml
new file mode 100644 (file)
index 0000000..a4fdf2f
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Strict mode + SVG cursor fallback test</title>
+</head>
+<body>
+<p>Test svg cursor fallback, should show help cursor:</p>
+<svg xmlns="http://www.w3.org/2000/svg" 
+     xmlns:xlink="http://www.w3.org/1999/xlink" width="500" height="300">
+<defs>
+    <cursor id="help" xlink:href="resources/helpcursor.tiff" x="10" y="11"/>
+</defs>
+<g cursor="url(nonexistent.png), url(custom-cursors.html), url(unknown-scheme:custom-cursors.html), url(#nonexistant), url(#help), text">
+    <rect x="0" y="0" width="50" height="50" fill="blue" />
+</g>
+<text y="62">Test svg cursor fallback with hotspot, should show help cursor:</text>
+<g cursor="url(#help) 1 1, text">
+    <rect x="0" y="70" width="50" height="50" fill="red" />
+</g>
+<text y="132">Test svg cursor fallback with illegal hotspot, should show default cursor:</text>
+<g cursor="url(#help) 1, text">
+    <rect x="0" y="140" width="50" height="50" fill="red" />
+</g>
+<text y="202">Test svg cursor fallback with illegal hotspot, should show default cursor:</text>
+<g cursor="url(#help) 1 2 3, text">
+    <rect x="0" y="210" width="50" height="50" fill="red" />
+</g>
+</svg>
+<p>Testing cursor fallback in strict mode, should show help cursor:</p>
+<div style='width:100px;height:100px;background-color:lightblue; cursor:url(nonexistent.png), url("resources/helpcursor.tiff"), text;'></div>
+</body>
+</html>
index 5a28c9f23ee81667e6c086c99d00ebb03d0901ba..dda84f885bde7da2c6d9ba59ec765dc5e15221b4 100644 (file)
 #include "SelectionController.h"
 #include "cssstyleselector.h"
 
+#if SVG_SUPPORT
+#include "XLinkNames.h"
+#include "SVGNames.h"
+#include "SVGCursorElement.h"
+#include "SVGLength.h"
+#endif
+
 namespace WebCore {
 
 using namespace EventNames;
 using namespace HTMLNames;
+#if SVG_SUPPORT
+using namespace SVGNames;
+#endif
 
 struct ScheduledEvent {
     RefPtr<Event> m_event;
@@ -646,11 +656,30 @@ static Cursor selectCursor(const MouseEventWithHitTestResults& event, Frame* fra
     RenderObject* renderer = node ? node->renderer() : 0;
     RenderStyle* style = renderer ? renderer->style() : 0;
 
-    if (style && style->cursorImage() && !style->cursorImage()->image()->isNull())
-        if (!style->cursorImage()->isErrorImage())
-            return style->cursorImage()->image();
-        else 
-            style = 0; // Fallback to CURSOR_AUTO
+    if (style && style->cursors()) {
+        const CursorList* cursors = style->cursors();
+        for (unsigned i = 0; i < cursors->size(); ++i) {
+            CachedImage* cimage = (*cursors)[i].cursorImage;
+            IntPoint hotSpot = (*cursors)[i].hotSpot;
+#if SVG_SUPPORT
+            if (!cimage) {
+                Element* e = node->document()->getElementById((*cursors)[i].cursorFragmentId);
+                if (e && e->hasTagName(cursorTag)) {
+                    hotSpot.setX(int(static_cast<SVGCursorElement*>(e)->x()->value()));
+                    hotSpot.setY(int(static_cast<SVGCursorElement*>(e)->y()->value()));
+                    cimage = static_cast<SVGCursorElement*>(e)->cachedImage();
+                }
+            }
+#endif
+            if (!cimage)
+                continue;
+            if (cimage->image()->isNull())
+                break;
+            if (!cimage->isErrorImage()) {
+                return Cursor(cimage->image(), hotSpot);
+}
+        }
+    }
 
     switch (style ? style->cursor() : CURSOR_AUTO) {
         case CURSOR_AUTO: {
index ad19420b30357986753a27e82a1df5103b8f76f9..719680b56fc0edbe747c977d73b834f91a3a8c61 100644 (file)
@@ -48,6 +48,7 @@ class NSCursor;
 namespace WebCore {
 
     class Image;
+    class IntPoint;
 
 #if PLATFORM(WIN)
     typedef HCURSOR PlatformCursor;
@@ -69,7 +70,7 @@ namespace WebCore {
 #endif
         { }
 
-        Cursor(Image*);
+        Cursor(Image*, const IntPoint& hotspot);
         Cursor(const Cursor&);
         ~Cursor();
         Cursor& operator=(const Cursor&);
index d6625e472d6fd42c20fd2984421e2fb1824196b4..5854d100cef03577887a9ef0ae40fd8910227607 100644 (file)
@@ -29,6 +29,7 @@
 #import "BlockExceptions.h"
 #import "FoundationExtras.h"
 #import "Image.h"
+#import "IntPoint.h"
 
 @interface WebCoreCursorBundle : NSObject { }
 @end
@@ -41,14 +42,14 @@ namespace WebCore {
 // Simple NSCursor calls shouldn't need protection,
 // but creating a cursor with a bad image might throw.
 
-static NSCursor* createCustomCursor(Image* image)
+static NSCursor* createCustomCursor(Image* image, const IntPoint& hotspot)
 {
     // FIXME: The cursor won't animate.  Not sure if that's a big deal.
     NSImage* img = image->getNSImage();
     if (!img)
         return 0;
     BEGIN_BLOCK_OBJC_EXCEPTIONS;
-    return [[NSCursor alloc] initWithImage:img hotSpot:NSZeroPoint];
+    return [[NSCursor alloc] initWithImage:img hotSpot:hotspot];
     END_BLOCK_OBJC_EXCEPTIONS;
     return 0;
 }
@@ -74,8 +75,8 @@ static NSCursor* leakNamedCursor(const char* name, int x, int y)
     return 0;
 }
 
-Cursor::Cursor(Image* image)
-    : m_impl(HardRetainWithNSRelease(createCustomCursor(image)))
+Cursor::Cursor(Image* image, const IntPoint& hotspot)
+    : m_impl(HardRetainWithNSRelease(createCustomCursor(image, hotspot)))
 {
 }
 
index c11a951a0dcbf6c4789bf7c22a828923cb2617d0..fe35cce5651c416332ea119828ad40cb578c5930 100644 (file)
@@ -53,7 +53,7 @@ Cursor::~Cursor()
 {
 }
 
-Cursor::Cursor(Image*)
+Cursor::Cursor(Image*, const IntPoint&)
 {
     notImplemented();
 }
index 364be09db4a25e9fafa9269695b8fe6fad51bb7c..c98c10cdfa0670e0f63d8eb5cf44d2610109d104 100644 (file)
@@ -510,7 +510,7 @@ bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData&
 StyleInheritedData::StyleInheritedData()
     : indent(RenderStyle::initialTextIndent()), line_height(RenderStyle::initialLineHeight()), 
       style_image(RenderStyle::initialListStyleImage()),
-      cursor_image(0), color(RenderStyle::initialColor()), 
+      color(RenderStyle::initialColor()), 
       horizontal_border_spacing(RenderStyle::initialHorizontalBorderSpacing()), 
       vertical_border_spacing(RenderStyle::initialVerticalBorderSpacing()),
       widows(RenderStyle::initialWidows()), orphans(RenderStyle::initialOrphans()),
@@ -525,8 +525,8 @@ StyleInheritedData::~StyleInheritedData()
 StyleInheritedData::StyleInheritedData(const StyleInheritedData& o )
     : Shared<StyleInheritedData>(),
       indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ),
-      cursor_image( o.cursor_image ), font( o.font ),
-      color( o.color ),
+      cursorData(o.cursorData),
+      font( o.font ), color( o.color ),
       horizontal_border_spacing( o.horizontal_border_spacing ),
       vertical_border_spacing( o.vertical_border_spacing ),
       widows(o.widows), orphans(o.orphans), page_break_inside(o.page_break_inside)
@@ -539,7 +539,7 @@ bool StyleInheritedData::operator==(const StyleInheritedData& o) const
         indent == o.indent &&
         line_height == o.line_height &&
         style_image == o.style_image &&
-        cursor_image == o.cursor_image &&
+        cursorData  == o.cursorData &&
         font == o.font &&
         color == o.color &&
         horizontal_border_spacing == o.horizontal_border_spacing &&
@@ -827,7 +827,7 @@ RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
         !(inherited->indent == other->inherited->indent) ||
         !(inherited->line_height == other->inherited->line_height) ||
         !(inherited->style_image == other->inherited->style_image) ||
-        !(inherited->cursor_image == other->inherited->cursor_image) ||
+        !(inherited->cursorData  == other->inherited->cursorData) ||
         !(inherited->font == other->inherited->font) ||
         !(inherited->horizontal_border_spacing == other->inherited->horizontal_border_spacing) ||
         !(inherited->vertical_border_spacing == other->inherited->vertical_border_spacing) ||
@@ -986,6 +986,35 @@ void RenderStyle::setClip( Length top, Length right, Length bottom, Length left
     data->clip.left = left;
 }
 
+void RenderStyle::addCursor(CachedImage* image, const IntPoint& hotSpot)
+{
+    CursorData data;
+    data.cursorImage = image;
+    data.hotSpot = hotSpot;
+    if (!inherited.access()->cursorData)
+        inherited.access()->cursorData = new CursorList;
+    inherited.access()->cursorData->append(data);
+}
+
+void RenderStyle::addSVGCursor(const String& fragmentId)
+{
+    CursorData data;
+    data.cursorFragmentId = fragmentId;
+    if (!inherited.access()->cursorData)
+        inherited.access()->cursorData = new CursorList;
+    inherited.access()->cursorData->append(data);
+}
+
+void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
+{
+    inherited.access()->cursorData = other;
+}
+
+void RenderStyle::clearCursorList()
+{
+    inherited.access()->cursorData = new CursorList;
+}
+
 bool RenderStyle::contentDataEquivalent(const RenderStyle* otherStyle) const
 {
     ContentData* c1 = content;
index 14d327fd792680b39ba9b2af8dcd1289dff674de..d730f0d5e01886f47bb5404a89382525bcd555b4 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 #include "Color.h"
+#include "CSSCursorImageValue.h"
 #include "DataRef.h"
 #include "Font.h"
 #include "GraphicsTypes.h"
@@ -62,6 +63,8 @@ using std::max;
 class CSSStyleSelector;
 class CachedImage;
 class CachedResource;
+struct CursorData;
+class CursorList;
 class RenderArena;
 class ShadowValue;
 class StringImpl;
@@ -824,7 +827,7 @@ public:
     Length line_height;
 
     CachedImage *style_image;
-    CachedImage *cursor_image;
+    RefPtr<CursorList> cursorData;
 
     Font font;
     Color color;
@@ -868,6 +871,29 @@ enum ECursor {
     CURSOR_COL_RESIZE, CURSOR_ROW_RESIZE, CURSOR_TEXT, CURSOR_WAIT, CURSOR_HELP
 };
 
+struct CursorData {
+    CursorData()
+        : cursorImage(0)
+    {}
+    
+    IntPoint hotSpot; // for CSS3 support
+    CachedImage* cursorImage; // weak pointer, the CSSValueImage takes care of deleting cursorImage
+    String cursorFragmentId; // only used for SVGCursorElement, a direct pointer would get stale
+};
+
+class CursorList : public Shared<CursorList> {
+public:
+    const CursorData& operator[](int i) const {
+        return m_vector[i];
+    }
+
+    size_t size() const { return m_vector.size(); }
+    void append(const CursorData& cursorData) { m_vector.append(cursorData); }
+
+private:
+    Vector<CursorData> m_vector;
+};
+
 enum ContentType {
     CONTENT_NONE, CONTENT_OBJECT, CONTENT_TEXT, CONTENT_COUNTER
 };
@@ -1314,7 +1340,7 @@ public:
 
     ECursor cursor() const { return static_cast<ECursor>(inherited_flags._cursor_style); }
     
-    CachedImage *cursorImage() const { return inherited->cursor_image; }
+    CursorList* cursors() const { return inherited->cursorData.get(); }
 
     short widows() const { return inherited->widows; }
     short orphans() const { return inherited->orphans; }
@@ -1521,7 +1547,10 @@ public:
     void setPaddingRight(Length v)  {  SET_VAR(surround,padding.right,v) }
 
     void setCursor( ECursor c ) { inherited_flags._cursor_style = c; }
-    void setCursorImage( CachedImage *v ) { SET_VAR(inherited,cursor_image,v) }
+    void addCursor(CachedImage*, const IntPoint& = IntPoint());
+    void addSVGCursor(const String&);
+    void setCursorList(PassRefPtr<CursorList>);
+    void clearCursorList();
 
     bool forceBackgroundsToWhite() const { return inherited_flags._force_backgrounds_to_white; }
     void setForceBackgroundsToWhite(bool b=true) { inherited_flags._force_backgrounds_to_white = b; }