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 "DocLoader.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 "SVGURIReference.h" 34 #endif 35 36 namespace WebCore { 37 38 #if ENABLE(SVG) 39 static inline bool isSVGCursorIdentifier(const String& url) 40 { 41 KURL kurl(ParsedURLString, url); 42 return kurl.hasFragmentIdentifier(); 43 } 44 45 static inline SVGCursorElement* resourceReferencedByCursorElement(const String& fragmentId, Document* document) 46 { 47 Element* element = document->getElementById(SVGURIReference::getTarget(fragmentId)); 48 if (element && element->hasTagName(SVGNames::cursorTag)) 49 return static_cast<SVGCursorElement*>(element); 50 51 return 0; 52 } 53 #endif 54 55 CSSCursorImageValue::CSSCursorImageValue(const String& url, const IntPoint& hotspot) 56 : CSSImageValue(url) 57 , m_hotspot(hotspot) 58 { 59 } 60 61 CSSCursorImageValue::~CSSCursorImageValue() 62 { 63 #if ENABLE(SVG) 64 const String& url = getStringValue(); 65 if (!isSVGCursorIdentifier(url)) 66 return; 67 68 HashSet<SVGElement*>::const_iterator it = m_referencedElements.begin(); 69 HashSet<SVGElement*>::const_iterator end = m_referencedElements.end(); 70 71 for (; it != end; ++it) { 72 SVGElement* referencedElement = *it; 73 referencedElement->setCursorImageValue(0); 74 if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, referencedElement->document())) 75 cursorElement->removeClient(referencedElement); 76 } 77 #endif 78 } 79 80 bool CSSCursorImageValue::updateIfSVGCursorIsUsed(Element* element) 81 { 82 #if !ENABLE(SVG) 83 UNUSED_PARAM(element); 84 #else 85 if (!element || !element->isSVGElement()) 86 return false; 87 88 const String& url = getStringValue(); 89 if (!isSVGCursorIdentifier(url)) 90 return false; 91 92 if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, element->document())) { 93 float x = roundf(cursorElement->x().value(0)); 94 m_hotspot.setX(static_cast<int>(x)); 95 96 float y = roundf(cursorElement->y().value(0)); 97 m_hotspot.setY(static_cast<int>(y)); 98 99 if (cachedImageURL() != element->document()->completeURL(cursorElement->href())) 100 clearCachedImage(); 101 102 SVGElement* svgElement = static_cast<SVGElement*>(element); 103 m_referencedElements.add(svgElement); 104 svgElement->setCursorImageValue(this); 105 cursorElement->addClient(svgElement); 106 return true; 107 } 108 #endif 109 110 return false; 111 } 112 113 StyleCachedImage* CSSCursorImageValue::cachedImage(DocLoader* loader) 114 { 115 String url = getStringValue(); 116 117 #if ENABLE(SVG) 118 if (isSVGCursorIdentifier(url) && loader && loader->doc()) { 119 if (SVGCursorElement* cursorElement = resourceReferencedByCursorElement(url, loader->doc())) 120 url = cursorElement->href(); 121 } 122 #endif 123 124 return CSSImageValue::cachedImage(loader, url); 125 } 126 127 #if ENABLE(SVG) 128 void CSSCursorImageValue::removeReferencedElement(SVGElement* element) 129 { 130 m_referencedElements.remove(element); 131 } 132 #endif 133 134 } // namespace WebCore 135