void LayoutGeometryMap::mapToAncestor(TransformState& transformState, const LayoutBoxModelObject* ancestor) const { // If the mapping includes something like columns, we have to go via layoutObjects. if (hasNonUniformStep()) { m_mapping.last().m_layoutObject->mapLocalToAncestor(ancestor, transformState, ApplyContainerFlip | m_mapCoordinatesFlags); transformState.flatten(); return; } bool inFixed = false; #if ENABLE(ASSERT) bool foundAncestor = !ancestor || (m_mapping.size() && m_mapping[0].m_layoutObject == ancestor); #endif for (int i = m_mapping.size() - 1; i >= 0; --i) { const LayoutGeometryMapStep& currentStep = m_mapping[i]; // If container is the root LayoutView (step 0) we want to apply its fixed position offset. if (i > 0 && currentStep.m_layoutObject == ancestor) { #if ENABLE(ASSERT) foundAncestor = true; #endif break; } // If this box has a transform, it acts as a fixed position container // for fixed descendants, which prevents the propagation of 'fixed' // unless the layer itself is also fixed position. if (i && currentStep.m_flags & HasTransform && !(currentStep.m_flags & IsFixedPosition)) inFixed = false; else if (currentStep.m_flags & IsFixedPosition) inFixed = true; ASSERT(!i == isTopmostLayoutView(currentStep.m_layoutObject)); if (!i) { // A null container indicates mapping through the root LayoutView, so including its transform (the page scale). if (!ancestor && currentStep.m_transform) transformState.applyTransform(*currentStep.m_transform.get()); } else { TransformState::TransformAccumulation accumulate = currentStep.m_flags & AccumulatingTransform ? TransformState::AccumulateTransform : TransformState::FlattenTransform; if (currentStep.m_transform) transformState.applyTransform(*currentStep.m_transform.get(), accumulate); else transformState.move(currentStep.m_offset.width(), currentStep.m_offset.height(), accumulate); } if (inFixed && !currentStep.m_offsetForFixedPosition.isZero()) { ASSERT(currentStep.m_layoutObject->isLayoutView()); transformState.move(currentStep.m_offsetForFixedPosition); } } ASSERT(foundAncestor); transformState.flatten(); }
void RenderGeometryMap::mapToContainer(TransformState& transformState, const RenderLayerModelObject* container) const { // If the mapping includes something like columns, we have to go via renderers. if (hasNonUniformStep()) { m_mapping.last().m_renderer->mapLocalToContainer(container, transformState, ApplyContainerFlip | m_mapCoordinatesFlags); transformState.flatten(); return; } bool inFixed = false; #if !ASSERT_DISABLED bool foundContainer = !container || (m_mapping.size() && m_mapping[0].m_renderer == container); #endif for (int i = m_mapping.size() - 1; i >= 0; --i) { const RenderGeometryMapStep& currentStep = m_mapping[i]; // If container is the RenderView (step 0) we want to apply its scroll offset. if (i > 0 && currentStep.m_renderer == container) { #if !ASSERT_DISABLED foundContainer = true; #endif break; } // If this box has a transform, it acts as a fixed position container // for fixed descendants, which prevents the propagation of 'fixed' // unless the layer itself is also fixed position. if (i && currentStep.m_hasTransform && !currentStep.m_isFixedPosition) inFixed = false; else if (currentStep.m_isFixedPosition) inFixed = true; if (!i) { // The root gets special treatment for fixed position if (inFixed) transformState.move(currentStep.m_offset.width(), currentStep.m_offset.height()); // A null container indicates mapping through the RenderView, so including its transform (the page scale). if (!container && currentStep.m_transform) transformState.applyTransform(*currentStep.m_transform.get()); } else { TransformState::TransformAccumulation accumulate = currentStep.m_accumulatingTransform ? TransformState::AccumulateTransform : TransformState::FlattenTransform; if (currentStep.m_transform) transformState.applyTransform(*currentStep.m_transform.get(), accumulate); else transformState.move(currentStep.m_offset.width(), currentStep.m_offset.height(), accumulate); } } ASSERT(foundContainer); transformState.flatten(); }
void RenderGeometryMap::mapToContainer(TransformState& transformState, const RenderBox* container) const { // If the mapping includes something like columns, we have to go via // renderers. if (hasNonUniformStep()) { m_mapping.last().m_renderer->mapLocalToContainer( container, transformState, ApplyContainerFlip | m_mapCoordinatesFlags); transformState.flatten(); return; } #if ENABLE(ASSERT) bool foundContainer = !container || (m_mapping.size() && m_mapping[0].m_renderer == container); #endif for (int i = m_mapping.size() - 1; i >= 0; --i) { const RenderGeometryMapStep& currentStep = m_mapping[i]; // If container is the root RenderView (step 0) we want to apply its fixed // position offset. if (i > 0 && currentStep.m_renderer == container) { #if ENABLE(ASSERT) foundContainer = true; #endif break; } ASSERT(!i == isTopmostRenderView(currentStep.m_renderer)); if (!i) { // A null container indicates mapping through the root RenderView, so // including its transform (the page scale). if (!container && currentStep.m_transform) transformState.applyTransform(*currentStep.m_transform.get()); } else { TransformState::TransformAccumulation accumulate = currentStep.m_accumulatingTransform ? TransformState::AccumulateTransform : TransformState::FlattenTransform; if (currentStep.m_transform) transformState.applyTransform(*currentStep.m_transform.get(), accumulate); else transformState.move(currentStep.m_offset.width(), currentStep.m_offset.height(), accumulate); } } ASSERT(foundContainer); transformState.flatten(); }
void SVGLayoutSupport::mapLocalToAncestor(const LayoutObject* object, const LayoutBoxModelObject* ancestor, TransformState& transformState) { transformState.applyTransform(object->localToSVGParentTransform()); LayoutObject* parent = object->parent(); // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the localToBorderBoxTransform // to map an element from SVG viewport coordinates to CSS box coordinates. // LayoutSVGRoot's mapLocalToAncestor method expects CSS box coordinates. if (parent->isSVGRoot()) transformState.applyTransform(toLayoutSVGRoot(parent)->localToBorderBoxTransform()); MapCoordinatesFlags mode = UseTransforms; parent->mapLocalToAncestor(ancestor, transformState, mode); }
void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed) { transformState.applyTransform(object->localToParentTransform()); RenderObject* parent = object->parent(); // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform // to map an element from SVG viewport coordinates to CSS box coordinates. // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates. if (parent->isSVGRoot()) transformState.applyTransform(toRenderSVGRoot(parent)->localToBorderBoxTransform()); MapCoordinatesFlags mode = UseTransforms; parent->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); }
void RenderMultiColumnFlowThread::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const { // First get the transform state's point into the block flow thread's physical coordinate space. parent()->mapAbsoluteToLocalPoint(mode, transformState); LayoutPoint transformPoint = roundedLayoutPoint(transformState.mappedPoint()); // Now walk through each region. const RenderMultiColumnSet* candidateColumnSet = nullptr; LayoutPoint candidatePoint; LayoutSize candidateContainerOffset; for (const auto& columnSet : childrenOfType<RenderMultiColumnSet>(*parent())) { candidateContainerOffset = columnSet.offsetFromContainer(parent(), LayoutPoint()); candidatePoint = transformPoint - candidateContainerOffset; candidateColumnSet = &columnSet; // We really have no clue what to do with overflow. We'll just use the closest region to the point in that case. LayoutUnit pointOffset = isHorizontalWritingMode() ? candidatePoint.y() : candidatePoint.x(); LayoutUnit regionOffset = isHorizontalWritingMode() ? columnSet.topLeftLocation().y() : columnSet.topLeftLocation().x(); if (pointOffset < regionOffset + columnSet.logicalHeight()) break; } // Once we have a good guess as to which region we hit tested through (and yes, this was just a heuristic, but it's // the best we could do), then we can map from the region into the flow thread. LayoutSize translationOffset = physicalTranslationFromRegionToFlow(candidateColumnSet, candidatePoint) + candidateContainerOffset; bool preserve3D = mode & UseTransforms && (parent()->style().preserves3D() || style().preserves3D()); if (mode & UseTransforms && shouldUseTransformFromContainer(parent())) { TransformationMatrix t; getTransformFromContainer(parent(), translationOffset, t); transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); } else transformState.move(translationOffset.width(), translationOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); }
void RenderView::mapLocalToContainer(const RenderLayerModelObject* paintInvalidationContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) const { ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == static_cast<bool>(mode & IsFixed)); if (!paintInvalidationContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } if ((mode & IsFixed) && m_frameView) { transformState.move(m_frameView->scrollOffsetForFixedPosition()); // IsFixed flag is only applicable within this RenderView. mode &= ~IsFixed; } if (paintInvalidationContainer == this) return; if (mode & TraverseDocumentBoundaries) { if (RenderObject* parentDocRenderer = frame()->ownerRenderer()) { transformState.move(-frame()->view()->scrollOffset()); if (parentDocRenderer->isBox()) transformState.move(toLayoutSize(toRenderBox(parentDocRenderer)->contentBoxRect().location())); parentDocRenderer->mapLocalToContainer(paintInvalidationContainer, transformState, mode, wasFixed, paintInvalidationState); return; } } }
void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const { ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == static_cast<bool>(mode & IsFixed)); if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } if (mode & IsFixed && m_frameView) transformState.move(m_frameView->scrollOffsetForFixedPosition()); if (repaintContainer == this) return; if (mode & TraverseDocumentBoundaries) { if (RenderObject* parentDocRenderer = frame()->ownerRenderer()) { transformState.move(-frame()->view()->scrollOffset()); if (parentDocRenderer->isBox()) transformState.move(toLayoutSize(toRenderBox(parentDocRenderer)->contentBoxRect().location())); parentDocRenderer->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); return; } } // If a container was specified, and was not 0 or the RenderView, // then we should have found it by now. ASSERT_ARG(repaintContainer, !repaintContainer); }
void SVGRenderBase::mapLocalToContainer(const RenderObject* object, RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) { ASSERT(!fixed); // We should have no fixed content in the SVG rendering tree. ASSERT(useTransforms); // Mapping a point through SVG w/o respecting transforms is useless. transformState.applyTransform(object->localToParentTransform()); object->parent()->mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState); }
void RenderBoxModelObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const { RenderObject* o = container(); if (!o) return; if (o->isRenderFlowThread()) transformState.move(o->columnOffset(LayoutPoint(transformState.mappedPoint()))); o->mapAbsoluteToLocalPoint(mode, transformState); LayoutSize containerOffset = offsetFromContainer(o, LayoutPoint()); if (!style()->hasOutOfFlowPosition() && o->hasColumns()) { RenderBlock* block = toRenderBlock(o); LayoutPoint point(roundedLayoutPoint(transformState.mappedPoint())); point -= containerOffset; block->adjustForColumnRect(containerOffset, point); } bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D()); if (mode & UseTransforms && shouldUseTransformFromContainer(o)) { TransformationMatrix t; getTransformFromContainer(o, containerOffset, t); transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); } else transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform); }
void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const { if (mode & UseTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } }
void RenderView::mapLocalToContainer(const RenderBox* paintInvalidationContainer, TransformState& transformState, MapCoordinatesFlags mode) const { if (!paintInvalidationContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } }
void RenderSVGRoot::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed , bool useTransforms, TransformState& transformState) const { ASSERT(!fixed); // We should have no fixed content in the SVG rendering tree. ASSERT(useTransforms); // mapping a point through SVG w/o respecting trasnforms is useless. // Transform to our border box and let RenderBox transform the rest of the way. transformState.applyTransform(localToBorderBoxTransform()); RenderBox::mapLocalToContainer(repaintContainer, fixed, useTransforms, transformState); }
void SVGRenderSupport::mapLocalToContainer(const RenderElement& renderer, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed) { AffineTransform transform; auto& parent = localToParentTransform(renderer, transform); transformState.applyTransform(transform); MapCoordinatesFlags mode = UseTransforms; parent.mapLocalToContainer(repaintContainer, transformState, mode, wasFixed); }
void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const { if (mode & IsFixed) transformState.move(frameView().scrollOffsetForFixedPosition()); if (mode & UseTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } }
void RenderView::mapAbsoluteToLocalPoint(bool fixed, bool useTransforms, TransformState& transformState) const { if (fixed && m_frameView) transformState.move(m_frameView->scrollOffsetForFixedPosition()); if (useTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } }
void RenderGeometryMap::mapToAbsolute(TransformState& transformState) const { // If the mapping includes something like columns, we have to go via renderers. if (hasNonUniformStep()) { bool fixed = false; m_mapping.last()->m_renderer->mapLocalToContainer(0, fixed, true, transformState, RenderObject::ApplyContainerFlip); return; } bool inFixed = false; for (int i = m_mapping.size() - 1; i >= 0; --i) { const RenderGeometryMapStep* currStep = m_mapping[i].get(); // If this box has a transform, it acts as a fixed position container // for fixed descendants, which prevents the propagation of 'fixed' // unless the layer itself is also fixed position. if (currStep->m_hasTransform && !currStep->m_isFixedPosition) inFixed = false; else if (currStep->m_isFixedPosition) inFixed = true; if (!i) { if (currStep->m_transform) transformState.applyTransform(*currStep->m_transform.get()); // The root gets special treatment for fixed position if (inFixed) transformState.move(currStep->m_offset.width(), currStep->m_offset.height()); } else { TransformState::TransformAccumulation accumulate = currStep->m_accumulatingTransform ? TransformState::AccumulateTransform : TransformState::FlattenTransform; if (currStep->m_transform) transformState.applyTransform(*currStep->m_transform.get(), accumulate); else transformState.move(currStep->m_offset.width(), currStep->m_offset.height(), accumulate); } } transformState.flatten(); }
void SVGLayoutSupport::mapLocalToContainer(const LayoutObject* object, const LayoutBoxModelObject* paintInvalidationContainer, TransformState& transformState, bool* wasFixed, const PaintInvalidationState* paintInvalidationState) { transformState.applyTransform(object->localToParentTransform()); if (paintInvalidationState && paintInvalidationState->canMapToContainer(paintInvalidationContainer)) { // |svgTransform| contains localToBorderBoxTransform mentioned below. transformState.applyTransform(paintInvalidationState->svgTransform()); transformState.move(paintInvalidationState->paintOffset()); return; } LayoutObject* parent = object->parent(); // At the SVG/HTML boundary (aka LayoutSVGRoot), we apply the localToBorderBoxTransform // to map an element from SVG viewport coordinates to CSS box coordinates. // LayoutSVGRoot's mapLocalToContainer method expects CSS box coordinates. if (parent->isSVGRoot()) transformState.applyTransform(toLayoutSVGRoot(parent)->localToBorderBoxTransform()); MapCoordinatesFlags mode = UseTransforms; parent->mapLocalToContainer(paintInvalidationContainer, transformState, mode, wasFixed, paintInvalidationState); }
void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState) const { // If a container was specified, and was not 0 or the RenderView, // then we should have found it by now. ASSERT_UNUSED(repaintContainer, !repaintContainer || repaintContainer == this); if (useTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, IntSize(), t); transformState.applyTransform(t); } if (fixed && m_frameView) transformState.move(m_frameView->scrollOffset()); }
void SVGLayoutSupport::mapAncestorToLocal(const LayoutObject& object, const LayoutBoxModelObject* ancestor, TransformState& transformState) { // |object| is either a LayoutSVGModelObject or a LayoutSVGBlock here. In // the former case, |object| can never be an ancestor while in the latter // the caller is responsible for doing the ancestor check. Because of this, // computing the transform to the SVG root is always what we want to do here. ASSERT(ancestor != &object); ASSERT(object.isSVGContainer() || object.isSVGShape() || object.isSVGImage() || object.isSVGText() || object.isSVGForeignObject()); AffineTransform localToSVGRoot; const LayoutSVGRoot& svgRoot = computeTransformToSVGRoot(object, localToSVGRoot); MapCoordinatesFlags mode = UseTransforms | ApplyContainerFlip; svgRoot.mapAncestorToLocal(ancestor, transformState, mode); transformState.applyTransform(localToSVGRoot); }
void RenderView::mapLocalToContainer(RenderBoxModelObject* repaintContainer, bool fixed, bool useTransforms, TransformState& transformState, ApplyContainerFlipOrNot, bool* wasFixed) const { // If a container was specified, and was not 0 or the RenderView, // then we should have found it by now. ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this); ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == fixed); if (!repaintContainer && useTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } if (fixed && m_frameView) transformState.move(m_frameView->scrollOffsetForFixedPosition()); }
void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const { // If a container was specified, and was not 0 or the RenderView, // then we should have found it by now. ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this); ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode & IsFixed)); if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) { TransformationMatrix t; getTransformFromContainer(0, LayoutSize(), t); transformState.applyTransform(t); } if (mode & IsFixed && m_frameView) transformState.move(m_frameView->scrollOffsetForFixedPosition()); }
void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, RenderBoxModelObject* repaintContainer, TransformState& transformState, bool* wasFixed) { transformState.applyTransform(object->localToParentTransform()); object->parent()->mapLocalToContainer(repaintContainer, false, true, transformState, wasFixed); }