1 /* 2 * Copyright (C) 2006 Rob Buis <buis (at) kde.org> 3 * (C) 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 4 * Copyright (C) 2008 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #include "config.h" 23 #include "CSSCursorImageValue.h" 24 25 #include "CachedResourceLoader.h" 26 #include "Document.h" 27 #include "PlatformString.h" 28 #include <wtf/MathExtras.h> 29 #include <wtf/UnusedParam.h> 30 31 #if ENABLE(SVG) 32 #include "SVGCursorElement.h" 33 #include "SVGNames.h" 34 #include "SVGURIReference.h" 35 #endif 36 37 namespace WebCore { 38 39 #if ENABLE(SVG) 40 static inline bool isSVGCursorIdentifier(const String& url) 41 { 42 KURL kurl(ParsedURLString, url); 43 return kurl.hasFragmentIdentifier(); 44 } 45 46 static inline SVGCursorElement* resourceReferencedByCursorElement(const String& fragmentId, Document* document) 47 { 48 Element* element = document->getElementById(SVGURIReference::getTarget(fragmentId)); 49 if (element && element->hasTagName(SVGNames::cursorTag)) 50 return static_cast<SVGCursorElement*>(element); 51 52 return 0; 53 } 54 #endif 55 56 CSSCursorImageValue::CSSCursorImageValue(const String& url, const IntPoint& hotSpot) 57 : CSSImageValue(url) 58 , m_hotSpot(hotSpot) 59 { 60 } 61 62 CSSCursorImageValue::~CSSCursorImageValue() 63 { 64 #if ENABLE(SVG) 65 const String& url = getStringValue(); 66 if (!isSVGCursorIdentifier(url)) 67 return; 68 69 HashSet<SVGElement*>::const_iterator it = m_referencedElements.begin(); 70 HashSet<SVGElement*>::const_iterator end = m_referencedElements.end(); 71 72 for (; it != end; ++it) { 73 SVGElement* referencedElement = *it; 74 referencedElement->cursorImageValueRemoved(); 75 if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->document())) 76 cursorElement->removeClient(referencedElement); 77 } 78 #endif 79 } 80 81 bool CSSCursorImageValue::updateIfSVGCursorIsUsed(Element* element) 82 { 83 #if !ENABLE(SVG) 84 UNUSED_PARAM(element); 85 #else 86 if (!element || !element->isSVGElement()) 87 return false; 88 89 const String& url = getStringValue(); 90 if (!isSVGCursorIdentifier(url)) 91 return false; 92 93 if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, element->document())) { 94 // FIXME: This will override hot spot specified in CSS, which is probably incorrect. 95 float x = roundf(cursorElement->x().value(0)); 96 m_hotSpot.setX(static_cast<int>(x)); 97 98 float y = roundf(cursorElement->y().value(0)); 99 m_hotSpot.setY(static_cast<int>(y)); 100 101 if (cachedImageURL() != element->document()->completeURL(cursorElement->href())) 102 clearCachedImage(); 103 104 SVGElement* svgElement = static_cast<SVGElement*>(element); 105 m_referencedElements.add(svgElement); 106 svgElement->setCursorImageValue(this); 107 cursorElement->addClient(svgElement); 108 return true; 109 } 110 #endif 111 112 return false; 113 } 114 115 StyleCachedImage* CSSCursorImageValue::cachedImage(CachedResourceLoader* loader) 116 { 117 String url = getStringValue(); 118 119 #if ENABLE(SVG) 120 if (isSVGCursorIdentifier(url) && loader && loader->document()) { 121 if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, loader->document())) 122 url = cursorElement->href(); 123 } 124 #endif 125 126 return CSSImageValue::cachedImage(loader, url); 127 } 128 129 #if ENABLE(SVG) 130 void CSSCursorImageValue::removeReferencedElement(SVGElement* element) 131 { 132 m_referencedElements.remove(element); 133 } 134 #endif 135 136 } // namespace WebCore 137