Chromium Code Reviews| Index: Source/core/rendering/RenderObject.cpp |
| diff --git a/Source/core/rendering/RenderObject.cpp b/Source/core/rendering/RenderObject.cpp |
| index a08b09ea579df1363cce8c85ad388e62bab2db78..05056d340300993bb5801f676ed48140178f79e7 100644 |
| --- a/Source/core/rendering/RenderObject.cpp |
| +++ b/Source/core/rendering/RenderObject.cpp |
| @@ -34,6 +34,7 @@ |
| #include "core/editing/FrameSelection.h" |
| #include "core/editing/htmlediting.h" |
| #include "core/html/HTMLElement.h" |
| +#include "core/html/HTMLFrameOwnerElement.h" |
| #include "core/page/EventHandler.h" |
| #include "core/page/Frame.h" |
| #include "core/page/FrameView.h" |
| @@ -639,6 +640,53 @@ RenderNamedFlowThread* RenderObject::renderNamedFlowThreadWrapper() const |
| return object && object->isRenderNamedFlowThread() ? toRenderNamedFlowThread(object) : 0; |
| } |
| +void RenderObject::enclosingCompositedLayerAndOffset(const RenderLayer** enclosingCompositedLayer, LayoutPoint& offset) const |
| +{ |
| + // Determine the new compositing layer and the offset from it. |
| + RenderLayer* layer = enclosingLayer(); |
| + *enclosingCompositedLayer = layer->enclosingCompositingLayerForRepaint(); |
| + |
| + if (!*enclosingCompositedLayer) { |
| + if (document()) { |
| + if (HTMLFrameOwnerElement* ownerElement = document()->ownerElement()) { |
| + if (RenderObject* parentDocRenderer = ownerElement->renderer()) { |
| + // Nearest composited layer is in another document. |
| + // TODO There must be a simpler way to achieve this! |
| + // Would it be simpler to use FrameView::contentsToWindow/windowToContents as in |
| + // convertTargetSpaceQuadToCompositedLayer in LinkHighlight.cpp? |
| + |
| + // First get the offset of this frame within the composited layer. |
| + parentDocRenderer->enclosingCompositedLayerAndOffset(enclosingCompositedLayer, offset); |
| + |
| + // Add the offset of the frame contents within the frame (i.e. border+padding). |
| + if (parentDocRenderer->isBox()) |
| + offset.moveBy(toRenderBox(parentDocRenderer)->contentBoxRect().location()); |
| + |
| + // Now add the offset of this object within our frame. |
| + TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); |
| + mapLocalToContainer(view(), transformState, ApplyContainerFlip | UseTransforms); |
| + transformState.flatten(); |
| + offset.moveBy(LayoutPoint(transformState.lastPlanarPoint())); |
| + |
| + // And subtract the scroll offset of this frame. |
| + offset -= frame()->view()->scrollOffset(); |
| + } |
| + } |
| + } |
| + return; |
| + } |
| + |
| + // Self-painting layers subtract the renderer's location. Otherwise, we need to map our location to layer space. |
| + if ((*enclosingCompositedLayer)->renderer() == this) { |
| + offset = LayoutPoint(); |
| + } else { |
| + TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint()); |
| + mapLocalToContainer((*enclosingCompositedLayer)->renderer(), transformState, ApplyContainerFlip | UseTransforms); |
| + transformState.flatten(); |
| + offset = LayoutPoint(transformState.lastPlanarPoint()); |
| + } |
| +} |
| + |
| RenderBlock* RenderObject::firstLineBlock() const |
| { |
| return 0; |
| @@ -2267,6 +2315,49 @@ LayoutRect RenderObject::localCaretRect(InlineBox*, int, LayoutUnit* extraWidthT |
| return LayoutRect(); |
| } |
| +void RenderObject::computeLayerHitTestRects(LayerHitTestRects& layerRects) const |
| +{ |
| + // Figure out what composited layer our container is in. Any offset (or new layer) for this |
| + // renderer within it's container will be applied in addLayerHitTestRects. |
| + LayoutPoint layerOffset; |
| + const RenderLayer* currentCompositedLayer; |
| + if (container()) |
| + container()->enclosingCompositedLayerAndOffset(¤tCompositedLayer, layerOffset); |
| + else |
| + enclosingCompositedLayerAndOffset(¤tCompositedLayer, layerOffset); |
| + if (!currentCompositedLayer) |
| + return; |
| + |
| + this->addLayerHitTestRects(layerRects, currentCompositedLayer, layerOffset); |
| +} |
| + |
| +void RenderObject::addLayerHitTestRects(LayerHitTestRects& layerRects, const RenderLayer* currentCompositedLayer, const LayoutPoint& layerOffset) const |
| +{ |
| + ASSERT(currentCompositedLayer); |
| + |
| + // If it's possible for children to have rects outside our bounds, then we need to descend into the |
| + // children and compute them. |
| + // TODO: Any tighter guarantee on when we don't need to descend into children? |
|
leviw_travelin_and_unemployed
2013/07/10 01:51:16
I don't think there's any tighter guarantee, but g
|
| + // TODO: Should I improve Region and use it? https://bugs.webkit.org/show_bug.cgi?id=100814 |
| + if (!isRoot()) { |
| + for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
| + // TODO: levi's original patch excluded curr->isText(), curr->isListMarker() and !curr->isBox(). Why? |
|
leviw_travelin_and_unemployed
2013/07/10 01:51:16
I can't recall on the latter two, but text nodes a
|
| + curr->addLayerHitTestRects(layerRects, currentCompositedLayer, layerOffset); |
| + } |
| + } |
| + |
| + // Compute the rects for this renderer only and add them to the results. |
| + // TODO: We could avoid passing the offset here and instead offset each result. |
| + Vector<IntRect> ownRects; |
| + computeOwnHitTestRects(ownRects, layerOffset); |
| + |
| + LayerHitTestRects::iterator iter = layerRects.find(currentCompositedLayer); |
| + if (iter == layerRects.end()) |
| + layerRects.add(currentCompositedLayer, ownRects); |
| + else |
| + iter->value.append(ownRects); |
| +} |
| + |
| bool RenderObject::isRooted(RenderView** view) const |
| { |
| const RenderObject* o = this; |