7#include "xfa/fxfa/layout/cxfa_contentlayoutprocessor.h"
14#include "core/fxcrt/check.h"
15#include "core/fxcrt/containers/adapters.h"
16#include "core/fxcrt/notreached.h"
17#include "core/fxcrt/stl_util.h"
18#include "fxjs/gc/container_trace.h"
19#include "fxjs/xfa/cjx_object.h"
20#include "xfa/fxfa/cxfa_ffdoc.h"
21#include "xfa/fxfa/cxfa_ffnotify.h"
22#include "xfa/fxfa/cxfa_ffwidget.h"
23#include "xfa/fxfa/layout/cxfa_contentlayoutitem.h"
24#include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
25#include "xfa/fxfa/layout/cxfa_viewlayoutitem.h"
26#include "xfa/fxfa/layout/cxfa_viewlayoutprocessor.h"
27#include "xfa/fxfa/parser/cxfa_document.h"
28#include "xfa/fxfa/parser/cxfa_keep.h"
29#include "xfa/fxfa/parser/cxfa_localemgr.h"
30#include "xfa/fxfa/parser/cxfa_margin.h"
31#include "xfa/fxfa/parser/cxfa_measurement.h"
32#include "xfa/fxfa/parser/cxfa_node.h"
33#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
34#include "xfa/fxfa/parser/cxfa_occur.h"
35#include "xfa/fxfa/parser/cxfa_para.h"
36#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
37#include "xfa/fxfa/parser/xfa_utils.h"
41using NextPosRow =
std::array<uint8_t, 9>;
42constexpr std::array<
const NextPosRow, 4> kNextPosTable = {{
43 {{0, 1, 2, 3, 4, 5, 6, 7, 8}},
44 {{6, 3, 0, 7, 4, 1, 8, 5, 2}},
45 {{8, 7, 6, 5, 4, 3, 2, 1, 0}},
46 {{2, 5, 8, 1, 4, 7, 0, 3, 6}},
49std::vector<WideString> SeparateStringOnSpace(
50 pdfium::span<
const wchar_t> spStr) {
51 std::vector<WideString> ret;
57 while (nPos < spStr.size()) {
58 if (spStr[nPos] == L' ') {
59 ret.emplace_back(
WideStringView(spStr.subspan(nToken, nPos - nToken)));
64 ret.emplace_back(
WideStringView(spStr.subspan(nToken, nPos - nToken)));
68void UpdateWidgetSize(CXFA_ContentLayoutItem* pLayoutItem,
78 *pWidth = pLayoutItem->m_sSize.width;
80 *pHeight = pLayoutItem->m_sSize.height;
85 pNode
->GetDocument()->GetNotify()->StartFieldDrawLayout(pNode, pWidth,
95 bool* bContainerWidthAutoSize,
96 bool* bContainerHeightAutoSize) {
97 *bContainerWidthAutoSize =
true;
98 *bContainerHeightAutoSize =
true;
105 pFormNode->JSObject()->TryMeasure(XFA_Attribute::W,
false);
108 *bContainerWidthAutoSize =
false;
112 pFormNode->JSObject()->TryMeasure(XFA_Attribute::H,
false);
115 *bContainerHeightAutoSize =
false;
119 if (*bContainerWidthAutoSize && eType ==
XFA_Element::Subform) {
121 pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxW,
false);
124 *bContainerWidthAutoSize =
false;
128 pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxH,
false);
131 *bContainerHeightAutoSize =
false;
134 return containerSize;
137CFX_SizeF CalculateContainerComponentSizeFromContentSize(
139 bool bContainerWidthAutoSize,
140 float fContentCalculatedWidth,
141 bool bContainerHeightAutoSize,
142 float fContentCalculatedHeight,
144 CFX_SizeF componentSize = currentContainerSize;
145 CXFA_Margin* pMarginNode =
146 pFormNode->GetFirstChildByClass<CXFA_Margin>(
XFA_Element::Margin);
147 if (bContainerWidthAutoSize) {
148 componentSize.width = fContentCalculatedWidth;
151 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::LeftInset,
false);
152 if (leftInset.has_value())
156 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::RightInset,
false);
157 if (rightInset.has_value())
158 componentSize.width += rightInset->ToUnit(
XFA_Unit::Pt);
162 if (bContainerHeightAutoSize) {
163 componentSize.height = fContentCalculatedHeight;
166 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::TopInset,
false);
167 if (topInset.has_value())
171 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::BottomInset,
173 if (bottomInset.has_value())
174 componentSize.height += bottomInset->ToUnit(
XFA_Unit::Pt);
177 return componentSize;
191 inset
.bottom = pMargin->JSObject()->GetMeasureInUnit(
196void RelocateTableRowCells(CXFA_ContentLayoutItem* pLayoutRow,
197 const std::vector<
float>& rgSpecifiedColumnWidths,
199 bool bContainerWidthAutoSize =
true;
200 bool bContainerHeightAutoSize =
true;
201 const CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
202 pLayoutRow->GetFormNode(), &bContainerWidthAutoSize,
203 &bContainerHeightAutoSize);
205 CXFA_Margin* pMargin =
206 pLayoutRow
->GetFormNode()->GetFirstChildByClass<CXFA_Margin>(
210 const float fContentWidthLimit =
211 bContainerWidthAutoSize ? FLT_MAX
212 : containerSize.width - inset.left - inset.right;
213 const float fContentCurrentHeight =
214 pLayoutRow->m_sSize.height - inset
.top - inset
.bottom;
216 float fContentCalculatedWidth = 0;
217 float fContentCalculatedHeight = 0;
218 float fCurrentColX = 0;
219 size_t nCurrentColIdx = 0;
220 bool bMetWholeRowCell =
false;
223 pIter = pIter->GetNextSibling()) {
228 const int32_t nOriginalColSpan =
233 if (nOriginalColSpan > 0)
234 nColSpan =
static_cast<size_t>(nOriginalColSpan);
235 else if (nOriginalColSpan == -1)
236 nColSpan = rgSpecifiedColumnWidths.size();
240 CHECK(nCurrentColIdx <= rgSpecifiedColumnWidths.size());
241 const size_t remaining = rgSpecifiedColumnWidths.size() - nCurrentColIdx;
242 nColSpan =
std::min(nColSpan, remaining);
244 float fColSpanWidth = 0;
245 for (size_t i = 0; i < nColSpan; i++)
246 fColSpanWidth += rgSpecifiedColumnWidths[nCurrentColIdx + i];
248 if (nOriginalColSpan == -1 ||
249 nColSpan !=
static_cast<size_t>(nOriginalColSpan)) {
250 fColSpanWidth = bMetWholeRowCell ? 0
251 :
std::max(fColSpanWidth,
252 pLayoutChild->m_sSize.height);
254 if (nOriginalColSpan == -1)
255 bMetWholeRowCell =
true;
257 pLayoutChild->m_sPos = CFX_PointF(fCurrentColX, 0);
258 pLayoutChild->m_sSize.width = fColSpanWidth;
262 fCurrentColX += fColSpanWidth;
263 nCurrentColIdx += nColSpan;
264 float fNewHeight = bContainerHeightAutoSize ? -1 : fContentCurrentHeight;
265 UpdateWidgetSize(pLayoutChild, &fColSpanWidth, &fNewHeight);
266 pLayoutChild->m_sSize.height = fNewHeight;
267 if (bContainerHeightAutoSize) {
268 fContentCalculatedHeight =
269 std::max(fContentCalculatedHeight, pLayoutChild->m_sSize.height);
273 if (bContainerHeightAutoSize) {
275 pIter = pIter->GetNextSibling()) {
280 UpdateWidgetSize(pLayoutChild, &pLayoutChild->m_sSize.width,
281 &fContentCalculatedHeight);
282 float fOldChildHeight = pLayoutChild->m_sSize.height;
283 pLayoutChild->m_sSize.height = fContentCalculatedHeight;
284 CXFA_Para* pParaNode =
285 pLayoutChild
->GetFormNode()->GetFirstChildByClass<CXFA_Para>(
287 if (!pParaNode || !pLayoutChild->GetFirstChild())
290 float fOffHeight = fContentCalculatedHeight - fOldChildHeight;
295 fOffHeight = fOffHeight / 2;
308 pInnerIter; pInnerIter = pInnerIter->GetNextSibling()) {
311 pInnerChild->m_sPos.y += fOffHeight;
316 if (bContainerWidthAutoSize) {
317 float fChildSuppliedWidth = fCurrentColX;
318 if (fContentWidthLimit < FLT_MAX &&
319 fContentWidthLimit > fChildSuppliedWidth) {
320 fChildSuppliedWidth = fContentWidthLimit;
322 fContentCalculatedWidth =
323 std::max(fContentCalculatedWidth, fChildSuppliedWidth);
325 fContentCalculatedWidth = containerSize.width - inset
.left - inset
.right;
331 pIter = pIter->GetNextSibling()) {
336 pLayoutChild->m_sPos.x = fContentCalculatedWidth -
337 pLayoutChild->m_sPos.x -
338 pLayoutChild->m_sSize.width;
341 pLayoutRow->m_sSize = CalculateContainerComponentSizeFromContentSize(
342 pLayoutRow->GetFormNode(), bContainerWidthAutoSize,
343 fContentCalculatedWidth, bContainerHeightAutoSize,
344 fContentCalculatedHeight, containerSize);
348 *bRootForceTb =
false;
350 pFormNode->JSObject()->TryEnum(XFA_Attribute::Layout,
false);
351 if (layoutMode.has_value())
352 return layoutMode.value();
354 CXFA_Node* pParentNode = pFormNode->GetParent();
356 *bRootForceTb =
true;
362bool ExistContainerKeep(
CXFA_Node* pCurNode,
bool bPreFind) {
372 pCurNode->GetFirstChildByClass<CXFA_Keep>(
XFA_Element::Keep);
379 pKeep->JSObject()->TryEnum(eKeepType,
false);
386 pKeep = pPreContainer->GetFirstChildByClass<CXFA_Keep>(
XFA_Element::Keep);
395 pKeep->JSObject()->TryEnum(eKeepType,
false);
406 for (
CXFA_Node* pBreakNode = pContainerNode; pBreakNode;
407 pBreakNode = pBreakNode->GetNextSibling()) {
410 *pCurActionNode = pBreakNode;
413 if (pBreakNode->JSObject()->GetEnum(
XFA_Attribute::Before) ==
417 *pCurActionNode = pBreakNode;
429 for (
CXFA_Node* pBreakNode = pContainerNode; pBreakNode;
430 pBreakNode = pBreakNode->GetNextSibling()) {
433 *pCurActionNode = pBreakNode;
440 *pCurActionNode = pBreakNode;
449void DeleteLayoutGeneratedNode(
CXFA_Node* pGenerateNode) {
453 CXFA_NodeIterator sIterator(pGenerateNode);
454 for (
CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
455 pNode = sIterator.MoveToNext()) {
456 CXFA_ContentLayoutItem* pCurLayoutItem =
457 ToContentLayoutItem(pNode->JSObject()->GetLayoutItem());
458 while (pCurLayoutItem) {
459 CXFA_ContentLayoutItem* pNextLayoutItem = pCurLayoutItem
->GetNext();
461 pCurLayoutItem = pNextLayoutItem;
464 pGenerateNode->GetParent()->RemoveChildAndNotify(pGenerateNode,
true);
479bool FindLayoutItemSplitPos(CXFA_ContentLayoutItem* pLayoutItem,
480 float fCurVerticalOffset,
481 float* fProposedSplitPos,
483 bool bCalculateMargin) {
486 *fProposedSplitPos > fCurVerticalOffset + pLayoutItem->m_sSize.height -
493 bool bAnyChanged =
false;
496 float fCurTopMargin = 0;
497 float fCurBottomMargin = 0;
498 CXFA_Margin* pMarginNode =
499 pFormNode->GetFirstChildByClass<CXFA_Margin>(
XFA_Element::Margin);
500 if (pMarginNode && bCalculateMargin) {
501 fCurTopMargin = pMarginNode->JSObject()->GetMeasureInUnit(
503 fCurBottomMargin = pMarginNode->JSObject()->GetMeasureInUnit(
506 bool bChanged =
true;
510 std::optional<
float> fRelSplitPos = pFormNode->FindSplitPos(
511 pNotify->GetFFDoc()->GetDocView(), pLayoutItem->GetIndex(),
512 *fProposedSplitPos - fCurVerticalOffset);
513 if (fRelSplitPos.has_value()) {
516 *fProposedSplitPos = fCurVerticalOffset + fRelSplitPos.value();
518 if (*fProposedSplitPos <=
524 float fRelSplitPos = *fProposedSplitPos - fCurBottomMargin;
526 pIter = pIter->GetNextSibling()) {
532 fCurVerticalOffset + fCurTopMargin + pChildItem->m_sPos.y;
533 bool bChange =
false;
534 if (FindLayoutItemSplitPos(pChildItem, fChildOffset, &fRelSplitPos,
535 &bChange, bCalculateMargin)) {
537 *fProposedSplitPos = fRelSplitPos - fCurTopMargin;
539 *fProposedSplitPos = fRelSplitPos + fCurBottomMargin;
543 if (*fProposedSplitPos <=
556 *fProposedSplitPos = fCurVerticalOffset;
568 int32_t nAnchorType = 0;
569 switch (eAnchorType) {
601 pNode->JSObject()->GetMeasureInUnit(XFA_Attribute::X, XFA_Unit::Pt),
602 pNode->JSObject()->GetMeasureInUnit(XFA_Attribute::Y, XFA_Unit::Pt));
604 XFA_MapRotation(pNode->JSObject()->GetInteger(
XFA_Attribute::Rotate)) /
606 int32_t nAbsoluteAnchorType = kNextPosTable[nRotate][nAnchorType];
607 switch (nAbsoluteAnchorType / 3) {
609 pos.y -= size.height / 2;
612 pos.y -= size.height;
617 switch (nAbsoluteAnchorType % 3) {
619 pos.x -= size.width / 2;
638 m_pViewLayoutProcessor(pViewLayoutProcessor) {
640 DCHECK(GetFormNode()->IsContainerNode() ||
641 GetFormNode()->GetElementType() == XFA_Element::Form);
643 ToContentLayoutItem(GetFormNode()->JSObject()->GetLayoutItem());
649 visitor->Trace(m_pFormNode);
650 visitor->Trace(m_pCurChildNode);
651 visitor->Trace(m_pKeepHeadNode);
652 visitor->Trace(m_pKeepTailNode);
653 visitor->Trace(m_pLayoutItem);
654 visitor->Trace(m_pOldLayoutItem);
655 visitor->Trace(m_pViewLayoutProcessor);
656 visitor->Trace(m_pCurChildPreprocessor);
657 ContainerTrace(visitor, m_ArrayKeepItems);
658 ContainerTrace(visitor, m_PendingNodes);
659 ContainerTrace(visitor, m_PendingNodesCount);
667 if (m_pOldLayoutItem) {
668 CXFA_ContentLayoutItem* pLayoutItem = m_pOldLayoutItem;
669 m_pOldLayoutItem = m_pOldLayoutItem->GetNext();
673 auto* pNewLayoutItem = cppgc::MakeGarbageCollected<CXFA_ContentLayoutItem>(
674 GetHeap()->GetAllocationHandle(), pFormNode,
675 pNotify->OnCreateContentLayoutItem(pFormNode));
677 CXFA_ContentLayoutItem* pPrevLayoutItem =
678 ToContentLayoutItem(pFormNode->JSObject()->GetLayoutItem());
679 if (pPrevLayoutItem) {
682 pFormNode->JSObject()->SetLayoutItem(pNewLayoutItem);
684 return pNewLayoutItem;
693 bool bAppChange =
false;
694 if (!FindLayoutItemSplitPos(m_pLayoutItem.Get(), 0, &fProposedSplitPos,
695 &bAppChange, bCalculateMargin)) {
699 return fProposedSplitPos;
703 CXFA_ContentLayoutItem* pLayoutItem,
704 CXFA_ContentLayoutItem* pSecondParent,
706 float fCurTopMargin = 0;
707 float fCurBottomMargin = 0;
710 bool bCalculateMargin =
true;
712 bCalculateMargin =
false;
714 CXFA_Margin* pMarginNode =
715 pLayoutItem
->GetFormNode()->GetFirstChildByClass<CXFA_Margin>(
717 if (pMarginNode && bCalculateMargin) {
718 fCurTopMargin = pMarginNode->JSObject()->GetMeasureInUnit(
720 fCurBottomMargin = pMarginNode->JSObject()->GetMeasureInUnit(
724 CXFA_ContentLayoutItem* pSecondLayoutItem =
nullptr;
725 if (m_pCurChildPreprocessor &&
726 m_pCurChildPreprocessor->GetFormNode() == pLayoutItem->GetFormNode()) {
727 pSecondLayoutItem = m_pCurChildPreprocessor->CreateContentLayoutItem(
728 pLayoutItem->GetFormNode());
730 pSecondLayoutItem = CreateContentLayoutItem(pLayoutItem
->GetFormNode());
732 pSecondLayoutItem->m_sPos.x = pLayoutItem->m_sPos.x;
733 pSecondLayoutItem->m_sSize.width = pLayoutItem->m_sSize.width;
734 pSecondLayoutItem->m_sPos.y = 0;
735 pSecondLayoutItem->m_sSize.height = pLayoutItem->m_sSize.height - fSplitPos;
736 pLayoutItem->m_sSize.height -= pSecondLayoutItem->m_sSize.height;
737 if (pLayoutItem->GetFirstChild())
738 pSecondLayoutItem->m_sSize.height += fCurTopMargin;
740 bool bOrphanedItem =
false;
742 pSecondParent->AppendLastChild(pSecondLayoutItem);
743 if (fCurTopMargin > 0 && pLayoutItem->GetFirstChild()) {
744 pSecondParent->m_sSize.height += fCurTopMargin;
746 pParentIter; pParentIter = pParentIter->GetParent()) {
747 CXFA_ContentLayoutItem* pContentItem =
752 pContentItem->m_sSize.height += fCurTopMargin;
755 }
else if (pLayoutItem->GetParent()) {
756 pLayoutItem->GetParent()->InsertAfter(pSecondLayoutItem, pLayoutItem);
762 bOrphanedItem =
true;
765 std::vector<CXFA_ContentLayoutItem*> children;
766 while (
auto* pFirst = ToContentLayoutItem(pLayoutItem->GetFirstChild())) {
767 children.push_back(pFirst);
768 pLayoutItem->RemoveChild(children.back());
771 float lHeightForKeep = 0;
772 float fAddMarginHeight = 0;
773 std::vector<CXFA_ContentLayoutItem*> keepLayoutItems;
774 for (CXFA_ContentLayoutItem* pChildItem : children) {
775 if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin +
776 kXFALayoutPrecision) {
777 if (!ExistContainerKeep(pChildItem->GetFormNode(),
true)) {
778 pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin;
779 pChildItem->m_sPos.y += lHeightForKeep;
780 pChildItem->m_sPos.y += fAddMarginHeight;
781 pSecondLayoutItem->AppendLastChild(pChildItem);
784 if (lHeightForKeep < kXFALayoutPrecision) {
785 for (CXFA_ContentLayoutItem* pPreItem : keepLayoutItems) {
786 pLayoutItem->RemoveChild(pPreItem);
787 pPreItem->m_sPos.y -= fSplitPos;
788 if (pPreItem->m_sPos.y < 0)
789 pPreItem->m_sPos.y = 0;
790 if (pPreItem->m_sPos.y + pPreItem->m_sSize.height > lHeightForKeep) {
791 pPreItem->m_sPos.y = lHeightForKeep;
792 lHeightForKeep += pPreItem->m_sSize.height;
793 pSecondLayoutItem->m_sSize.height += pPreItem->m_sSize.height;
795 pSecondParent->m_sSize.height += pPreItem->m_sSize.height;
797 pSecondLayoutItem->AppendLastChild(pPreItem);
800 pChildItem->m_sPos.y -= fSplitPos;
801 pChildItem->m_sPos.y += lHeightForKeep;
802 pChildItem->m_sPos.y += fAddMarginHeight;
803 pSecondLayoutItem->AppendLastChild(pChildItem);
806 if (fSplitPos + kXFALayoutPrecision >= fCurTopMargin + fCurBottomMargin +
807 pChildItem->m_sPos.y +
808 pChildItem->m_sSize.height) {
809 pLayoutItem->AppendLastChild(pChildItem);
810 if (ExistContainerKeep(pChildItem->GetFormNode(),
false))
811 keepLayoutItems.push_back(pChildItem);
813 keepLayoutItems.clear();
817 float fOldHeight = pSecondLayoutItem->m_sSize.height;
819 pChildItem, pSecondLayoutItem,
820 fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y);
821 fAddMarginHeight = pSecondLayoutItem->m_sSize.height - fOldHeight;
822 pLayoutItem->AppendLastChild(pChildItem);
825 pLayoutItem->AppendLastChild(pSecondLayoutItem);
830 SplitLayoutItem(m_pLayoutItem.Get(),
nullptr, fSplitPos);
834 CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem;
836 m_pLayoutItem = ToContentLayoutItem(pLayoutItem->GetNextSibling());
837 pLayoutItem->RemoveSelfIfParented();
839 if (m_nCurChildNodeStage != Stage::kDone || !m_pOldLayoutItem)
843 m_pOldLayoutItem->GetFormNode()->GetDocument()->GetNotify();
844 auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(
845 m_pOldLayoutItem->GetFormNode()->GetDocument());
847 while (m_pOldLayoutItem) {
848 CXFA_ContentLayoutItem* pToDeleteItem = m_pOldLayoutItem;
849 m_pOldLayoutItem = pToDeleteItem->GetNext();
850 if (pToDeleteItem == pLayoutItem)
853 pToDeleteItem->RemoveSelfIfParented();
859 std::tie(m_nCurChildNodeStage, m_pCurChildNode) = GotoNextContainerNode(
860 m_nCurChildNodeStage, GetFormNode(), m_pCurChildNode);
871 pChildContainer = pCurActionNode->GetParent();
876 pChildContainer = pCurActionNode;
879 pChildContainer =
nullptr;
886 ret = HandleKeep(pChildContainer->GetFirstChild(), &pCurActionNode);
888 return {ret.value(), pCurActionNode};
892 pCurActionNode =
nullptr;
896 ret = HandleBookendLeader(pParentContainer, &pCurActionNode);
898 return {ret.value(), pCurActionNode};
899 pCurActionNode =
nullptr;
903 ret = HandleBreakBefore(pChildContainer, &pCurActionNode);
905 return {ret.value(), pCurActionNode};
909 pCurActionNode =
nullptr;
913 ret = HandleBreakAfter(pChildContainer, &pCurActionNode);
915 return {ret.value(), pCurActionNode};
919 ret = HandleBookendTrailer(pParentContainer, &pCurActionNode);
921 return {ret.value(), pCurActionNode};
928 ret = HandleCheckNextChildContainer(pParentContainer, pChildContainer,
931 return {ret.value(), pCurActionNode};
933 pCurActionNode =
nullptr;
934 ret = HandleBookendTrailer(pParentContainer, &pCurActionNode);
936 return {ret.value(), pCurActionNode};
945 bool* pLastKeepNode) {
946 const bool bCanSplit =
948 const bool bNextKeep = ExistContainerKeep(*pNextContainer,
false);
950 if (bNextKeep && !bCanSplit) {
951 if (!m_bIsProcessKeep && !m_bKeepBreakFinish) {
952 m_pKeepHeadNode = *pNextContainer;
953 m_bIsProcessKeep =
true;
958 if (!m_bIsProcessKeep || !m_pKeepHeadNode) {
959 if (m_bKeepBreakFinish)
960 *pLastKeepNode =
true;
961 m_bKeepBreakFinish =
false;
965 m_pKeepTailNode = *pNextContainer;
966 if (m_bKeepBreakFinish) {
967 *pNextContainer = m_pKeepHeadNode;
968 ProcessKeepNodesEnd();
973 FindBreakBeforeNode((*pNextContainer)->GetFirstChild(), pCurActionNode);
974 if (!ret.has_value()) {
975 *pNextContainer = m_pKeepHeadNode;
976 ProcessKeepNodesEnd();
987 if (m_pKeepTailNode == pContainerNode) {
988 *pCurActionNode = m_pKeepHeadNode;
989 ProcessKeepNodesEnd();
993 CXFA_Node* pBreakAfterNode = pContainerNode->GetFirstChild();
994 return FindBreakAfterNode(pBreakAfterNode, pCurActionNode);
998 CXFA_ViewLayoutItem* pPageAreaLayoutItem) {
1004 std::tie(nCurChildNodeStage, pCurChildNode) =
1005 GotoNextContainerNode(nCurChildNodeStage, pFormNode, pCurChildNode);
1013 auto* pProcessor = cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1014 GetHeap()->GetAllocationHandle(), GetHeap(), pCurChildNode,
nullptr);
1015 pProcessor->DoLayout(
false, FLT_MAX, FLT_MAX);
1016 if (!pProcessor->HasLayoutItem())
1019 pProcessor->SetCurrentComponentPos(CalculatePositionedContainerPos(
1020 pCurChildNode, pProcessor->GetCurrentComponentSize()));
1024 pPageAreaLayoutItem->AppendFirstChild(pProcessItem);
1026 pPageAreaLayoutItem->InsertAfter(pProcessItem, pBeforeItem);
1028 pBeforeItem = pProcessItem;
1031 pBeforeItem =
nullptr;
1033 while (pLayoutItem) {
1036 pLayoutItem = pLayoutItem->GetNextSibling();
1043 pPageAreaLayoutItem->RemoveChild(pLayoutItem);
1045 pPageAreaLayoutItem->AppendFirstChild(pLayoutItem);
1047 pPageAreaLayoutItem->InsertAfter(pLayoutItem, pBeforeItem);
1049 pBeforeItem = pLayoutItem;
1050 pLayoutItem = pNextLayoutItem;
1055 Context* pContext) {
1059 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1063 bool bContainerWidthAutoSize =
true;
1064 bool bContainerHeightAutoSize =
true;
1065 CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
1066 GetFormNode(), &bContainerWidthAutoSize, &bContainerHeightAutoSize);
1068 float fContentCalculatedWidth = 0;
1069 float fContentCalculatedHeight = 0;
1070 float fHiddenContentCalculatedWidth = 0;
1071 float fHiddenContentCalculatedHeight = 0;
1072 if (!m_pCurChildNode)
1073 GotoNextContainerNodeSimple();
1075 int32_t iColIndex = 0;
1076 for (; m_pCurChildNode; GotoNextContainerNodeSimple()) {
1079 if (m_pCurChildNode->GetElementType() == XFA_Element::Variables)
1082 auto* pProcessor = cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1083 GetHeap()->GetAllocationHandle(), GetHeap(), m_pCurChildNode,
1084 m_pViewLayoutProcessor);
1086 if (pContext && pContext->m_prgSpecifiedColumnWidths) {
1088 m_pCurChildNode->JSObject()->GetInteger(XFA_Attribute::ColSpan);
1089 if (iColSpan <=
fxcrt::CollectionSize<int32_t>(
1090 *pContext->m_prgSpecifiedColumnWidths) -
1092 pContext->m_fCurColumnWidth = 0.0f;
1093 if (iColSpan == -1) {
1094 iColSpan =
fxcrt::CollectionSize<int32_t>(
1095 *pContext->m_prgSpecifiedColumnWidths);
1097 for (int32_t i = 0; iColIndex + i < iColSpan; ++i) {
1098 pContext->m_fCurColumnWidth.value() +=
1099 (*pContext->m_prgSpecifiedColumnWidths)[iColIndex + i];
1101 if (pContext->m_fCurColumnWidth.value() == 0)
1102 pContext->m_fCurColumnWidth.reset();
1104 iColIndex += iColSpan >= 0 ? iColSpan : 0;
1108 pProcessor->DoLayoutInternal(
false, FLT_MAX, FLT_MAX, pContext);
1109 if (!pProcessor->HasLayoutItem())
1112 CFX_SizeF size = pProcessor->GetCurrentComponentSize();
1113 bool bChangeParentSize =
false;
1114 if (m_pCurChildNode->PresenceRequiresSpace())
1115 bChangeParentSize =
true;
1119 absolutePos = CalculatePositionedContainerPos(m_pCurChildNode, size);
1121 pProcessor->SetCurrentComponentPos(absolutePos);
1122 if (bContainerWidthAutoSize) {
1123 float fChildSuppliedWidth = absolutePos.x + size.width;
1124 if (bChangeParentSize) {
1125 fContentCalculatedWidth =
1126 std::max(fContentCalculatedWidth, fChildSuppliedWidth);
1128 if (fHiddenContentCalculatedWidth < fChildSuppliedWidth &&
1129 m_pCurChildNode->GetElementType() != XFA_Element::Subform) {
1130 fHiddenContentCalculatedWidth = fChildSuppliedWidth;
1135 if (bContainerHeightAutoSize) {
1136 float fChildSuppliedHeight = absolutePos.y + size.height;
1137 if (bChangeParentSize) {
1138 fContentCalculatedHeight =
1139 std::max(fContentCalculatedHeight, fChildSuppliedHeight);
1141 if (fHiddenContentCalculatedHeight < fChildSuppliedHeight &&
1142 m_pCurChildNode->GetElementType() != XFA_Element::Subform) {
1143 fHiddenContentCalculatedHeight = fChildSuppliedHeight;
1147 m_pLayoutItem->AppendLastChild(pProcessor->ExtractLayoutItem());
1152 fContentCalculatedWidth = fHiddenContentCalculatedWidth;
1154 fContentCalculatedHeight = fHiddenContentCalculatedHeight;
1156 containerSize = CalculateContainerComponentSizeFromContentSize(
1157 GetFormNode(), bContainerWidthAutoSize, fContentCalculatedWidth,
1158 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize);
1159 SetCurrentComponentSize(containerSize);
1169 DCHECK(!m_pCurChildNode);
1171 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1172 bool bContainerWidthAutoSize =
true;
1173 bool bContainerHeightAutoSize =
true;
1174 CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
1175 GetFormNode(), &bContainerWidthAutoSize, &bContainerHeightAutoSize);
1176 float fContentCalculatedWidth = 0;
1177 float fContentCalculatedHeight = 0;
1178 CXFA_Margin* pMarginNode =
1180 float fLeftInset = 0;
1181 float fRightInset = 0;
1183 fLeftInset = pMarginNode->JSObject()->GetMeasureInUnit(
1185 fRightInset = pMarginNode->JSObject()->GetMeasureInUnit(
1189 float fContentWidthLimit =
1190 bContainerWidthAutoSize ? FLT_MAX
1191 : containerSize.width - fLeftInset - fRightInset;
1193 pLayoutNode->JSObject()->GetCData(
XFA_Attribute::ColumnWidths);
1194 if (!wsColumnWidths.IsEmpty()) {
1195 for (
auto& width : SeparateStringOnSpace(wsColumnWidths.span())) {
1196 width.TrimFront(L' ');
1197 if (width.IsEmpty())
1200 m_rgSpecifiedColumnWidths.push_back(
1201 CXFA_Measurement(width.AsStringView()).ToUnit(XFA_Unit::Pt));
1205 int32_t iSpecifiedColumnCount =
1206 fxcrt::CollectionSize<int32_t>(m_rgSpecifiedColumnWidths);
1207 Context layoutContext;
1208 layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths;
1209 Context* pLayoutContext =
1210 iSpecifiedColumnCount > 0 ? &layoutContext :
nullptr;
1211 if (!m_pCurChildNode)
1212 GotoNextContainerNodeSimple();
1214 for (; m_pCurChildNode; GotoNextContainerNodeSimple()) {
1215 layoutContext.m_fCurColumnWidth.reset();
1219 auto* pProcessor = cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1220 GetHeap()->GetAllocationHandle(), GetHeap(), m_pCurChildNode,
1221 m_pViewLayoutProcessor);
1223 pProcessor->DoLayoutInternal(
false, FLT_MAX, FLT_MAX, pLayoutContext);
1224 if (!pProcessor->HasLayoutItem())
1227 m_pLayoutItem->AppendLastChild(pProcessor->ExtractLayoutItem());
1230 int32_t iRowCount = 0;
1231 int32_t iColCount = 0;
1233 std::vector<CXFA_ContentLayoutItem*> rgRowItems;
1234 std::vector<int32_t> rgRowItemsSpan;
1235 std::vector<
float> rgRowItemsWidth;
1237 pIter = pIter->GetNextSibling()) {
1253 CXFA_ContentLayoutItem* pRowLayoutCell =
1254 ToContentLayoutItem(pLayoutChild->GetFirstChild());
1255 if (pRowLayoutCell) {
1256 rgRowItems.push_back(pRowLayoutCell);
1260 rgRowItemsSpan.push_back(iColSpan);
1261 rgRowItemsWidth.push_back(pRowLayoutCell->m_sSize.width);
1265 iRowCount =
fxcrt::CollectionSize<int32_t>(rgRowItems);
1267 bool bMoreColumns =
true;
1268 while (bMoreColumns) {
1269 bMoreColumns =
false;
1270 bool bAutoCol =
false;
1271 for (int32_t i = 0; i < iRowCount; i++) {
1272 while (rgRowItems[i] &&
1273 (rgRowItemsSpan[i] <= 0 ||
1274 !rgRowItems[i]->GetFormNode()->PresenceRequiresSpace())) {
1275 CXFA_ContentLayoutItem* pNewCell =
1276 ToContentLayoutItem(rgRowItems[i]->GetNextSibling());
1277 if (rgRowItemsSpan[i] < 0 &&
1278 rgRowItems[i]->GetFormNode()->PresenceRequiresSpace()) {
1281 rgRowItems[i] = pNewCell;
1286 rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.width : 0;
1288 CXFA_ContentLayoutItem* pCell = rgRowItems[i];
1292 bMoreColumns =
true;
1293 if (rgRowItemsSpan[i] != 1)
1296 if (iColCount >= iSpecifiedColumnCount) {
1297 int32_t c = iColCount + 1 -
1298 fxcrt::CollectionSize<int32_t>(m_rgSpecifiedColumnWidths);
1299 for (int32_t j = 0; j < c; j++)
1300 m_rgSpecifiedColumnWidths.push_back(0);
1302 if (m_rgSpecifiedColumnWidths[iColCount] < kXFALayoutPrecision)
1305 m_rgSpecifiedColumnWidths[iColCount] < rgRowItemsWidth[i]) {
1306 m_rgSpecifiedColumnWidths[iColCount] = rgRowItemsWidth[i];
1313 float fFinalColumnWidth = 0.0f;
1314 if (fxcrt::IndexInBounds(m_rgSpecifiedColumnWidths, iColCount))
1315 fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount];
1317 for (int32_t i = 0; i < iRowCount; ++i) {
1320 --rgRowItemsSpan[i];
1321 rgRowItemsWidth[i] -= fFinalColumnWidth;
1327 float fCurrentRowY = 0;
1329 pIter = pIter->GetNextSibling()) {
1331 if (!pLayoutChild || !pLayoutChild
->GetFormNode()->PresenceRequiresSpace())
1340 RelocateTableRowCells(pLayoutChild, m_rgSpecifiedColumnWidths,
1345 pLayoutChild->m_sPos.y = fCurrentRowY;
1346 if (bContainerWidthAutoSize) {
1347 pLayoutChild->m_sPos.x = 0;
1352 pLayoutChild->m_sPos.x =
1353 (fContentWidthLimit - pLayoutChild->m_sSize.width) / 2;
1356 pLayoutChild->m_sPos.x =
1357 fContentWidthLimit - pLayoutChild->m_sSize.width;
1361 pLayoutChild->m_sPos.x = 0;
1366 if (bContainerWidthAutoSize) {
1367 float fChildSuppliedWidth =
1368 pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.width;
1369 if (fContentWidthLimit < FLT_MAX &&
1370 fContentWidthLimit > fChildSuppliedWidth) {
1371 fChildSuppliedWidth = fContentWidthLimit;
1373 fContentCalculatedWidth =
1374 std::max(fContentCalculatedWidth, fChildSuppliedWidth);
1376 fCurrentRowY += pLayoutChild->m_sSize.height;
1379 if (bContainerHeightAutoSize)
1380 fContentCalculatedHeight =
std::max(fContentCalculatedHeight, fCurrentRowY);
1382 containerSize = CalculateContainerComponentSizeFromContentSize(
1383 GetFormNode(), bContainerWidthAutoSize, fContentCalculatedWidth,
1384 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize);
1385 SetCurrentComponentSize(containerSize);
1389 CXFA_ContentLayoutItem* pTrailerItem) {
1393 float fWidth = pTrailerItem->m_sSize.width;
1400 if (m_ArrayKeepItems.empty())
1403 if (!m_pLayoutItem) {
1404 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1405 m_pLayoutItem->m_sSize.clear();
1408 float fTotalHeight = 0;
1409 for (
const auto& item : pdfium::Reversed(m_ArrayKeepItems)) {
1410 AddLeaderAfterSplit(item);
1411 fTotalHeight += item->m_sSize.height;
1413 m_ArrayKeepItems.clear();
1415 return fTotalHeight;
1421 ContentLayoutItemVector& rgCurLineLayoutItem,
1422 float* fContentCurRowAvailWidth,
1423 float* fContentCurRowHeight,
1424 float* fContentCurRowY,
1425 bool* bAddedItemInRow,
1426 bool* bForceEndPage,
1428 if (!pChildProcessor)
1431 if (m_pCurChildNode->GetIntact() == XFA_AttributeValue::None &&
1432 pChildProcessor->m_bHasAvailHeight)
1435 if (!ExistContainerKeep(m_pCurChildNode,
true))
1438 CFX_SizeF childSize = pChildProcessor->GetCurrentComponentSize();
1439 std::vector<CXFA_ContentLayoutItem*> keepLayoutItems;
1440 if (JudgePutNextPage(m_pLayoutItem.Get(), childSize.height,
1441 &keepLayoutItems)) {
1442 m_ArrayKeepItems.clear();
1443 for (CXFA_ContentLayoutItem* item : keepLayoutItems) {
1444 m_pLayoutItem->RemoveChild(item);
1445 *fContentCurRowY -= item->m_sSize.height;
1446 m_ArrayKeepItems.push_back(item);
1448 *bAddedItemInRow =
true;
1449 *bForceEndPage =
true;
1455 *bAddedItemInRow =
true;
1456 *fContentCurRowAvailWidth -= childSize.width;
1457 *fContentCurRowHeight =
std::max(*fContentCurRowHeight, childSize.height);
1458 *result = eRetValue;
1463 CXFA_ContentLayoutItem* pParentLayoutItem,
1465 std::vector<CXFA_ContentLayoutItem*>* pKeepItems) {
1466 if (!pParentLayoutItem)
1469 float fItemsHeight = 0;
1470 for (
CXFA_LayoutItem* pIter = pParentLayoutItem->GetFirstChild(); pIter;
1471 pIter = pIter->GetNextSibling()) {
1473 if (!pChildLayoutItem)
1476 if (ExistContainerKeep(pChildLayoutItem
->GetFormNode(),
false)) {
1477 pKeepItems->push_back(pChildLayoutItem);
1478 fItemsHeight += pChildLayoutItem->m_sSize.height;
1480 pKeepItems->clear();
1484 fItemsHeight += fChildHeight;
1485 return m_pViewLayoutProcessor->GetNextAvailContentHeight(fItemsHeight);
1492 CXFA_NodeIterator sIterator(pFormNode);
1493 for (
CXFA_Node* pNode = sIterator.MoveToNext(); pNode;
1494 pNode = sIterator.MoveToNext()) {
1509 CXFA_ContentLayoutItem* pTrailerItem,
1511 ProcessUnUseBinds(pLeaderNode);
1512 ProcessUnUseBinds(pTrailerNode);
1518 pFormNode = pFormNode->GetParent();
1520 if (pLeaderNode && pFormNode)
1522 if (pTrailerNode && pFormNode)
1525 XFA_ReleaseLayoutItem(pTrailerItem);
1530 bool bUseBreakControl,
1535 bool bRootForceTb) {
1536 m_bHasAvailHeight =
true;
1537 if (m_pCurChildPreprocessor)
1538 m_pCurChildPreprocessor->m_ePreProcessRs = Result::kDone;
1540 bool bContainerWidthAutoSize =
true;
1541 bool bContainerHeightAutoSize =
true;
1542 CFX_SizeF container_size = CalculateContainerSpecifiedSize(
1543 GetFormNode(), &bContainerWidthAutoSize, &bContainerHeightAutoSize);
1544 AdjustContainerSpecifiedSize(pContext, &container_size,
1545 &bContainerWidthAutoSize,
1546 &bContainerHeightAutoSize);
1548 CXFA_Margin* pMargin =
1551 float fContentWidthLimit =
1552 bContainerWidthAutoSize ? FLT_MAX
1553 : container_size.width - inset.left - inset.right;
1554 float fAvailHeight = fHeightLimit - inset
.top - inset
.bottom;
1555 if (fAvailHeight < 0)
1556 m_bHasAvailHeight =
false;
1558 fRealHeight = fRealHeight - inset
.top - inset
.bottom;
1560 float fContentCurRowY = 0;
1561 CXFA_ContentLayoutItem* pLastChild =
nullptr;
1562 if (m_pLayoutItem) {
1563 pLastChild = FindLastContentLayoutItem(eFlowStrategy);
1564 calculated_size = CalculateLayoutItemSize(pLastChild);
1566 pLastChild ? pLastChild->m_sPos.y : calculated_size.height;
1569 fContentCurRowY += InsertKeepLayoutItems();
1571 GotoNextContainerNodeSimple();
1574 if (m_pCurChildPreprocessor && m_nCurChildNodeStage == Stage::kContainer) {
1575 if (ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(),
false)) {
1576 m_pKeepHeadNode = m_pCurChildNode;
1577 m_bIsProcessKeep =
true;
1582 bool bForceEndPage =
false;
1583 bool bBreakDone =
false;
1584 bool bIsManualBreak =
false;
1586 float fContentCurRowHeight = 0;
1587 float fContentCurRowAvailWidth = fContentWidthLimit;
1588 m_fWidthLimit = fContentCurRowAvailWidth;
1589 std::array<ContentLayoutItemVector, 3> rgCurLineLayoutItems;
1590 uint8_t uCurHAlignState =
1594 pNext = pNext->GetNextSibling()) {
1598 if (!pLayoutNext->GetNextSibling() && m_pCurChildPreprocessor &&
1599 m_pCurChildPreprocessor->GetFormNode() ==
1600 pLayoutNext->GetFormNode()) {
1601 if (m_pCurChildPreprocessor->m_pLayoutItem &&
1602 m_pCurChildPreprocessor->m_pLayoutItem != pLayoutNext) {
1603 pLayoutNext->InsertAfter(
1604 m_pCurChildPreprocessor->m_pLayoutItem.Get());
1606 m_pCurChildPreprocessor->m_pLayoutItem = pLayoutNext;
1610 HAlignEnumToInt(pLayoutNext
->GetFormNode()->JSObject()->GetEnum(
1612 rgCurLineLayoutItems[uHAlign].emplace_back(pLayoutNext);
1614 if (uHAlign > uCurHAlignState)
1615 uCurHAlignState = uHAlign;
1616 }
else if (uHAlign < uCurHAlignState) {
1617 uCurHAlignState = uHAlign;
1620 if (pLayoutNext->m_sSize.height > fContentCurRowHeight)
1621 fContentCurRowHeight = pLayoutNext->m_sSize.height;
1622 fContentCurRowAvailWidth -= pLayoutNext->m_sSize.width;
1626 CXFA_ContentLayoutItem* pLayoutNextTemp = pLastChild;
1627 while (pLayoutNextTemp) {
1628 CXFA_ContentLayoutItem* pSaveLayoutNext =
1629 ToContentLayoutItem(pLayoutNextTemp->GetNextSibling());
1630 pLayoutNextTemp->RemoveSelfIfParented();
1631 pLayoutNextTemp = pSaveLayoutNext;
1633 pLastChild =
nullptr;
1636 while (m_pCurChildNode) {
1638 bool bAddedItemInRow =
false;
1640 switch (m_nCurChildNodeStage) {
1645 for (
auto& item : m_ArrayKeepItems) {
1646 m_pLayoutItem->RemoveChild(item);
1647 calculated_size.height -= item->m_sSize.height;
1650 if (!bUseBreakControl || !m_pViewLayoutProcessor)
1654 m_pViewLayoutProcessor->ProcessBreakBefore(m_pCurChildNode);
1655 if (!break_data.has_value() || !break_data.value().bCreatePage ||
1660 CXFA_Node* pLeaderNode = break_data.value().pLeader;
1661 CXFA_Node* pTrailerNode = break_data.value().pTrailer;
1662 if (JudgeLeaderOrTrailerForOccur(pLeaderNode))
1663 AddPendingNode(pLeaderNode,
true);
1665 if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) {
1666 if (GetFormNode()->GetParent()->GetElementType() ==
1667 XFA_Element::Form &&
1669 AddPendingNode(pTrailerNode,
true);
1671 auto* pTempProcessor =
1672 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1673 GetHeap()->GetAllocationHandle(), GetHeap(), pTrailerNode,
1677 pTempProcessor, bContainerWidthAutoSize,
1678 bContainerHeightAutoSize, container_size.height,
1679 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
false,
1680 FLT_MAX, FLT_MAX, fContentWidthLimit, &fContentCurRowY,
1681 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1682 &bAddedItemInRow, &bForceEndPage, pContext,
false);
1685 GotoNextContainerNodeSimple();
1686 bForceEndPage =
true;
1687 bIsManualBreak =
true;
1688 goto SuspendAndCreateNewRow;
1691 if (!bUseBreakControl || !m_pViewLayoutProcessor)
1695 m_pViewLayoutProcessor->ProcessBreakAfter(m_pCurChildNode);
1696 if (!break_data.has_value() ||
1701 CXFA_Node* pLeaderNode = break_data.value().pLeader;
1702 CXFA_Node* pTrailerNode = break_data.value().pTrailer;
1703 bool bCreatePage = break_data.value().bCreatePage;
1704 if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) {
1705 auto* pTempProcessor =
1706 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1707 GetHeap()->GetAllocationHandle(), GetHeap(), pTrailerNode,
1710 InsertFlowedItem(pTempProcessor, bContainerWidthAutoSize,
1711 bContainerHeightAutoSize, container_size.height,
1712 eFlowStrategy, &uCurHAlignState,
1713 rgCurLineLayoutItems,
false, FLT_MAX, FLT_MAX,
1714 fContentWidthLimit, &fContentCurRowY,
1715 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1716 &bAddedItemInRow, &bForceEndPage, pContext,
false);
1719 if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) {
1720 CalculateRowChildPosition(
1721 rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize,
1722 bContainerWidthAutoSize, &calculated_size.width,
1723 &calculated_size.height, &fContentCurRowY,
1724 fContentCurRowHeight, fContentWidthLimit,
false);
1725 rgCurLineLayoutItems.front().clear();
1726 auto* pTempProcessor =
1727 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1728 GetHeap()->GetAllocationHandle(), GetHeap(), pLeaderNode,
1731 pTempProcessor, bContainerWidthAutoSize,
1732 bContainerHeightAutoSize, container_size.height,
1733 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
false,
1734 FLT_MAX, FLT_MAX, fContentWidthLimit, &fContentCurRowY,
1735 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1736 &bAddedItemInRow, &bForceEndPage, pContext,
false);
1739 if (JudgeLeaderOrTrailerForOccur(pLeaderNode))
1740 AddPendingNode(pLeaderNode,
true);
1743 GotoNextContainerNodeSimple();
1745 bForceEndPage =
true;
1746 bIsManualBreak =
true;
1750 goto SuspendAndCreateNewRow;
1753 if (m_pCurChildPreprocessor) {
1754 pProcessor = m_pCurChildPreprocessor.Get();
1755 m_pCurChildPreprocessor =
nullptr;
1756 }
else if (m_pViewLayoutProcessor) {
1758 m_pViewLayoutProcessor->ProcessBookendLeader(m_pCurChildNode);
1761 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1762 GetHeap()->GetAllocationHandle(), GetHeap(), pLeaderNode,
1763 m_pViewLayoutProcessor);
1768 if (InsertFlowedItem(
1769 pProcessor, bContainerWidthAutoSize,
1770 bContainerHeightAutoSize, container_size.height,
1771 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
1772 bUseBreakControl, fAvailHeight, fRealHeight,
1773 fContentWidthLimit, &fContentCurRowY,
1774 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1775 &bAddedItemInRow, &bForceEndPage, pContext,
1776 false) != Result::kDone) {
1777 goto SuspendAndCreateNewRow;
1779 pProcessor =
nullptr;
1784 if (m_pCurChildPreprocessor) {
1785 pProcessor = m_pCurChildPreprocessor;
1786 m_pCurChildPreprocessor.Clear();
1787 }
else if (m_pViewLayoutProcessor) {
1789 m_pViewLayoutProcessor->ProcessBookendTrailer(m_pCurChildNode);
1792 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1793 GetHeap()->GetAllocationHandle(), GetHeap(), pTrailerNode,
1794 m_pViewLayoutProcessor);
1798 if (InsertFlowedItem(
1799 pProcessor, bContainerWidthAutoSize,
1800 bContainerHeightAutoSize, container_size.height,
1801 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
1802 bUseBreakControl, fAvailHeight, fRealHeight,
1803 fContentWidthLimit, &fContentCurRowY,
1804 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1805 &bAddedItemInRow, &bForceEndPage, pContext,
1806 false) != Result::kDone) {
1807 goto SuspendAndCreateNewRow;
1809 pProcessor =
nullptr;
1814 DCHECK(m_pCurChildNode->IsContainerNode());
1815 if (m_pCurChildNode->GetElementType() == XFA_Element::Variables)
1817 if (fContentCurRowY >= fHeightLimit + kXFALayoutPrecision &&
1818 m_pCurChildNode->PresenceRequiresSpace()) {
1819 bForceEndPage =
true;
1820 goto SuspendAndCreateNewRow;
1822 if (!m_pCurChildNode->IsContainerNode())
1825 bool bNewRow =
false;
1826 if (m_pCurChildPreprocessor) {
1827 pProcessor = m_pCurChildPreprocessor;
1828 m_pCurChildPreprocessor.Clear();
1832 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1833 GetHeap()->GetAllocationHandle(), GetHeap(),
1834 m_pCurChildNode, m_pViewLayoutProcessor);
1837 pProcessor->InsertPendingItems(m_pCurChildNode);
1838 Result rs = InsertFlowedItem(
1839 pProcessor, bContainerWidthAutoSize, bContainerHeightAutoSize,
1840 container_size.height, eFlowStrategy, &uCurHAlignState,
1841 rgCurLineLayoutItems, bUseBreakControl, fAvailHeight, fRealHeight,
1842 fContentWidthLimit, &fContentCurRowY, &fContentCurRowAvailWidth,
1843 &fContentCurRowHeight, &bAddedItemInRow, &bForceEndPage, pContext,
1847 bIsManualBreak =
true;
1850 bForceEndPage =
true;
1853 goto SuspendAndCreateNewRow;
1856 pProcessor->InsertPendingItems(m_pCurChildNode);
1857 pProcessor =
nullptr;
1865 GotoNextContainerNodeSimple();
1869 SuspendAndCreateNewRow:
1871 m_pCurChildPreprocessor = pProcessor;
1872 pProcessor =
nullptr;
1877 CalculateRowChildPosition(rgCurLineLayoutItems, eFlowStrategy,
1878 bContainerHeightAutoSize, bContainerWidthAutoSize,
1879 &calculated_size.width, &calculated_size.height,
1880 &fContentCurRowY, fContentCurRowHeight,
1881 fContentWidthLimit, bRootForceTb);
1882 m_fWidthLimit = fContentCurRowAvailWidth;
1888 m_nCurChildNodeStage == Stage::kDone && m_PendingNodes.empty();
1892 container_size = CalculateContainerComponentSizeFromContentSize(
1893 GetFormNode(), bContainerWidthAutoSize, calculated_size.width,
1894 bContainerHeightAutoSize, calculated_size.height, container_size);
1896 if (container_size.height >= kXFALayoutPrecision || m_pLayoutItem ||
1899 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1900 container_size.height =
std::max(container_size.height, 0.f);
1902 SetCurrentComponentSize(container_size);
1906 m_fUsedSize += m_pLayoutItem->m_sSize.height;
1915 std::array<ContentLayoutItemVector, 3>& rgCurLineLayoutItems,
1917 bool bContainerHeightAutoSize,
1918 bool bContainerWidthAutoSize,
1919 float* fContentCalculatedWidth,
1920 float* fContentCalculatedHeight,
1921 float* fContentCurRowY,
1922 float fContentCurRowHeight,
1923 float fContentWidthLimit,
1924 bool bRootForceTb) {
1925 std::array<int32_t, 3> nGroupLengths = {};
1926 std::array<
float, 3> fGroupWidths = {};
1927 int32_t nTotalLength = 0;
1928 for (int32_t i = 0; i < 3; i++) {
1929 nGroupLengths[i] =
fxcrt::CollectionSize<int32_t>(rgCurLineLayoutItems[i]);
1930 for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) {
1932 if (rgCurLineLayoutItems[i][j]->GetFormNode()->PresenceRequiresSpace())
1933 fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.width;
1936 if (!nTotalLength) {
1937 if (bContainerHeightAutoSize) {
1938 *fContentCalculatedHeight =
1939 std::min(*fContentCalculatedHeight, *fContentCurRowY);
1944 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1949 for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) {
1951 rgCurLineLayoutItems[0][j]->m_sPos = CalculatePositionedContainerPos(
1952 rgCurLineLayoutItems[0][j]->GetFormNode(),
1953 rgCurLineLayoutItems[0][j]->m_sSize);
1955 rgCurLineLayoutItems[0][j]->m_sPos =
1956 CFX_PointF(fCurPos, *fContentCurRowY);
1957 if (rgCurLineLayoutItems[0][j]->GetFormNode()->PresenceRequiresSpace())
1958 fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.width;
1960 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[0][j]);
1961 m_fLastRowWidth = fCurPos;
1963 fCurPos = (fContentWidthLimit + fGroupWidths[0] - fGroupWidths[1] -
1966 for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) {
1968 rgCurLineLayoutItems[1][j]->m_sPos = CalculatePositionedContainerPos(
1969 rgCurLineLayoutItems[1][j]->GetFormNode(),
1970 rgCurLineLayoutItems[1][j]->m_sSize);
1972 rgCurLineLayoutItems[1][j]->m_sPos =
1973 CFX_PointF(fCurPos, *fContentCurRowY);
1974 if (rgCurLineLayoutItems[1][j]->GetFormNode()->PresenceRequiresSpace())
1975 fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.width;
1977 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[1][j]);
1978 m_fLastRowWidth = fCurPos;
1980 fCurPos = fContentWidthLimit - fGroupWidths[2];
1981 for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) {
1983 rgCurLineLayoutItems[2][j]->m_sPos = CalculatePositionedContainerPos(
1984 rgCurLineLayoutItems[2][j]->GetFormNode(),
1985 rgCurLineLayoutItems[2][j]->m_sSize);
1987 rgCurLineLayoutItems[2][j]->m_sPos =
1988 CFX_PointF(fCurPos, *fContentCurRowY);
1989 if (rgCurLineLayoutItems[2][j]->GetFormNode()->PresenceRequiresSpace())
1990 fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.width;
1992 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[2][j]);
1993 m_fLastRowWidth = fCurPos;
1997 fCurPos = fGroupWidths[0];
1998 for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) {
1999 if (rgCurLineLayoutItems[0][j]->GetFormNode()->PresenceRequiresSpace())
2000 fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.width;
2002 rgCurLineLayoutItems[0][j]->m_sPos =
2003 CFX_PointF(fCurPos, *fContentCurRowY);
2004 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[0][j]);
2005 m_fLastRowWidth = fCurPos;
2007 fCurPos = (fContentWidthLimit + fGroupWidths[0] + fGroupWidths[1] -
2010 for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) {
2011 if (rgCurLineLayoutItems[1][j]->GetFormNode()->PresenceRequiresSpace())
2012 fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.width;
2014 rgCurLineLayoutItems[1][j]->m_sPos =
2015 CFX_PointF(fCurPos, *fContentCurRowY);
2016 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[1][j]);
2017 m_fLastRowWidth = fCurPos;
2019 fCurPos = fContentWidthLimit;
2020 for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) {
2021 if (rgCurLineLayoutItems[2][j]->GetFormNode()->PresenceRequiresSpace())
2022 fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.width;
2024 rgCurLineLayoutItems[2][j]->m_sPos =
2025 CFX_PointF(fCurPos, *fContentCurRowY);
2026 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[2][j]);
2027 m_fLastRowWidth = fCurPos;
2030 m_fLastRowY = *fContentCurRowY;
2031 *fContentCurRowY += fContentCurRowHeight;
2032 if (bContainerWidthAutoSize) {
2033 float fChildSuppliedWidth = fGroupWidths[0];
2034 if (fContentWidthLimit < FLT_MAX &&
2035 fContentWidthLimit > fChildSuppliedWidth) {
2036 fChildSuppliedWidth = fContentWidthLimit;
2038 *fContentCalculatedWidth =
2039 std::max(*fContentCalculatedWidth, fChildSuppliedWidth);
2041 if (bContainerHeightAutoSize) {
2042 *fContentCalculatedHeight =
2043 std::max(*fContentCalculatedHeight, *fContentCurRowY);
2051 CXFA_Node* pParent = pSubformSet->GetParent();
2055 pParent = pParent->GetParent();
2065 DCHECK(!m_pCurChildNode);
2066 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
2075 int32_t nRotate = XFA_MapRotation(
2077 if (nRotate == 90 || nRotate == 270)
2078 std::swap(size.width, size.height);
2080 SetCurrentComponentSize(size);
2084 bool bUseBreakControl,
2086 float fRealHeight) {
2087 return DoLayoutInternal(bUseBreakControl, fHeightLimit, fRealHeight,
nullptr);
2094 Context* pContext) {
2100 bool bRootForceTb =
false;
2103 GetLayout(pLayoutNode, &bRootForceTb);
2104 switch (eLayoutStrategy) {
2108 return DoLayoutFlowedContainer(bUseBreakControl, eLayoutStrategy,
2109 fHeightLimit, fRealHeight, pContext,
2115 DoLayoutPositionedContainer(pContext);
2119 DoLayoutTableContainer(pLayoutNode);
2136 return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height);
2141 m_pLayoutItem->m_sPos = pos;
2146 m_pLayoutItem->m_sSize = size;
2156 pTemplate = pFormNode;
2159 pTemplate->GetFirstChildByClass<CXFA_Occur>(
XFA_Element::Occur);
2163 int32_t iMax = pOccur->GetMax();
2167 int32_t iCount = m_PendingNodesCount[pTemplate];
2171 m_PendingNodesCount[pTemplate] = iCount + 1;
2176 CXFA_ContentLayoutItem* pLayoutItem) {
2180 case XFA_AttributeValue::Row:
2181 case XFA_AttributeValue::Rl_row:
2182 RelocateTableRowCells(pLayoutItem, m_rgSpecifiedColumnWidths, eLayout);
2191 CXFA_ContentLayoutItem* pTrailerLayoutItem,
2192 bool bUseInherited) {
2193 if (!pTrailerLayoutItem)
2196 float fHeight = pTrailerLayoutItem->m_sSize.height;
2197 if (bUseInherited) {
2198 float fNewSplitPos = 0;
2200 fNewSplitPos = FindSplitPos(fSplitPos - fHeight);
2202 SplitLayoutItem(fNewSplitPos);
2206 UpdatePendingItemLayout(pTrailerLayoutItem);
2207 CXFA_Margin* pMargin =
2210 if (!IsAddNewRowForTrailer(pTrailerLayoutItem)) {
2211 pTrailerLayoutItem->m_sPos.y = m_fLastRowY;
2212 pTrailerLayoutItem->m_sPos.x = m_fLastRowWidth;
2213 m_pLayoutItem->m_sSize.width += pTrailerLayoutItem->m_sSize.width;
2214 m_pLayoutItem->AppendLastChild(pTrailerLayoutItem);
2218 float fNewSplitPos = 0;
2220 fNewSplitPos = FindSplitPos(fSplitPos - fHeight);
2223 SplitLayoutItem(fNewSplitPos);
2224 pTrailerLayoutItem->m_sPos.y = fNewSplitPos - inset
.top - inset
.bottom;
2226 pTrailerLayoutItem->m_sPos.y = fSplitPos - inset
.top - inset
.bottom;
2229 switch (pTrailerLayoutItem
->GetFormNode()->JSObject()->GetEnum(
2231 case XFA_AttributeValue::Right:
2232 pTrailerLayoutItem->m_sPos.x = m_pLayoutItem->m_sSize.width -
2234 pTrailerLayoutItem->m_sSize.width;
2236 case XFA_AttributeValue::Center:
2237 pTrailerLayoutItem->m_sPos.x =
2238 (m_pLayoutItem->m_sSize.width - inset.left - inset.right -
2239 pTrailerLayoutItem->m_sSize.width) /
2244 pTrailerLayoutItem->m_sPos.x = inset
.left;
2247 m_pLayoutItem->m_sSize.height += fHeight;
2248 m_pLayoutItem->AppendLastChild(pTrailerLayoutItem);
2252 CXFA_ContentLayoutItem* pLeaderLayoutItem) {
2253 UpdatePendingItemLayout(pLeaderLayoutItem);
2255 CXFA_Margin* pMarginNode =
2257 float fLeftInset = 0;
2258 float fRightInset = 0;
2260 fLeftInset = pMarginNode->JSObject()->GetMeasureInUnit(
2262 fRightInset = pMarginNode->JSObject()->GetMeasureInUnit(
2266 float fHeight = pLeaderLayoutItem->m_sSize.height;
2268 pIter = pIter->GetNextSibling()) {
2273 pContentItem->m_sPos.y += fHeight;
2275 pLeaderLayoutItem->m_sPos.y = 0;
2277 switch (pLeaderLayoutItem
->GetFormNode()->JSObject()->GetEnum(
2279 case XFA_AttributeValue::Right:
2280 pLeaderLayoutItem->m_sPos.x = m_pLayoutItem->m_sSize.width - fRightInset -
2281 pLeaderLayoutItem->m_sSize.width;
2283 case XFA_AttributeValue::Center:
2284 pLeaderLayoutItem->m_sPos.x =
2285 (m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset -
2286 pLeaderLayoutItem->m_sSize.width) /
2291 pLeaderLayoutItem->m_sPos.x = fLeftInset;
2294 m_pLayoutItem->m_sSize.height += fHeight;
2295 m_pLayoutItem->AppendLastChild(pLeaderLayoutItem);
2299 bool bBreakPending) {
2300 m_PendingNodes.push_back(pPendingNode);
2301 m_bBreakPending = bBreakPending;
2306 float fTotalHeight = 0;
2307 if (m_PendingNodes.empty())
2308 return fTotalHeight;
2310 if (!m_pLayoutItem) {
2311 m_pLayoutItem = CreateContentLayoutItem(pCurChildNode);
2312 m_pLayoutItem->m_sSize.clear();
2315 while (!m_PendingNodes.empty()) {
2316 auto* pPendingProcessor =
2317 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
2318 GetHeap()->GetAllocationHandle(), GetHeap(), m_PendingNodes.front(),
2320 m_PendingNodes.pop_front();
2321 pPendingProcessor->DoLayout(
false, FLT_MAX, FLT_MAX);
2322 CXFA_ContentLayoutItem* pPendingLayoutItem =
nullptr;
2323 if (pPendingProcessor->HasLayoutItem())
2324 pPendingLayoutItem = pPendingProcessor->ExtractLayoutItem();
2325 if (pPendingLayoutItem) {
2326 AddLeaderAfterSplit(pPendingLayoutItem);
2327 if (m_bBreakPending)
2328 fTotalHeight += pPendingLayoutItem->m_sSize.height;
2331 return fTotalHeight;
2337 bool bContainerWidthAutoSize,
2338 bool bContainerHeightAutoSize,
2339 float fContainerHeight,
2341 uint8_t* uCurHAlignState,
2342 std::array<ContentLayoutItemVector, 3>& rgCurLineLayoutItems,
2343 bool bUseBreakControl,
2346 float fContentWidthLimit,
2347 float* fContentCurRowY,
2348 float* fContentCurRowAvailWidth,
2349 float* fContentCurRowHeight,
2350 bool* bAddedItemInRow,
2351 bool* bForceEndPage,
2352 Context* pLayoutContext,
2355 uint8_t uHAlign = HAlignEnumToInt(
2356 m_pCurChildNode->JSObject()->GetEnum(XFA_Attribute::HAlign));
2357 if (bContainerWidthAutoSize)
2361 uHAlign < *uCurHAlignState) ||
2363 uHAlign > *uCurHAlignState)) {
2367 *uCurHAlignState = uHAlign;
2370 bool bUseRealHeight = bTakeSpace && bContainerHeightAutoSize && bIsOwnSplit &&
2373 bool bIsTransHeight = bTakeSpace;
2374 if (bIsTransHeight && !bIsOwnSplit) {
2375 bool bRootForceTb =
false;
2380 bIsTransHeight =
false;
2384 bool bUseInherited =
false;
2385 Context layoutContext;
2386 if (m_pViewLayoutProcessor) {
2388 m_pViewLayoutProcessor->QueryOverflow(GetFormNode());
2389 if (pOverflowNode) {
2390 layoutContext.m_pOverflowNode = pOverflowNode;
2391 layoutContext.m_pOverflowProcessor =
this;
2392 pLayoutContext = &layoutContext;
2397 if (!bNewRow || pProcessor->m_ePreProcessRs ==
Result::kDone) {
2398 eRetValue = pProcessor->DoLayoutInternal(
2399 bTakeSpace && bUseBreakControl,
2400 bUseRealHeight ? fRealHeight - *fContentCurRowY : FLT_MAX,
2401 bIsTransHeight ? fRealHeight - *fContentCurRowY : FLT_MAX,
2403 pProcessor->m_ePreProcessRs = eRetValue;
2405 eRetValue = pProcessor->m_ePreProcessRs;
2408 if (!pProcessor->HasLayoutItem())
2411 CFX_SizeF childSize = pProcessor->GetCurrentComponentSize();
2413 fRealHeight = FLT_MAX;
2414 fAvailHeight = FLT_MAX;
2422 CXFA_Node* pOverflowLeaderNode =
nullptr;
2423 CXFA_Node* pOverflowTrailerNode =
nullptr;
2425 CXFA_ContentLayoutItem* pTrailerLayoutItem =
nullptr;
2426 bool bIsAddTrailerHeight =
false;
2427 if (m_pViewLayoutProcessor &&
2428 pProcessor->GetFormNode()->GetIntact() == XFA_AttributeValue::None) {
2430 m_pViewLayoutProcessor->QueryOverflow(pProcessor->GetFormNode());
2431 if (!pFormNode && pLayoutContext && pLayoutContext->m_pOverflowProcessor) {
2432 pFormNode = pLayoutContext->m_pOverflowNode;
2433 bUseInherited =
true;
2436 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
false);
2437 if (overflow_data.has_value()) {
2438 pOverflowLeaderNode = overflow_data.value().pLeader;
2439 pOverflowTrailerNode = overflow_data.value().pTrailer;
2440 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowTrailerNode)) {
2441 if (pOverflowTrailerNode) {
2442 auto* pOverflowLeaderProcessor =
2443 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
2444 GetHeap()->GetAllocationHandle(), GetHeap(),
2445 pOverflowTrailerNode,
nullptr);
2446 pOverflowLeaderProcessor->DoLayout(
false, FLT_MAX, FLT_MAX);
2447 pTrailerLayoutItem =
2448 pOverflowLeaderProcessor->HasLayoutItem()
2449 ? pOverflowLeaderProcessor->ExtractLayoutItem()
2453 bIsAddTrailerHeight =
2455 ? IsAddNewRowForTrailer(pTrailerLayoutItem)
2456 : pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem);
2457 if (bIsAddTrailerHeight) {
2458 childSize.height += pTrailerLayoutItem->m_sSize.height;
2459 bIsAddTrailerHeight =
true;
2466 *fContentCurRowY + childSize.height <=
2468 (!bContainerHeightAutoSize &&
2471 if (pProcessor->m_bUseInherited) {
2472 if (pTrailerLayoutItem)
2473 pProcessor->AddTrailerBeforeSplit(childSize.height,
2474 pTrailerLayoutItem,
false);
2475 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode))
2476 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2478 pProcessor->m_bUseInherited =
false;
2480 if (bIsAddTrailerHeight)
2481 childSize.height -= pTrailerLayoutItem->m_sSize.height;
2483 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2484 pOverflowTrailerNode,
2485 pTrailerLayoutItem, pFormNode);
2488 CXFA_ContentLayoutItem* pChildLayoutItem =
2492 m_ArrayKeepItems.push_back(pChildLayoutItem);
2494 m_ArrayKeepItems.clear();
2496 rgCurLineLayoutItems[uHAlign].push_back(pChildLayoutItem);
2497 *bAddedItemInRow =
true;
2499 *fContentCurRowAvailWidth -= childSize.width;
2500 *fContentCurRowHeight =
2501 std::max(*fContentCurRowHeight, childSize.height);
2507 if (pProcessor->m_bUseInherited) {
2508 if (pTrailerLayoutItem) {
2509 pProcessor->AddTrailerBeforeSplit(childSize.height,
2510 pTrailerLayoutItem,
false);
2512 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode))
2513 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2515 pProcessor->m_bUseInherited =
false;
2517 if (bIsAddTrailerHeight)
2518 childSize.height -= pTrailerLayoutItem->m_sSize.height;
2520 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2521 pOverflowTrailerNode,
2522 pTrailerLayoutItem, pFormNode);
2526 *bAddedItemInRow =
true;
2527 *fContentCurRowAvailWidth -= childSize.width;
2528 *fContentCurRowHeight =
std::max(*fContentCurRowHeight, childSize.height);
2533 if (ProcessKeepForSplit(pProcessor, eRetValue, rgCurLineLayoutItems[uHAlign],
2534 fContentCurRowAvailWidth, fContentCurRowHeight,
2535 fContentCurRowY, bAddedItemInRow, bForceEndPage,
2540 *bForceEndPage =
true;
2541 float fSplitPos = pProcessor->FindSplitPos(fAvailHeight - *fContentCurRowY);
2546 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2547 pOverflowTrailerNode, pTrailerLayoutItem,
2550 *bAddedItemInRow =
true;
2552 *fContentCurRowAvailWidth -= childSize.width;
2553 *fContentCurRowHeight =
2554 std::max(*fContentCurRowHeight, childSize.height);
2559 if (m_pViewLayoutProcessor && !pProcessor->m_bUseInherited &&
2560 eRetValue != Result::kPageFullBreak) {
2561 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2563 if (pTrailerLayoutItem && bIsAddTrailerHeight) {
2564 pProcessor->AddTrailerBeforeSplit(fSplitPos, pTrailerLayoutItem,
2567 pProcessor->SplitLayoutItem(fSplitPos);
2570 if (bUseInherited) {
2571 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2572 pOverflowTrailerNode, pTrailerLayoutItem,
2574 m_bUseInherited =
true;
2576 CXFA_LayoutItem* firstChild = pProcessor->m_pLayoutItem->GetFirstChild();
2577 if (firstChild && !firstChild->GetNextSibling() &&
2579 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2580 pOverflowTrailerNode,
2581 pTrailerLayoutItem, pFormNode);
2582 }
else if (pProcessor->JudgeLeaderOrTrailerForOccur(
2583 pOverflowLeaderNode)) {
2584 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2588 if (pProcessor->m_pLayoutItem->GetNextSibling()) {
2589 childSize = pProcessor->GetCurrentComponentSize();
2591 *bAddedItemInRow =
true;
2593 *fContentCurRowAvailWidth -= childSize.width;
2594 *fContentCurRowHeight =
2595 std::max(*fContentCurRowHeight, childSize.height);
2602 childSize = pProcessor->GetCurrentComponentSize();
2603 if (pProcessor->m_pViewLayoutProcessor->GetNextAvailContentHeight(
2604 childSize.height)) {
2605 if (m_pViewLayoutProcessor) {
2606 if (!pFormNode && pLayoutContext)
2607 pFormNode = pLayoutContext->m_pOverflowProcessor->GetFormNode();
2609 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2611 if (bUseInherited) {
2612 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2613 pOverflowTrailerNode,
2614 pTrailerLayoutItem, pFormNode);
2615 m_bUseInherited =
true;
2621 *bAddedItemInRow =
true;
2623 *fContentCurRowAvailWidth -= childSize.width;
2624 *fContentCurRowHeight =
std::max(*fContentCurRowHeight, childSize.height);
2627 *bForceEndPage =
false;
2636 if (m_pViewLayoutProcessor) {
2638 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2639 if (overflow_data.has_value()) {
2640 pOverflowLeaderNode = overflow_data.value().pLeader;
2641 pOverflowTrailerNode = overflow_data.value().pTrailer;
2644 if (pTrailerLayoutItem)
2645 pProcessor->AddTrailerBeforeSplit(fSplitPos, pTrailerLayoutItem,
false);
2646 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode))
2647 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2655 if (!pFormNode && pLayoutContext)
2656 pFormNode = pLayoutContext->m_pOverflowProcessor->GetFormNode();
2657 if (m_pViewLayoutProcessor) {
2659 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2660 if (overflow_data.has_value()) {
2661 pOverflowLeaderNode = overflow_data.value().pLeader;
2662 pOverflowTrailerNode = overflow_data.value().pTrailer;
2665 if (bUseInherited) {
2666 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode,
2667 pTrailerLayoutItem, pFormNode);
2668 m_bUseInherited =
true;
2676 if (m_bKeepBreakFinish)
2677 return std::nullopt;
2678 return FindBreakAfterNode(pBreakAfterNode, pCurActionNode);
2684 for (
CXFA_Node* pBookendNode = *pCurActionNode
2685 ? (*pCurActionNode)->GetNextSibling()
2686 : pParentContainer->GetFirstChild();
2687 pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) {
2691 *pCurActionNode = pBookendNode;
2697 return std::nullopt;
2703 if (!*pCurActionNode)
2704 return std::nullopt;
2706 CXFA_Node* pBreakBeforeNode = (*pCurActionNode)->GetNextSibling();
2707 if (!m_bKeepBreakFinish) {
2709 FindBreakBeforeNode(pBreakBeforeNode, pCurActionNode);
2710 if (ret.has_value())
2713 if (m_bIsProcessKeep)
2714 return ProcessKeepNodesForBreakBefore(pCurActionNode, pChildContainer);
2716 *pCurActionNode = pChildContainer;
2723 if (*pCurActionNode) {
2724 CXFA_Node* pBreakAfterNode = (*pCurActionNode)->GetNextSibling();
2725 return FindBreakAfterNode(pBreakAfterNode, pCurActionNode);
2728 CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild();
2729 return HandleKeep(pBreakAfterNode, pCurActionNode);
2741 CXFA_Node* pSaveNode = pNextChildContainer;
2744 DeleteLayoutGeneratedNode(pSaveNode);
2746 if (!pNextChildContainer)
2747 return std::nullopt;
2749 bool bLastKeep =
false;
2750 std::optional<
Stage> ret = ProcessKeepNodesForCheckNext(
2751 pCurActionNode, &pNextChildContainer, &bLastKeep);
2752 if (ret.has_value())
2755 if (!m_bKeepBreakFinish && !bLastKeep) {
2756 ret = FindBreakBeforeNode(pNextChildContainer->GetFirstChild(),
2758 if (ret.has_value())
2761 *pCurActionNode = pNextChildContainer;
2768 for (
CXFA_Node* pBookendNode = *pCurActionNode
2769 ? (*pCurActionNode)->GetNextSibling()
2770 : pParentContainer->GetFirstChild();
2771 pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) {
2775 *pCurActionNode = pBookendNode;
2781 return std::nullopt;
2785 m_bKeepBreakFinish =
true;
2786 m_pKeepHeadNode =
nullptr;
2787 m_pKeepTailNode =
nullptr;
2788 m_bIsProcessKeep =
false;
2794 bool* pContainerWidthAutoSize,
2795 bool* pContainerHeightAutoSize) {
2796 if (pContext && pContext->m_fCurColumnWidth.has_value()) {
2797 pSize->width = pContext->m_fCurColumnWidth.value();
2798 *pContainerWidthAutoSize =
false;
2800 if (*pContainerHeightAutoSize)
2803 pSize->height -= m_fUsedSize;
2805 bool bFocrTb =
false;
2816 *pContainerHeightAutoSize =
true;
2826 CXFA_ContentLayoutItem* pLastChild =
2827 ToContentLayoutItem(m_pLayoutItem->GetFirstChild());
2829 pNext = pNext->GetNextSibling()) {
2831 if (pContentNext && pContentNext->m_sPos.y != pLastChild->m_sPos.y)
2832 pLastChild = pContentNext;
2838 const CXFA_ContentLayoutItem* pLastChild) {
2841 pChild != pLastChild; pChild = pChild->GetNextSibling()) {
2843 if (!pLayout || !pLayout
->GetFormNode()->PresenceRequiresSpace())
2846 float fWidth = pLayout->m_sPos.x + pLayout->m_sSize.width;
2847 float fHeight = pLayout->m_sPos.y + pLayout->m_sSize.height;
2848 size.width =
std::max(size.width, fWidth);
2849 size.height =
std::max(size.height, fHeight);
void InsertAfter(CXFA_ContentLayoutItem *pNext)
CXFA_ContentLayoutItem * GetNext() const
CXFA_ContentLayoutItem * GetLast()
~CXFA_ContentLayoutProcessor()
Result DoLayout(bool bUseBreakControl, float fHeightLimit, float fRealHeight)
void DoLayoutPageArea(CXFA_ViewLayoutItem *pPageAreaLayoutItem)
CXFA_ContentLayoutItem * ExtractLayoutItem()
CXFA_Node * GetFormNode()
CXFA_FFNotify * GetNotify() const
void StartFieldDrawLayout(CXFA_Node *pItem, float *pCalcWidth, float *pCalcHeight)
void OnLayoutItemRemoving(CXFA_LayoutProcessor *pLayout, CXFA_LayoutItem *pSender)
bool IsContentLayoutItem() const
CXFA_ContentLayoutItem * AsContentLayoutItem()
CXFA_Node * GetFormNode() const
static CXFA_LayoutProcessor * FromDocument(const CXFA_Document *pXFADoc)
void RemoveChildAndNotify(CXFA_Node *pNode, bool bNotify)
CXFA_Node * GetFirstContainerChild() const
CXFA_Node * GetNextContainerSibling() const
XFA_AttributeValue GetIntact()
bool IsLayoutGeneratedNode() const
void SetBindingNode(CXFA_Node *node)
void SetFlag(XFA_NodeFlag dwFlag)
CXFA_Node * GetTemplateNodeIfExists() const
CXFA_Node * GetPrevContainerSibling() const
CXFA_Node * GetBindData()
bool RemoveBindItem(CXFA_Node *pFormNode)
bool IsUnusedNode() const
bool PresenceRequiresSpace() const
XFA_Element GetElementType() const
CXFA_Document * GetDocument() const
bool IsContainerNode() const
constexpr float kXFALayoutPrecision
CFX_PTemplate< float > CFX_PointF
CFX_STemplate< float > CFX_SizeF
#define NOTREACHED_NORETURN()
fxcrt::WideStringView WideStringView
fxcrt::WideString WideString