Remove potentially tree-corrupting methods from CXFA_LayoutItem.
SetParent(), SetNextSibling() and SetFirstChild() all leave the
nodes of the tree in an inconsistent state and rely on the callers
to make futher adjustments to restore consistency. Use other
methods instead.
- Tidy InsertChild() method.
- Remove a no-op cast and a needless null assignment.
Change-Id: If1a2a3b052daa38638a99f69e4aeb9d42878de18
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/53391
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
index a6ddfc8..2387b57 100644
--- a/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
+++ b/xfa/fxfa/layout/cxfa_itemlayoutprocessor.cpp
@@ -722,22 +722,21 @@
}
}
} else {
- pSecondLayoutItem->SetParent(pLayoutItem->GetParent());
- pSecondLayoutItem->SetNextSibling(pLayoutItem->GetNextSibling());
- pLayoutItem->SetNextSibling(pSecondLayoutItem);
+ if (pSecondLayoutItem->GetParent())
+ pSecondLayoutItem->GetParent()->RemoveChild(pSecondLayoutItem);
+ pLayoutItem->GetParent()->InsertChild(pLayoutItem, pSecondLayoutItem);
}
- CXFA_ContentLayoutItem* pChildren =
- ToContentLayoutItem(pLayoutItem->GetFirstChild());
- pLayoutItem->SetFirstChild(nullptr);
+ std::vector<CXFA_ContentLayoutItem*> children;
+ while (auto* pFirst = ToContentLayoutItem(pLayoutItem->GetFirstChild())) {
+ children.push_back(pFirst);
+ pLayoutItem->RemoveChild(pFirst);
+ }
float lHeightForKeep = 0;
float fAddMarginHeight = 0;
std::vector<CXFA_ContentLayoutItem*> keepLayoutItems;
- for (CXFA_ContentLayoutItem *pChildItem = pChildren, *pChildNext = nullptr;
- pChildItem; pChildItem = pChildNext) {
- pChildNext = ToContentLayoutItem(pChildItem->GetNextSibling());
- pChildItem->SetNextSibling(nullptr);
+ for (auto* pChildItem : children) {
if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin +
kXFALayoutPrecision) {
if (!ExistContainerKeep(pChildItem->GetFormNode(), true)) {
@@ -798,7 +797,8 @@
CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem;
if (pLayoutItem) {
m_pLayoutItem = ToContentLayoutItem(pLayoutItem->GetNextSibling());
- pLayoutItem->SetNextSibling(nullptr);
+ if (pLayoutItem->GetParent())
+ pLayoutItem->GetParent()->RemoveChild(pLayoutItem);
}
if (m_nCurChildNodeStage != Stage::kDone || !m_pOldLayoutItem)
@@ -1588,28 +1588,23 @@
}
}
- if (ToContentLayoutItem(m_pLayoutItem->GetFirstChild()) == pLastChild) {
- m_pLayoutItem->SetFirstChild(nullptr);
- } else {
- for (CXFA_LayoutItem* pLayoutNext = m_pLayoutItem->GetFirstChild();
- pLayoutNext; pLayoutNext = pLayoutNext->GetNextSibling()) {
- if (ToContentLayoutItem(pLayoutNext->GetNextSibling()) ==
- pLastChild) {
- pLayoutNext->SetNextSibling(nullptr);
- break;
- }
+ // TODO(tsepez): avoid looping if we can prove it is in the list.
+ for (CXFA_LayoutItem* pLayoutNext = m_pLayoutItem->GetFirstChild();
+ pLayoutNext; pLayoutNext = pLayoutNext->GetNextSibling()) {
+ if (ToContentLayoutItem(pLayoutNext) == pLastChild) {
+ m_pLayoutItem->RemoveChild(pLastChild);
+ break;
}
}
- CXFA_ContentLayoutItem* pLayoutNextTemp = ToContentLayoutItem(pLastChild);
+ CXFA_ContentLayoutItem* pLayoutNextTemp = pLastChild;
while (pLayoutNextTemp) {
- pLayoutNextTemp->SetParent(nullptr);
CXFA_ContentLayoutItem* pSaveLayoutNext =
ToContentLayoutItem(pLayoutNextTemp->GetNextSibling());
- pLayoutNextTemp->SetNextSibling(nullptr);
+ if (pLayoutNextTemp->GetParent())
+ pLayoutNextTemp->GetParent()->RemoveChild(pLayoutNextTemp);
pLayoutNextTemp = pSaveLayoutNext;
}
- pLastChild = nullptr;
}
while (m_pCurChildNode) {
diff --git a/xfa/fxfa/layout/cxfa_layoutitem.cpp b/xfa/fxfa/layout/cxfa_layoutitem.cpp
index 3dc65ce..543e99d 100644
--- a/xfa/fxfa/layout/cxfa_layoutitem.cpp
+++ b/xfa/fxfa/layout/cxfa_layoutitem.cpp
@@ -21,7 +21,7 @@
CXFA_LayoutProcessor* pDocLayout = pDocument->GetLayoutProcessor();
while (pNode) {
CXFA_LayoutItem* pNext = pNode->GetNextSibling();
- pNode->SetParent(nullptr);
+ pLayoutItem->RemoveChild(pNode);
pNotify->OnLayoutItemRemoving(pDocLayout, pNode);
XFA_ReleaseLayoutItem(pNode);
pNode = pNext;
@@ -103,14 +103,11 @@
CXFA_LayoutItem* pChildItem) {
if (pBeforeItem->m_pParent != this)
return;
- if (pChildItem->m_pParent)
- pChildItem->m_pParent = nullptr;
+ ASSERT(!pChildItem->m_pParent);
pChildItem->m_pParent = this;
-
- CXFA_LayoutItem* pExistingChildItem = pBeforeItem->m_pNextSibling;
+ pChildItem->m_pNextSibling = pBeforeItem->m_pNextSibling;
pBeforeItem->m_pNextSibling = pChildItem;
- pChildItem->m_pNextSibling = pExistingChildItem;
}
void CXFA_LayoutItem::RemoveChild(CXFA_LayoutItem* pChildItem) {
diff --git a/xfa/fxfa/layout/cxfa_layoutitem.h b/xfa/fxfa/layout/cxfa_layoutitem.h
index 3dd6754..c983668 100644
--- a/xfa/fxfa/layout/cxfa_layoutitem.h
+++ b/xfa/fxfa/layout/cxfa_layoutitem.h
@@ -32,11 +32,6 @@
CXFA_Node* GetFormNode() const { return m_pFormNode.Get(); }
void SetFormNode(CXFA_Node* pNode) { m_pFormNode = pNode; }
- // TODO(tsepez) replace these calls with AddChild() etc.
- void SetParent(CXFA_LayoutItem* pParent) { m_pParent = pParent; }
- void SetFirstChild(CXFA_LayoutItem* pChild) { m_pFirstChild = pChild; }
- void SetNextSibling(CXFA_LayoutItem* pSibling) { m_pNextSibling = pSibling; }
-
void AddChild(CXFA_LayoutItem* pChildItem);
void AddHeadChild(CXFA_LayoutItem* pChildItem);
void RemoveChild(CXFA_LayoutItem* pChildItem);
diff --git a/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp b/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp
index 917e748..63743ce 100644
--- a/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp
+++ b/xfa/fxfa/layout/cxfa_layoutpagemgr.cpp
@@ -158,7 +158,7 @@
}
}
-void ReorderLayoutItemToTail(CXFA_ViewLayoutItem* pLayoutItem) {
+void ReorderLayoutItemToTail(CXFA_LayoutItem* pLayoutItem) {
CXFA_ViewLayoutItem* pParentLayoutItem =
ToViewLayoutItem(pLayoutItem->GetParent());
if (!pParentLayoutItem)
@@ -168,7 +168,7 @@
pParentLayoutItem->AddChild(pLayoutItem);
}
-void RemoveLayoutItem(CXFA_ViewLayoutItem* pLayoutItem) {
+void RemoveLayoutItem(CXFA_LayoutItem* pLayoutItem) {
CXFA_ViewLayoutItem* pParentLayoutItem =
ToViewLayoutItem(pLayoutItem->GetParent());
if (!pParentLayoutItem)
@@ -389,9 +389,7 @@
ASSERT(m_pTemplatePageSetRoot);
if (m_pPageSetLayoutItemRoot) {
- m_pPageSetLayoutItemRoot->SetParent(nullptr);
- m_pPageSetLayoutItemRoot->SetFirstChild(nullptr);
- m_pPageSetLayoutItemRoot->SetNextSibling(nullptr);
+ RemoveLayoutItem(m_pPageSetLayoutItemRoot);
m_pPageSetLayoutItemRoot->SetFormNode(m_pTemplatePageSetRoot);
} else {
m_pPageSetLayoutItemRoot =
@@ -649,7 +647,7 @@
while (pPrePageSet->GetNextSibling()) {
pPrePageSet = pPrePageSet->GetNextSibling()->AsViewLayoutItem();
}
- pPrePageSet->SetNextSibling(pPageSetLayoutItem);
+ pPrePageSet->GetParent()->InsertChild(pPrePageSet, pPageSetLayoutItem);
m_pPageSetCurRoot = pPageSetLayoutItem;
} else {
pParentPageSetLayout->AddChild(pPageSetLayoutItem);
@@ -1644,9 +1642,7 @@
if (pCurLayoutItem->GetFirstChild())
SaveLayoutItem(pCurLayoutItem);
- pCurLayoutItem->SetParent(nullptr);
- pCurLayoutItem->SetNextSibling(nullptr);
- pCurLayoutItem->SetFirstChild(nullptr);
+ RemoveLayoutItem(pCurLayoutItem);
if (!pCurLayoutItem->IsContentLayoutItem() &&
pCurLayoutItem->GetFormNode()->GetElementType() !=
XFA_Element::PageArea) {
@@ -1941,7 +1937,7 @@
CXFA_LayoutItem* pNode = pLayoutItem->GetFirstChild();
while (pNode) {
CXFA_LayoutItem* pNext = pNode->GetNextSibling();
- pNode->SetParent(nullptr);
+ pLayoutItem->RemoveChild(pNode);
XFA_ReleaseLayoutItem_NoPageArea(pNode);
pNode = pNext;
}