Index: third_party/WebKit/Source/core/html/HTMLAreaElement.cpp |
diff --git a/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp b/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp |
index 11ffd7311a31beb671927a78a697d29056062b88..ab5fb707ad4d325122a93ecca2ced3ffdfbc70d9 100644 |
--- a/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp |
+++ b/third_party/WebKit/Source/core/html/HTMLAreaElement.cpp |
@@ -48,7 +48,6 @@ using namespace HTMLNames; |
inline HTMLAreaElement::HTMLAreaElement(Document& document) |
: HTMLAnchorElement(areaTag, document) |
- , m_lastSize(-1, -1) |
, m_shape(Rect) |
{ |
} |
@@ -78,10 +77,10 @@ void HTMLAreaElement::parseAttribute(const QualifiedName& name, const AtomicStri |
// 'shape' attribute is 'rect'. |
m_shape = Rect; |
} |
- invalidateCachedRegion(); |
+ invalidateCachedPath(); |
} else if (name == coordsAttr) { |
m_coords = parseHTMLListOfFloatingPointNumbers(value.getString()); |
- invalidateCachedRegion(); |
+ invalidateCachedPath(); |
} else if (name == altAttr || name == accesskeyAttr) { |
// Do nothing. |
} else { |
@@ -89,88 +88,94 @@ void HTMLAreaElement::parseAttribute(const QualifiedName& name, const AtomicStri |
} |
} |
-void HTMLAreaElement::invalidateCachedRegion() |
+void HTMLAreaElement::invalidateCachedPath() |
{ |
- m_lastSize = LayoutSize(-1, -1); |
+ m_path = nullptr; |
} |
-bool HTMLAreaElement::pointInArea(LayoutPoint location, const LayoutSize& containerSize) |
+bool HTMLAreaElement::pointInArea(const LayoutPoint& location, const LayoutObject* containerObject) const |
{ |
- if (m_lastSize != containerSize) { |
- m_region = adoptPtr(new Path(getRegion(containerSize))); |
- m_lastSize = containerSize; |
- } |
- |
- return m_region->contains(FloatPoint(location)); |
+ return getPath(containerObject).contains(FloatPoint(location)); |
} |
-Path HTMLAreaElement::computePath(const LayoutObject* obj) const |
+LayoutRect HTMLAreaElement::computeAbsoluteRect(const LayoutObject* containerObject) const |
{ |
- if (!obj) |
- return Path(); |
+ if (!containerObject) |
+ return LayoutRect(); |
// FIXME: This doesn't work correctly with transforms. |
- FloatPoint absPos = obj->localToAbsolute(); |
- |
- // Default should default to the size of the containing object. |
- LayoutSize size = m_lastSize; |
- if (m_shape == Default) |
- size = obj->absoluteClippedOverflowRect().size(); |
- |
- Path p = getRegion(size); |
- float zoomFactor = obj->style()->effectiveZoom(); |
- if (zoomFactor != 1.0f) { |
- AffineTransform zoomTransform; |
- zoomTransform.scale(zoomFactor); |
- p.transform(zoomTransform); |
- } |
- |
- p.translate(toFloatSize(absPos)); |
- return p; |
-} |
+ FloatPoint absPos = containerObject->localToAbsolute(); |
-LayoutRect HTMLAreaElement::computeRect(const LayoutObject* obj) const |
-{ |
- return enclosingLayoutRect(computePath(obj).boundingRect()); |
+ Path path = getPath(containerObject); |
+ path.translate(toFloatSize(absPos)); |
+ return enclosingLayoutRect(path.boundingRect()); |
} |
-Path HTMLAreaElement::getRegion(const LayoutSize& size) const |
+Path HTMLAreaElement::getPath(const LayoutObject* containerObject) const |
{ |
- if (m_coords.isEmpty() && m_shape != Default) |
+ if (!containerObject) |
return Path(); |
+ // Always recompute for default shape because it depends on container object's size |
+ // and is cheap. |
+ if (m_shape == Default) { |
+ Path path; |
+ // No need to zoom because it is already applied in containerObject->borderBoxRect(). |
+ if (containerObject->isBox()) |
+ path.addRect(FloatRect(toLayoutBox(containerObject)->borderBoxRect())); |
+ m_path = nullptr; |
+ return path; |
+ } |
+ |
Path path; |
- switch (m_shape) { |
- case Poly: |
- if (m_coords.size() >= 6) { |
- int numPoints = m_coords.size() / 2; |
- path.moveTo(FloatPoint(clampCoordinate(m_coords[0]), clampCoordinate(m_coords[1]))); |
- for (int i = 1; i < numPoints; ++i) |
- path.addLineTo(FloatPoint(clampCoordinate(m_coords[i * 2]), clampCoordinate(m_coords[i * 2 + 1]))); |
- path.closeSubpath(); |
- path.setWindRule(RULE_EVENODD); |
- } |
- break; |
- case Circle: |
- if (m_coords.size() >= 3 && m_coords[2] > 0) { |
- float r = clampCoordinate(m_coords[2]); |
- path.addEllipse(FloatRect(clampCoordinate(m_coords[0]) - r, clampCoordinate(m_coords[1]) - r, 2 * r, 2 * r)); |
- } |
- break; |
- case Rect: |
- if (m_coords.size() >= 4) { |
- float x0 = clampCoordinate(m_coords[0]); |
- float y0 = clampCoordinate(m_coords[1]); |
- float x1 = clampCoordinate(m_coords[2]); |
- float y1 = clampCoordinate(m_coords[3]); |
- path.addRect(FloatRect(x0, y0, x1 - x0, y1 - y0)); |
+ if (m_path) { |
+ path = *m_path; |
+ } else { |
+ if (m_coords.isEmpty()) |
+ return path; |
+ |
+ switch (m_shape) { |
+ case Poly: |
+ if (m_coords.size() >= 6) { |
+ int numPoints = m_coords.size() / 2; |
+ path.moveTo(FloatPoint(clampCoordinate(m_coords[0]), clampCoordinate(m_coords[1]))); |
+ for (int i = 1; i < numPoints; ++i) |
+ path.addLineTo(FloatPoint(clampCoordinate(m_coords[i * 2]), clampCoordinate(m_coords[i * 2 + 1]))); |
+ path.closeSubpath(); |
+ path.setWindRule(RULE_EVENODD); |
+ } |
+ break; |
+ case Circle: |
+ if (m_coords.size() >= 3 && m_coords[2] > 0) { |
+ float r = clampCoordinate(m_coords[2]); |
+ path.addEllipse(FloatRect(clampCoordinate(m_coords[0]) - r, clampCoordinate(m_coords[1]) - r, 2 * r, 2 * r)); |
+ } |
+ break; |
+ case Rect: |
+ if (m_coords.size() >= 4) { |
+ float x0 = clampCoordinate(m_coords[0]); |
+ float y0 = clampCoordinate(m_coords[1]); |
+ float x1 = clampCoordinate(m_coords[2]); |
+ float y1 = clampCoordinate(m_coords[3]); |
+ path.addRect(FloatRect(x0, y0, x1 - x0, y1 - y0)); |
+ } |
+ break; |
+ default: |
+ ASSERT_NOT_REACHED(); |
+ break; |
} |
- break; |
- case Default: |
- path.addRect(FloatRect(FloatPoint(0, 0), FloatSize(size))); |
- break; |
+ |
+ // Cache the original path, not depending on containerObject. |
+ m_path = adoptPtr(new Path(path)); |
} |
+ // Zoom the path into coordinates of the container object. |
+ float zoomFactor = containerObject->styleRef().effectiveZoom(); |
+ if (zoomFactor != 1.0f) { |
+ AffineTransform zoomTransform; |
+ zoomTransform.scale(zoomFactor); |
+ path.transform(zoomTransform); |
+ } |
return path; |
} |