2c7f2717bd982bb8dd72d5d71983c1c56196e39a
[WebKit-https.git] / WebCore / html / HTMLAreaElement.cpp
1 /**
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB.  If not, write to
20  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23 #include "config.h"
24 #include "HTMLAreaElement.h"
25
26 #include "Document.h"
27 #include "HTMLNames.h"
28 #include "FloatRect.h"
29 #include "IntSize.h"
30
31 using namespace std;
32
33 namespace WebCore {
34
35 using namespace HTMLNames;
36
37 HTMLAreaElement::HTMLAreaElement(Document *doc)
38     : HTMLAnchorElement(areaTag, doc)
39     , m_coords(0)
40     , m_coordsLen(0)
41     , m_lastSize(-1, -1)
42     , m_shape(Unknown)
43 {
44 }
45
46 HTMLAreaElement::~HTMLAreaElement()
47 {
48     delete [] m_coords;
49 }
50
51 void HTMLAreaElement::parseMappedAttribute(MappedAttribute *attr)
52 {
53     if (attr->name() == shapeAttr) {
54         if (equalIgnoringCase(attr->value(), "default"))
55             m_shape = Default;
56         else if (equalIgnoringCase(attr->value(), "circle"))
57             m_shape = Circle;
58         else if (equalIgnoringCase(attr->value(), "poly"))
59             m_shape = Poly;
60         else if (equalIgnoringCase(attr->value(), "rect"))
61             m_shape = Rect;
62     } else if (attr->name() == coordsAttr) {
63         delete [] m_coords;
64         m_coords = attr->value().toCoordsArray(m_coordsLen);
65     } else if (attr->name() == altAttr || attr->name() == accesskeyAttr) {
66         // Do nothing.
67     } else
68         HTMLAnchorElement::parseMappedAttribute(attr);
69 }
70
71 bool HTMLAreaElement::mapMouseEvent(int x, int y, const IntSize& size, RenderObject::NodeInfo& info)
72 {
73     if (m_lastSize != size) {
74         region = getRegion(size);
75         m_lastSize = size;
76     }
77
78     if (!region.contains(IntPoint(x, y)))
79         return false;
80     
81     info.setInnerNode(this);
82     info.setURLElement(this);
83     return true;
84 }
85
86 IntRect HTMLAreaElement::getRect(RenderObject* obj) const
87 {
88     int dx, dy;
89     obj->absolutePosition(dx, dy);
90     Path p = getRegion(m_lastSize);
91     p.translate(IntSize(dx, dy));
92     return enclosingIntRect(p.boundingRect());
93 }
94
95 Path HTMLAreaElement::getRegion(const IntSize& size) const
96 {
97     if (!m_coords)
98         return Path();
99         
100     int width = size.width();
101     int height = size.height();
102
103     // If element omits the shape attribute, select shape based on number of coordinates.
104     Shape shape = m_shape;
105     if (shape == Unknown) {
106         if (m_coordsLen == 3)
107             shape = Circle;
108         else if (m_coordsLen == 4)
109             shape = Rect;
110         else if (m_coordsLen >= 6)
111             shape = Poly;
112     }
113
114     Path path;
115     switch (shape) {
116         case Poly:
117             if (m_coordsLen >= 6) {
118                 int numPoints = m_coordsLen / 2;
119                 path.moveTo(FloatPoint(m_coords[0].calcMinValue(width), m_coords[1].calcMinValue(height)));
120                 for (int i = 1; i < numPoints; ++i)
121                     path.addLineTo(FloatPoint(m_coords[i * 2].calcMinValue(width), m_coords[i * 2 + 1].calcMinValue(height)));
122                 path.closeSubpath();
123             }
124             break;
125         case Circle:
126             if (m_coordsLen >= 3) {
127                 Length radius = m_coords[2];
128                 int r = min(radius.calcMinValue(width), radius.calcMinValue(height));
129                 path.addEllipse(FloatRect(m_coords[0].calcMinValue(width) - r, m_coords[1].calcMinValue(height) - r, 2 * r, 2 * r));
130             }
131             break;
132         case Rect:
133             if (m_coordsLen >= 4) {
134                 int x0 = m_coords[0].calcMinValue(width);
135                 int y0 = m_coords[1].calcMinValue(height);
136                 int x1 = m_coords[2].calcMinValue(width);
137                 int y1 = m_coords[3].calcMinValue(height);
138                 path.addRect(FloatRect(x0, y0, x1 - x0, y1 - y0));
139             }
140             break;
141         case Default:
142             path.addRect(FloatRect(0, 0, width, height));
143             break;
144         case Unknown:
145             break;
146     }
147
148     return path;
149 }
150
151 String HTMLAreaElement::accessKey() const
152 {
153     return getAttribute(accesskeyAttr);
154 }
155
156 void HTMLAreaElement::setAccessKey(const String& value)
157 {
158     setAttribute(accesskeyAttr, value);
159 }
160
161 String HTMLAreaElement::alt() const
162 {
163     return getAttribute(altAttr);
164 }
165
166 void HTMLAreaElement::setAlt(const String& value)
167 {
168     setAttribute(altAttr, value);
169 }
170
171 String HTMLAreaElement::coords() const
172 {
173     return getAttribute(coordsAttr);
174 }
175
176 void HTMLAreaElement::setCoords(const String& value)
177 {
178     setAttribute(coordsAttr, value);
179 }
180
181 String HTMLAreaElement::href() const
182 {
183     return document()->completeURL(getAttribute(hrefAttr));
184 }
185
186 void HTMLAreaElement::setHref(const String& value)
187 {
188     setAttribute(hrefAttr, value);
189 }
190
191 bool HTMLAreaElement::noHref() const
192 {
193     return !getAttribute(nohrefAttr).isNull();
194 }
195
196 void HTMLAreaElement::setNoHref(bool noHref)
197 {
198     setAttribute(nohrefAttr, noHref ? "" : 0);
199 }
200
201 String HTMLAreaElement::shape() const
202 {
203     return getAttribute(shapeAttr);
204 }
205
206 void HTMLAreaElement::setShape(const String& value)
207 {
208     setAttribute(shapeAttr, value);
209 }
210
211 int HTMLAreaElement::tabIndex() const
212 {
213     return getAttribute(tabindexAttr).toInt();
214 }
215
216 void HTMLAreaElement::setTabIndex(int tabIndex)
217 {
218     setAttribute(tabindexAttr, String::number(tabIndex));
219 }
220
221 String HTMLAreaElement::target() const
222 {
223     return getAttribute(targetAttr);
224 }
225
226 void HTMLAreaElement::setTarget(const String& value)
227 {
228     setAttribute(targetAttr, value);
229 }
230
231 }