Bug 806256 - Improve WrapPreserve3DList's behaviour by walking through nsDisplayWrapList without flushing the temp list. r=roc

This commit is contained in:
Matt Woodrow 2012-11-01 14:25:45 +13:00
Родитель 1509c7378c
Коммит 608df10dff
1 изменённых файлов: 27 добавлений и 24 удалений

Просмотреть файл

@ -1764,69 +1764,63 @@ DisplayDebugBorders(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
#endif
static nsresult
WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, nsDisplayList *aList, uint32_t& aIndex)
WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, nsDisplayList *aList, nsDisplayList *aOutput, uint32_t& aIndex, nsDisplayList* aTemp)
{
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();
// 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
// and then flush this list into aOutput by wrapping the whole lot with a single
// nsDisplayTransform.
if (childFrame && (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) {
switch (item->GetType()) {
case nsDisplayItem::TYPE_TRANSFORM: {
if (!temp.IsEmpty()) {
newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
if (!aTemp->IsEmpty()) {
aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, aTemp, aIndex++));
}
newList.AppendToTop(item);
aOutput->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 = WrapPreserve3DListInternal(aFrame, aBuilder, list->GetList(), aIndex);
newList.AppendToTop(list->GetList());
rv = WrapPreserve3DListInternal(aFrame, aBuilder, list->GetList(), aOutput, aIndex, aTemp);
list->~nsDisplayWrapList();
break;
}
case nsDisplayItem::TYPE_OPACITY: {
if (!temp.IsEmpty()) {
newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
if (!aTemp->IsEmpty()) {
aOutput->AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, aTemp, aIndex++));
}
nsDisplayOpacity *opacity = static_cast<nsDisplayOpacity*>(item);
rv = WrapPreserve3DListInternal(aFrame, aBuilder, opacity->GetList(), aIndex);
nsDisplayList output;
rv = WrapPreserve3DListInternal(aFrame, aBuilder, opacity->GetList(), &output, aIndex, aTemp);
if (!aTemp->IsEmpty()) {
output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, aTemp, aIndex++));
}
opacity->GetList()->AppendToTop(&output);
opacity->UpdateBounds(aBuilder);
newList.AppendToTop(item);
aOutput->AppendToTop(item);
break;
}
default: {
temp.AppendToTop(item);
aTemp->AppendToTop(item);
break;
}
}
} else {
temp.AppendToTop(item);
aTemp->AppendToTop(item);
}
if (NS_FAILED(rv) || !item || aIndex > nsDisplayTransform::INDEX_MAX)
return rv;
}
if (!temp.IsEmpty()) {
newList.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, aIndex++));
}
aList->AppendToTop(&newList);
return NS_OK;
}
@ -1834,7 +1828,16 @@ static nsresult
WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayList *aList)
{
uint32_t index = 0;
return WrapPreserve3DListInternal(aFrame, aBuilder, aList, index);
nsDisplayList temp;
nsDisplayList output;
nsresult rv = WrapPreserve3DListInternal(aFrame, aBuilder, aList, &output, index, &temp);
if (!temp.IsEmpty()) {
output.AppendToTop(new (aBuilder) nsDisplayTransform(aBuilder, aFrame, &temp, index++));
}
aList->AppendToTop(&output);
return rv;
}
nsresult