mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Move transforms from RenderLayer to RenderBox.
This is more member data on RenderLayer that is now only used by RenderBox. R=eseidel@chromium.org Review URL: https://codereview.chromium.org/965013003
This commit is contained in:
parent
c8912dd14c
commit
f01bea301b
@ -149,10 +149,52 @@ void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle
|
||||
layer()->styleChanged(diff, oldStyle);
|
||||
}
|
||||
|
||||
updateTransform(oldStyle);
|
||||
|
||||
if (needsLayout() && oldStyle)
|
||||
RenderBlock::removePercentHeightDescendantIfNeeded(this);
|
||||
}
|
||||
|
||||
void RenderBox::updateTransformationMatrix()
|
||||
{
|
||||
if (m_transform) {
|
||||
m_transform->makeIdentity();
|
||||
style()->applyTransform(*m_transform, pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
|
||||
// FIXME(sky): We shouldn't need to do this once Skia has 4x4 matrix support.
|
||||
// Until then, 3d transforms don't work right.
|
||||
m_transform->makeAffine();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderBox::updateTransform(const RenderStyle* oldStyle)
|
||||
{
|
||||
if (oldStyle && style()->transformDataEquivalent(*oldStyle))
|
||||
return;
|
||||
|
||||
// hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
|
||||
// so check style too.
|
||||
bool localHasTransform = hasTransform() && style()->hasTransform();
|
||||
bool had3DTransform = has3DTransform();
|
||||
|
||||
bool hadTransform = m_transform;
|
||||
if (localHasTransform != hadTransform) {
|
||||
if (localHasTransform)
|
||||
m_transform = adoptPtr(new TransformationMatrix);
|
||||
else
|
||||
m_transform.clear();
|
||||
|
||||
// Layers with transforms act as clip rects roots, so clear the cached clip rects here.
|
||||
layer()->clipper().clearClipRectsIncludingDescendants();
|
||||
} else if (localHasTransform) {
|
||||
layer()->clipper().clearClipRectsIncludingDescendants(AbsoluteClipRects);
|
||||
}
|
||||
|
||||
updateTransformationMatrix();
|
||||
|
||||
if (had3DTransform != has3DTransform())
|
||||
layer()->dirty3DTransformedDescendantStatus();
|
||||
}
|
||||
|
||||
// TODO(ojan): Inline this into styleDidChange,
|
||||
void RenderBox::updateFromStyle()
|
||||
{
|
||||
@ -246,9 +288,8 @@ void RenderBox::absoluteQuads(Vector<FloatQuad>& quads) const
|
||||
|
||||
void RenderBox::updateLayerTransformAfterLayout()
|
||||
{
|
||||
// Transform-origin depends on box size, so we need to update the layer transform after layout.
|
||||
if (hasLayer())
|
||||
layer()->updateTransformationMatrix();
|
||||
// Transform-origin depends on box size, so we need to update the transform after layout.
|
||||
updateTransformationMatrix();
|
||||
}
|
||||
|
||||
LayoutUnit RenderBox::constrainLogicalWidthByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb) const
|
||||
@ -548,11 +589,11 @@ bool RenderBox::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer
|
||||
HitTestLocation localHitTestLocation = hitTestLocation;
|
||||
|
||||
// We need transform state for the first time, or to offset the container state, or to accumulate the new transform.
|
||||
if (layer()->transform() || transformState || layer()->has3DTransformedDescendant() || layer()->preserves3D())
|
||||
if (transform() || transformState || layer()->has3DTransformedDescendant() || style()->preserves3D())
|
||||
localTransformState = createLocalTransformState(rootLayer, containerLayer, localHitTestRect, localHitTestLocation, transformState);
|
||||
|
||||
// Apply a transform if we have one.
|
||||
if (layer()->transform()) {
|
||||
if (transform()) {
|
||||
// The RenderView cannot have transforms.
|
||||
ASSERT(parent());
|
||||
// Make sure the parent's clip rects have been calculated.
|
||||
@ -596,7 +637,7 @@ bool RenderBox::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer
|
||||
}
|
||||
|
||||
RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
|
||||
if (localTransformState && !layer()->preserves3D()) {
|
||||
if (localTransformState && !style()->preserves3D()) {
|
||||
// Keep a copy of the pre-flattening state, for computing z-offsets for the container
|
||||
unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
|
||||
// This layer is flattening, so flatten the state passed to descendants.
|
||||
@ -610,7 +651,7 @@ bool RenderBox::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer
|
||||
double* zOffsetForContentsPtr = 0;
|
||||
|
||||
bool depthSortDescendants = false;
|
||||
if (layer()->preserves3D()) {
|
||||
if (style()->preserves3D()) {
|
||||
depthSortDescendants = true;
|
||||
// Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
|
||||
zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
|
||||
@ -720,9 +761,7 @@ void RenderBox::paintLayer(GraphicsContext* context, const LayerPaintingInfo& pa
|
||||
if (!opacity())
|
||||
return;
|
||||
|
||||
TransformationMatrix* layerTransform = layer()->transform();
|
||||
|
||||
if (!layerTransform) {
|
||||
if (!transform()) {
|
||||
paintLayerContents(context, paintingInfo);
|
||||
return;
|
||||
}
|
||||
@ -731,7 +770,7 @@ void RenderBox::paintLayer(GraphicsContext* context, const LayerPaintingInfo& pa
|
||||
ASSERT(layer()->parent());
|
||||
|
||||
// If the transform can't be inverted, then don't paint anything.
|
||||
if (!layerTransform->isInvertible())
|
||||
if (!transform()->isInvertible())
|
||||
return;
|
||||
|
||||
// Make sure the parent's clip rects have been calculated.
|
||||
@ -746,20 +785,20 @@ void RenderBox::paintLayer(GraphicsContext* context, const LayerPaintingInfo& pa
|
||||
// the accumulated error for sub-pixel layout.
|
||||
LayoutPoint delta;
|
||||
layer()->convertToLayerCoords(paintingInfo.rootLayer, delta);
|
||||
TransformationMatrix transform(*layerTransform);
|
||||
TransformationMatrix localTransform(*transform());
|
||||
IntPoint roundedDelta = roundedIntPoint(delta);
|
||||
transform.translateRight(roundedDelta.x(), roundedDelta.y());
|
||||
localTransform.translateRight(roundedDelta.x(), roundedDelta.y());
|
||||
LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
|
||||
|
||||
// Apply the transform.
|
||||
GraphicsContextStateSaver stateSaver(*context, false);
|
||||
if (!transform.isIdentity()) {
|
||||
if (!localTransform.isIdentity()) {
|
||||
stateSaver.save();
|
||||
context->concatCTM(transform.toAffineTransform());
|
||||
context->concatCTM(localTransform.toAffineTransform());
|
||||
}
|
||||
|
||||
// Now do a paint with the root layer shifted to be us.
|
||||
LayerPaintingInfo transformedPaintingInfo(layer(), enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)),
|
||||
LayerPaintingInfo transformedPaintingInfo(layer(), enclosingIntRect(localTransform.inverse().mapRect(paintingInfo.paintDirtyRect)),
|
||||
adjustedSubPixelAccumulation);
|
||||
paintLayerContents(context, transformedPaintingInfo);
|
||||
|
||||
@ -785,7 +824,7 @@ static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLaye
|
||||
// paintDirtyRect, and that should cut down on the amount we have to paint. Still it
|
||||
// would be better to respect clips.
|
||||
|
||||
if (rootLayer != layer && layer->transform()) {
|
||||
if (rootLayer != layer && layer->renderer()->transform()) {
|
||||
// The best we can do here is to use enclosed bounding boxes to establish a "fuzzy" enough clip to encompass
|
||||
// the transformed layer and all of its children.
|
||||
const RenderLayer* rootLayerForTransform = rootLayer;
|
||||
@ -796,7 +835,7 @@ static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLaye
|
||||
IntPoint pixelSnappedDelta = roundedIntPoint(delta);
|
||||
TransformationMatrix transform;
|
||||
transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y());
|
||||
transform = transform * *layer->transform();
|
||||
transform = transform * *layer->renderer()->transform();
|
||||
|
||||
// We don't use fragment boxes when collecting a transformed layer's bounding box, since it always
|
||||
// paints unfragmented.y
|
||||
@ -3013,8 +3052,8 @@ LayoutRect RenderBox::layoutOverflowRectForPropagation() const
|
||||
if (!hasOverflowClip())
|
||||
rect.unite(layoutOverflowRect());
|
||||
|
||||
if (hasLayer() && layer()->transform())
|
||||
rect = layer()->transform()->mapRect(rect);
|
||||
if (transform())
|
||||
rect = transform()->mapRect(rect);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ struct LayerPaintingInfo;
|
||||
struct PaintInfo;
|
||||
class HitTestingTransformState;
|
||||
class RenderBlockFlow;
|
||||
class TransformationMatrix;
|
||||
|
||||
enum SizeType { MainOrPreferredSize, MinSize, MaxSize };
|
||||
enum AvailableLogicalHeightType { ExcludeMarginBorderPadding, IncludeMarginBorderPadding };
|
||||
@ -217,6 +218,10 @@ public:
|
||||
|
||||
void updateLayerTransformAfterLayout();
|
||||
|
||||
// This transform has the transform-origin baked in.
|
||||
TransformationMatrix* transform() const { return m_transform.get(); }
|
||||
bool has3DTransform() const { return m_transform && !m_transform->isAffine(); }
|
||||
|
||||
LayoutUnit contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
|
||||
LayoutUnit contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }
|
||||
LayoutUnit contentLogicalWidth() const { return contentWidth(); }
|
||||
@ -485,6 +490,8 @@ protected:
|
||||
void updateIntrinsicContentLogicalHeight(LayoutUnit intrinsicContentLogicalHeight) const { m_intrinsicContentLogicalHeight = intrinsicContentLogicalHeight; }
|
||||
|
||||
private:
|
||||
void updateTransformationMatrix();
|
||||
void updateTransform(const RenderStyle* oldStyle);
|
||||
void updateFromStyle();
|
||||
void updateFilters();
|
||||
|
||||
@ -557,7 +564,9 @@ protected:
|
||||
// Our overflow information.
|
||||
OwnPtr<RenderOverflow> m_overflow;
|
||||
|
||||
// TODO(ojan): Move these two into RenderBoxRareData.
|
||||
OwnPtr<FilterEffectRenderer> m_filterRenderer;
|
||||
OwnPtr<TransformationMatrix> m_transform;
|
||||
|
||||
private:
|
||||
OwnPtr<RenderLayer> m_layer;
|
||||
|
||||
@ -2324,7 +2324,7 @@ const RenderObject* RenderBoxModelObject::pushMappingToContainer(const RenderBox
|
||||
return 0;
|
||||
|
||||
bool isInline = isRenderInline();
|
||||
bool hasTransform = !isInline && hasLayer() && toRenderBox(this)->layer()->transform();
|
||||
bool hasTransform = !isInline && isBox() && toRenderBox(this)->transform();
|
||||
|
||||
LayoutSize adjustmentForSkippedAncestor;
|
||||
if (ancestorSkipped) {
|
||||
|
||||
@ -102,46 +102,6 @@ void RenderLayer::updateLayerPositionsAfterLayout()
|
||||
m_clipper.clearClipRectsIncludingDescendants();
|
||||
}
|
||||
|
||||
void RenderLayer::updateTransformationMatrix()
|
||||
{
|
||||
if (m_transform) {
|
||||
RenderBox* box = renderer();
|
||||
m_transform->makeIdentity();
|
||||
box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
|
||||
// FIXME(sky): We shouldn't need to do this once Skia has 4x4 matrix support.
|
||||
// Until then, 3d transforms don't work right.
|
||||
m_transform->makeAffine();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderLayer::updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle)
|
||||
{
|
||||
if (oldStyle && newStyle->transformDataEquivalent(*oldStyle))
|
||||
return;
|
||||
|
||||
// hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
|
||||
// so check style too.
|
||||
bool hasTransform = renderer()->hasTransform() && newStyle->hasTransform();
|
||||
bool had3DTransform = has3DTransform();
|
||||
|
||||
bool hadTransform = m_transform;
|
||||
if (hasTransform != hadTransform) {
|
||||
if (hasTransform)
|
||||
m_transform = adoptPtr(new TransformationMatrix);
|
||||
else
|
||||
m_transform.clear();
|
||||
|
||||
// Layers with transforms act as clip rects roots, so clear the cached clip rects here.
|
||||
m_clipper.clearClipRectsIncludingDescendants();
|
||||
} else if (hasTransform) {
|
||||
m_clipper.clearClipRectsIncludingDescendants(AbsoluteClipRects);
|
||||
}
|
||||
|
||||
updateTransformationMatrix();
|
||||
|
||||
if (had3DTransform != has3DTransform())
|
||||
dirty3DTransformedDescendantStatus();
|
||||
}
|
||||
|
||||
void RenderLayer::dirty3DTransformedDescendantStatus()
|
||||
{
|
||||
@ -153,7 +113,7 @@ void RenderLayer::dirty3DTransformedDescendantStatus()
|
||||
|
||||
// This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
|
||||
// Note that preserves3D() creates stacking context, so we can just run up the stacking containers.
|
||||
while (stackingNode && stackingNode->layer()->preserves3D()) {
|
||||
while (stackingNode && stackingNode->layer()->renderer()->style()->preserves3D()) {
|
||||
stackingNode->layer()->m_3DTransformedDescendantStatusDirty = true;
|
||||
stackingNode = stackingNode->ancestorStackingContextNode();
|
||||
}
|
||||
@ -178,10 +138,10 @@ bool RenderLayer::update3DTransformedDescendantStatus()
|
||||
|
||||
// If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
|
||||
// the m_has3DTransformedDescendant set.
|
||||
if (preserves3D())
|
||||
return has3DTransform() || m_has3DTransformedDescendant;
|
||||
if (renderer()->style()->preserves3D())
|
||||
return renderer()->has3DTransform() || m_has3DTransformedDescendant;
|
||||
|
||||
return has3DTransform();
|
||||
return renderer()->has3DTransform();
|
||||
}
|
||||
|
||||
IntSize RenderLayer::size() const
|
||||
@ -571,8 +531,8 @@ LayoutRect RenderLayer::boundingBoxForCompositing(const RenderLayer* ancestorLay
|
||||
|
||||
LayoutRect localClipRect = clipper().localClipRect();
|
||||
if (localClipRect != PaintInfo::infiniteRect()) {
|
||||
if (transform())
|
||||
localClipRect = transform()->mapRect(localClipRect);
|
||||
if (renderer()->transform())
|
||||
localClipRect = renderer()->transform()->mapRect(localClipRect);
|
||||
|
||||
LayoutPoint delta;
|
||||
convertToLayerCoords(ancestorLayer, delta);
|
||||
@ -592,8 +552,8 @@ LayoutRect RenderLayer::boundingBoxForCompositing(const RenderLayer* ancestorLay
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=81239
|
||||
m_renderer->style()->filterOutsets().expandRect(result);
|
||||
|
||||
if (transform())
|
||||
result = transform()->mapRect(result);
|
||||
if (renderer()->transform())
|
||||
result = renderer()->transform()->mapRect(result);
|
||||
|
||||
LayoutPoint delta;
|
||||
convertToLayerCoords(ancestorLayer, delta);
|
||||
@ -614,8 +574,6 @@ void RenderLayer::styleChanged(StyleDifference diff, const RenderStyle* oldStyle
|
||||
// Overlay scrollbars can make this layer self-painting so we need
|
||||
// to recompute the bit once scrollbars have been updated.
|
||||
m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
|
||||
|
||||
updateTransform(oldStyle, renderer()->style());
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
|
||||
@ -55,12 +55,7 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
class FilterOperations;
|
||||
class HitTestRequest;
|
||||
class HitTestResult;
|
||||
class HitTestingTransformState;
|
||||
class RenderStyle;
|
||||
class TransformationMatrix;
|
||||
|
||||
enum BorderRadiusClippingRule { IncludeSelfForBorderRadius, DoNotIncludeSelfForBorderRadius };
|
||||
enum IncludeSelfOrNot { IncludeSelf, ExcludeSelf };
|
||||
@ -103,7 +98,6 @@ public:
|
||||
bool isRootLayer() const { return m_isRootLayer; }
|
||||
|
||||
void updateLayerPositionsAfterLayout();
|
||||
void updateTransformationMatrix();
|
||||
|
||||
RenderLayerStackingNode* stackingNode() { return m_stackingNode.get(); }
|
||||
const RenderLayerStackingNode* stackingNode() const { return m_stackingNode.get(); }
|
||||
@ -125,19 +119,10 @@ public:
|
||||
LayoutRect physicalBoundingBoxIncludingReflectionAndStackingChildren(const RenderLayer* ancestorLayer, const LayoutPoint& offsetFromRoot) const;
|
||||
LayoutRect boundingBoxForCompositing(const RenderLayer* ancestorLayer = 0) const;
|
||||
|
||||
// This transform has the transform-origin baked in.
|
||||
TransformationMatrix* transform() const { return m_transform.get(); }
|
||||
|
||||
bool preserves3D() const { return renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; }
|
||||
bool has3DTransform() const { return m_transform && !m_transform->isAffine(); }
|
||||
|
||||
bool has3DTransformedDescendant() const { return m_has3DTransformedDescendant; }
|
||||
// Both updates the status, and returns true if descendants of this have 3d.
|
||||
bool update3DTransformedDescendantStatus();
|
||||
|
||||
// FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
|
||||
bool shouldPreserve3D() const { return renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; }
|
||||
|
||||
void* operator new(size_t);
|
||||
// Only safe to call from RenderBox::destroyLayer()
|
||||
void operator delete(void*);
|
||||
@ -154,7 +139,6 @@ public:
|
||||
void clipToRect(const LayerPaintingInfo&, GraphicsContext*, const ClipRect&, BorderRadiusClippingRule = IncludeSelfForBorderRadius);
|
||||
void restoreClip(GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&);
|
||||
|
||||
private:
|
||||
// Bounding box in the coordinates of this layer.
|
||||
LayoutRect logicalBoundingBox() const;
|
||||
|
||||
@ -165,10 +149,9 @@ private:
|
||||
|
||||
bool shouldBeSelfPaintingLayer() const;
|
||||
|
||||
void updateTransform(const RenderStyle* oldStyle, RenderStyle* newStyle);
|
||||
|
||||
void dirty3DTransformedDescendantStatus();
|
||||
|
||||
private:
|
||||
LayerType m_layerType;
|
||||
|
||||
// Self-painting layer is an optimization where we avoid the heavy RenderLayer painting
|
||||
@ -191,8 +174,6 @@ private:
|
||||
RenderLayer* m_first;
|
||||
RenderLayer* m_last;
|
||||
|
||||
OwnPtr<TransformationMatrix> m_transform;
|
||||
|
||||
RenderLayerClipper m_clipper; // FIXME: Lazily allocate?
|
||||
OwnPtr<RenderLayerStackingNode> m_stackingNode;
|
||||
};
|
||||
|
||||
@ -317,7 +317,7 @@ RenderLayer* RenderLayerClipper::clippingRootForPainting() const
|
||||
|
||||
current = current->compositingContainer();
|
||||
ASSERT(current);
|
||||
if (current->transform())
|
||||
if (current->renderer()->transform())
|
||||
return const_cast<RenderLayer*>(current);
|
||||
}
|
||||
|
||||
|
||||
@ -1418,16 +1418,16 @@ bool RenderObject::shouldUseTransformFromContainer(const RenderObject* container
|
||||
{
|
||||
// hasTransform() indicates whether the object has transform, transform-style or perspective. We just care about transform,
|
||||
// so check the layer's transform directly.
|
||||
return (hasLayer() && toRenderBox(this)->layer()->transform()) || (containerObject && containerObject->style()->hasPerspective());
|
||||
return (isBox() && toRenderBox(this)->transform()) || (containerObject && containerObject->style()->hasPerspective());
|
||||
}
|
||||
|
||||
void RenderObject::getTransformFromContainer(const RenderObject* containerObject, const LayoutSize& offsetInContainer, TransformationMatrix& transform) const
|
||||
{
|
||||
transform.makeIdentity();
|
||||
transform.translate(offsetInContainer.width().toFloat(), offsetInContainer.height().toFloat());
|
||||
RenderLayer* layer = hasLayer() ? toRenderBox(this)->layer() : 0;
|
||||
if (layer && layer->transform())
|
||||
transform.multiply(*layer->transform());
|
||||
TransformationMatrix* localTransform = isBox() ? toRenderBox(this)->transform() : 0;
|
||||
if (localTransform)
|
||||
transform.multiply(*localTransform);
|
||||
|
||||
if (containerObject && containerObject->hasLayer() && containerObject->style()->hasPerspective()) {
|
||||
// Perpsective on the container affects us, so we have to factor it in here.
|
||||
|
||||
@ -353,7 +353,7 @@ IntRect RenderView::documentRect() const
|
||||
{
|
||||
FloatRect overflowRect(unscaledDocumentRect());
|
||||
if (hasTransform())
|
||||
overflowRect = layer()->transform()->mapRect(overflowRect);
|
||||
overflowRect = transform()->mapRect(overflowRect);
|
||||
return IntRect(overflowRect);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user