HitRegion* HitRegionManager::getHitRegionAtPoint( const FloatPoint& point) const { HitRegionIterator itEnd = m_hitRegionList.rend(); for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) { HitRegion* hitRegion = *it; if (hitRegion->contains(point)) return hitRegion; } return nullptr; }
void CanvasRenderingContext2D::addHitRegion(const HitRegionOptions& options, ExceptionState& exceptionState) { if (options.id().isEmpty() && !options.control()) { exceptionState.throwDOMException(NotSupportedError, "Both id and control are null."); return; } if (options.control() && !canvas()->isSupportedInteractiveCanvasFallback(*options.control())) { exceptionState.throwDOMException(NotSupportedError, "The control is neither null nor a " "supported interactive canvas fallback " "element."); return; } Path hitRegionPath = options.hasPath() ? options.path()->path() : m_path; SkCanvas* c = drawingCanvas(); if (hitRegionPath.isEmpty() || !c || !state().isTransformInvertible() || !c->getClipDeviceBounds(0)) { exceptionState.throwDOMException(NotSupportedError, "The specified path has no pixels."); return; } hitRegionPath.transform(state().transform()); if (state().hasClip()) { hitRegionPath.intersectPath(state().getCurrentClipPath()); if (hitRegionPath.isEmpty()) exceptionState.throwDOMException(NotSupportedError, "The specified path has no pixels."); } if (!m_hitRegionManager) m_hitRegionManager = HitRegionManager::create(); // Remove previous region (with id or control) m_hitRegionManager->removeHitRegionById(options.id()); m_hitRegionManager->removeHitRegionByControl(options.control()); HitRegion* hitRegion = HitRegion::create(hitRegionPath, options); Element* element = hitRegion->control(); if (element && element->isDescendantOf(canvas())) updateElementAccessibility(hitRegion->path(), hitRegion->control()); m_hitRegionManager->addHitRegion(hitRegion); }
void HitRegionManager::removeHitRegionsInRect(const FloatRect& rect, const AffineTransform& ctm) { Path clearArea; clearArea.addRect(rect); clearArea.transform(ctm); HitRegionIterator itEnd = m_hitRegionList.rend(); HitRegionList toBeRemoved; for (HitRegionIterator it = m_hitRegionList.rbegin(); it != itEnd; ++it) { HitRegion* hitRegion = *it; hitRegion->removePixels(clearArea); if (hitRegion->path().isEmpty()) toBeRemoved.add(hitRegion); } itEnd = toBeRemoved.rend(); for (HitRegionIterator it = toBeRemoved.rbegin(); it != itEnd; ++it) removeHitRegion(it->get()); }
HitTestCanvasResult* CanvasRenderingContext2D::getControlAndIdIfHitRegionExists( const LayoutPoint& location) { if (hitRegionsCount() <= 0) return HitTestCanvasResult::create(String(), nullptr); LayoutBox* box = canvas()->layoutBox(); FloatPoint localPos = box->absoluteToLocal(FloatPoint(location), UseTransforms); if (box->hasBorderOrPadding()) localPos.move(-box->contentBoxOffset()); localPos.scale(canvas()->width() / box->contentWidth(), canvas()->height() / box->contentHeight()); HitRegion* hitRegion = hitRegionAtPoint(localPos); if (hitRegion) { Element* control = hitRegion->control(); if (control && canvas()->isSupportedInteractiveCanvasFallback(*control)) return HitTestCanvasResult::create(hitRegion->id(), hitRegion->control()); return HitTestCanvasResult::create(hitRegion->id(), nullptr); } return HitTestCanvasResult::create(String(), nullptr); }