| Index: Source/core/html/canvas/HitRegion.cpp
 | 
| diff --git a/Source/core/html/canvas/HitRegion.cpp b/Source/core/html/canvas/HitRegion.cpp
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..ba25dd998385f56c65fb577f303701a9a2716d9d
 | 
| --- /dev/null
 | 
| +++ b/Source/core/html/canvas/HitRegion.cpp
 | 
| @@ -0,0 +1,158 @@
 | 
| +// Copyright 2014 The Chromium Authors. All rights reserved.
 | 
| +// Use of this source code is governed by a BSD-style license that can be
 | 
| +// found in the LICENSE file.
 | 
| +
 | 
| +#include "config.h"
 | 
| +#include "core/html/canvas/HitRegion.h"
 | 
| +
 | 
| +#include "core/accessibility/AXObjectCache.h"
 | 
| +#include "core/rendering/RenderBoxModelObject.h"
 | 
| +
 | 
| +namespace WebCore {
 | 
| +
 | 
| +HitRegion::HitRegion(const HitRegionOptions& options)
 | 
| +    : m_id(options.id)
 | 
| +    , m_control(options.control)
 | 
| +    , m_path(options.path)
 | 
| +{
 | 
| +}
 | 
| +
 | 
| +void HitRegion::updateAccessibility(Element* canvas)
 | 
| +{
 | 
| +    if (!m_control || !canvas || !canvas->renderer() || !m_control->isDescendantOf(canvas))
 | 
| +        return;
 | 
| +
 | 
| +    AXObjectCache* axObjectCache = m_control->document().existingAXObjectCache();
 | 
| +    if (!axObjectCache)
 | 
| +        return;
 | 
| +
 | 
| +    FloatRect boundingRect = m_path.boundingRect();
 | 
| +
 | 
| +    // Offset by the canvas rect, taking border and padding into account.
 | 
| +    RenderBoxModelObject* rbmo = canvas->renderBoxModelObject();
 | 
| +    IntRect canvasRect = canvas->renderer()->absoluteBoundingBoxRect();
 | 
| +    canvasRect.move(rbmo->borderLeft() + rbmo->paddingLeft(),
 | 
| +        rbmo->borderTop() + rbmo->paddingTop());
 | 
| +    LayoutRect elementRect = enclosingLayoutRect(boundingRect);
 | 
| +    elementRect.moveBy(canvasRect.location());
 | 
| +
 | 
| +    axObjectCache->setCanvasObjectBounds(m_control.get(), elementRect);
 | 
| +}
 | 
| +
 | 
| +bool HitRegion::contains(const LayoutPoint& point) const
 | 
| +{
 | 
| +    if (!m_path.boundingRect().contains(point))
 | 
| +        return false;
 | 
| +
 | 
| +    return m_path.contains(point, RULE_NONZERO);
 | 
| +}
 | 
| +
 | 
| +void HitRegion::removePixels(const Path& clearArea)
 | 
| +{
 | 
| +    m_path.subtractPath(clearArea);
 | 
| +}
 | 
| +
 | 
| +void HitRegion::trace(Visitor* visitor)
 | 
| +{
 | 
| +    visitor->trace(m_control);
 | 
| +}
 | 
| +
 | 
| +void HitRegionManager::addHitRegion(PassRefPtrWillBeRawPtr<HitRegion> passHitRegion)
 | 
| +{
 | 
| +    RefPtrWillBeRawPtr<HitRegion> hitRegion = passHitRegion;
 | 
| +
 | 
| +    m_hitRegionList.add(hitRegion);
 | 
| +
 | 
| +    if (!hitRegion->id().isEmpty())
 | 
| +        m_hitRegionIdMap.set(hitRegion->id(), hitRegion);
 | 
| +
 | 
| +    if (hitRegion->control())
 | 
| +        m_hitRegionControlMap.set(hitRegion->control(), hitRegion);
 | 
| +}
 | 
| +
 | 
| +void HitRegionManager::removeHitRegion(HitRegion* hitRegion)
 | 
| +{
 | 
| +    if (!hitRegion)
 | 
| +        return;
 | 
| +
 | 
| +    if (!hitRegion->id().isEmpty())
 | 
| +        m_hitRegionIdMap.remove(hitRegion->id());
 | 
| +
 | 
| +    if (hitRegion->control())
 | 
| +        m_hitRegionControlMap.remove(hitRegion->control());
 | 
| +
 | 
| +    m_hitRegionList.remove(hitRegion);
 | 
| +}
 | 
| +
 | 
| +void HitRegionManager::removeHitRegionById(const String& id)
 | 
| +{
 | 
| +    if (!id.isEmpty())
 | 
| +        removeHitRegion(getHitRegionById(id));
 | 
| +}
 | 
| +
 | 
| +void HitRegionManager::removeHitRegionByControl(Element* control)
 | 
| +{
 | 
| +    removeHitRegion(getHitRegionByControl(control));
 | 
| +}
 | 
| +
 | 
| +void HitRegionManager::removeHitRegionsInRect(const FloatRect& rect, const AffineTransform& ctm)
 | 
| +{
 | 
| +    Path clearArea;
 | 
| +    clearArea.addRect(rect);
 | 
| +    clearArea.transform(ctm);
 | 
| +
 | 
| +    HitRegionIterator itEnd = m_hitRegionList.rend();
 | 
| +
 | 
| +    for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) {
 | 
| +        RefPtrWillBeRawPtr<HitRegion> hitRegion = *it;
 | 
| +        hitRegion->removePixels(clearArea);
 | 
| +        if (hitRegion->path().isEmpty())
 | 
| +            removeHitRegion(hitRegion.get());
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +void HitRegionManager::removeAllHitRegions()
 | 
| +{
 | 
| +    m_hitRegionList.clear();
 | 
| +    m_hitRegionIdMap.clear();
 | 
| +}
 | 
| +
 | 
| +HitRegion* HitRegionManager::getHitRegionById(const String& id) const
 | 
| +{
 | 
| +    return m_hitRegionIdMap.get(id);
 | 
| +}
 | 
| +
 | 
| +HitRegion* HitRegionManager::getHitRegionByControl(Element* control) const
 | 
| +{
 | 
| +    if (control)
 | 
| +        return m_hitRegionControlMap.get(control);
 | 
| +
 | 
| +    return 0;
 | 
| +}
 | 
| +
 | 
| +HitRegion* HitRegionManager::getHitRegionAtPoint(const LayoutPoint& point) const
 | 
| +{
 | 
| +    HitRegionIterator itEnd = m_hitRegionList.rend();
 | 
| +
 | 
| +    for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) {
 | 
| +        RefPtrWillBeRawPtr<HitRegion> hitRegion = *it;
 | 
| +        if (hitRegion->contains(point))
 | 
| +            return hitRegion.get();
 | 
| +    }
 | 
| +
 | 
| +    return 0;
 | 
| +}
 | 
| +
 | 
| +unsigned HitRegionManager::getHitRegionsCount() const
 | 
| +{
 | 
| +    return m_hitRegionList.size();
 | 
| +}
 | 
| +
 | 
| +void HitRegionManager::trace(Visitor* visitor)
 | 
| +{
 | 
| +    visitor->trace(m_hitRegionList);
 | 
| +    visitor->trace(m_hitRegionIdMap);
 | 
| +    visitor->trace(m_hitRegionControlMap);
 | 
| +}
 | 
| +
 | 
| +} // namespace WebCore
 | 
| 
 |