• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  * Copyright (C) 2004, 2005, 2006, 2009 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 "HTMLAreaElement.h"
24 
25 #include "HTMLNames.h"
26 #include "HitTestResult.h"
27 #include "MappedAttribute.h"
28 #include "Path.h"
29 #include "RenderObject.h"
30 
31 using namespace std;
32 
33 namespace WebCore {
34 
35 using namespace HTMLNames;
36 
HTMLAreaElement(const QualifiedName & tagName,Document * document)37 HTMLAreaElement::HTMLAreaElement(const QualifiedName& tagName, Document* document)
38     : HTMLAnchorElement(tagName, document)
39     , m_coords(0)
40     , m_coordsLen(0)
41     , m_lastSize(-1, -1)
42     , m_shape(Unknown)
43 {
44     ASSERT(hasTagName(areaTag));
45 }
46 
~HTMLAreaElement()47 HTMLAreaElement::~HTMLAreaElement()
48 {
49     delete [] m_coords;
50 }
51 
parseMappedAttribute(MappedAttribute * attr)52 void HTMLAreaElement::parseMappedAttribute(MappedAttribute* attr)
53 {
54     if (attr->name() == shapeAttr) {
55         if (equalIgnoringCase(attr->value(), "default"))
56             m_shape = Default;
57         else if (equalIgnoringCase(attr->value(), "circle"))
58             m_shape = Circle;
59         else if (equalIgnoringCase(attr->value(), "poly"))
60             m_shape = Poly;
61         else if (equalIgnoringCase(attr->value(), "rect"))
62             m_shape = Rect;
63     } else if (attr->name() == coordsAttr) {
64         delete [] m_coords;
65         m_coords = newCoordsArray(attr->value().string(), m_coordsLen);
66     } else if (attr->name() == altAttr || attr->name() == accesskeyAttr) {
67         // Do nothing.
68     } else
69         HTMLAnchorElement::parseMappedAttribute(attr);
70 }
71 
mapMouseEvent(int x,int y,const IntSize & size,HitTestResult & result)72 bool HTMLAreaElement::mapMouseEvent(int x, int y, const IntSize& size, HitTestResult& result)
73 {
74     if (m_lastSize != size) {
75         m_region.set(new Path(getRegion(size)));
76         m_lastSize = size;
77     }
78 
79     if (!m_region->contains(IntPoint(x, y)))
80         return false;
81 
82     result.setInnerNode(this);
83     result.setURLElement(this);
84     return true;
85 }
86 
getRect(RenderObject * obj) const87 IntRect HTMLAreaElement::getRect(RenderObject* obj) const
88 {
89     // FIXME: This doesn't work correctly with transforms.
90     FloatPoint absPos = obj->localToAbsolute();
91     Path p = getRegion(m_lastSize);
92     p.translate(absPos - FloatPoint());
93     return enclosingIntRect(p.boundingRect());
94 }
95 
getRegion(const IntSize & size) const96 Path HTMLAreaElement::getRegion(const IntSize& size) const
97 {
98     if (!m_coords && m_shape != Default)
99         return Path();
100 
101     int width = size.width();
102     int height = size.height();
103 
104     // If element omits the shape attribute, select shape based on number of coordinates.
105     Shape shape = m_shape;
106     if (shape == Unknown) {
107         if (m_coordsLen == 3)
108             shape = Circle;
109         else if (m_coordsLen == 4)
110             shape = Rect;
111         else if (m_coordsLen >= 6)
112             shape = Poly;
113     }
114 
115     Path path;
116     switch (shape) {
117         case Poly:
118             if (m_coordsLen >= 6) {
119                 int numPoints = m_coordsLen / 2;
120                 path.moveTo(FloatPoint(m_coords[0].calcMinValue(width), m_coords[1].calcMinValue(height)));
121                 for (int i = 1; i < numPoints; ++i)
122                     path.addLineTo(FloatPoint(m_coords[i * 2].calcMinValue(width), m_coords[i * 2 + 1].calcMinValue(height)));
123                 path.closeSubpath();
124             }
125             break;
126         case Circle:
127             if (m_coordsLen >= 3) {
128                 Length radius = m_coords[2];
129                 int r = min(radius.calcMinValue(width), radius.calcMinValue(height));
130                 path.addEllipse(FloatRect(m_coords[0].calcMinValue(width) - r, m_coords[1].calcMinValue(height) - r, 2 * r, 2 * r));
131             }
132             break;
133         case Rect:
134             if (m_coordsLen >= 4) {
135                 int x0 = m_coords[0].calcMinValue(width);
136                 int y0 = m_coords[1].calcMinValue(height);
137                 int x1 = m_coords[2].calcMinValue(width);
138                 int y1 = m_coords[3].calcMinValue(height);
139                 path.addRect(FloatRect(x0, y0, x1 - x0, y1 - y0));
140             }
141             break;
142         case Default:
143             path.addRect(FloatRect(0, 0, width, height));
144             break;
145         case Unknown:
146             break;
147     }
148 
149     return path;
150 }
151 
href() const152 KURL HTMLAreaElement::href() const
153 {
154     return document()->completeURL(getAttribute(hrefAttr));
155 }
156 
noHref() const157 bool HTMLAreaElement::noHref() const
158 {
159     return !getAttribute(nohrefAttr).isNull();
160 }
161 
setNoHref(bool noHref)162 void HTMLAreaElement::setNoHref(bool noHref)
163 {
164     setAttribute(nohrefAttr, noHref ? "" : 0);
165 }
166 
isFocusable() const167 bool HTMLAreaElement::isFocusable() const
168 {
169     return HTMLElement::isFocusable();
170 }
171 
target() const172 String HTMLAreaElement::target() const
173 {
174     return getAttribute(targetAttr);
175 }
176 
177 }
178