Bug 691106 - Merge sequential nsDisplayTransforms and give them unique frame keys. r=roc

This commit is contained in:
Matt Woodrow 2011-10-03 17:02:25 +13:00
parent a20a2599bb
commit ae2391fce2
3 changed files with 50 additions and 19 deletions

View File

@ -2451,13 +2451,6 @@ nsDisplayTransform::GetResultingTransformMatrix(const nsIFrame* aFrame,
*aOutAncestor = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
}
/* Preserve-3d can cause frames without a transform to get an nsDisplayTransform created, we should
* use our parent's transform here.
*/
if (!aFrame->GetStyleDisplay()->HasTransform()) {
return GetResultingTransformMatrix(aFrame->GetParent(), aOrigin - aFrame->GetPosition(), aFactor, nsnull, aOutAncestor);
}
/* Account for the -moz-transform-origin property by translating the
* coordinate space to the new origin.
*/

View File

@ -2079,16 +2079,16 @@ public:
* ferries the underlying frame to the nsDisplayItem constructor.
*/
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayList *aList) :
nsDisplayItem(aBuilder, aFrame), mStoredList(aBuilder, aFrame, aList)
nsDisplayList *aList, PRUint32 aIndex = 0) :
nsDisplayItem(aBuilder, aFrame), mStoredList(aBuilder, aFrame, aList), mIndex(aIndex)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
NS_ABORT_IF_FALSE(aFrame, "Must have a frame!");
}
nsDisplayTransform(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame,
nsDisplayItem *aItem) :
nsDisplayItem(aBuilder, aFrame), mStoredList(aBuilder, aFrame, aItem)
nsDisplayItem *aItem, PRUint32 aIndex = 0) :
nsDisplayItem(aBuilder, aFrame), mStoredList(aBuilder, aFrame, aItem), mIndex(aIndex)
{
MOZ_COUNT_CTOR(nsDisplayTransform);
NS_ABORT_IF_FALSE(aFrame, "Must have a frame!");
@ -2127,6 +2127,12 @@ public:
nsRegion *aVisibleRegion,
const nsRect& aAllowVisibleRegionExpansion);
virtual bool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem);
virtual PRUint32 GetPerFrameKey() { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); }
enum {
INDEX_MAX = PR_UINT32_MAX >> nsDisplayItem::TYPE_BITS
};
const gfx3DMatrix& GetTransform(float aFactor);
@ -2205,6 +2211,7 @@ private:
nsDisplayWrapList mStoredList;
gfx3DMatrix mTransform;
float mCachedFactor;
PRUint32 mIndex;
};
/**

View File

@ -1518,47 +1518,78 @@ DisplayDebugBorders(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
#endif
static nsresult
WrapPreserve3DList(nsIFrame *aFrame, nsDisplayListBuilder *aBuilder, nsDisplayList *aList)
WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, nsDisplayList *aList, PRUint32& aIndex)
{
if (aIndex > nsDisplayTransform::INDEX_MAX) {
return NS_OK;
}
nsresult rv = NS_OK;
nsDisplayList newList;
nsDisplayList temp;
while (nsDisplayItem *item = aList->RemoveBottom()) {
nsIFrame *childFrame = item->GetUnderlyingFrame();
NS_ASSERTION(childFrame, "All display items to be wrapped must have a frame!");
// We accumulate sequential items that aren't transforms into the 'temp' list
// and then flush this list into newList by wrapping the whole lot with a single
// nsDisplayTransform.
if (childFrame->GetParent()->Preserves3DChildren()) {
switch (item->GetType()) {
case nsDisplayItem::TYPE_TRANSFORM: {
if (!temp.IsEmpty()) {
newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
}
newList.AppendToTop(item);
break;
}
case nsDisplayItem::TYPE_WRAP_LIST: {
if (!temp.IsEmpty()) {
newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
}
nsDisplayWrapList *list = static_cast<nsDisplayWrapList*>(item);
rv = WrapPreserve3DList(aFrame, aBuilder, list->GetList());
rv = WrapPreserve3DListInternal(aFrame, aBuilder, list->GetList(), aIndex);
newList.AppendToTop(item);
break;
}
case nsDisplayItem::TYPE_OPACITY: {
if (!temp.IsEmpty()) {
newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
}
nsDisplayOpacity *opacity = static_cast<nsDisplayOpacity*>(item);
rv = WrapPreserve3DList(aFrame, aBuilder, opacity->GetList());
rv = WrapPreserve3DListInternal(aFrame, aBuilder, opacity->GetList(), aIndex);
newList.AppendToTop(item);
break;
}
default: {
item = new (aBuilder) nsDisplayTransform(aBuilder, childFrame, item);
temp.AppendToTop(item);
break;
}
}
} else {
item = new (aBuilder) nsDisplayTransform(aBuilder, childFrame, item);
temp.AppendToTop(item);
}
if (NS_FAILED(rv) || !item)
if (NS_FAILED(rv) || !item || aIndex > nsDisplayTransform::INDEX_MAX)
return rv;
newList.AppendToTop(item);
}
if (!temp.IsEmpty()) {
newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
}
aList->AppendToTop(&newList);
return NS_OK;
}
static nsresult
WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayList *aList)
{
PRUint32 index = 0;
return WrapPreserve3DListInternal(aFrame, aBuilder, aList, index);
}
nsresult
nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,