diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index c7e4173f02f..a8cc0f1267a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1310,6 +1310,41 @@ nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncesto return ctm; } +bool +nsLayoutUtils::GetLayerTransformForFrame(nsIFrame* aFrame, + gfx3DMatrix* aTransform) +{ + // FIXME/bug 796690: we can sometimes compute a transform in these + // cases, it just increases complexity considerably. Punt for now. + if (aFrame->Preserves3DChildren() || aFrame->HasTransformGetter()) { + return false; + } + + nsIFrame* root = nsLayoutUtils::GetDisplayRootFrame(aFrame); + if (root->HasAnyStateBits(NS_FRAME_UPDATE_LAYER_TREE)) { + // Content may have been invalidated, so we can't reliably compute + // the "layer transform" in general. + return false; + } + // If the caller doesn't care about the value, early-return to skip + // overhead below. + if (!aTransform) { + return true; + } + + nsDisplayListBuilder builder(root, nsDisplayListBuilder::OTHER, + false/*don't build caret*/); + nsDisplayList list; + nsDisplayTransform* item = + new (&builder) nsDisplayTransform(&builder, aFrame, &list); + + *aTransform = + item->GetTransform(aFrame->PresContext()->AppUnitsPerDevPixel()); + list.DeleteAll(); + + return true; +} + static gfxPoint TransformGfxPointFromAncestor(nsIFrame *aFrame, const gfxPoint &aPoint, diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 7e7e59ba99e..65a458e067d 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -536,6 +536,15 @@ public: */ static gfx3DMatrix GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor); + /** + * Return true if a "layer transform" could be computed for aFrame, + * and optionally return the computed transform. The returned + * transform is what would be set on the layer currently if a layers + * transaction were opened at the time this helper is called. + */ + static bool GetLayerTransformForFrame(nsIFrame* aFrame, + gfx3DMatrix* aTransform); + /** * Given a point in the global coordinate space, returns that point expressed * in the coordinate system of aFrame. This effectively inverts all transforms diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 9e3dee52b3f..192d68eab5a 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1271,6 +1271,11 @@ public: bool HasOpacity() const; + /** + * Return true if this frame might be using a transform getter. + */ + virtual bool HasTransformGetter() const { return false; } + /** * Returns true if this frame is an SVG frame that has SVG transforms applied * to it, or if its parent frame is an SVG frame that has children-only @@ -2225,7 +2230,7 @@ public: * */ virtual void InvalidateFrameForRemoval() {} - + /** * Checks if a frame has had InvalidateFrame() called on it since the * last paint. diff --git a/layout/generic/nsPageContentFrame.h b/layout/generic/nsPageContentFrame.h index e49eba279ad..88834a9d25d 100644 --- a/layout/generic/nsPageContentFrame.h +++ b/layout/generic/nsPageContentFrame.h @@ -42,6 +42,8 @@ public: nsSize aMargin, nsSize aBorder, nsSize aPadding, uint32_t aFlags) MOZ_OVERRIDE; + virtual bool HasTransformGetter() const MOZ_OVERRIDE { return true; } + /** * Get the "type" of the frame * diff --git a/layout/generic/nsSimplePageSequence.h b/layout/generic/nsSimplePageSequence.h index c5895eab81c..4d2e1f8c719 100644 --- a/layout/generic/nsSimplePageSequence.h +++ b/layout/generic/nsSimplePageSequence.h @@ -91,6 +91,8 @@ public: // user's settings virtual bool HonorPrintBackgroundSettings() { return false; } + virtual bool HasTransformGetter() const MOZ_OVERRIDE { return true; } + /** * Get the "type" of the frame *