7#include "xfa/fxfa/layout/cxfa_contentlayoutprocessor.h"
13#include "core/fxcrt/stl_util.h"
14#include "fxjs/gc/container_trace.h"
15#include "fxjs/xfa/cjx_object.h"
16#include "third_party/base/check.h"
17#include "third_party/base/containers/adapters.h"
18#include "third_party/base/notreached.h"
19#include "xfa/fxfa/cxfa_ffdoc.h"
20#include "xfa/fxfa/cxfa_ffnotify.h"
21#include "xfa/fxfa/cxfa_ffwidget.h"
22#include "xfa/fxfa/layout/cxfa_contentlayoutitem.h"
23#include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
24#include "xfa/fxfa/layout/cxfa_viewlayoutitem.h"
25#include "xfa/fxfa/layout/cxfa_viewlayoutprocessor.h"
26#include "xfa/fxfa/parser/cxfa_document.h"
27#include "xfa/fxfa/parser/cxfa_keep.h"
28#include "xfa/fxfa/parser/cxfa_localemgr.h"
29#include "xfa/fxfa/parser/cxfa_margin.h"
30#include "xfa/fxfa/parser/cxfa_measurement.h"
31#include "xfa/fxfa/parser/cxfa_node.h"
32#include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
33#include "xfa/fxfa/parser/cxfa_occur.h"
34#include "xfa/fxfa/parser/cxfa_para.h"
35#include "xfa/fxfa/parser/cxfa_traversestrategy_xfanode.h"
36#include "xfa/fxfa/parser/xfa_utils.h"
40std::vector<WideString> SeparateStringOnSpace(
41 pdfium::span<
const wchar_t> spStr) {
42 std::vector<WideString> ret;
48 while (nPos < spStr.size()) {
49 if (spStr[nPos] == L' ') {
50 ret.emplace_back(WideStringView(spStr.subspan(nToken, nPos - nToken)));
55 ret.emplace_back(WideStringView(spStr.subspan(nToken, nPos - nToken)));
59void UpdateWidgetSize(CXFA_ContentLayoutItem* pLayoutItem,
69 *pWidth = pLayoutItem->m_sSize.width;
71 *pHeight = pLayoutItem->m_sSize.height;
76 pNode
->GetDocument()->GetNotify()->StartFieldDrawLayout(pNode, pWidth,
81 NOTREACHED_NORETURN();
85CFX_SizeF CalculateContainerSpecifiedSize(
CXFA_Node* pFormNode,
86 bool* bContainerWidthAutoSize,
87 bool* bContainerHeightAutoSize) {
88 *bContainerWidthAutoSize =
true;
89 *bContainerHeightAutoSize =
true;
93 CFX_SizeF containerSize;
95 absl::optional<CXFA_Measurement> wValue =
96 pFormNode->JSObject()->TryMeasure(XFA_Attribute::W,
false);
97 if (wValue.has_value() && wValue->GetValue() > kXFALayoutPrecision) {
98 containerSize.width = wValue->ToUnit(XFA_Unit::Pt);
99 *bContainerWidthAutoSize =
false;
102 absl::optional<CXFA_Measurement> hValue =
103 pFormNode->JSObject()->TryMeasure(XFA_Attribute::H,
false);
104 if (hValue.has_value() && hValue->GetValue() > kXFALayoutPrecision) {
105 containerSize.height = hValue->ToUnit(XFA_Unit::Pt);
106 *bContainerHeightAutoSize =
false;
110 if (*bContainerWidthAutoSize && eType ==
XFA_Element::Subform) {
111 absl::optional<CXFA_Measurement> maxW =
112 pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxW,
false);
113 if (maxW.has_value() && maxW->GetValue() > kXFALayoutPrecision) {
114 containerSize.width = maxW->ToUnit(XFA_Unit::Pt);
115 *bContainerWidthAutoSize =
false;
118 absl::optional<CXFA_Measurement> maxH =
119 pFormNode->JSObject()->TryMeasure(XFA_Attribute::MaxH,
false);
120 if (maxH.has_value() && maxH->GetValue() > kXFALayoutPrecision) {
121 containerSize.height = maxH->ToUnit(XFA_Unit::Pt);
122 *bContainerHeightAutoSize =
false;
125 return containerSize;
128CFX_SizeF CalculateContainerComponentSizeFromContentSize(
130 bool bContainerWidthAutoSize,
131 float fContentCalculatedWidth,
132 bool bContainerHeightAutoSize,
133 float fContentCalculatedHeight,
134 const CFX_SizeF& currentContainerSize) {
135 CFX_SizeF componentSize = currentContainerSize;
136 CXFA_Margin* pMarginNode =
137 pFormNode->GetFirstChildByClass<CXFA_Margin>(
XFA_Element::Margin);
138 if (bContainerWidthAutoSize) {
139 componentSize.width = fContentCalculatedWidth;
141 absl::optional<CXFA_Measurement> leftInset =
142 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::LeftInset,
false);
143 if (leftInset.has_value())
144 componentSize.width += leftInset->ToUnit(XFA_Unit::Pt);
146 absl::optional<CXFA_Measurement> rightInset =
147 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::RightInset,
false);
148 if (rightInset.has_value())
149 componentSize.width += rightInset->ToUnit(XFA_Unit::Pt);
153 if (bContainerHeightAutoSize) {
154 componentSize.height = fContentCalculatedHeight;
156 absl::optional<CXFA_Measurement> topInset =
157 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::TopInset,
false);
158 if (topInset.has_value())
159 componentSize.height += topInset->ToUnit(XFA_Unit::Pt);
161 absl::optional<CXFA_Measurement> bottomInset =
162 pMarginNode->JSObject()->TryMeasure(XFA_Attribute::BottomInset,
164 if (bottomInset.has_value())
165 componentSize.height += bottomInset->ToUnit(XFA_Unit::Pt);
168 return componentSize;
182 inset
.bottom = pMargin->JSObject()->GetMeasureInUnit(
187void RelocateTableRowCells(CXFA_ContentLayoutItem* pLayoutRow,
188 const std::vector<
float>& rgSpecifiedColumnWidths,
190 bool bContainerWidthAutoSize =
true;
191 bool bContainerHeightAutoSize =
true;
192 const CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
193 pLayoutRow->GetFormNode(), &bContainerWidthAutoSize,
194 &bContainerHeightAutoSize);
196 CXFA_Margin* pMargin =
197 pLayoutRow
->GetFormNode()->GetFirstChildByClass<CXFA_Margin>(
201 const float fContentWidthLimit =
202 bContainerWidthAutoSize ? FLT_MAX
203 : containerSize.width - inset.left - inset.right;
204 const float fContentCurrentHeight =
205 pLayoutRow->m_sSize.height - inset
.top - inset
.bottom;
207 float fContentCalculatedWidth = 0;
208 float fContentCalculatedHeight = 0;
209 float fCurrentColX = 0;
210 size_t nCurrentColIdx = 0;
211 bool bMetWholeRowCell =
false;
214 pIter = pIter->GetNextSibling()) {
219 const int32_t nOriginalColSpan =
224 if (nOriginalColSpan > 0)
225 nColSpan =
static_cast<size_t>(nOriginalColSpan);
226 else if (nOriginalColSpan == -1)
227 nColSpan = rgSpecifiedColumnWidths.size();
231 CHECK(nCurrentColIdx <= rgSpecifiedColumnWidths.size());
232 const size_t remaining = rgSpecifiedColumnWidths.size() - nCurrentColIdx;
233 nColSpan =
std::min(nColSpan, remaining);
235 float fColSpanWidth = 0;
236 for (size_t i = 0; i < nColSpan; i++)
237 fColSpanWidth += rgSpecifiedColumnWidths[nCurrentColIdx + i];
239 if (nOriginalColSpan == -1 ||
240 nColSpan !=
static_cast<size_t>(nOriginalColSpan)) {
241 fColSpanWidth = bMetWholeRowCell ? 0
242 :
std::max(fColSpanWidth,
243 pLayoutChild->m_sSize.height);
245 if (nOriginalColSpan == -1)
246 bMetWholeRowCell =
true;
248 pLayoutChild->m_sPos = CFX_PointF(fCurrentColX, 0);
249 pLayoutChild->m_sSize.width = fColSpanWidth;
253 fCurrentColX += fColSpanWidth;
254 nCurrentColIdx += nColSpan;
255 float fNewHeight = bContainerHeightAutoSize ? -1 : fContentCurrentHeight;
256 UpdateWidgetSize(pLayoutChild, &fColSpanWidth, &fNewHeight);
257 pLayoutChild->m_sSize.height = fNewHeight;
258 if (bContainerHeightAutoSize) {
259 fContentCalculatedHeight =
260 std::max(fContentCalculatedHeight, pLayoutChild->m_sSize.height);
264 if (bContainerHeightAutoSize) {
266 pIter = pIter->GetNextSibling()) {
271 UpdateWidgetSize(pLayoutChild, &pLayoutChild->m_sSize.width,
272 &fContentCalculatedHeight);
273 float fOldChildHeight = pLayoutChild->m_sSize.height;
274 pLayoutChild->m_sSize.height = fContentCalculatedHeight;
275 CXFA_Para* pParaNode =
276 pLayoutChild
->GetFormNode()->GetFirstChildByClass<CXFA_Para>(
278 if (!pParaNode || !pLayoutChild->GetFirstChild())
281 float fOffHeight = fContentCalculatedHeight - fOldChildHeight;
286 fOffHeight = fOffHeight / 2;
299 pInnerIter; pInnerIter = pInnerIter->GetNextSibling()) {
302 pInnerChild->m_sPos.y += fOffHeight;
307 if (bContainerWidthAutoSize) {
308 float fChildSuppliedWidth = fCurrentColX;
309 if (fContentWidthLimit < FLT_MAX &&
310 fContentWidthLimit > fChildSuppliedWidth) {
311 fChildSuppliedWidth = fContentWidthLimit;
313 fContentCalculatedWidth =
314 std::max(fContentCalculatedWidth, fChildSuppliedWidth);
316 fContentCalculatedWidth = containerSize.width - inset
.left - inset
.right;
322 pIter = pIter->GetNextSibling()) {
327 pLayoutChild->m_sPos.x = fContentCalculatedWidth -
328 pLayoutChild->m_sPos.x -
329 pLayoutChild->m_sSize.width;
332 pLayoutRow->m_sSize = CalculateContainerComponentSizeFromContentSize(
333 pLayoutRow->GetFormNode(), bContainerWidthAutoSize,
334 fContentCalculatedWidth, bContainerHeightAutoSize,
335 fContentCalculatedHeight, containerSize);
339 *bRootForceTb =
false;
340 absl::optional<XFA_AttributeValue> layoutMode =
341 pFormNode->JSObject()->TryEnum(XFA_Attribute::Layout,
false);
342 if (layoutMode.has_value())
343 return layoutMode.value();
345 CXFA_Node* pParentNode = pFormNode->GetParent();
347 *bRootForceTb =
true;
353bool ExistContainerKeep(
CXFA_Node* pCurNode,
bool bPreFind) {
363 pCurNode->GetFirstChildByClass<CXFA_Keep>(
XFA_Element::Keep);
369 absl::optional<XFA_AttributeValue> previous =
370 pKeep->JSObject()->TryEnum(eKeepType,
false);
371 if (previous == XFA_AttributeValue::ContentArea ||
372 previous == XFA_AttributeValue::PageArea) {
377 pKeep = pPreContainer->GetFirstChildByClass<CXFA_Keep>(
XFA_Element::Keep);
385 absl::optional<XFA_AttributeValue> next =
386 pKeep->JSObject()->TryEnum(eKeepType,
false);
387 if (next == XFA_AttributeValue::ContentArea ||
388 next == XFA_AttributeValue::PageArea) {
394absl::optional<CXFA_ContentLayoutProcessor::Stage> FindBreakBeforeNode(
397 for (
CXFA_Node* pBreakNode = pContainerNode; pBreakNode;
398 pBreakNode = pBreakNode->GetNextSibling()) {
401 *pCurActionNode = pBreakNode;
404 if (pBreakNode->JSObject()->GetEnum(
XFA_Attribute::Before) ==
408 *pCurActionNode = pBreakNode;
414 return absl::nullopt;
417absl::optional<CXFA_ContentLayoutProcessor::Stage> FindBreakAfterNode(
420 for (
CXFA_Node* pBreakNode = pContainerNode; pBreakNode;
421 pBreakNode = pBreakNode->GetNextSibling()) {
424 *pCurActionNode = pBreakNode;
431 *pCurActionNode = pBreakNode;
437 return absl::nullopt;
440void DeleteLayoutGeneratedNode(
CXFA_Node* pGenerateNode) {
444 CXFA_NodeIterator sIterator(pGenerateNode);
445 for (
CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
446 pNode = sIterator.MoveToNext()) {
447 CXFA_ContentLayoutItem* pCurLayoutItem =
448 ToContentLayoutItem(pNode->JSObject()->GetLayoutItem());
449 while (pCurLayoutItem) {
450 CXFA_ContentLayoutItem* pNextLayoutItem = pCurLayoutItem
->GetNext();
452 pCurLayoutItem = pNextLayoutItem;
455 pGenerateNode->GetParent()->RemoveChildAndNotify(pGenerateNode,
true);
470bool FindLayoutItemSplitPos(CXFA_ContentLayoutItem* pLayoutItem,
471 float fCurVerticalOffset,
472 float* fProposedSplitPos,
474 bool bCalculateMargin) {
477 *fProposedSplitPos > fCurVerticalOffset + pLayoutItem->m_sSize.height -
484 bool bAnyChanged =
false;
487 float fCurTopMargin = 0;
488 float fCurBottomMargin = 0;
489 CXFA_Margin* pMarginNode =
490 pFormNode->GetFirstChildByClass<CXFA_Margin>(
XFA_Element::Margin);
491 if (pMarginNode && bCalculateMargin) {
492 fCurTopMargin = pMarginNode->JSObject()->GetMeasureInUnit(
494 fCurBottomMargin = pMarginNode->JSObject()->GetMeasureInUnit(
497 bool bChanged =
true;
501 absl::optional<
float> fRelSplitPos = pFormNode->FindSplitPos(
502 pNotify->GetFFDoc()->GetDocView(), pLayoutItem->GetIndex(),
503 *fProposedSplitPos - fCurVerticalOffset);
504 if (fRelSplitPos.has_value()) {
507 *fProposedSplitPos = fCurVerticalOffset + fRelSplitPos.value();
509 if (*fProposedSplitPos <=
515 float fRelSplitPos = *fProposedSplitPos - fCurBottomMargin;
517 pIter = pIter->GetNextSibling()) {
523 fCurVerticalOffset + fCurTopMargin + pChildItem->m_sPos.y;
524 bool bChange =
false;
525 if (FindLayoutItemSplitPos(pChildItem, fChildOffset, &fRelSplitPos,
526 &bChange, bCalculateMargin)) {
528 *fProposedSplitPos = fRelSplitPos - fCurTopMargin;
530 *fProposedSplitPos = fRelSplitPos + fCurBottomMargin;
534 if (*fProposedSplitPos <=
547 *fProposedSplitPos = fCurVerticalOffset;
555CFX_PointF CalculatePositionedContainerPos(
CXFA_Node* pNode,
556 const CFX_SizeF& size) {
559 int32_t nAnchorType = 0;
560 switch (eAnchorType) {
591 static const uint8_t nNextPos[4][9] = {{0, 1, 2, 3, 4, 5, 6, 7, 8},
592 {6, 3, 0, 7, 4, 1, 8, 5, 2},
593 {8, 7, 6, 5, 4, 3, 2, 1, 0},
594 {2, 5, 8, 1, 4, 7, 0, 3, 6}};
597 pNode->JSObject()->GetMeasureInUnit(XFA_Attribute::X, XFA_Unit::Pt),
598 pNode->JSObject()->GetMeasureInUnit(XFA_Attribute::Y, XFA_Unit::Pt));
600 XFA_MapRotation(pNode->JSObject()->GetInteger(
XFA_Attribute::Rotate)) /
602 int32_t nAbsoluteAnchorType = nNextPos[nRotate][nAnchorType];
603 switch (nAbsoluteAnchorType / 3) {
605 pos.y -= size.height / 2;
608 pos.y -= size.height;
613 switch (nAbsoluteAnchorType % 3) {
615 pos.x -= size.width / 2;
634 m_pViewLayoutProcessor(pViewLayoutProcessor) {
635 DCHECK(GetFormNode());
636 DCHECK(GetFormNode()->IsContainerNode() ||
637 GetFormNode()->GetElementType() == XFA_Element::Form);
639 ToContentLayoutItem(GetFormNode()->JSObject()->GetLayoutItem());
645 visitor->Trace(m_pFormNode);
646 visitor->Trace(m_pCurChildNode);
647 visitor->Trace(m_pKeepHeadNode);
648 visitor->Trace(m_pKeepTailNode);
649 visitor->Trace(m_pLayoutItem);
650 visitor->Trace(m_pOldLayoutItem);
651 visitor->Trace(m_pViewLayoutProcessor);
652 visitor->Trace(m_pCurChildPreprocessor);
653 ContainerTrace(visitor, m_ArrayKeepItems);
654 ContainerTrace(visitor, m_PendingNodes);
655 ContainerTrace(visitor, m_PendingNodesCount);
663 if (m_pOldLayoutItem) {
664 CXFA_ContentLayoutItem* pLayoutItem = m_pOldLayoutItem;
665 m_pOldLayoutItem = m_pOldLayoutItem->GetNext();
669 auto* pNewLayoutItem = cppgc::MakeGarbageCollected<CXFA_ContentLayoutItem>(
670 GetHeap()->GetAllocationHandle(), pFormNode,
671 pNotify->OnCreateContentLayoutItem(pFormNode));
673 CXFA_ContentLayoutItem* pPrevLayoutItem =
674 ToContentLayoutItem(pFormNode->JSObject()->GetLayoutItem());
675 if (pPrevLayoutItem) {
678 pFormNode->JSObject()->SetLayoutItem(pNewLayoutItem);
680 return pNewLayoutItem;
684 DCHECK(m_pLayoutItem);
689 bool bAppChange =
false;
690 if (!FindLayoutItemSplitPos(m_pLayoutItem.Get(), 0, &fProposedSplitPos,
691 &bAppChange, bCalculateMargin)) {
695 return fProposedSplitPos;
699 CXFA_ContentLayoutItem* pLayoutItem,
700 CXFA_ContentLayoutItem* pSecondParent,
702 float fCurTopMargin = 0;
703 float fCurBottomMargin = 0;
706 bool bCalculateMargin =
true;
708 bCalculateMargin =
false;
710 CXFA_Margin* pMarginNode =
711 pLayoutItem
->GetFormNode()->GetFirstChildByClass<CXFA_Margin>(
713 if (pMarginNode && bCalculateMargin) {
714 fCurTopMargin = pMarginNode->JSObject()->GetMeasureInUnit(
716 fCurBottomMargin = pMarginNode->JSObject()->GetMeasureInUnit(
720 CXFA_ContentLayoutItem* pSecondLayoutItem =
nullptr;
721 if (m_pCurChildPreprocessor &&
722 m_pCurChildPreprocessor->GetFormNode() == pLayoutItem->GetFormNode()) {
723 pSecondLayoutItem = m_pCurChildPreprocessor->CreateContentLayoutItem(
724 pLayoutItem->GetFormNode());
726 pSecondLayoutItem = CreateContentLayoutItem(pLayoutItem
->GetFormNode());
728 pSecondLayoutItem->m_sPos.x = pLayoutItem->m_sPos.x;
729 pSecondLayoutItem->m_sSize.width = pLayoutItem->m_sSize.width;
730 pSecondLayoutItem->m_sPos.y = 0;
731 pSecondLayoutItem->m_sSize.height = pLayoutItem->m_sSize.height - fSplitPos;
732 pLayoutItem->m_sSize.height -= pSecondLayoutItem->m_sSize.height;
733 if (pLayoutItem->GetFirstChild())
734 pSecondLayoutItem->m_sSize.height += fCurTopMargin;
736 bool bOrphanedItem =
false;
738 pSecondParent->AppendLastChild(pSecondLayoutItem);
739 if (fCurTopMargin > 0 && pLayoutItem->GetFirstChild()) {
740 pSecondParent->m_sSize.height += fCurTopMargin;
742 pParentIter; pParentIter = pParentIter->GetParent()) {
743 CXFA_ContentLayoutItem* pContentItem =
748 pContentItem->m_sSize.height += fCurTopMargin;
751 }
else if (pLayoutItem->GetParent()) {
752 pLayoutItem->GetParent()->InsertAfter(pSecondLayoutItem, pLayoutItem);
758 bOrphanedItem =
true;
761 std::vector<CXFA_ContentLayoutItem*> children;
762 while (
auto* pFirst = ToContentLayoutItem(pLayoutItem->GetFirstChild())) {
763 children.push_back(pFirst);
764 pLayoutItem->RemoveChild(children.back());
767 float lHeightForKeep = 0;
768 float fAddMarginHeight = 0;
769 std::vector<CXFA_ContentLayoutItem*> keepLayoutItems;
770 for (CXFA_ContentLayoutItem* pChildItem : children) {
771 if (fSplitPos <= fCurTopMargin + pChildItem->m_sPos.y + fCurBottomMargin +
772 kXFALayoutPrecision) {
773 if (!ExistContainerKeep(pChildItem->GetFormNode(),
true)) {
774 pChildItem->m_sPos.y -= fSplitPos - fCurBottomMargin;
775 pChildItem->m_sPos.y += lHeightForKeep;
776 pChildItem->m_sPos.y += fAddMarginHeight;
777 pSecondLayoutItem->AppendLastChild(pChildItem);
780 if (lHeightForKeep < kXFALayoutPrecision) {
781 for (CXFA_ContentLayoutItem* pPreItem : keepLayoutItems) {
782 pLayoutItem->RemoveChild(pPreItem);
783 pPreItem->m_sPos.y -= fSplitPos;
784 if (pPreItem->m_sPos.y < 0)
785 pPreItem->m_sPos.y = 0;
786 if (pPreItem->m_sPos.y + pPreItem->m_sSize.height > lHeightForKeep) {
787 pPreItem->m_sPos.y = lHeightForKeep;
788 lHeightForKeep += pPreItem->m_sSize.height;
789 pSecondLayoutItem->m_sSize.height += pPreItem->m_sSize.height;
791 pSecondParent->m_sSize.height += pPreItem->m_sSize.height;
793 pSecondLayoutItem->AppendLastChild(pPreItem);
796 pChildItem->m_sPos.y -= fSplitPos;
797 pChildItem->m_sPos.y += lHeightForKeep;
798 pChildItem->m_sPos.y += fAddMarginHeight;
799 pSecondLayoutItem->AppendLastChild(pChildItem);
802 if (fSplitPos + kXFALayoutPrecision >= fCurTopMargin + fCurBottomMargin +
803 pChildItem->m_sPos.y +
804 pChildItem->m_sSize.height) {
805 pLayoutItem->AppendLastChild(pChildItem);
806 if (ExistContainerKeep(pChildItem->GetFormNode(),
false))
807 keepLayoutItems.push_back(pChildItem);
809 keepLayoutItems.clear();
813 float fOldHeight = pSecondLayoutItem->m_sSize.height;
815 pChildItem, pSecondLayoutItem,
816 fSplitPos - fCurTopMargin - fCurBottomMargin - pChildItem->m_sPos.y);
817 fAddMarginHeight = pSecondLayoutItem->m_sSize.height - fOldHeight;
818 pLayoutItem->AppendLastChild(pChildItem);
821 pLayoutItem->AppendLastChild(pSecondLayoutItem);
825 DCHECK(m_pLayoutItem);
826 SplitLayoutItem(m_pLayoutItem.Get(),
nullptr, fSplitPos);
830 CXFA_ContentLayoutItem* pLayoutItem = m_pLayoutItem;
832 m_pLayoutItem = ToContentLayoutItem(pLayoutItem->GetNextSibling());
833 pLayoutItem->RemoveSelfIfParented();
835 if (m_nCurChildNodeStage != Stage::kDone || !m_pOldLayoutItem)
839 m_pOldLayoutItem->GetFormNode()->GetDocument()->GetNotify();
840 auto* pDocLayout = CXFA_LayoutProcessor::FromDocument(
841 m_pOldLayoutItem->GetFormNode()->GetDocument());
843 while (m_pOldLayoutItem) {
844 CXFA_ContentLayoutItem* pToDeleteItem = m_pOldLayoutItem;
845 m_pOldLayoutItem = pToDeleteItem->GetNext();
846 if (pToDeleteItem == pLayoutItem)
849 pToDeleteItem->RemoveSelfIfParented();
855 std::tie(m_nCurChildNodeStage, m_pCurChildNode) = GotoNextContainerNode(
856 m_nCurChildNodeStage, GetFormNode(), m_pCurChildNode);
867 pChildContainer = pCurActionNode->GetParent();
872 pChildContainer = pCurActionNode;
875 pChildContainer =
nullptr;
879 absl::optional<Stage> ret;
882 ret = HandleKeep(pChildContainer->GetFirstChild(), &pCurActionNode);
884 return {ret.value(), pCurActionNode};
888 pCurActionNode =
nullptr;
891 case Stage::kBookendLeader:
892 ret = HandleBookendLeader(pParentContainer, &pCurActionNode);
894 return {ret.value(), pCurActionNode};
895 pCurActionNode =
nullptr;
898 case Stage::kBreakBefore:
899 ret = HandleBreakBefore(pChildContainer, &pCurActionNode);
901 return {ret.value(), pCurActionNode};
905 pCurActionNode =
nullptr;
908 case Stage::kBreakAfter:
909 ret = HandleBreakAfter(pChildContainer, &pCurActionNode);
911 return {ret.value(), pCurActionNode};
914 case Stage::kBookendTrailer:
915 ret = HandleBookendTrailer(pParentContainer, &pCurActionNode);
917 return {ret.value(), pCurActionNode};
924 ret = HandleCheckNextChildContainer(pParentContainer, pChildContainer,
927 return {ret.value(), pCurActionNode};
929 pCurActionNode =
nullptr;
930 ret = HandleBookendTrailer(pParentContainer, &pCurActionNode);
932 return {ret.value(), pCurActionNode};
937absl::optional<CXFA_ContentLayoutProcessor::Stage>
941 bool* pLastKeepNode) {
942 const bool bCanSplit =
944 const bool bNextKeep = ExistContainerKeep(*pNextContainer,
false);
946 if (bNextKeep && !bCanSplit) {
947 if (!m_bIsProcessKeep && !m_bKeepBreakFinish) {
948 m_pKeepHeadNode = *pNextContainer;
949 m_bIsProcessKeep =
true;
951 return absl::nullopt;
954 if (!m_bIsProcessKeep || !m_pKeepHeadNode) {
955 if (m_bKeepBreakFinish)
956 *pLastKeepNode =
true;
957 m_bKeepBreakFinish =
false;
958 return absl::nullopt;
961 m_pKeepTailNode = *pNextContainer;
962 if (m_bKeepBreakFinish) {
963 *pNextContainer = m_pKeepHeadNode;
964 ProcessKeepNodesEnd();
965 return absl::nullopt;
968 absl::optional<Stage> ret =
969 FindBreakBeforeNode((*pNextContainer)->GetFirstChild(), pCurActionNode);
970 if (!ret.has_value()) {
971 *pNextContainer = m_pKeepHeadNode;
972 ProcessKeepNodesEnd();
973 return absl::nullopt;
979absl::optional<CXFA_ContentLayoutProcessor::Stage>
983 if (m_pKeepTailNode == pContainerNode) {
984 *pCurActionNode = m_pKeepHeadNode;
985 ProcessKeepNodesEnd();
989 CXFA_Node* pBreakAfterNode = pContainerNode->GetFirstChild();
990 return FindBreakAfterNode(pBreakAfterNode, pCurActionNode);
994 CXFA_ViewLayoutItem* pPageAreaLayoutItem) {
1000 std::tie(nCurChildNodeStage, pCurChildNode) =
1001 GotoNextContainerNode(nCurChildNodeStage, pFormNode, pCurChildNode);
1009 auto* pProcessor = cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1010 GetHeap()->GetAllocationHandle(), GetHeap(), pCurChildNode,
nullptr);
1011 pProcessor->DoLayout(
false, FLT_MAX, FLT_MAX);
1012 if (!pProcessor->HasLayoutItem())
1015 pProcessor->SetCurrentComponentPos(CalculatePositionedContainerPos(
1016 pCurChildNode, pProcessor->GetCurrentComponentSize()));
1020 pPageAreaLayoutItem->AppendFirstChild(pProcessItem);
1022 pPageAreaLayoutItem->InsertAfter(pProcessItem, pBeforeItem);
1024 pBeforeItem = pProcessItem;
1027 pBeforeItem =
nullptr;
1029 while (pLayoutItem) {
1032 pLayoutItem = pLayoutItem->GetNextSibling();
1039 pPageAreaLayoutItem->RemoveChild(pLayoutItem);
1041 pPageAreaLayoutItem->AppendFirstChild(pLayoutItem);
1043 pPageAreaLayoutItem->InsertAfter(pLayoutItem, pBeforeItem);
1045 pBeforeItem = pLayoutItem;
1046 pLayoutItem = pNextLayoutItem;
1051 Context* pContext) {
1055 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1059 bool bContainerWidthAutoSize =
true;
1060 bool bContainerHeightAutoSize =
true;
1061 CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
1062 GetFormNode(), &bContainerWidthAutoSize, &bContainerHeightAutoSize);
1064 float fContentCalculatedWidth = 0;
1065 float fContentCalculatedHeight = 0;
1066 float fHiddenContentCalculatedWidth = 0;
1067 float fHiddenContentCalculatedHeight = 0;
1068 if (!m_pCurChildNode)
1069 GotoNextContainerNodeSimple();
1071 int32_t iColIndex = 0;
1072 for (; m_pCurChildNode; GotoNextContainerNodeSimple()) {
1075 if (m_pCurChildNode->GetElementType() == XFA_Element::Variables)
1078 auto* pProcessor = cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1079 GetHeap()->GetAllocationHandle(), GetHeap(), m_pCurChildNode,
1080 m_pViewLayoutProcessor);
1082 if (pContext && pContext->m_prgSpecifiedColumnWidths) {
1084 m_pCurChildNode->JSObject()->GetInteger(XFA_Attribute::ColSpan);
1085 if (iColSpan <=
fxcrt::CollectionSize<int32_t>(
1086 *pContext->m_prgSpecifiedColumnWidths) -
1088 pContext->m_fCurColumnWidth = 0.0f;
1089 if (iColSpan == -1) {
1090 iColSpan =
fxcrt::CollectionSize<int32_t>(
1091 *pContext->m_prgSpecifiedColumnWidths);
1093 for (int32_t i = 0; iColIndex + i < iColSpan; ++i) {
1094 pContext->m_fCurColumnWidth.value() +=
1095 (*pContext->m_prgSpecifiedColumnWidths)[iColIndex + i];
1097 if (pContext->m_fCurColumnWidth.value() == 0)
1098 pContext->m_fCurColumnWidth.reset();
1100 iColIndex += iColSpan >= 0 ? iColSpan : 0;
1104 pProcessor->DoLayoutInternal(
false, FLT_MAX, FLT_MAX, pContext);
1105 if (!pProcessor->HasLayoutItem())
1108 CFX_SizeF size = pProcessor->GetCurrentComponentSize();
1109 bool bChangeParentSize =
false;
1110 if (m_pCurChildNode->PresenceRequiresSpace())
1111 bChangeParentSize =
true;
1113 CFX_PointF absolutePos;
1115 absolutePos = CalculatePositionedContainerPos(m_pCurChildNode, size);
1117 pProcessor->SetCurrentComponentPos(absolutePos);
1118 if (bContainerWidthAutoSize) {
1119 float fChildSuppliedWidth = absolutePos.x + size.width;
1120 if (bChangeParentSize) {
1121 fContentCalculatedWidth =
1122 std::max(fContentCalculatedWidth, fChildSuppliedWidth);
1124 if (fHiddenContentCalculatedWidth < fChildSuppliedWidth &&
1125 m_pCurChildNode->GetElementType() != XFA_Element::Subform) {
1126 fHiddenContentCalculatedWidth = fChildSuppliedWidth;
1131 if (bContainerHeightAutoSize) {
1132 float fChildSuppliedHeight = absolutePos.y + size.height;
1133 if (bChangeParentSize) {
1134 fContentCalculatedHeight =
1135 std::max(fContentCalculatedHeight, fChildSuppliedHeight);
1137 if (fHiddenContentCalculatedHeight < fChildSuppliedHeight &&
1138 m_pCurChildNode->GetElementType() != XFA_Element::Subform) {
1139 fHiddenContentCalculatedHeight = fChildSuppliedHeight;
1143 m_pLayoutItem->AppendLastChild(pProcessor->ExtractLayoutItem());
1148 fContentCalculatedWidth = fHiddenContentCalculatedWidth;
1150 fContentCalculatedHeight = fHiddenContentCalculatedHeight;
1152 containerSize = CalculateContainerComponentSizeFromContentSize(
1153 GetFormNode(), bContainerWidthAutoSize, fContentCalculatedWidth,
1154 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize);
1155 SetCurrentComponentSize(containerSize);
1165 DCHECK(!m_pCurChildNode);
1167 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1168 bool bContainerWidthAutoSize =
true;
1169 bool bContainerHeightAutoSize =
true;
1170 CFX_SizeF containerSize = CalculateContainerSpecifiedSize(
1171 GetFormNode(), &bContainerWidthAutoSize, &bContainerHeightAutoSize);
1172 float fContentCalculatedWidth = 0;
1173 float fContentCalculatedHeight = 0;
1174 CXFA_Margin* pMarginNode =
1176 float fLeftInset = 0;
1177 float fRightInset = 0;
1179 fLeftInset = pMarginNode->JSObject()->GetMeasureInUnit(
1181 fRightInset = pMarginNode->JSObject()->GetMeasureInUnit(
1185 float fContentWidthLimit =
1186 bContainerWidthAutoSize ? FLT_MAX
1187 : containerSize.width - fLeftInset - fRightInset;
1188 WideString wsColumnWidths =
1189 pLayoutNode->JSObject()->GetCData(
XFA_Attribute::ColumnWidths);
1191 for (
auto& width : SeparateStringOnSpace(wsColumnWidths.span())) {
1192 width.TrimLeft(L' ');
1193 if (width.IsEmpty())
1196 m_rgSpecifiedColumnWidths.push_back(
1197 CXFA_Measurement(width.AsStringView()).ToUnit(XFA_Unit::Pt));
1201 int32_t iSpecifiedColumnCount =
1202 fxcrt::CollectionSize<int32_t>(m_rgSpecifiedColumnWidths);
1203 Context layoutContext;
1204 layoutContext.m_prgSpecifiedColumnWidths = &m_rgSpecifiedColumnWidths;
1205 Context* pLayoutContext =
1206 iSpecifiedColumnCount > 0 ? &layoutContext :
nullptr;
1207 if (!m_pCurChildNode)
1208 GotoNextContainerNodeSimple();
1210 for (; m_pCurChildNode; GotoNextContainerNodeSimple()) {
1211 layoutContext.m_fCurColumnWidth.reset();
1215 auto* pProcessor = cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1216 GetHeap()->GetAllocationHandle(), GetHeap(), m_pCurChildNode,
1217 m_pViewLayoutProcessor);
1219 pProcessor->DoLayoutInternal(
false, FLT_MAX, FLT_MAX, pLayoutContext);
1220 if (!pProcessor->HasLayoutItem())
1223 m_pLayoutItem->AppendLastChild(pProcessor->ExtractLayoutItem());
1226 int32_t iRowCount = 0;
1227 int32_t iColCount = 0;
1229 std::vector<CXFA_ContentLayoutItem*> rgRowItems;
1230 std::vector<int32_t> rgRowItemsSpan;
1231 std::vector<
float> rgRowItemsWidth;
1233 pIter = pIter->GetNextSibling()) {
1249 CXFA_ContentLayoutItem* pRowLayoutCell =
1250 ToContentLayoutItem(pLayoutChild->GetFirstChild());
1251 if (pRowLayoutCell) {
1252 rgRowItems.push_back(pRowLayoutCell);
1256 rgRowItemsSpan.push_back(iColSpan);
1257 rgRowItemsWidth.push_back(pRowLayoutCell->m_sSize.width);
1261 iRowCount =
fxcrt::CollectionSize<int32_t>(rgRowItems);
1263 bool bMoreColumns =
true;
1264 while (bMoreColumns) {
1265 bMoreColumns =
false;
1266 bool bAutoCol =
false;
1267 for (int32_t i = 0; i < iRowCount; i++) {
1268 while (rgRowItems[i] &&
1269 (rgRowItemsSpan[i] <= 0 ||
1270 !rgRowItems[i]->GetFormNode()->PresenceRequiresSpace())) {
1271 CXFA_ContentLayoutItem* pNewCell =
1272 ToContentLayoutItem(rgRowItems[i]->GetNextSibling());
1273 if (rgRowItemsSpan[i] < 0 &&
1274 rgRowItems[i]->GetFormNode()->PresenceRequiresSpace()) {
1277 rgRowItems[i] = pNewCell;
1282 rgRowItemsWidth[i] = pNewCell ? pNewCell->m_sSize.width : 0;
1284 CXFA_ContentLayoutItem* pCell = rgRowItems[i];
1288 bMoreColumns =
true;
1289 if (rgRowItemsSpan[i] != 1)
1292 if (iColCount >= iSpecifiedColumnCount) {
1293 int32_t c = iColCount + 1 -
1294 fxcrt::CollectionSize<int32_t>(m_rgSpecifiedColumnWidths);
1295 for (int32_t j = 0; j < c; j++)
1296 m_rgSpecifiedColumnWidths.push_back(0);
1298 if (m_rgSpecifiedColumnWidths[iColCount] < kXFALayoutPrecision)
1301 m_rgSpecifiedColumnWidths[iColCount] < rgRowItemsWidth[i]) {
1302 m_rgSpecifiedColumnWidths[iColCount] = rgRowItemsWidth[i];
1309 float fFinalColumnWidth = 0.0f;
1310 if (fxcrt::IndexInBounds(m_rgSpecifiedColumnWidths, iColCount))
1311 fFinalColumnWidth = m_rgSpecifiedColumnWidths[iColCount];
1313 for (int32_t i = 0; i < iRowCount; ++i) {
1316 --rgRowItemsSpan[i];
1317 rgRowItemsWidth[i] -= fFinalColumnWidth;
1323 float fCurrentRowY = 0;
1325 pIter = pIter->GetNextSibling()) {
1327 if (!pLayoutChild || !pLayoutChild
->GetFormNode()->PresenceRequiresSpace())
1336 RelocateTableRowCells(pLayoutChild, m_rgSpecifiedColumnWidths,
1341 pLayoutChild->m_sPos.y = fCurrentRowY;
1342 if (bContainerWidthAutoSize) {
1343 pLayoutChild->m_sPos.x = 0;
1348 pLayoutChild->m_sPos.x =
1349 (fContentWidthLimit - pLayoutChild->m_sSize.width) / 2;
1352 pLayoutChild->m_sPos.x =
1353 fContentWidthLimit - pLayoutChild->m_sSize.width;
1357 pLayoutChild->m_sPos.x = 0;
1362 if (bContainerWidthAutoSize) {
1363 float fChildSuppliedWidth =
1364 pLayoutChild->m_sPos.x + pLayoutChild->m_sSize.width;
1365 if (fContentWidthLimit < FLT_MAX &&
1366 fContentWidthLimit > fChildSuppliedWidth) {
1367 fChildSuppliedWidth = fContentWidthLimit;
1369 fContentCalculatedWidth =
1370 std::max(fContentCalculatedWidth, fChildSuppliedWidth);
1372 fCurrentRowY += pLayoutChild->m_sSize.height;
1375 if (bContainerHeightAutoSize)
1376 fContentCalculatedHeight =
std::max(fContentCalculatedHeight, fCurrentRowY);
1378 containerSize = CalculateContainerComponentSizeFromContentSize(
1379 GetFormNode(), bContainerWidthAutoSize, fContentCalculatedWidth,
1380 bContainerHeightAutoSize, fContentCalculatedHeight, containerSize);
1381 SetCurrentComponentSize(containerSize);
1385 CXFA_ContentLayoutItem* pTrailerItem) {
1389 float fWidth = pTrailerItem->m_sSize.width;
1396 if (m_ArrayKeepItems.empty())
1399 if (!m_pLayoutItem) {
1400 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1401 m_pLayoutItem->m_sSize.clear();
1404 float fTotalHeight = 0;
1405 for (
const auto& item : pdfium::base::Reversed(m_ArrayKeepItems)) {
1406 AddLeaderAfterSplit(item);
1407 fTotalHeight += item->m_sSize.height;
1409 m_ArrayKeepItems.clear();
1411 return fTotalHeight;
1417 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>>* rgCurLineLayoutItem,
1418 float* fContentCurRowAvailWidth,
1419 float* fContentCurRowHeight,
1420 float* fContentCurRowY,
1421 bool* bAddedItemInRow,
1422 bool* bForceEndPage,
1424 if (!pChildProcessor)
1427 if (m_pCurChildNode->GetIntact() == XFA_AttributeValue::None &&
1428 pChildProcessor->m_bHasAvailHeight)
1431 if (!ExistContainerKeep(m_pCurChildNode,
true))
1434 CFX_SizeF childSize = pChildProcessor->GetCurrentComponentSize();
1435 std::vector<CXFA_ContentLayoutItem*> keepLayoutItems;
1436 if (JudgePutNextPage(m_pLayoutItem.Get(), childSize.height,
1437 &keepLayoutItems)) {
1438 m_ArrayKeepItems.clear();
1439 for (CXFA_ContentLayoutItem* item : keepLayoutItems) {
1440 m_pLayoutItem->RemoveChild(item);
1441 *fContentCurRowY -= item->m_sSize.height;
1442 m_ArrayKeepItems.push_back(item);
1444 *bAddedItemInRow =
true;
1445 *bForceEndPage =
true;
1446 *result = Result::kPageFullBreak;
1450 rgCurLineLayoutItem->push_back(pChildProcessor->ExtractLayoutItem());
1451 *bAddedItemInRow =
true;
1452 *fContentCurRowAvailWidth -= childSize.width;
1453 *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height);
1454 *result = eRetValue;
1459 CXFA_ContentLayoutItem* pParentLayoutItem,
1461 std::vector<CXFA_ContentLayoutItem*>* pKeepItems) {
1462 if (!pParentLayoutItem)
1465 float fItemsHeight = 0;
1466 for (
CXFA_LayoutItem* pIter = pParentLayoutItem->GetFirstChild(); pIter;
1467 pIter = pIter->GetNextSibling()) {
1469 if (!pChildLayoutItem)
1472 if (ExistContainerKeep(pChildLayoutItem
->GetFormNode(),
false)) {
1473 pKeepItems->push_back(pChildLayoutItem);
1474 fItemsHeight += pChildLayoutItem->m_sSize.height;
1476 pKeepItems->clear();
1480 fItemsHeight += fChildHeight;
1481 return m_pViewLayoutProcessor->GetNextAvailContentHeight(fItemsHeight);
1488 CXFA_NodeIterator sIterator(pFormNode);
1489 for (
CXFA_Node* pNode = sIterator.MoveToNext(); pNode;
1490 pNode = sIterator.MoveToNext()) {
1505 CXFA_ContentLayoutItem* pTrailerItem,
1507 ProcessUnUseBinds(pLeaderNode);
1508 ProcessUnUseBinds(pTrailerNode);
1514 pFormNode = pFormNode->GetParent();
1516 if (pLeaderNode && pFormNode)
1518 if (pTrailerNode && pFormNode)
1521 XFA_ReleaseLayoutItem(pTrailerItem);
1526 bool bUseBreakControl,
1531 bool bRootForceTb) {
1532 m_bHasAvailHeight =
true;
1533 if (m_pCurChildPreprocessor)
1534 m_pCurChildPreprocessor->m_ePreProcessRs = Result::kDone;
1536 bool bContainerWidthAutoSize =
true;
1537 bool bContainerHeightAutoSize =
true;
1538 CFX_SizeF container_size = CalculateContainerSpecifiedSize(
1539 GetFormNode(), &bContainerWidthAutoSize, &bContainerHeightAutoSize);
1540 AdjustContainerSpecifiedSize(pContext, &container_size,
1541 &bContainerWidthAutoSize,
1542 &bContainerHeightAutoSize);
1544 CXFA_Margin* pMargin =
1547 float fContentWidthLimit =
1548 bContainerWidthAutoSize ? FLT_MAX
1549 : container_size.width - inset.left - inset.right;
1550 float fAvailHeight = fHeightLimit - inset
.top - inset
.bottom;
1551 if (fAvailHeight < 0)
1552 m_bHasAvailHeight =
false;
1554 fRealHeight = fRealHeight - inset
.top - inset
.bottom;
1555 CFX_SizeF calculated_size;
1556 float fContentCurRowY = 0;
1557 CXFA_ContentLayoutItem* pLastChild =
nullptr;
1558 if (m_pLayoutItem) {
1559 pLastChild = FindLastContentLayoutItem(eFlowStrategy);
1560 calculated_size = CalculateLayoutItemSize(pLastChild);
1562 pLastChild ? pLastChild->m_sPos.y : calculated_size.height;
1565 fContentCurRowY += InsertKeepLayoutItems();
1567 GotoNextContainerNodeSimple();
1570 if (m_pCurChildPreprocessor && m_nCurChildNodeStage == Stage::kContainer) {
1571 if (ExistContainerKeep(m_pCurChildPreprocessor->GetFormNode(),
false)) {
1572 m_pKeepHeadNode = m_pCurChildNode;
1573 m_bIsProcessKeep =
true;
1578 bool bForceEndPage =
false;
1579 bool bBreakDone =
false;
1580 bool bIsManualBreak =
false;
1582 float fContentCurRowHeight = 0;
1583 float fContentCurRowAvailWidth = fContentWidthLimit;
1584 m_fWidthLimit = fContentCurRowAvailWidth;
1585 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>>
1586 rgCurLineLayoutItems[3];
1587 uint8_t uCurHAlignState =
1591 pNext = pNext->GetNextSibling()) {
1595 if (!pLayoutNext->GetNextSibling() && m_pCurChildPreprocessor &&
1596 m_pCurChildPreprocessor->GetFormNode() ==
1597 pLayoutNext->GetFormNode()) {
1598 if (m_pCurChildPreprocessor->m_pLayoutItem &&
1599 m_pCurChildPreprocessor->m_pLayoutItem != pLayoutNext) {
1600 pLayoutNext->InsertAfter(
1601 m_pCurChildPreprocessor->m_pLayoutItem.Get());
1603 m_pCurChildPreprocessor->m_pLayoutItem = pLayoutNext;
1607 HAlignEnumToInt(pLayoutNext
->GetFormNode()->JSObject()->GetEnum(
1609 rgCurLineLayoutItems[uHAlign].emplace_back(pLayoutNext);
1611 if (uHAlign > uCurHAlignState)
1612 uCurHAlignState = uHAlign;
1613 }
else if (uHAlign < uCurHAlignState) {
1614 uCurHAlignState = uHAlign;
1617 if (pLayoutNext->m_sSize.height > fContentCurRowHeight)
1618 fContentCurRowHeight = pLayoutNext->m_sSize.height;
1619 fContentCurRowAvailWidth -= pLayoutNext->m_sSize.width;
1623 CXFA_ContentLayoutItem* pLayoutNextTemp = pLastChild;
1624 while (pLayoutNextTemp) {
1625 CXFA_ContentLayoutItem* pSaveLayoutNext =
1626 ToContentLayoutItem(pLayoutNextTemp->GetNextSibling());
1627 pLayoutNextTemp->RemoveSelfIfParented();
1628 pLayoutNextTemp = pSaveLayoutNext;
1630 pLastChild =
nullptr;
1633 while (m_pCurChildNode) {
1635 bool bAddedItemInRow =
false;
1637 switch (m_nCurChildNodeStage) {
1642 for (
auto& item : m_ArrayKeepItems) {
1643 m_pLayoutItem->RemoveChild(item);
1644 calculated_size.height -= item->m_sSize.height;
1647 if (!bUseBreakControl || !m_pViewLayoutProcessor)
1650 absl::optional<CXFA_ViewLayoutProcessor::BreakData> break_data =
1651 m_pViewLayoutProcessor->ProcessBreakBefore(m_pCurChildNode);
1652 if (!break_data.has_value() || !break_data.value().bCreatePage ||
1653 GetFormNode()->GetElementType() == XFA_Element::Form) {
1657 CXFA_Node* pLeaderNode = break_data.value().pLeader;
1658 CXFA_Node* pTrailerNode = break_data.value().pTrailer;
1659 if (JudgeLeaderOrTrailerForOccur(pLeaderNode))
1660 AddPendingNode(pLeaderNode,
true);
1662 if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) {
1663 if (GetFormNode()->GetParent()->GetElementType() ==
1664 XFA_Element::Form &&
1666 AddPendingNode(pTrailerNode,
true);
1668 auto* pTempProcessor =
1669 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1670 GetHeap()->GetAllocationHandle(), GetHeap(), pTrailerNode,
1674 pTempProcessor, bContainerWidthAutoSize,
1675 bContainerHeightAutoSize, container_size.height,
1676 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
false,
1677 FLT_MAX, FLT_MAX, fContentWidthLimit, &fContentCurRowY,
1678 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1679 &bAddedItemInRow, &bForceEndPage, pContext,
false);
1682 GotoNextContainerNodeSimple();
1683 bForceEndPage =
true;
1684 bIsManualBreak =
true;
1685 goto SuspendAndCreateNewRow;
1688 if (!bUseBreakControl || !m_pViewLayoutProcessor)
1691 absl::optional<CXFA_ViewLayoutProcessor::BreakData> break_data =
1692 m_pViewLayoutProcessor->ProcessBreakAfter(m_pCurChildNode);
1693 if (!break_data.has_value() ||
1694 GetFormNode()->GetElementType() == XFA_Element::Form) {
1698 CXFA_Node* pLeaderNode = break_data.value().pLeader;
1699 CXFA_Node* pTrailerNode = break_data.value().pTrailer;
1700 bool bCreatePage = break_data.value().bCreatePage;
1701 if (JudgeLeaderOrTrailerForOccur(pTrailerNode)) {
1702 auto* pTempProcessor =
1703 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1704 GetHeap()->GetAllocationHandle(), GetHeap(), pTrailerNode,
1707 InsertFlowedItem(pTempProcessor, bContainerWidthAutoSize,
1708 bContainerHeightAutoSize, container_size.height,
1709 eFlowStrategy, &uCurHAlignState,
1710 rgCurLineLayoutItems,
false, FLT_MAX, FLT_MAX,
1711 fContentWidthLimit, &fContentCurRowY,
1712 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1713 &bAddedItemInRow, &bForceEndPage, pContext,
false);
1716 if (JudgeLeaderOrTrailerForOccur(pLeaderNode)) {
1717 CalculateRowChildPosition(
1718 rgCurLineLayoutItems, eFlowStrategy, bContainerHeightAutoSize,
1719 bContainerWidthAutoSize, &calculated_size.width,
1720 &calculated_size.height, &fContentCurRowY,
1721 fContentCurRowHeight, fContentWidthLimit,
false);
1722 rgCurLineLayoutItems->clear();
1723 auto* pTempProcessor =
1724 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1725 GetHeap()->GetAllocationHandle(), GetHeap(), pLeaderNode,
1728 pTempProcessor, bContainerWidthAutoSize,
1729 bContainerHeightAutoSize, container_size.height,
1730 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
false,
1731 FLT_MAX, FLT_MAX, fContentWidthLimit, &fContentCurRowY,
1732 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1733 &bAddedItemInRow, &bForceEndPage, pContext,
false);
1736 if (JudgeLeaderOrTrailerForOccur(pLeaderNode))
1737 AddPendingNode(pLeaderNode,
true);
1740 GotoNextContainerNodeSimple();
1742 bForceEndPage =
true;
1743 bIsManualBreak =
true;
1747 goto SuspendAndCreateNewRow;
1750 if (m_pCurChildPreprocessor) {
1751 pProcessor = m_pCurChildPreprocessor.Get();
1752 m_pCurChildPreprocessor =
nullptr;
1753 }
else if (m_pViewLayoutProcessor) {
1755 m_pViewLayoutProcessor->ProcessBookendLeader(m_pCurChildNode);
1758 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1759 GetHeap()->GetAllocationHandle(), GetHeap(), pLeaderNode,
1760 m_pViewLayoutProcessor);
1765 if (InsertFlowedItem(
1766 pProcessor, bContainerWidthAutoSize,
1767 bContainerHeightAutoSize, container_size.height,
1768 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
1769 bUseBreakControl, fAvailHeight, fRealHeight,
1770 fContentWidthLimit, &fContentCurRowY,
1771 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1772 &bAddedItemInRow, &bForceEndPage, pContext,
1773 false) != Result::kDone) {
1774 goto SuspendAndCreateNewRow;
1776 pProcessor =
nullptr;
1781 if (m_pCurChildPreprocessor) {
1782 pProcessor = m_pCurChildPreprocessor;
1783 m_pCurChildPreprocessor.Clear();
1784 }
else if (m_pViewLayoutProcessor) {
1786 m_pViewLayoutProcessor->ProcessBookendTrailer(m_pCurChildNode);
1789 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1790 GetHeap()->GetAllocationHandle(), GetHeap(), pTrailerNode,
1791 m_pViewLayoutProcessor);
1795 if (InsertFlowedItem(
1796 pProcessor, bContainerWidthAutoSize,
1797 bContainerHeightAutoSize, container_size.height,
1798 eFlowStrategy, &uCurHAlignState, rgCurLineLayoutItems,
1799 bUseBreakControl, fAvailHeight, fRealHeight,
1800 fContentWidthLimit, &fContentCurRowY,
1801 &fContentCurRowAvailWidth, &fContentCurRowHeight,
1802 &bAddedItemInRow, &bForceEndPage, pContext,
1803 false) != Result::kDone) {
1804 goto SuspendAndCreateNewRow;
1806 pProcessor =
nullptr;
1811 DCHECK(m_pCurChildNode->IsContainerNode());
1812 if (m_pCurChildNode->GetElementType() == XFA_Element::Variables)
1814 if (fContentCurRowY >= fHeightLimit + kXFALayoutPrecision &&
1815 m_pCurChildNode->PresenceRequiresSpace()) {
1816 bForceEndPage =
true;
1817 goto SuspendAndCreateNewRow;
1819 if (!m_pCurChildNode->IsContainerNode())
1822 bool bNewRow =
false;
1823 if (m_pCurChildPreprocessor) {
1824 pProcessor = m_pCurChildPreprocessor;
1825 m_pCurChildPreprocessor.Clear();
1829 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
1830 GetHeap()->GetAllocationHandle(), GetHeap(),
1831 m_pCurChildNode, m_pViewLayoutProcessor);
1834 pProcessor->InsertPendingItems(m_pCurChildNode);
1835 Result rs = InsertFlowedItem(
1836 pProcessor, bContainerWidthAutoSize, bContainerHeightAutoSize,
1837 container_size.height, eFlowStrategy, &uCurHAlignState,
1838 rgCurLineLayoutItems, bUseBreakControl, fAvailHeight, fRealHeight,
1839 fContentWidthLimit, &fContentCurRowY, &fContentCurRowAvailWidth,
1840 &fContentCurRowHeight, &bAddedItemInRow, &bForceEndPage, pContext,
1844 bIsManualBreak =
true;
1847 bForceEndPage =
true;
1850 goto SuspendAndCreateNewRow;
1853 pProcessor->InsertPendingItems(m_pCurChildNode);
1854 pProcessor =
nullptr;
1862 GotoNextContainerNodeSimple();
1866 SuspendAndCreateNewRow:
1868 m_pCurChildPreprocessor = pProcessor;
1869 pProcessor =
nullptr;
1874 CalculateRowChildPosition(rgCurLineLayoutItems, eFlowStrategy,
1875 bContainerHeightAutoSize, bContainerWidthAutoSize,
1876 &calculated_size.width, &calculated_size.height,
1877 &fContentCurRowY, fContentCurRowHeight,
1878 fContentWidthLimit, bRootForceTb);
1879 m_fWidthLimit = fContentCurRowAvailWidth;
1885 m_nCurChildNodeStage == Stage::kDone && m_PendingNodes.empty();
1889 container_size = CalculateContainerComponentSizeFromContentSize(
1890 GetFormNode(), bContainerWidthAutoSize, calculated_size.width,
1891 bContainerHeightAutoSize, calculated_size.height, container_size);
1893 if (container_size.height >= kXFALayoutPrecision || m_pLayoutItem ||
1896 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1897 container_size.height =
std::max(container_size.height, 0.f);
1899 SetCurrentComponentSize(container_size);
1903 m_fUsedSize += m_pLayoutItem->m_sSize.height;
1912 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> (
1913 &rgCurLineLayoutItems)[3],
1914 XFA_AttributeValue eFlowStrategy,
1915 bool bContainerHeightAutoSize,
1916 bool bContainerWidthAutoSize,
1917 float* fContentCalculatedWidth,
1918 float* fContentCalculatedHeight,
1919 float* fContentCurRowY,
1920 float fContentCurRowHeight,
1921 float fContentWidthLimit,
1922 bool bRootForceTb) {
1923 int32_t nGroupLengths[3] = {0, 0, 0};
1924 float fGroupWidths[3] = {0, 0, 0};
1925 int32_t nTotalLength = 0;
1926 for (int32_t i = 0; i < 3; i++) {
1927 nGroupLengths[i] = fxcrt::CollectionSize<int32_t>(rgCurLineLayoutItems[i]);
1928 for (int32_t c = nGroupLengths[i], j = 0; j < c; j++) {
1930 if (rgCurLineLayoutItems[i][j]->GetFormNode()->PresenceRequiresSpace())
1931 fGroupWidths[i] += rgCurLineLayoutItems[i][j]->m_sSize.width;
1934 if (!nTotalLength) {
1935 if (bContainerHeightAutoSize) {
1936 *fContentCalculatedHeight =
1937 std::min(*fContentCalculatedHeight, *fContentCurRowY);
1942 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
1944 if (eFlowStrategy != XFA_AttributeValue::Rl_tb) {
1947 for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) {
1949 rgCurLineLayoutItems[0][j]->m_sPos = CalculatePositionedContainerPos(
1950 rgCurLineLayoutItems[0][j]->GetFormNode(),
1951 rgCurLineLayoutItems[0][j]->m_sSize);
1953 rgCurLineLayoutItems[0][j]->m_sPos =
1954 CFX_PointF(fCurPos, *fContentCurRowY);
1955 if (rgCurLineLayoutItems[0][j]->GetFormNode()->PresenceRequiresSpace())
1956 fCurPos += rgCurLineLayoutItems[0][j]->m_sSize.width;
1958 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[0][j]);
1959 m_fLastRowWidth = fCurPos;
1961 fCurPos = (fContentWidthLimit + fGroupWidths[0] - fGroupWidths[1] -
1964 for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) {
1966 rgCurLineLayoutItems[1][j]->m_sPos = CalculatePositionedContainerPos(
1967 rgCurLineLayoutItems[1][j]->GetFormNode(),
1968 rgCurLineLayoutItems[1][j]->m_sSize);
1970 rgCurLineLayoutItems[1][j]->m_sPos =
1971 CFX_PointF(fCurPos, *fContentCurRowY);
1972 if (rgCurLineLayoutItems[1][j]->GetFormNode()->PresenceRequiresSpace())
1973 fCurPos += rgCurLineLayoutItems[1][j]->m_sSize.width;
1975 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[1][j]);
1976 m_fLastRowWidth = fCurPos;
1978 fCurPos = fContentWidthLimit - fGroupWidths[2];
1979 for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) {
1981 rgCurLineLayoutItems[2][j]->m_sPos = CalculatePositionedContainerPos(
1982 rgCurLineLayoutItems[2][j]->GetFormNode(),
1983 rgCurLineLayoutItems[2][j]->m_sSize);
1985 rgCurLineLayoutItems[2][j]->m_sPos =
1986 CFX_PointF(fCurPos, *fContentCurRowY);
1987 if (rgCurLineLayoutItems[2][j]->GetFormNode()->PresenceRequiresSpace())
1988 fCurPos += rgCurLineLayoutItems[2][j]->m_sSize.width;
1990 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[2][j]);
1991 m_fLastRowWidth = fCurPos;
1995 fCurPos = fGroupWidths[0];
1996 for (int32_t c = nGroupLengths[0], j = 0; j < c; j++) {
1997 if (rgCurLineLayoutItems[0][j]->GetFormNode()->PresenceRequiresSpace())
1998 fCurPos -= rgCurLineLayoutItems[0][j]->m_sSize.width;
2000 rgCurLineLayoutItems[0][j]->m_sPos =
2001 CFX_PointF(fCurPos, *fContentCurRowY);
2002 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[0][j]);
2003 m_fLastRowWidth = fCurPos;
2005 fCurPos = (fContentWidthLimit + fGroupWidths[0] + fGroupWidths[1] -
2008 for (int32_t c = nGroupLengths[1], j = 0; j < c; j++) {
2009 if (rgCurLineLayoutItems[1][j]->GetFormNode()->PresenceRequiresSpace())
2010 fCurPos -= rgCurLineLayoutItems[1][j]->m_sSize.width;
2012 rgCurLineLayoutItems[1][j]->m_sPos =
2013 CFX_PointF(fCurPos, *fContentCurRowY);
2014 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[1][j]);
2015 m_fLastRowWidth = fCurPos;
2017 fCurPos = fContentWidthLimit;
2018 for (int32_t c = nGroupLengths[2], j = 0; j < c; j++) {
2019 if (rgCurLineLayoutItems[2][j]->GetFormNode()->PresenceRequiresSpace())
2020 fCurPos -= rgCurLineLayoutItems[2][j]->m_sSize.width;
2022 rgCurLineLayoutItems[2][j]->m_sPos =
2023 CFX_PointF(fCurPos, *fContentCurRowY);
2024 m_pLayoutItem->AppendLastChild(rgCurLineLayoutItems[2][j]);
2025 m_fLastRowWidth = fCurPos;
2028 m_fLastRowY = *fContentCurRowY;
2029 *fContentCurRowY += fContentCurRowHeight;
2030 if (bContainerWidthAutoSize) {
2031 float fChildSuppliedWidth = fGroupWidths[0];
2032 if (fContentWidthLimit < FLT_MAX &&
2033 fContentWidthLimit > fChildSuppliedWidth) {
2034 fChildSuppliedWidth = fContentWidthLimit;
2036 *fContentCalculatedWidth =
2037 std::max(*fContentCalculatedWidth, fChildSuppliedWidth);
2039 if (bContainerHeightAutoSize) {
2040 *fContentCalculatedHeight =
2041 std::max(*fContentCalculatedHeight, *fContentCurRowY);
2049 CXFA_Node* pParent = pSubformSet->GetParent();
2053 pParent = pParent->GetParent();
2063 DCHECK(!m_pCurChildNode);
2064 m_pLayoutItem = CreateContentLayoutItem(GetFormNode());
2070 CFX_SizeF size(-1, -1);
2073 int32_t nRotate = XFA_MapRotation(
2075 if (nRotate == 90 || nRotate == 270)
2076 std::swap(size.width, size.height);
2078 SetCurrentComponentSize(size);
2082 bool bUseBreakControl,
2084 float fRealHeight) {
2085 return DoLayoutInternal(bUseBreakControl, fHeightLimit, fRealHeight,
nullptr);
2092 Context* pContext) {
2098 bool bRootForceTb =
false;
2101 GetLayout(pLayoutNode, &bRootForceTb);
2102 switch (eLayoutStrategy) {
2106 return DoLayoutFlowedContainer(bUseBreakControl, eLayoutStrategy,
2107 fHeightLimit, fRealHeight, pContext,
2113 DoLayoutPositionedContainer(pContext);
2117 DoLayoutTableContainer(pLayoutNode);
2134 return CFX_SizeF(m_pLayoutItem->m_sSize.width, m_pLayoutItem->m_sSize.height);
2138 const CFX_PointF& pos) {
2139 m_pLayoutItem->m_sPos = pos;
2143 const CFX_SizeF& size) {
2144 m_pLayoutItem->m_sSize = size;
2154 pTemplate = pFormNode;
2157 pTemplate->GetFirstChildByClass<CXFA_Occur>(
XFA_Element::Occur);
2161 int32_t iMax = pOccur->GetMax();
2165 int32_t iCount = m_PendingNodesCount[pTemplate];
2169 m_PendingNodesCount[pTemplate] = iCount + 1;
2174 CXFA_ContentLayoutItem* pLayoutItem) {
2178 case XFA_AttributeValue::Row:
2179 case XFA_AttributeValue::Rl_row:
2180 RelocateTableRowCells(pLayoutItem, m_rgSpecifiedColumnWidths, eLayout);
2189 CXFA_ContentLayoutItem* pTrailerLayoutItem,
2190 bool bUseInherited) {
2191 if (!pTrailerLayoutItem)
2194 float fHeight = pTrailerLayoutItem->m_sSize.height;
2195 if (bUseInherited) {
2196 float fNewSplitPos = 0;
2198 fNewSplitPos = FindSplitPos(fSplitPos - fHeight);
2200 SplitLayoutItem(fNewSplitPos);
2204 UpdatePendingItemLayout(pTrailerLayoutItem);
2205 CXFA_Margin* pMargin =
2208 if (!IsAddNewRowForTrailer(pTrailerLayoutItem)) {
2209 pTrailerLayoutItem->m_sPos.y = m_fLastRowY;
2210 pTrailerLayoutItem->m_sPos.x = m_fLastRowWidth;
2211 m_pLayoutItem->m_sSize.width += pTrailerLayoutItem->m_sSize.width;
2212 m_pLayoutItem->AppendLastChild(pTrailerLayoutItem);
2216 float fNewSplitPos = 0;
2218 fNewSplitPos = FindSplitPos(fSplitPos - fHeight);
2221 SplitLayoutItem(fNewSplitPos);
2222 pTrailerLayoutItem->m_sPos.y = fNewSplitPos - inset
.top - inset
.bottom;
2224 pTrailerLayoutItem->m_sPos.y = fSplitPos - inset
.top - inset
.bottom;
2227 switch (pTrailerLayoutItem
->GetFormNode()->JSObject()->GetEnum(
2229 case XFA_AttributeValue::Right:
2230 pTrailerLayoutItem->m_sPos.x = m_pLayoutItem->m_sSize.width -
2232 pTrailerLayoutItem->m_sSize.width;
2234 case XFA_AttributeValue::Center:
2235 pTrailerLayoutItem->m_sPos.x =
2236 (m_pLayoutItem->m_sSize.width - inset.left - inset.right -
2237 pTrailerLayoutItem->m_sSize.width) /
2242 pTrailerLayoutItem->m_sPos.x = inset
.left;
2245 m_pLayoutItem->m_sSize.height += fHeight;
2246 m_pLayoutItem->AppendLastChild(pTrailerLayoutItem);
2250 CXFA_ContentLayoutItem* pLeaderLayoutItem) {
2251 UpdatePendingItemLayout(pLeaderLayoutItem);
2253 CXFA_Margin* pMarginNode =
2255 float fLeftInset = 0;
2256 float fRightInset = 0;
2258 fLeftInset = pMarginNode->JSObject()->GetMeasureInUnit(
2260 fRightInset = pMarginNode->JSObject()->GetMeasureInUnit(
2264 float fHeight = pLeaderLayoutItem->m_sSize.height;
2266 pIter = pIter->GetNextSibling()) {
2271 pContentItem->m_sPos.y += fHeight;
2273 pLeaderLayoutItem->m_sPos.y = 0;
2275 switch (pLeaderLayoutItem
->GetFormNode()->JSObject()->GetEnum(
2277 case XFA_AttributeValue::Right:
2278 pLeaderLayoutItem->m_sPos.x = m_pLayoutItem->m_sSize.width - fRightInset -
2279 pLeaderLayoutItem->m_sSize.width;
2281 case XFA_AttributeValue::Center:
2282 pLeaderLayoutItem->m_sPos.x =
2283 (m_pLayoutItem->m_sSize.width - fLeftInset - fRightInset -
2284 pLeaderLayoutItem->m_sSize.width) /
2289 pLeaderLayoutItem->m_sPos.x = fLeftInset;
2292 m_pLayoutItem->m_sSize.height += fHeight;
2293 m_pLayoutItem->AppendLastChild(pLeaderLayoutItem);
2297 bool bBreakPending) {
2298 m_PendingNodes.push_back(pPendingNode);
2299 m_bBreakPending = bBreakPending;
2304 float fTotalHeight = 0;
2305 if (m_PendingNodes.empty())
2306 return fTotalHeight;
2308 if (!m_pLayoutItem) {
2309 m_pLayoutItem = CreateContentLayoutItem(pCurChildNode);
2310 m_pLayoutItem->m_sSize.clear();
2313 while (!m_PendingNodes.empty()) {
2314 auto* pPendingProcessor =
2315 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
2316 GetHeap()->GetAllocationHandle(), GetHeap(), m_PendingNodes.front(),
2318 m_PendingNodes.pop_front();
2319 pPendingProcessor->DoLayout(
false, FLT_MAX, FLT_MAX);
2320 CXFA_ContentLayoutItem* pPendingLayoutItem =
nullptr;
2321 if (pPendingProcessor->HasLayoutItem())
2322 pPendingLayoutItem = pPendingProcessor->ExtractLayoutItem();
2323 if (pPendingLayoutItem) {
2324 AddLeaderAfterSplit(pPendingLayoutItem);
2325 if (m_bBreakPending)
2326 fTotalHeight += pPendingLayoutItem->m_sSize.height;
2329 return fTotalHeight;
2335 bool bContainerWidthAutoSize,
2336 bool bContainerHeightAutoSize,
2337 float fContainerHeight,
2339 uint8_t* uCurHAlignState,
2340 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> (
2341 &rgCurLineLayoutItems)[3],
2342 bool bUseBreakControl,
2345 float fContentWidthLimit,
2346 float* fContentCurRowY,
2347 float* fContentCurRowAvailWidth,
2348 float* fContentCurRowHeight,
2349 bool* bAddedItemInRow,
2350 bool* bForceEndPage,
2351 Context* pLayoutContext,
2354 uint8_t uHAlign = HAlignEnumToInt(
2355 m_pCurChildNode->JSObject()->GetEnum(XFA_Attribute::HAlign));
2356 if (bContainerWidthAutoSize)
2360 uHAlign < *uCurHAlignState) ||
2362 uHAlign > *uCurHAlignState)) {
2366 *uCurHAlignState = uHAlign;
2369 bool bUseRealHeight = bTakeSpace && bContainerHeightAutoSize && bIsOwnSplit &&
2372 bool bIsTransHeight = bTakeSpace;
2373 if (bIsTransHeight && !bIsOwnSplit) {
2374 bool bRootForceTb =
false;
2379 bIsTransHeight =
false;
2383 bool bUseInherited =
false;
2384 Context layoutContext;
2385 if (m_pViewLayoutProcessor) {
2387 m_pViewLayoutProcessor->QueryOverflow(GetFormNode());
2388 if (pOverflowNode) {
2389 layoutContext.m_pOverflowNode = pOverflowNode;
2390 layoutContext.m_pOverflowProcessor =
this;
2391 pLayoutContext = &layoutContext;
2396 if (!bNewRow || pProcessor->m_ePreProcessRs == Result::kDone) {
2397 eRetValue = pProcessor->DoLayoutInternal(
2398 bTakeSpace && bUseBreakControl,
2399 bUseRealHeight ? fRealHeight - *fContentCurRowY : FLT_MAX,
2400 bIsTransHeight ? fRealHeight - *fContentCurRowY : FLT_MAX,
2402 pProcessor->m_ePreProcessRs = eRetValue;
2404 eRetValue = pProcessor->m_ePreProcessRs;
2407 if (!pProcessor->HasLayoutItem())
2410 CFX_SizeF childSize = pProcessor->GetCurrentComponentSize();
2411 if (bUseRealHeight && fRealHeight < kXFALayoutPrecision) {
2412 fRealHeight = FLT_MAX;
2413 fAvailHeight = FLT_MAX;
2416 (childSize.width > *fContentCurRowAvailWidth + kXFALayoutPrecision) &&
2417 (fContentWidthLimit - *fContentCurRowAvailWidth > kXFALayoutPrecision)) {
2421 CXFA_Node* pOverflowLeaderNode =
nullptr;
2422 CXFA_Node* pOverflowTrailerNode =
nullptr;
2424 CXFA_ContentLayoutItem* pTrailerLayoutItem =
nullptr;
2425 bool bIsAddTrailerHeight =
false;
2426 if (m_pViewLayoutProcessor &&
2427 pProcessor->GetFormNode()->GetIntact() == XFA_AttributeValue::None) {
2429 m_pViewLayoutProcessor->QueryOverflow(pProcessor->GetFormNode());
2430 if (!pFormNode && pLayoutContext && pLayoutContext->m_pOverflowProcessor) {
2431 pFormNode = pLayoutContext->m_pOverflowNode;
2432 bUseInherited =
true;
2434 absl::optional<CXFA_ViewLayoutProcessor::OverflowData> overflow_data =
2435 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
false);
2436 if (overflow_data.has_value()) {
2437 pOverflowLeaderNode = overflow_data.value().pLeader;
2438 pOverflowTrailerNode = overflow_data.value().pTrailer;
2439 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowTrailerNode)) {
2440 if (pOverflowTrailerNode) {
2441 auto* pOverflowLeaderProcessor =
2442 cppgc::MakeGarbageCollected<CXFA_ContentLayoutProcessor>(
2443 GetHeap()->GetAllocationHandle(), GetHeap(),
2444 pOverflowTrailerNode,
nullptr);
2445 pOverflowLeaderProcessor->DoLayout(
false, FLT_MAX, FLT_MAX);
2446 pTrailerLayoutItem =
2447 pOverflowLeaderProcessor->HasLayoutItem()
2448 ? pOverflowLeaderProcessor->ExtractLayoutItem()
2452 bIsAddTrailerHeight =
2454 ? IsAddNewRowForTrailer(pTrailerLayoutItem)
2455 : pProcessor->IsAddNewRowForTrailer(pTrailerLayoutItem);
2456 if (bIsAddTrailerHeight) {
2457 childSize.height += pTrailerLayoutItem->m_sSize.height;
2458 bIsAddTrailerHeight =
true;
2465 *fContentCurRowY + childSize.height <=
2466 fAvailHeight + kXFALayoutPrecision ||
2467 (!bContainerHeightAutoSize &&
2468 m_fUsedSize + fAvailHeight + kXFALayoutPrecision >= fContainerHeight)) {
2470 if (pProcessor->m_bUseInherited) {
2471 if (pTrailerLayoutItem)
2472 pProcessor->AddTrailerBeforeSplit(childSize.height,
2473 pTrailerLayoutItem,
false);
2474 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode))
2475 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2477 pProcessor->m_bUseInherited =
false;
2479 if (bIsAddTrailerHeight)
2480 childSize.height -= pTrailerLayoutItem->m_sSize.height;
2482 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2483 pOverflowTrailerNode,
2484 pTrailerLayoutItem, pFormNode);
2487 CXFA_ContentLayoutItem* pChildLayoutItem =
2491 m_ArrayKeepItems.push_back(pChildLayoutItem);
2493 m_ArrayKeepItems.clear();
2495 rgCurLineLayoutItems[uHAlign].push_back(pChildLayoutItem);
2496 *bAddedItemInRow =
true;
2498 *fContentCurRowAvailWidth -= childSize.width;
2499 *fContentCurRowHeight =
2500 std::max(*fContentCurRowHeight, childSize.height);
2506 if (pProcessor->m_bUseInherited) {
2507 if (pTrailerLayoutItem) {
2508 pProcessor->AddTrailerBeforeSplit(childSize.height,
2509 pTrailerLayoutItem,
false);
2511 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode))
2512 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2514 pProcessor->m_bUseInherited =
false;
2516 if (bIsAddTrailerHeight)
2517 childSize.height -= pTrailerLayoutItem->m_sSize.height;
2519 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2520 pOverflowTrailerNode,
2521 pTrailerLayoutItem, pFormNode);
2524 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem());
2525 *bAddedItemInRow =
true;
2526 *fContentCurRowAvailWidth -= childSize.width;
2527 *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height);
2532 if (ProcessKeepForSplit(pProcessor, eRetValue, &rgCurLineLayoutItems[uHAlign],
2533 fContentCurRowAvailWidth, fContentCurRowHeight,
2534 fContentCurRowY, bAddedItemInRow, bForceEndPage,
2539 *bForceEndPage =
true;
2540 float fSplitPos = pProcessor->FindSplitPos(fAvailHeight - *fContentCurRowY);
2545 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2546 pOverflowTrailerNode, pTrailerLayoutItem,
2548 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem());
2549 *bAddedItemInRow =
true;
2551 *fContentCurRowAvailWidth -= childSize.width;
2552 *fContentCurRowHeight =
2553 std::max(*fContentCurRowHeight, childSize.height);
2558 if (m_pViewLayoutProcessor && !pProcessor->m_bUseInherited &&
2559 eRetValue != Result::kPageFullBreak) {
2560 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2562 if (pTrailerLayoutItem && bIsAddTrailerHeight) {
2563 pProcessor->AddTrailerBeforeSplit(fSplitPos, pTrailerLayoutItem,
2566 pProcessor->SplitLayoutItem(fSplitPos);
2569 if (bUseInherited) {
2570 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2571 pOverflowTrailerNode, pTrailerLayoutItem,
2573 m_bUseInherited =
true;
2575 CXFA_LayoutItem* firstChild = pProcessor->m_pLayoutItem->GetFirstChild();
2576 if (firstChild && !firstChild->GetNextSibling() &&
2578 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2579 pOverflowTrailerNode,
2580 pTrailerLayoutItem, pFormNode);
2581 }
else if (pProcessor->JudgeLeaderOrTrailerForOccur(
2582 pOverflowLeaderNode)) {
2583 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2587 if (pProcessor->m_pLayoutItem->GetNextSibling()) {
2588 childSize = pProcessor->GetCurrentComponentSize();
2589 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem());
2590 *bAddedItemInRow =
true;
2592 *fContentCurRowAvailWidth -= childSize.width;
2593 *fContentCurRowHeight =
2594 std::max(*fContentCurRowHeight, childSize.height);
2600 if (*fContentCurRowY <= kXFALayoutPrecision) {
2601 childSize = pProcessor->GetCurrentComponentSize();
2602 if (pProcessor->m_pViewLayoutProcessor->GetNextAvailContentHeight(
2603 childSize.height)) {
2604 if (m_pViewLayoutProcessor) {
2605 if (!pFormNode && pLayoutContext)
2606 pFormNode = pLayoutContext->m_pOverflowProcessor->GetFormNode();
2608 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2610 if (bUseInherited) {
2611 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode,
2612 pOverflowTrailerNode,
2613 pTrailerLayoutItem, pFormNode);
2614 m_bUseInherited =
true;
2619 rgCurLineLayoutItems[uHAlign].push_back(pProcessor->ExtractLayoutItem());
2620 *bAddedItemInRow =
true;
2622 *fContentCurRowAvailWidth -= childSize.width;
2623 *fContentCurRowHeight = std::max(*fContentCurRowHeight, childSize.height);
2625 if (eRetValue == Result::kDone)
2626 *bForceEndPage =
false;
2635 if (m_pViewLayoutProcessor) {
2636 absl::optional<CXFA_ViewLayoutProcessor::OverflowData> overflow_data =
2637 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2638 if (overflow_data.has_value()) {
2639 pOverflowLeaderNode = overflow_data.value().pLeader;
2640 pOverflowTrailerNode = overflow_data.value().pTrailer;
2643 if (pTrailerLayoutItem)
2644 pProcessor->AddTrailerBeforeSplit(fSplitPos, pTrailerLayoutItem,
false);
2645 if (pProcessor->JudgeLeaderOrTrailerForOccur(pOverflowLeaderNode))
2646 pProcessor->AddPendingNode(pOverflowLeaderNode,
false);
2654 if (!pFormNode && pLayoutContext)
2655 pFormNode = pLayoutContext->m_pOverflowProcessor->GetFormNode();
2656 if (m_pViewLayoutProcessor) {
2657 absl::optional<CXFA_ViewLayoutProcessor::OverflowData> overflow_data =
2658 m_pViewLayoutProcessor->ProcessOverflow(pFormNode,
true);
2659 if (overflow_data.has_value()) {
2660 pOverflowLeaderNode = overflow_data.value().pLeader;
2661 pOverflowTrailerNode = overflow_data.value().pTrailer;
2664 if (bUseInherited) {
2665 pProcessor->ProcessUnUseOverFlow(pOverflowLeaderNode, pOverflowTrailerNode,
2666 pTrailerLayoutItem, pFormNode);
2667 m_bUseInherited =
true;
2672absl::optional<CXFA_ContentLayoutProcessor::Stage>
2675 if (m_bKeepBreakFinish)
2676 return absl::nullopt;
2677 return FindBreakAfterNode(pBreakAfterNode, pCurActionNode);
2680absl::optional<CXFA_ContentLayoutProcessor::Stage>
2683 for (
CXFA_Node* pBookendNode = *pCurActionNode
2684 ? (*pCurActionNode)->GetNextSibling()
2685 : pParentContainer->GetFirstChild();
2686 pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) {
2690 *pCurActionNode = pBookendNode;
2696 return absl::nullopt;
2699absl::optional<CXFA_ContentLayoutProcessor::Stage>
2702 if (!*pCurActionNode)
2703 return absl::nullopt;
2705 CXFA_Node* pBreakBeforeNode = (*pCurActionNode)->GetNextSibling();
2706 if (!m_bKeepBreakFinish) {
2707 absl::optional<Stage> ret =
2708 FindBreakBeforeNode(pBreakBeforeNode, pCurActionNode);
2709 if (ret.has_value())
2712 if (m_bIsProcessKeep)
2713 return ProcessKeepNodesForBreakBefore(pCurActionNode, pChildContainer);
2715 *pCurActionNode = pChildContainer;
2719absl::optional<CXFA_ContentLayoutProcessor::Stage>
2722 if (*pCurActionNode) {
2723 CXFA_Node* pBreakAfterNode = (*pCurActionNode)->GetNextSibling();
2724 return FindBreakAfterNode(pBreakAfterNode, pCurActionNode);
2727 CXFA_Node* pBreakAfterNode = pChildContainer->GetFirstChild();
2728 return HandleKeep(pBreakAfterNode, pCurActionNode);
2731absl::optional<CXFA_ContentLayoutProcessor::Stage>
2740 CXFA_Node* pSaveNode = pNextChildContainer;
2743 DeleteLayoutGeneratedNode(pSaveNode);
2745 if (!pNextChildContainer)
2746 return absl::nullopt;
2748 bool bLastKeep =
false;
2749 absl::optional<Stage> ret = ProcessKeepNodesForCheckNext(
2750 pCurActionNode, &pNextChildContainer, &bLastKeep);
2751 if (ret.has_value())
2754 if (!m_bKeepBreakFinish && !bLastKeep) {
2755 ret = FindBreakBeforeNode(pNextChildContainer->GetFirstChild(),
2757 if (ret.has_value())
2760 *pCurActionNode = pNextChildContainer;
2764absl::optional<CXFA_ContentLayoutProcessor::Stage>
2767 for (
CXFA_Node* pBookendNode = *pCurActionNode
2768 ? (*pCurActionNode)->GetNextSibling()
2769 : pParentContainer->GetFirstChild();
2770 pBookendNode; pBookendNode = pBookendNode->GetNextSibling()) {
2774 *pCurActionNode = pBookendNode;
2780 return absl::nullopt;
2784 m_bKeepBreakFinish =
true;
2785 m_pKeepHeadNode =
nullptr;
2786 m_pKeepTailNode =
nullptr;
2787 m_bIsProcessKeep =
false;
2793 bool* pContainerWidthAutoSize,
2794 bool* pContainerHeightAutoSize) {
2795 if (pContext && pContext->m_fCurColumnWidth.has_value()) {
2796 pSize->width = pContext->m_fCurColumnWidth.value();
2797 *pContainerWidthAutoSize =
false;
2799 if (*pContainerHeightAutoSize)
2802 pSize->height -= m_fUsedSize;
2804 bool bFocrTb =
false;
2815 *pContainerHeightAutoSize =
true;
2825 CXFA_ContentLayoutItem* pLastChild =
2826 ToContentLayoutItem(m_pLayoutItem->GetFirstChild());
2828 pNext = pNext->GetNextSibling()) {
2830 if (pContentNext && pContentNext->m_sPos.y != pLastChild->m_sPos.y)
2831 pLastChild = pContentNext;
2837 const CXFA_ContentLayoutItem* pLastChild) {
2840 pChild != pLastChild; pChild = pChild->GetNextSibling()) {
2842 if (!pLayout || !pLayout
->GetFormNode()->PresenceRequiresSpace())
2845 float fWidth = pLayout->m_sPos.x + pLayout->m_sSize.width;
2846 float fHeight = pLayout->m_sPos.y + pLayout->m_sSize.height;
2847 size.width =
std::max(size.width, fWidth);
2848 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